rdos/boot/fat.asm

211 lines
3.3 KiB
NASM

; Bootsector for FAT12/FAT16 filesystems
; Memory layout
ourself: equ 0x0800 ; 1 sector, this code
cluslist: equ 0x0A00 ; up-growing list of words
stack: equ 0x7C00 ; growing down
bootsect: equ 0x7C00 ; our origin before reloc
; default buffer for reads
cpu 8086
org 0x0800
jmp short init
nop
%include "inc/bpb.asm"
%define V 0x %+ VERSION
dd V, V
times ( 0x0B - ($-$$) ) db 0
bpb: times BPBSIZ4 db 0
; Area for BPB
times ( 0x3E - ($-$$) ) db 0
init: xor ax, ax
mov ss, ax
mov sp, stack
push sp
push dx
; save potential partition table entry
push ds
push si
mov ds, ax
mov es, ax
mov si, bootsect
mov di, ourself
mov cx, 0x0100
rep movsw
jmp 0x0:main
%include "inc/booterr.asm"
; Read sectors from disk
; IN ES:DI target buffer
; DX:AX absulute 32-bit sector number
; CX numeber of sectors
read: push ax
push cx
push dx
xchg ax, bx
mov al, byte [bp+BPBNOS]
mul byte [bp+BPBSPT]
xchg ax, bx
; dx:ax = lba
div word bx
xchg ax, dx
; dx = cylinder, ax = head * tracksectors + sector
div byte [bp+BPBSPT]
; dx = cylinder, al = head, ah = sector
xchg dl, dh
ror dl, 1
ror dl, 1
or dl, ah
inc dx
; al: head number
; dh bit 0-7: cylinder bits 0-7
; dl bit 0-5: sector bits 0-5
; dl bit 6-7: cylinder bits 8-9
mov cx, dx
mov dh, al
mov dl, [bp-1]
mov ax, 0x0201
mov bx, di
int 0x13
jc errjmp
pop dx
pop cx
pop ax
add ax, 1
adc dx, 0
add di, 0x200
loop read
ret
rootdirsects: mov bx, [bp+BPBRDE]
mov cl, 4
shr bx, cl ; 32 bytes per entry
ret
offset_cluster: ; add offset of cluster data area to DX:AX
call rootdirsects
add ax, bx
adc dx, 0
offset_rootdir: ; add length of fat table times number of fats
xor ch, ch
mov cl, byte [bp+BPBFN]
.loop: add ax, [bp+BPBFS]
adc dx, 0
loop .loop
offset_fat: ; add reserved sectors
add ax, [bp+BPBRSC]
adc dx, 0
offset_part: ; add partition offset
add ax, [bp+BPBHS]
add dx, [bp+BPBHS+2]
ret
resetbuf: ; DS = ES
push es
pop ds
; ES:DI = 07C0:0000
mov ax, ( bootsect >> 4 )
mov es, ax
xor di, di
; AX,CX = 0
xor ax, ax
xor dx, dx
ret
main: mov bp, bpb
mov [bp-1], dl
; load root directory
call resetbuf
push di
call offset_rootdir
call rootdirsects
mov cx, bx
call read
; search for file
pop bx
mov cx, [bp+BPBRDE]
.loop: push cx
mov si, filename
mov di, bx
add bx, 0x20
mov cx, 0x0B
repe cmpsb
pop cx
loopne .loop
jne err_not_found
push word [es:bx-0x20+0x1A]
; load fat table
call resetbuf
push di
call offset_fat
mov cx, [bp+BPBFS]
call read
; fetch cluster numbers (FAT12-specific)
call resetbuf
mov es, ax
mov di, cluslist
pop si ; buffer offset
pop ax ; clus num
push di ; save list for later
readfat: stosw
mov bx, ax
shr bx, 1
pushf
add bx, ax
mov ax, [bx]
popf ; CF: 0=even, 1=odd entry
jc .odd
and ax, 0x0FFF
jmp .both
.odd: mov cl, 4
shr ax, cl
.both: cmp ax, 0xFF8
jc readfat
xor ax, ax
stosw
; load clusters
pop si
call resetbuf
loadclus: lodsw
sub ax, 2
jc .jump
mul byte [bp+BPBSC]
call offset_cluster
xor cx, cx
mov cl, [bp+BPBSC]
call read
jmp loadclus
.jump: pop si
pop ds
pop dx
ret
err_not_found:
hlt: hlt
jmp hlt
times (0x1F3 - ($-$$)) db 0
filename: db "KERNEL ", "BS "
dw 0xAA55