rdos/boot/fat.asm

189 lines
3.1 KiB
NASM

; Bootsector for FAT12/FAT16 filesystems
; Takes defines:
; FAT12 FAT has 1.5 bytes per entry
; FAT16 FAT has WORD per entry
cpu 8086
org 0x0800
jmp short init
nop
%include "inc/bpb.asm"
times ( 0x0B - ($-$$) ) db 0
params: times bpb_size db 0
; Area for BPB
times ( 0x3E - ($-$$) ) db 0
init: xor ax, ax
mov ss, ax
mov sp, ax
; save potential partition table entry
push ds
push si
mov ds, ax
mov es, ax
mov si, 0x7C00
mov di, 0x0800
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+bpb.heads]
mul byte [bp+bpb.tracksectors]
xchg ax, bx
; dx:ax = lba
div word bx
xchg ax, dx
; dx = cylinder, ax = head * tracksectors + sector
div byte [bp+bpb.tracksectors]
; 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+bpb.drivenum]
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+bpb.direntries]
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+bpb.fatnumber]
.loop: add ax, [bp+bpb.fatsectors]
adc dx, 0
loop .loop
offset_fat: ; add reserved sectors
add ax, [bp+bpb.reservedsects]
adc dx, 0
offset_part: ; add partition offset
add ax, [bp+bpb.sectoroffset]
add dx, [bp+bpb.sectoroffset+2]
ret
resetbuf: xor ax, ax
mov dx, ax
mov di, buf
ret
main: mov bp, params
mov [bp+bpb.drivenum], dl
; load root directory
call resetbuf
call offset_rootdir
call rootdirsects
mov cx, bx
call read
; search for file
mov bx, buf
mov cx, [bp+bpb.direntries]
.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 [bx-0x20+0x1A]
; load fat table
call resetbuf
call offset_fat
mov cx, [bp+bpb.fatsectors]
call read
; fetch cluster numbers (FAT12-specific)
mov di, 0x0500
pop ax
readfat: stosw
mov bx, ax
shr bx, 1
pushf
add bx, ax
mov ax, [buf+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
mov si, 0x500
mov di, 0x7C00
loadclus: lodsw
sub ax, 2
jc .jump
mul byte [bp+bpb.clustersects]
call offset_cluster
xor cx, cx
mov cl, [bp+bpb.clustersects]
call read
jmp loadclus
.jump: pop si
pop ds
jmp 0x7C00
err_not_found:
hlt: hlt
jmp hlt
times (0x1F3 - ($-$$)) db 0
filename: db "KERNEL ", "BS "
dw 0xAA55
buf: