; 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 dskerr: call msg db "DISK", 0 err: call msg db "ERR", 0x0A, 0x0D, 0 hlt: hlt jmp hlt ; offsets relative to FS readd: ; 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 readr: ; 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 readf: ; add offset to FAT table to DX:AX add ax, word [rsc] adc dx, 0 readp: ; read sector DX:AX from partition add ax, word [po] adc dx, word [po+2] jc err read_: ; 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 dskerr add sp, bp ret next: ; Advances DX:AX to next FAT entry 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 mov cx, 1 call readf pop bx ; get lower part of cluster number pop si ; multiply with 4 sal si, 1 sal si, 1 ; make sure its within sector range and si, 0x1FF add si, buf ; load dword from FAT lodsw mov dx, [si] 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, [sc] 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, [sc] xor ch, ch call readd xchg bp, cx mov cl, 5 sal bp, cl add bx, bp pop dx pop ax ret ; load cluster chain DX:AX to [dest]:0 load: mov bx, 0x07C0 lloop: call readc call next cmp word dx, 0x0FFF jne lloop ret ; Search for first entry with matching fsattr search: mov si, (0x7C00-0x20) loop: add si, 0x20 ; check if entry is valid mov al, [si] ; unallocated direntry test al, al jz end ; deleted files cmp al, 0xE2 je loop ; check attr mov al, [si+11] and al, 0x5C cmp al, ah jne loop ret loadr: mov ax, 2 xor dx, dx jmp load loadf: call search jne end mov ax, [si+0x1A] mov dx, [si+0x14] jmp load main: ; load root directory call loadr ; search for first system directory mov ah, 0x14 call loadf ; search for first system file mov ah, 0x04 call loadf ; jump jmp 0:0x7C00 end: call msg db "DIR", 0 jmp err ; Padding and signature times (0x1FE - ($-$$)) db 0 dw 0xAA55 buf: