Rework VBR

This commit is contained in:
Nero 2019-05-19 20:07:08 +00:00
parent c288bbffb9
commit 1259fe14fe
3 changed files with 137 additions and 173 deletions

View File

@ -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

47
boot/chs.inc Normal file
View File

@ -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:

View File

@ -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