208 lines
3.0 KiB
NASM
208 lines
3.0 KiB
NASM
; Bootsector for FAT32 filesystems
|
|
org 0x0800
|
|
jmp short init
|
|
nop
|
|
|
|
; WORD reserved sector count
|
|
rsc: equ ( $$ + 0x00E )
|
|
|
|
; BYTE number of sectors per cluster
|
|
sc: equ ( $$ + 0x00D )
|
|
|
|
; BYTE number of FATs
|
|
fn: equ ( $$ + 0x010 )
|
|
|
|
; WORD number of root directory entries
|
|
rde: equ ( $$ + 0x011 )
|
|
|
|
; DWORD hidden sector count (partition offset)
|
|
po: equ ( $$ + 0x01C )
|
|
|
|
; DWORD sectors per FAT
|
|
sf: equ ( $$ + 0x024 )
|
|
|
|
; BYTE drive number (we set it from dl)
|
|
dn: equ ( $$ + 0x040 )
|
|
|
|
; Area for BPB
|
|
times (0x5A - ($-$$)) db 0
|
|
|
|
init: xor ax, ax
|
|
mov ds, ax
|
|
mov es, ax
|
|
mov ss, ax
|
|
mov sp, 0x7C00
|
|
|
|
mov si, sp
|
|
mov di, 0x0800
|
|
mov cx, 0x0100
|
|
rep movsw
|
|
jmp 0x0:main
|
|
|
|
msg: pop si
|
|
mloop: lodsb
|
|
test al, al
|
|
jz mend
|
|
mov ah, 0x0e
|
|
mov bx, 7
|
|
int 0x10
|
|
jmp mloop
|
|
mend: push si
|
|
ret
|
|
|
|
err: call msg
|
|
db "ERR", 0x0A, 0x0D, 0
|
|
hlt: hlt
|
|
jmp hlt
|
|
|
|
; offsets relative to FS
|
|
offd: ; add offset of cluster data area to DX:AX
|
|
push cx
|
|
mov di, [rde]
|
|
mov cl, 4
|
|
shr di, cl ; 32 bytes per entry
|
|
add ax, di
|
|
adc dx, 0
|
|
pop cx
|
|
offr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
|
|
push cx
|
|
xor ch, ch
|
|
mov cl, byte [fn]
|
|
fatlp: add ax, [sf]
|
|
adc dx, [sf+2]
|
|
loop fatlp
|
|
pop cx
|
|
offf: ; add offset to FAT table to DX:AX
|
|
add ax, word [rsc]
|
|
adc dx, 0
|
|
ret
|
|
|
|
readp: ; read sector DX:AX from partition
|
|
add ax, word [po]
|
|
adc dx, word [po+2]
|
|
jc err
|
|
|
|
readd: ; read sector DX:AX from disk
|
|
; qword sector number DX:AX
|
|
push cs
|
|
push cs
|
|
push dx
|
|
push ax
|
|
|
|
; dword target buffer: BX:0
|
|
push bx
|
|
push cs
|
|
|
|
; word sector number
|
|
push cx
|
|
|
|
; size & passing
|
|
mov bp, 0x10
|
|
push bp
|
|
|
|
mov si, sp
|
|
mov ah, 0x42
|
|
mov dl, 0x80
|
|
stc
|
|
int 0x13
|
|
jc err
|
|
|
|
add sp, bp
|
|
|
|
ret
|
|
|
|
next: ; Advances [clus] to next FAT entry
|
|
; get current cluster number
|
|
mov ax, [clus]
|
|
mov dx, [clus+2]
|
|
|
|
; 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
|
|
|
|
call offf
|
|
|
|
mov bx, 0xA0
|
|
mov cx, 1
|
|
call readp
|
|
|
|
; get lower part of cluster number
|
|
mov si, [clus]
|
|
; multiply with 4
|
|
sal si, 1
|
|
sal si, 1
|
|
; make sure its within sector range
|
|
and si, 0x1FF
|
|
add si, buf
|
|
mov di, clus
|
|
; copy dword from FAT to [clus]
|
|
movsw
|
|
movsw
|
|
|
|
ret
|
|
|
|
; reads current cluster into [dest]
|
|
readc: ; load cluster number
|
|
mov ax, [clus]
|
|
mov dx, [clus+2]
|
|
|
|
; 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 ch, [sc]
|
|
l02: shr cl, 1
|
|
jz l02e
|
|
clc
|
|
rcl dx, 1
|
|
rcl ax, 1
|
|
jmp l02
|
|
l02e:
|
|
; dx:ax is now sector num in data area
|
|
call offd
|
|
mov bx, [dest]
|
|
mov cx, [sc]
|
|
xor ch, ch
|
|
|
|
call readp
|
|
|
|
xchg bx, cx
|
|
mov cl, 5
|
|
sal bx, cl
|
|
add [dest], bx
|
|
|
|
ret
|
|
|
|
loadf: call readc
|
|
call next
|
|
cmp word [clus+2], 0x0FFF
|
|
jne loadf
|
|
ret
|
|
|
|
main: call loadf
|
|
mov ax, [0x7C00]
|
|
mov cx, [0x7C02]
|
|
int 3
|
|
|
|
xor ah,ah
|
|
int 0x16
|
|
int 0x19
|
|
jmp hlt
|
|
|
|
; current cluster number
|
|
clus: dd 2
|
|
|
|
; segment register for data
|
|
dest: dw 0x07c0
|
|
|
|
; Padding and signature
|
|
times (0x1FE - ($-$$)) db 0
|
|
dw 0xAA55
|
|
buf:
|