commit 99a3401106e67987264a577ac9c42c9bb80112be
parent feb49ae3f486ce121c90a888b91ceeae589fca46
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Mon, 25 Jul 2022 21:39:05 -0400
i386: booting up to init.fs!
Diffstat:
10 files changed, 133 insertions(+), 15 deletions(-)
diff --git a/Makefile b/Makefile
@@ -29,14 +29,14 @@ pc.bin: dusk buildpc.fs
pc.img: mbr.bin pc.bin
dd if=/dev/zero of=$@ bs=1M count=1
# We need to reserve (-R) enough sectors for MBR + pc.bin
- mformat -M 512 -d 1 -R 16 -i $@ ::
+ mformat -M 512 -d 1 -R 40 -i $@ ::
dd if=mbr.bin of=$@ bs=1 seek=62 conv=notrunc
dd if=pc.bin of=$@ bs=1 seek=512 conv=notrunc
mcopy -sQ -i $@ fs/* ::
.PHONY: pcrun
pcrun: pc.img
- qemu-system-i386 -drive file=pc.img,if=floppy,format=raw
+ qemu-system-i386 -drive file=pc.img,format=raw
.PHONY: run
run: dusk
diff --git a/buildpc.fs b/buildpc.fs
@@ -4,7 +4,13 @@
dup getc dup 0>= while stderr repeat ( fc c ) drop fclose ;
1 to fecho
f<< /xcomp/i386.fs
+f<< /xcomp/pc/kernel.fs
+xbindict orgifydict
org here org - spit
spitfile<< /xcomp/bootlo.fs
+spitfile<< /drv/pc/int13h.fs
spitfile<< /xcomp/pc/glue1.fs
+spitfile<< /fs/fatlo.fs
+spitfile<< /xcomp/pc/glue2.fs
+spitfile<< /xcomp/boothi.fs
bye
diff --git a/fs/asm/i386.fs b/fs/asm/i386.fs
@@ -162,6 +162,7 @@ $c3 op ret, $90 op nop, $fa op cli, $fc op cld,
$ac op lodsb, $ad op lods, $a6 op cmpsb, $a7 op cmps,
$a4 op movsb, $a5 op movs,
$f3 op repz, $f2 op repnz, $f3 op rep,
+$9c op pushf, $9d op popf, $cf op iret,
\ Jumps and relative addresses
\ i386 jumps and calls in their immediate modes are relative. We keep it that
@@ -247,6 +248,12 @@ $58 op pop, $50 op _push,
op8b if $6a else $68 then c, imm, asm$ else
_push, then ;
+\ IN/OUT
+: op ( op -- ) doer c, does> c@ ( opcode -- )
+ opreg oprm and -1 = _assert
+ maybe8b imm? if c, imm, else 8 + c, then asm$ ;
+$e4 op in, $e6 op out,
+
\ MOV has this special reg<-imm shortcut
: mov,
imm? if opmod 3 = if \ mov reg, imm shortcut
diff --git a/fs/drv/pc/fdc.fs b/fs/drv/pc/fdc.fs
@@ -0,0 +1,20 @@
+\ PC floppy disk controller driver
+
+\ get number of floppy drives from CMOS register $10
+$10 $70 pc! $71 pc@ dup $f and const FDSLAVETYPE 16 / const FDMASTERTYPE
+
+\ hardcode for 1.44M disks.
+
+2 const FDHEADS
+80 const FDCYLCNT
+18 const FDSECPERTRK
+FDSECPERTRK FDHEADS * const FDSECPERCYL
+
+: lba>chs ( lba -- cyl head sec )
+ dup FDSECPERCYL / ( lba cyl )
+ over FDHEADS mod ( lba cyl head )
+ rot FDSECPERCYL mod ( cyl head sec ) ;
+
+\ TODO finish this. I was set on starting with this driver because I thought
+\ that my hardware treated boot USB key as a floppy, but it doesn't (master and
+\ slave config from CMOS are both 0). I'll come back to floppies later.
diff --git a/fs/drv/pc/int13h.fs b/fs/drv/pc/int13h.fs
@@ -0,0 +1,14 @@
+\ Driver around int13h
+\ This implements a read-only drive protocol over a
+\ int13h ( drv head cyl sec dst ) word which must be implemented in the kernel.
+
+$200 const BIOSSECSZ
+$7c18 w@ const SECPERTRK
+$7c1a w@ const NUMHEADS
+$7c24 c@ const DRVNO
+$80 const DRVNO
+SECPERTRK NUMHEADS * const SECPERCYL
+
+: biossec@ ( sec dst -- )
+ >r DRVNO swap SECPERCYL /mod ( drv sec cyl )
+ swap SECPERTRK /mod ( drv cyl sec head ) rot> 1+ r> int13h ;
diff --git a/fs/xcomp/i386.fs b/fs/xcomp/i386.fs
@@ -260,6 +260,16 @@ xcode >>c
[ebp] setc,
ret,
+xcode lshift ( n u -- n )
+ CX pspop,
+ [ebp] shlcl,
+ ret,
+
+xcode rshift ( n u -- n )
+ CX pspop,
+ [ebp] shrcl,
+ ret,
+
xcode and
AX pspop,
[ebp] ax and,
@@ -310,6 +320,19 @@ pc to lblcwrite \ al=c
lblhere m) inc,
ret,
+xcode w@
+ si [ebp] mov,
+ ax ax xor,
+ 16b! ax [esi] mov,
+ [ebp] ax mov,
+ ret,
+
+xcode w!
+ AX pspop,
+ BX pspop,
+ 16b! ax 0 d) bx mov,
+ ret,
+
xcode @
ax [ebp] mov,
ax ax 0 d) mov,
@@ -336,6 +359,19 @@ pc to lblwrite \ eax=n
lblhere m) CELLSZ i) add,
ret,
+xcode pc@ ( port -- n )
+ dx [ebp] mov,
+ ax ax xor,
+ 8b! in,
+ [ebp] ax mov,
+ ret,
+
+xcode pc! ( n port -- )
+ DX pspop,
+ AX pspop,
+ 8b! out,
+ ret,
+
xcode move ( src dst u -- )
CX pspop,
DI pspop,
@@ -734,4 +770,3 @@ pc ( loop )
( pc ) abs>rel jmp,
pc lblbootptr pc>addr !
-xbindict orgifydict
diff --git a/fs/xcomp/pc/glue1.fs b/fs/xcomp/pc/glue1.fs
@@ -1,3 +1,2 @@
-: foo ." Hello World!" 5 >r begin r@ 'A' + emit next ; foo
-bye
-
+BIOSSECSZ const drvblksz
+alias biossec@ (drv@)
diff --git a/fs/xcomp/pc/glue2.fs b/fs/xcomp/pc/glue2.fs
@@ -0,0 +1,8 @@
+\ Glue code that goes between the filesystem part and boothi
+alias fatopenlo fopen
+alias fatchild fchild
+0 S" drv" fchild S" pc" fchild S" int13h.fs" fchild floaded,
+0 S" fs" fchild S" fatlo.fs" fchild floaded,
+: foo ." Hello World!" ; foo
+bye \ almost there! it *does* load init.fs, but this init.fs is written for the
+\ POSIX Dusk. I have to reorganize how init.fs is placed in the final FS.
diff --git a/fs/xcomp/pc/kernel.fs b/fs/xcomp/pc/kernel.fs
@@ -0,0 +1,30 @@
+\ Extra native code cross-compiled into the kernel
+\ For the PC platform, we need to fiddle with real mode/protected mode so that
+\ we can use int13h to properly boot ourselves to init.fs
+
+pc to L1 \ back to protected mode!
+ ax $10 i) mov, ds ax mov, ss ax mov, es ax mov, gs ax mov, fs ax mov,
+ ret,
+
+pc to L2 1 to realmode \ we're in realmode
+ ax ax xor, es ax mov,
+ ax $0201 i) mov, $13 int,
+ \ we've done what we came for, let's go back to 32bit
+ ax cr0 mov, ax 1 i) or, cr0 ax mov,
+ $08 L1 jmpfar,
+
+pc to L1 \ segment with ffff limits
+ ax $20 i) mov, ds ax mov, ss ax mov, es ax mov, gs ax mov, fs ax mov,
+ ax cr0 mov, ax $fffffffe i) and, cr0 ax mov,
+ 0 L2 jmpfar,
+0 to realmode
+
+xcode int13h ( drv head cyl sec dst -- ) pc lblcurrent pc>addr !
+ BX pspop,
+ AX pspop, cl al mov, \ sec
+ AX pspop, ch al mov, \ cyl
+ AX pspop, dh al mov, \ head
+ AX pspop, dl al mov, \ drive
+ $18 L1 jmpfar,
+
+pc lblbootptr pc>addr !
diff --git a/fs/xcomp/pc/mbr.fs b/fs/xcomp/pc/mbr.fs
@@ -12,11 +12,15 @@ forward8 jmp, to L1 \ bypass GDT
pc to lblgdt
\ Inspired by GNU grub at grub-core/kern/i386/realmode.S
\ First entry (the null entry) is a reference to itself
-$17 w, lblgdt , 0 w,
-\ Code segment. base=0, limit=ffffff*4kb, present, execute/read, DPL=0
+$27 w, lblgdt , 0 w,
+\ Code segment. base=0, limit=ffffff*4kb, present, 32bit, execute/read, DPL=0
$ffff w, 0 w, 0 c, $9a c, $cf c, 0 c,
-\ Data segment. base=0, limit=ffffff*4kb, present, read/write, DPL=0
+\ Data segment. base=0, limit=ffffff*4kb, present, 32bit, read/write, DPL=0
$ffff w, 0 w, 0 c, $92 c, $cf c, 0 c,
+\ Code segment. base=0, limit=ffff*1b, present, 32bit, execute/read, DPL=0
+$ffff w, 0 w, 0 c, $9a c, 0 c, 0 c,
+\ Data segment. base=0, limit=ffff*1b, present, 32bit, read/write, DPL=0
+$ffff w, 0 w, 0 c, $92 c, 0 c, 0 c,
L1 forward!
cli, cld, lblgdt m) lgdt,
ax $0003 i) mov, $10 int, \ video mode 80x25
@@ -28,11 +32,6 @@ bx $8000 i) mov, cx $0002 i) mov, dh 0 i) mov, $13 int,
ax cr0 mov, ax 1 i) or, cr0 ax mov,
$08 0 jmpfar, here org - binstart + here 4 - w! 0 to realmode
\ initialize all segments
-ax 16 i) mov,
-ds ax mov,
-ss ax mov,
-es ax mov,
-gs ax mov,
-fs ax mov,
+ax $10 i) mov, ds ax mov, ss ax mov, es ax mov, gs ax mov, fs ax mov,
\ Jump to payload
$08 $8000 jmpfar,