211 lines
3.3 KiB
NASM
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
|