Rework fat boot sector, load FAT only once instead of partial
This commit is contained in:
parent
31eac279c2
commit
adf67d9723
325
boot/fat.asm
325
boot/fat.asm
@ -19,7 +19,7 @@ params: times bpb_size db 0
|
|||||||
|
|
||||||
init: xor ax, ax
|
init: xor ax, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov sp, 0x7C00
|
mov sp, ax
|
||||||
|
|
||||||
; save potential partition table entry
|
; save potential partition table entry
|
||||||
push ds
|
push ds
|
||||||
@ -36,232 +36,153 @@ init: xor ax, ax
|
|||||||
|
|
||||||
%include "inc/booterr.asm"
|
%include "inc/booterr.asm"
|
||||||
|
|
||||||
; offsets relative to FS
|
; Read sectors from disk
|
||||||
readd: ; add offset of cluster data area to DX:AX
|
; IN ES:DI target buffer
|
||||||
push cx
|
; DX:AX absulute 32-bit sector number
|
||||||
mov di, [bp+bpb.direntries]
|
; CX numeber of sectors
|
||||||
mov cl, 4
|
read: push ax
|
||||||
shr di, cl ; 32 bytes per entry
|
|
||||||
add ax, di
|
|
||||||
adc dx, 0
|
|
||||||
pop cx
|
|
||||||
readr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
|
|
||||||
push cx
|
|
||||||
xor ch, ch
|
|
||||||
mov cl, byte [bp+bpb.fatnumber]
|
|
||||||
fatlp: add ax, [bp+bpb.fatsectors]
|
|
||||||
adc dx, 0
|
|
||||||
loop fatlp
|
|
||||||
pop cx
|
|
||||||
readf: ; add offset to FAT table to DX:AX
|
|
||||||
add ax, word [bp+bpb.reservedsects]
|
|
||||||
adc dx, 0
|
|
||||||
readp: ; read sector DX:AX from partition
|
|
||||||
add ax, word [bp+bpb.sectoroffset]
|
|
||||||
adc dx, word [bp+bpb.sectoroffset+2]
|
|
||||||
jnc ($+5)
|
|
||||||
call errcll
|
|
||||||
|
|
||||||
read_: ; read sector DX:AX from disk
|
|
||||||
; uses basic CHS disk IO
|
|
||||||
; this cant reliable read over track boundaries
|
|
||||||
; so we read each single sector in loop over CX
|
|
||||||
chslp: push ax
|
|
||||||
push cx
|
push cx
|
||||||
push dx
|
push dx
|
||||||
push bx
|
|
||||||
|
|
||||||
; calculate CHS data
|
xchg ax, bx
|
||||||
div word [bp+bpb.tracksectors] ; ax:temp = (lba / spt)
|
mov al, byte [bp+bpb.heads]
|
||||||
inc dx ; dx:sector = (lba % spt) + 1
|
mul byte [bp+bpb.tracksectors]
|
||||||
mov cl, dl ; sector number
|
xchg ax, bx
|
||||||
xor dx, dx
|
|
||||||
div word [bp+bpb.heads] ; ax:cylinder = (tmp / heads)
|
|
||||||
; dx:head = (tmp % heads)
|
|
||||||
mov ch, al ; cylinder number
|
|
||||||
mov dh, dl ; head number
|
|
||||||
mov dl, [bp+bpb.drivenum] ; drive number
|
|
||||||
|
|
||||||
; set up read buffer
|
; dx:ax = lba
|
||||||
mov es, bx
|
div word bx
|
||||||
xor bx, bx
|
xchg ax, dx
|
||||||
|
; dx = cylinder, ax = head * tracksectors + sector
|
||||||
; call bios
|
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 ax, 0x0201
|
||||||
int 0x13
|
mov bx, di
|
||||||
jnc ($+5)
|
|
||||||
call errcll
|
int 0x13
|
||||||
|
jc errjmp
|
||||||
|
|
||||||
pop bx
|
|
||||||
pop dx
|
pop dx
|
||||||
pop cx
|
pop cx
|
||||||
pop ax
|
pop ax
|
||||||
|
|
||||||
; increment sector num + write offset
|
|
||||||
add ax, 1
|
add ax, 1
|
||||||
adc dx, 0
|
adc dx, 0
|
||||||
add bx, 0x20
|
add di, 0x200
|
||||||
; loop on CX
|
loop read
|
||||||
loop chslp
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
next: ; Advances DX:AX to next FAT entry
|
rootdirsects: mov bx, [bp+bpb.direntries]
|
||||||
push ax
|
|
||||||
push bx
|
|
||||||
; shift 2 left for dword-sized FAT entries
|
|
||||||
; shift 9 right for sector size
|
|
||||||
mov cl, 7
|
|
||||||
shftl: clc
|
|
||||||
rcr dx, 1
|
|
||||||
rcr ax, 1
|
|
||||||
loop shftl
|
|
||||||
|
|
||||||
mov bx, 0xA0
|
|
||||||
%ifdef FAT12
|
|
||||||
; FAT item might span over two sectors
|
|
||||||
mov cx, 2
|
|
||||||
%else
|
|
||||||
mov cx, 1
|
|
||||||
%endif
|
|
||||||
call readf
|
|
||||||
|
|
||||||
pop bx
|
|
||||||
|
|
||||||
; get address of cluster within sector
|
|
||||||
pop si
|
|
||||||
%ifdef FAT12
|
|
||||||
push si
|
|
||||||
; times 1.5
|
|
||||||
mov ax, si
|
|
||||||
shr ax, 1
|
|
||||||
add si, ax
|
|
||||||
add si, buf
|
|
||||||
lodsw
|
|
||||||
pop si
|
|
||||||
test si, 1
|
|
||||||
jz .odd
|
|
||||||
.even: mov cl, 4
|
|
||||||
shr ax, cl
|
|
||||||
jmp .done
|
|
||||||
.odd: and ax, 0x0FFF
|
|
||||||
.done: xor dx, dx
|
|
||||||
%endif
|
|
||||||
|
|
||||||
%ifdef FAT16
|
|
||||||
; double
|
|
||||||
sal si, 1
|
|
||||||
; make sure its within sector range
|
|
||||||
and si, 0x1FF
|
|
||||||
add si, buf
|
|
||||||
; load word
|
|
||||||
lodsw
|
|
||||||
xor dx, dx
|
|
||||||
%endif
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
; reads current cluster into [dest]
|
|
||||||
readc: ; load cluster number
|
|
||||||
push ax
|
|
||||||
push dx
|
|
||||||
|
|
||||||
; subtract the two dummy entries from FAT start
|
|
||||||
sub ax, 2
|
|
||||||
sbb dx, 0
|
|
||||||
|
|
||||||
; convert cluster number to sector number
|
|
||||||
; this is some cheapo multiplication with 2^n
|
|
||||||
mov cl, [bp+bpb.clustersects]
|
|
||||||
l02: shr cl, 1
|
|
||||||
jz l02e
|
|
||||||
clc
|
|
||||||
rcl ax, 1
|
|
||||||
rcl dx, 1
|
|
||||||
jmp l02
|
|
||||||
l02e:
|
|
||||||
; dx:ax is now sector num in data area
|
|
||||||
mov cx, [bp+bpb.clustersects]
|
|
||||||
xor ch, ch
|
|
||||||
|
|
||||||
call readd
|
|
||||||
|
|
||||||
xchg di, cx
|
|
||||||
mov cl, 5
|
|
||||||
sal di, cl
|
|
||||||
add bx, di
|
|
||||||
|
|
||||||
pop dx
|
|
||||||
pop ax
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Load root directory
|
|
||||||
loadr: mov ax, [bp+bpb.direntries]
|
|
||||||
mov cl, 4
|
mov cl, 4
|
||||||
shr ax, cl
|
shr bx, cl ; 32 bytes per entry
|
||||||
mov cx, ax
|
|
||||||
xor ax, ax
|
|
||||||
xor dx, dx
|
|
||||||
mov bx, 0x07C0
|
|
||||||
jmp readr
|
|
||||||
|
|
||||||
; Load file identified by fsattr
|
|
||||||
; Directory data is expected at 0x07C00
|
|
||||||
loadf: mov si, (0x7C00-0x20)
|
|
||||||
sloop: add si, 0x20
|
|
||||||
; check if entry is valid
|
|
||||||
mov al, [si]
|
|
||||||
; unallocated direntry
|
|
||||||
test al, al
|
|
||||||
jnz ($+5)
|
|
||||||
call errcll
|
|
||||||
; deleted files
|
|
||||||
cmp al, 0xE2
|
|
||||||
je sloop
|
|
||||||
; check attr
|
|
||||||
mov al, [si+11]
|
|
||||||
and al, 0x5C
|
|
||||||
cmp al, ah
|
|
||||||
jne sloop
|
|
||||||
mov ax, [si+0x1A]
|
|
||||||
mov dx, [si+0x14]
|
|
||||||
|
|
||||||
; Load cluster chain DX:AX to 0x07C00
|
|
||||||
load: mov bx, 0x07C0
|
|
||||||
lloop: call readc
|
|
||||||
call next
|
|
||||||
%ifdef FAT12
|
|
||||||
cmp word ax, 0x0FF8
|
|
||||||
%endif
|
|
||||||
%ifdef FAT16
|
|
||||||
cmp word ax, 0xFFF8
|
|
||||||
%endif
|
|
||||||
jc lloop
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
main: ; Set up BP to point to BPB
|
offset_cluster: ; add offset of cluster data area to DX:AX
|
||||||
; Relative addressing saves one instruction byte per access
|
call rootdirsects
|
||||||
mov bp, params
|
add ax, bx
|
||||||
; Save DL contents
|
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
|
mov [bp+bpb.drivenum], dl
|
||||||
|
|
||||||
; load root directory
|
; load root directory
|
||||||
call loadr
|
call resetbuf
|
||||||
|
call offset_rootdir
|
||||||
|
call rootdirsects
|
||||||
|
mov cx, bx
|
||||||
|
call read
|
||||||
|
|
||||||
; search for first system file
|
; search for file
|
||||||
mov ah, 0x04
|
mov bx, buf
|
||||||
call loadf
|
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]
|
||||||
|
|
||||||
; restore drive number
|
; load fat table
|
||||||
mov dl, [bp+bpb.drivenum]
|
call resetbuf
|
||||||
|
call offset_fat
|
||||||
|
mov cx, [bp+bpb.fatsectors]
|
||||||
|
call read
|
||||||
|
|
||||||
; restore potential partition table
|
; fetch cluster numbers (FAT12-specific)
|
||||||
pop si
|
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
|
pop ds
|
||||||
|
|
||||||
jmp 0x7C00
|
jmp 0x7C00
|
||||||
|
|
||||||
; Padding and signature
|
err_not_found:
|
||||||
times (0x1FE - ($-$$)) db 0
|
hlt: hlt
|
||||||
|
jmp hlt
|
||||||
|
|
||||||
|
times (0x1F3 - ($-$$)) db 0
|
||||||
|
filename: db "KERNEL ", "BS "
|
||||||
dw 0xAA55
|
dw 0xAA55
|
||||||
buf:
|
buf:
|
||||||
|
Loading…
Reference in New Issue
Block a user