Load kernel off of FAT12 disk
This commit is contained in:
parent
8da504ca2d
commit
9a829fc71c
4
Makefile
4
Makefile
|
@ -3,10 +3,12 @@
|
|||
|
||||
all: nor86.img
|
||||
|
||||
nor86.img: bootsector.bin kernel.bin
|
||||
nor86.img: bootsector.bin kernel.bin CC0 README.md
|
||||
rm -f $@
|
||||
mkdosfs -C $@ 1440
|
||||
rw -i bootsector.bin -o $@
|
||||
mcopy -i $@ CC0 ::
|
||||
mcopy -i $@ README.md ::
|
||||
mcopy -i $@ kernel.bin ::
|
||||
|
||||
.asm.bin:
|
||||
|
|
185
bootsector.asm
185
bootsector.asm
|
@ -45,7 +45,7 @@ _start:
|
|||
; Save bootdrive
|
||||
mov [drivenumber], dl
|
||||
|
||||
root_dir:
|
||||
calc_constants:
|
||||
; Disk organization:
|
||||
; Reserved sectors (MBR)
|
||||
; FAT1
|
||||
|
@ -58,16 +58,51 @@ root_dir:
|
|||
add ax, [reservedsectors]
|
||||
mov [rootdir], ax
|
||||
|
||||
; Data area comes after root dir, so we need to add the size of
|
||||
; the root dir in sectors
|
||||
; One root dir entry is 32 bytes, and one sector has 512 bytes
|
||||
; Therefore 512 / 32 = 16 entries correspond to a sector
|
||||
; However, we can't just do a shift, since we need to round up
|
||||
; For integers, ceil(x/y) = floor((x+y-1)/y)
|
||||
mov ax, [rootdirentries]
|
||||
add ax, 15
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
mov [rootdirsectors], ax
|
||||
|
||||
fat:
|
||||
; FAT1 (the main one) follows right after bootsector(s)
|
||||
mov ax, [reservedsectors]
|
||||
call chs
|
||||
|
||||
; TODO: handle possible crossing of track boundary
|
||||
mov ax, [sectorsperfat]
|
||||
mov ah, 2
|
||||
mov dl, [drivenumber]
|
||||
mov bx, 0x8000
|
||||
int 0x13
|
||||
|
||||
root_dir:
|
||||
mov ax, [rootdir]
|
||||
call chs
|
||||
|
||||
; TODO: handle possible crossing of track boundary
|
||||
mov ax, [rootdirsectors]
|
||||
mov ah, 2
|
||||
mov al, 14 ; TODO: don't hardcode
|
||||
mov dl, [drivenumber]
|
||||
mov bx, 0x500
|
||||
int 0x13
|
||||
|
||||
print_root:
|
||||
mov byte [0x500 + 32*224], 0 ; TODO: don't hardcode
|
||||
search_root:
|
||||
mov bx, [rootdirentries]
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
shr ax, 1
|
||||
mov byte [bx + 0x500], 0
|
||||
mov si, 0x500
|
||||
.entry:
|
||||
cmp byte [si], 0
|
||||
|
@ -80,36 +115,137 @@ print_root:
|
|||
jmp .entry
|
||||
|
||||
.isfile:
|
||||
mov ah, 0xe
|
||||
mov cx, 8
|
||||
.name:
|
||||
mov cx, 11
|
||||
mov bx, kernel_name
|
||||
|
||||
.compare:
|
||||
lodsb
|
||||
int 0x10
|
||||
loop .name
|
||||
cmp al, [bx]
|
||||
jne .nomatch
|
||||
inc bx
|
||||
loop .compare
|
||||
|
||||
mov al, ' '
|
||||
int 0x10
|
||||
jmp found
|
||||
|
||||
mov cx, 3
|
||||
.ext:
|
||||
lodsb
|
||||
int 0x10
|
||||
loop .ext
|
||||
|
||||
mov al, 13
|
||||
int 0x10
|
||||
mov al, 10
|
||||
int 0x10
|
||||
|
||||
add si, 32 - 11
|
||||
.nomatch:
|
||||
; Each entry is 32 bytes long
|
||||
; During each iteration of the compare loop, si is
|
||||
; incremented and cx is decremented
|
||||
; At the top of the loop, si + cx = entry_start + 11, but
|
||||
; when we jump here si has been incremented by one already
|
||||
; while cx is still the same
|
||||
; Therefore, si + cx is one more, so add extra - 1 here
|
||||
add si, 32 - 11 - 1
|
||||
add si, cx
|
||||
jmp .entry
|
||||
|
||||
.end:
|
||||
|
||||
notfound:
|
||||
; TODO: Better error messages
|
||||
mov ax, 0x0e00 + '?'
|
||||
int 0x10
|
||||
|
||||
hang:
|
||||
hlt
|
||||
jmp hang
|
||||
|
||||
found:
|
||||
; SI points to 11 bytes after the start of the entry, so adjust all
|
||||
; offsets
|
||||
; TODO: Handle zero-length files
|
||||
mov ax, [si - 11 + 26] ; First cluster
|
||||
push ax
|
||||
|
||||
; Load OS at the start of the memory
|
||||
mov bx, 0x500
|
||||
|
||||
push bx
|
||||
|
||||
.tosector
|
||||
; Adjust the cluster number to account for first two
|
||||
; "clusters" in the FAT being used for metadata
|
||||
sub ax, 2
|
||||
|
||||
; Scale by number of sectors per cluster
|
||||
xor bx, bx
|
||||
mov bl, [sectorspercluster]
|
||||
mul word bx
|
||||
|
||||
; Offset by number of non-data sectors before data area
|
||||
add ax, [rootdir]
|
||||
add ax, [rootdirsectors]
|
||||
|
||||
; Load sectors
|
||||
pop bx
|
||||
xor cx, cx
|
||||
mov cl, [sectorspercluster]
|
||||
mov dl, [drivenumber]
|
||||
.loop:
|
||||
push ax
|
||||
push cx
|
||||
|
||||
call chs
|
||||
|
||||
mov ah, 2
|
||||
mov al, 1
|
||||
int 0x13
|
||||
|
||||
pop cx
|
||||
pop ax
|
||||
|
||||
add bx, 512
|
||||
inc ax
|
||||
loop .loop
|
||||
|
||||
.next:
|
||||
pop ax
|
||||
|
||||
; Multiply by 1.5 to get offset into the table
|
||||
; This rounds down, which is what we want in order to get
|
||||
; the first byte of the address
|
||||
mov si, ax
|
||||
shl si, 1
|
||||
add si, ax
|
||||
shr si, 1
|
||||
|
||||
; Load the entry from FAT
|
||||
mov dx, [si + 0x8000]
|
||||
|
||||
; Two clusters, 0xABC and 0xXYZ, are stored as
|
||||
; BC ZA XY
|
||||
; ^ where we start reading on even cluster numbers
|
||||
; ^^^^^ loading word → 0xZABC
|
||||
; ^ where we start reading on odd cluster numbers
|
||||
; ^^^^^ loading word: 0xXYZA
|
||||
test ax, 1
|
||||
jnz .odd
|
||||
|
||||
.even:
|
||||
and dx, 0x0fff
|
||||
jmp .check_cluster
|
||||
|
||||
.odd:
|
||||
shr dx, 1
|
||||
shr dx, 1
|
||||
shr dx, 1
|
||||
shr dx, 1
|
||||
|
||||
.check_cluster:
|
||||
mov ax, dx
|
||||
|
||||
; End of chain
|
||||
cmp ax, 0xFF8
|
||||
jg execute_kernel
|
||||
|
||||
push ax
|
||||
push bx
|
||||
jmp .tosector
|
||||
|
||||
execute_kernel:
|
||||
mov dl, [drivenumber]
|
||||
jmp 0:0x500
|
||||
|
||||
chs:
|
||||
push ax
|
||||
push bx
|
||||
|
@ -154,7 +290,10 @@ chs:
|
|||
|
||||
%include "hexprint.inc"
|
||||
|
||||
kernel_name: db "KERNEL BIN"
|
||||
|
||||
times 510-($-$$) db 0
|
||||
db 0x55, 0xaa
|
||||
_end:
|
||||
rootdir equ _end
|
||||
rootdirsectors equ _end + 2
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
org 0x500
|
||||
|
||||
mov ax, 0x0e40
|
||||
int 0x10
|
||||
|
||||
hang:
|
||||
hlt
|
||||
jmp hang
|
Loading…
Reference in New Issue