diff --git a/Makefile b/Makefile index 6ad8604..188447a 100644 --- a/Makefile +++ b/Makefile @@ -25,8 +25,8 @@ endif default: kernel.rom -kernel.rom: kernel/*.asm lib/*.inc - nasm -s -o $@ -I lib -I kernel kernel/main.asm && scripts/fix-rom.sh $@ +kernel.com: kernel/*.asm lib/*.inc + nasm -s -o $@ -I lib -I kernel kernel/main.asm debug.rom: debug/*.asm lib/*.inc nasm -s -o $@ -I lib -I debug debug/main.asm && scripts/fix-rom.sh $@ @@ -34,11 +34,11 @@ debug.rom: debug/*.asm lib/*.inc boot/%.bin: boot/%.asm lib/*.inc nasm -s -o $@ -I boot -I lib $< -fdimage.img: boot/floppy.bin kernel.rom +fdimage.img: boot/floppy.bin kernel.com dd if=/dev/zero bs=512 count=$$(( $(FD_CYLINDERS) * $(FD_HEADS) * $(FD_SECTORS) )) of=$@ mformat -i $@ -t $(FD_CYLINDERS) -h $(FD_HEADS) -n $(FD_SECTORS) -B boot/floppy.bin :: - mcopy -i $@ kernel.rom ::kernel.rom - mattrib -i $@ +s ::kernel.rom + mcopy -i $@ kernel.com ::kernel.com + mattrib -i $@ +s ::kernel.com clean: rm -f *.com *.bin *.rom *.img *.log boot/*.bin @@ -47,7 +47,7 @@ qemu-rom: kernel.rom $(DEBUGROM) $(QEMU) $(QEMU_ARGS) -option-rom kernel.rom qemu-floppy: fdimage.img $(DEBUGROM) - $(QEMU) $(QEMU_ARGS) -boot c -hda fdimage.img + $(QEMU) $(QEMU_ARGS) -boot c -fda fdimage.img qemu-serial: boot/serial.bin $(DEBUGROM) $(QEMU) $(QEMU_ARGS) -hda boot/serial.bin diff --git a/boot/chs.inc b/boot/chs.inc deleted file mode 100644 index 1cceb56..0000000 --- a/boot/chs.inc +++ /dev/null @@ -1,47 +0,0 @@ -fix_chs: - mov ah, 0x08 - int 0x13 - jc chs_end ; skip if function does not exist - inc dh - mov [cs:fdc.nos], dh - push cx - and cx, 0x003F - mov [cs:fdc.spt], cx ; no adjustment because sectors are 1-indexed - pop ax - xchg al, ah - mov cl,6 - shr ah,cl - inc ax ; convert from maximum number (0-based) to total number (1-based) of cylinders - mul word [cs:fdc.nos] ; number of tracks = number of cylinders * heads - mul word [cs:fdc.spt] ; number of sectors = number of tracks * sectors per track - mov [cs:fdc.ts], ax - jmp chs_end - -; Load a single sector into memory -; Does not return on error -; in dx:ax sector number (will be trashed) -; es:bx buffer -load_sector: - push cx - div word [cs:fdc.spt] ; ax:temp = (lba / spt) - inc dx ; dx:sector = (lba % spt) + 1 - mov cl, dl ; sector number - xor dx, dx - div word [cs:fdc.nos] ; ax:cylinder = (tmp / heads) - ; dx:head = (tmp % heads) - mov ch, al ; cylinder number - mov dh, dl ; head number - mov dl, [cs:fdc.drv] ; driver number - mov ax, 0x0201 ; ah=0x02 al=0x01 - int 0x13 - jc disk_error - ; return - pop cx - ret - -disk_error: - xchg al, ah - call error - db "DISK ERROR", 0 - -chs_end: \ No newline at end of file diff --git a/boot/floppy.asm b/boot/floppy.asm index 7a8ce27..5028537 100644 --- a/boot/floppy.asm +++ b/boot/floppy.asm @@ -1,8 +1,17 @@ -org 0x0000 +org 0x7600 -jmp 0x07C0:main +; Memory layout: +; 060:0000 PSP for loaded program +; 060:0100 Loaded program +; 060:7800 Our code (= 0:7C00) +; 060:8000 FAT table +; 060:E000 Root directory +; 060:FF00 Stack area -times (0x0B - ($-$$)) db 0 ; space-padded +init: + jmp 0x060:main + +times (0x0B - ($-$$)) db 0 fdc: .ss: dw 0x200 ; sector size @@ -41,119 +50,207 @@ fdc: db "FAT12" times (62 - ($-$$)) db " " -main: - cli - ; setup stack area growing down from directly below us - xor ax, ax - mov ss, ax - mov sp, 0x7C00 - ; setup base segments - mov ax, cs - mov ds, ax - mov es, ax - ; save initial environment - push bx +; 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, 0x0030 + jnz error + +.loop: + push ax push cx push dx - mov [fdc.drv], dl ; fix drive number in fdc + ; calculate CHS data + div word [cs:fdc.spt] ; ax:temp = (lba / spt) + inc dx ; dx:sector = (lba % spt) + 1 + mov cl, dl ; sector number + xor dx, dx + div word [cs:fdc.nos] ; ax:cylinder = (tmp / heads) + ; dx:head = (tmp % heads) + mov ch, al ; cylinder number + mov dh, dl ; head number + mov dl, [cs:fdc.drv] ; driver number + mov ax, 0x0201 ; ah=0x02 al=0x01 + int 0x13 + mov bp, 0x0031 + jc error -%include "chs.inc" + pop dx + pop cx + pop ax - mov di, 0x1000 ; loading address for roms - call search_rootdir + ; count up for next sector + add bx, 0x0200 + inc ax - mov ax, 0xFFFF - call error - db "THING", 0 + loop .loop + ret -search_rootdir: +; Load the file in [filename] +; or exit with carry set +load_file: + mov si, 0xE000 + mov cx, [fdc.rde] +.loop: + call file_match + je read_clusters + add si, 0x20 + loop .loop + ret + +; Compares the FAT dirent against [filename] +; in ds:si filename +; out ZF zero flag set if equal +file_match: + push cx + push si + mov di, filename + mov cx, 11 + repe cmpsb + pop si + pop cx + ret + +; Read the file given by cluster number +; into the target program area +; in ax cluster number +read_clusters: + add si, 0x1A + lodsw + mov bx, 0x0100 +.loop: + ; 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, 0x8000 + + ; 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 .loop + + ret + +main: + cli + ; Everything in one segment, stack starts on top + mov ax, cs + mov ds, ax + mov es, ax + mov ss, ax + mov sp, ax + mov [fdc.drv], dl ; save drive number in fdc + sti + + ; load fat table into memory + mov ax, [fdc.rsc] + mov cx, [fdc.sf] + xor dx, dx + mov bx, 0x8000 + call load_sectors + + ; calculate length of rootdir + mov ax, [fdc.rde] + dec ax + mov cl, 4 + shr ax, cl ; 32 bytes per entry + inc ax + mov cx, ax + + ; load root dir + xor dx, dx mov ax, [fdc.sf] mul byte [fdc.fn] add ax, [fdc.rsc] - mul word [fdc.ss] - mov si, ax ; now pointing to start of rootdir - mov cx, [fdc.rde] - jmp .start -.next: - dec cx - jz .end - add si, 0x20 -.start: - call lazy_load - cmp byte [si], 0 ; end of directory - je .end - cmp byte [si], 0xe5 ; deleted entry - je .next - cmp word [si+8], 0x4F52 ; first 2 chars of extension: "RO" - jne .next - mov ax, [si+10] ; 3rd char of extension, file flags - and ax, 0x14FF ; zero out flags except directory and system - cmp ax, 0x044D ; "M" , system flag set, directory flag unset - jne .next - mov ax, [si+26] - push si - push cx - call loadrom - pop cx - pop si - jmp .next -.end: - ret + mov bx, 0xE000 + call load_sectors -; in ax cluster number -loadrom: - call print16 - ret + ; remember where we left off + ; clusters start after rootdir + mov [cluster_offset], ax -; Makes sure the block starting with (or under SI) is -; already fetched from disk -; in ds:si data expected to be fetched from disk -; trashes ax, bx and dx -lazy_load: - cmp si, [max_si] - jc .end - ; calculate next sector number - mov ax, [max_si] + call load_file + mov bp, 0x0032 + jc error + + ; get length of arguments + mov cx, 0x007F + mov di, arguments + xor ax, ax + repe scasb + sub di, arguments + mov cx, di + + ; setup arguments field + mov [0x080], cl + mov di, [0x081] + mov si, arguments + rep movsb + + ; setup int 19h call at 0000, and push its address to stack + mov WORD [0000], 0x19CD + push sp + + ; clear out registers and jump into target + xor ax, ax + xor cx, cx xor dx, dx - div word [fdc.ss] - ; write to es:bx - xor dx, dx - push cs - pop es - mov bx, [max_si] - call load_sector - ; update max_si counter - mov ax, [max_si] - add ax, [fdc.ss] - mov [max_si], ax - ; loop until requirement is satisfied - jmp lazy_load -.end: - ret + xor bx, bx + mov dl, [fdc.drv] + jmp 0x0100 error: - call print16 - pop si - mov bx, 0x0000 - mov al, 0x20 -.loop: + mov ax, bp mov ah, 0x0e + mov bx, 7 int 0x10 - lodsb - cmp al, 0x00 - jne .loop -.hlt: - hlt - jmp .hlt + mov al, 0x21 + int 0x10 + xor ax, ax + int 0x16 + int 0x19 -%include "print.asm" +cluster_offset: + dw 0 -times (0x1FA - ($-$$)) db 0 +times (0x175 - ($-$$)) db 0 -dw 0x2B2B +filename: + db "KERNEL COM" -max_si: -dw 0x200 +arguments: + db " ", 0 + +times (0x1FE - ($-$$)) db 0 dw 0xAA55 diff --git a/kernel/main.asm b/kernel/main.asm index 32cb154..5791244 100644 --- a/kernel/main.asm +++ b/kernel/main.asm @@ -1,60 +1,5 @@ cpu 8086 -org 0x0000 -rom: - db 0x55, 0xAA -.sectors: - db 0x00 -.init: - push cs - pop es - - mov di, start - mov ax, 0x18 - call intr_register - - retf -.name: - db "ROM DOS", 0 - - times (0x18 - ($-$$)) db 0 -.pcir_ptr: - dw 0 - - times (0x1A - ($-$$)) db 0 -.pnp_ptr: - dw pnp - -pnp: - db "$PnP" -.version: - db 1 ; version 1 -.length: - db 2 ; 2 * 16 length - dw 0 ; offset of next header - db 0 -.checksum: - db 0 ; checksum (filled by fix-rom) - dd 0 ; device identifier - dw 0 ; manufacturer string - dw rom.name ; product name string - db 0,0,0 ; device type string - db 0x20 ; device indicator, bit for "read cacheable" set - dw 0 ; boot connection vector - dw 0 ; boot disconnect vector - dw start ; bootstrap entry point - dw 0 ; reserved - dw 0 - -start: - xor ax, ax - mov ds, ax - mov es, ax - mov ss, ax - mov sp, 0x800 - mov di, sp - - call drvtab_create - +org 0x0100 push cs pop es mov di, isr_dos_main @@ -64,7 +9,6 @@ start: .loop: mov ah, 0x01 int 0x21 - int3 jmp .loop cli @@ -91,4 +35,4 @@ isr_return: %include "chario.asm" -align 512 +times 1000 db 0xEA