diff --git a/boot/fat.asm b/boot/fat.asm index 9443bdb..71a2ab4 100644 --- a/boot/fat.asm +++ b/boot/fat.asm @@ -1,10 +1,18 @@ +; Memory layout: %define segment 0x00100 -%define self (0x7C00-(segment<<4)) ; 1 sector -cpu 8086 +%define self (0x7C00-(segment<<4)) ; 1 sector +%define fattab (self+0x200) ; variable size +%define rootdir 0x00100 ; variable size +%define prog 0x0F000 ; 4K at the end for OS + org self + jmp short init +cluster_offset: + dw 0 + times (0x0B - ($-$$)) db 0 fdc: @@ -57,16 +65,127 @@ main: ; Stack grows down from 64k mov ax, cs mov ss, ax - mov sp, BDOS + mov sp, prog mov ds, ax mov es, ax mov [fdc.drv], dl ; save drive number in fd + sti - mov ax, 1 - mov cx, 8 - mov dx, 0 - mov bx, BDOS + ; load fat table into memory + mov ax, [fdc.rsc] + mov cx, [fdc.sf] + xor dx, dx + mov bx, fattab + call load_sectors + + ; calculate length of rootdir + mov ax, [fdc.rde] + mov cl, 4 + shr ax, cl ; 32 bytes per entry + mov cx, ax + + ; load root dir + xor dx, dx + mov ax, [fdc.sf] + mul byte [fdc.fn] + add ax, [fdc.rsc] + mov bx, rootdir + call load_sectors + + ; remember where we left off + ; clusters start after rootdir + mov [cluster_offset], ax + + ; Load kernel + mov bx, prog + mov ax, kernel_name + call load_file + mov bp, 0x3332 + jc error + + mov dl, [fdc.drv] + + ; jump into kernel + jmp segment:prog + +; Load a file into memory +; IN AX pointer to 8.3 filename +; ES:BX pointer to target area +; OUT CF flag set if error +; DI file size in bytes (<64K) +load_file: + mov si, rootdir + mov cx, [fdc.rde] +.search: + push cx + push si + mov di, ax + mov cx, 11 + repe cmpsb + pop si + pop cx + je .read + add si, 0x20 + loop .search + xor di, di + stc + ret +.read: + mov ax, [si+0x1A] + mov di, [si+0x1C] + jmp read_clusters + +; Read the file given by cluster number +; into the target program area +; in ax cluster number +read_clusters: + ; read cluster into area for target file + push ax + sub ax, 2 + mul BYTE [fdc.sc] + add ax, [cluster_offset] + xor dx, dx + mov cx, [fdc.sc] + xor ch, ch + call load_sectors + pop ax + + ; calculate index in FAT + mov si, ax + shr si, 1 + add si, ax + add si, fattab + + ; load entry from FAT, truncate to 12 bit + mov dx, [si] + test ax, 1 + jz .noshift + mov cl, 4 + shr dx, 4 +.noshift: + mov ax, dx + + and ax, 0x0FFF + cmp ax, 0x0FF8 + jc read_clusters + + ret + +; Read sectors from disk +; Does not return on error +; ax and bx will be incremented, cx decremented +; in dx:ax sector number +; es:bx buffer +; cx number of sectors to read +; out dx:ax next sector to read +; es:bx next free buffer +; cx zero +load_sectors: + ; fail instantly if reading sectors > 16 bit + test dx, dx + mov bp, 0x3330 + jnz error .loop: push ax @@ -98,15 +217,10 @@ main: ; count up for next sector add bx, 0x0200 - add ax, 1 - adc dx, 0 + inc ax loop .loop - - mov dl, [fdc.drv] - - ; jump into bios cold boot entry point - jmp segment:BIOS + ret error: mov ax, bp @@ -119,6 +233,9 @@ error: int 0x16 int 0x19 +kernel_name: + db "BDOS BIN" + times (0x1FE - ($-$$)) db 0 dw 0xAA55 diff --git a/src/utils/fix-rom.c b/src/utils/fix-rom.c index 05cfc83..d1099ed 100644 --- a/src/utils/fix-rom.c +++ b/src/utils/fix-rom.c @@ -3,6 +3,7 @@ #include #include #include +#include struct stat sbuf;