diff --git a/Makefile b/Makefile index 28d24d3..4d77fe5 100644 --- a/Makefile +++ b/Makefile @@ -23,12 +23,13 @@ kernel.rom: kernel/*.asm kernel/*.inc lib/*.inc nasm -s -o $@ -I lib -I kernel kernel/main.asm && scripts/fix-rom.sh $@ boot/%.bin: boot/%.asm lib/*.inc - nasm -s -o $@ -I lib $< + nasm -s -o $@ -I boot -I lib $< fdimage.img: boot/floppy.bin kernel.rom 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 clean: rm -f *.com *.bin *.rom *.img *.log boot/*.bin diff --git a/boot/chs.inc b/boot/chs.inc new file mode 100644 index 0000000..53c5c4b --- /dev/null +++ b/boot/chs.inc @@ -0,0 +1,47 @@ +fix_chs: + mov ah, 0x08 + int 0x13 + jc chs_end ; skip if function does not exist + inc dh + mov [cs:fdc.nos], dh + mov ax, cx + and ax, 0x003F + mov [cs:fdc.spt], ax ; no adjustment because sectors are 1-indexed + mov ax, cx + 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 0725eae..7a8ce27 100644 --- a/boot/floppy.asm +++ b/boot/floppy.asm @@ -1,11 +1,9 @@ org 0x0000 -fdc: ; FDC Descriptor as per ECMA-107 - jmp _startup - times (0x03 - ($-$$)) nop -.oem: - db "2B" ; creating system identifier - times (0x0B - ($-$$)) db " " ; space-padded +jmp 0x07C0:main + +times (0x0B - ($-$$)) db 0 ; space-padded +fdc: .ss: dw 0x200 ; sector size .sc: @@ -43,62 +41,99 @@ fdc: ; FDC Descriptor as per ECMA-107 db "FAT12" times (62 - ($-$$)) db " " -_startup: - xor ax, ax - ; setup stack area growing down from 0x10000 - mov ss, ax - mov sp, ax - ; adjust CS - jmp 0x07C0:main - -; non-fdc variables -rootdir: -.start: - dw 0 -.length: - dw 0 - main: cli - - ; backup important values + ; 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 push cx push dx - ; setup buffer area directly at 4k - mov ax, 0x0100 - mov ds, ax - mov es, ax + mov [fdc.drv], dl ; fix drive number in fdc - mov [cs:fdc.drv], dl ; backup drive number +%include "chs.inc" - call fix_chs - call calc_sectors - call find_first_cluster - xor bx, bx - call load_cluster + mov di, 0x1000 ; loading address for roms + call search_rootdir - ; restore important variables - xor ax, ax - pop dx - pop cx - pop bx - mov di, [0x001A] - mov ax, [di+0x1A] - push ds - push ax - retf + mov ax, 0xFFFF call error - db "ROM ERROR", 0 + db "THING", 0 + +search_rootdir: + 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 + +; in ax cluster number +loadrom: + call print16 + ret + +; 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] + 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 -; Write AX, a string and bail out -; Return pointer is the string start -; String must be 0 suffixed error: call print16 - push cs - pop ds pop si mov bx, 0x0000 mov al, 0x20 @@ -112,132 +147,13 @@ error: hlt jmp .hlt -; Read CHS data from BIOS and fix fdc values -fix_chs: - mov ah, 0x08 - int 0x13 - jc .end ; skip if function does not exist - inc dh - mov [cs:fdc.nos], dh - mov ax, cx - and ax, 0x003F - mov [cs:fdc.spt], ax ; no adjustment because sectors are 1-indexed - mov ax, cx - 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 -.end: - ret - -calc_sectors: - mov bx, [cs:fdc.ss] ; bytes per sector - mov cl, 5 - shr bx, cl ; div by 2^5, 32 bytes per entry - mov ax, [cs:fdc.rde] ; number of entries - xor dx, dx - div bx - mov [cs:rootdir.length], ax - mov ax, [cs:fdc.sf] ; sectors per fat - mul byte [cs:fdc.fn] ; number of fats - add ax, [cs:fdc.rsc] ; reserved sectors - mov [cs:rootdir.start], ax - ret - -; Load the root directory -find_first_cluster: - mov ax, [cs:rootdir.start] - mov cx, [cs:rootdir.length] - xor bx, bx -.blkloop: - call loadblk - add bx, [cs:fdc.ss] - add ax, 1 - loop .blkloop - push cs - pop es - mov cx, [cs:fdc.rde] - xor bx, bx -.dirloop: - push cx - mov cx, 0x000B - mov si, bx - mov di, bootfilename - repe cmpsb - pop cx - jz .found - add bx, 0x0020 ; 32 bytes per directory entry - loop .dirloop - call error - db "NOT FOUND", 0 -.found: - push ds - pop es - add bx, 26 - mov ax, [bx] - ret - -; Load a single FAT cluster into memory -; in ax cluster number -; es:bx buffer -; -load_cluster: - xor ch, ch - mov cl, [cs:fdc.sc] ; sectors per cluster - xor dx, dx - dec ax ; somehow 2 is first cluster - div word cx - add ax, [cs:rootdir.start] - add ax, [cs:rootdir.length] -.loop: - call loadblk - inc ax - add bx, [cs:fdc.ss] - loop .loop - ret - -; Load a single block into memory -; Does not return on error -; in ax sector number -; es:bx buffer -loadblk: - push ax - push cx - push dx - xor dx, dx - 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 .error - pop dx - pop cx - pop ax - ret -.error: - xchg al, ah - call error - db "DISK ERROR", 0 - %include "print.asm" -times (0x1F0 - ($-$$)) db 0 +times (0x1FA - ($-$$)) db 0 -bootfilename: - db "KERNEL" - times (0x1F8 - ($-$$)) db " " - db "ROM" +dw 0x2B2B -times (0x1FE - ($-$$)) db 0 +max_si: +dw 0x200 dw 0xAA55