; Bootsector for FAT32 filesystems ; Takes defines: ; FAT12 FAT has 1.5 bytes per entry ; FAT16 FAT has WORD per entry ; FAT32 FAT has DWORD per entry ; CHS uses int13h/AH=02h ; LARGE requires 32 bit sector numbers ; LBA uses int13h/AH=42h cpu 8086 org 0x0800 jmp short init nop %include "inc/bpb.asm" bpb: equ 0x080B ; Area for BPB times ( 0x5A - ($-$$) ) db 0 init: xor ax, ax mov ss, ax mov sp, 0x7C00 ; 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" ; offsets relative to FS readd: ; add offset of cluster data area to DX:AX push cx mov di, [bp+bpb_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 [bp+bpb_fn] fatlp: add ax, [bp+bpb7_lsf] adc dx, [bp+bpb7_lsf+2] loop fatlp pop cx readf: ; add offset to FAT table to DX:AX add ax, word [bp+bpb_rsc] adc dx, 0 readp: ; read sector DX:AX from partition add ax, word [bp+bpb_po] adc dx, word [bp+bpb_po+2] jnc ($+5) call errcll %ifdef LBA read_: ; read sector DX:AX from disk ; this uses the EBIOS extensions ; 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 di, 0x10 push di mov si, sp mov ah, 0x42 mov dl, [bp+bpb7_dn] stc int 0x13 jnc ($+5) call errcll add sp, di ret %endif %ifdef CHS 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 dx push bx ; calculate CHS data div word [bp+bpb_spt] ; ax:temp = (lba / spt) inc dx ; dx:sector = (lba % spt) + 1 mov cl, dl ; sector number xor dx, dx div word [bp+bpb_nos] ; ax:cylinder = (tmp / heads) ; dx:head = (tmp % heads) mov ch, al ; cylinder number mov dh, dl ; head number mov dl, [bp+bpb7_dn] ; drive number ; set up read buffer mov es, bx xor bx, bx ; call bios mov ax, 0x0201 int 0x13 jnc ($+5) call errcll pop bx pop dx pop cx pop ax ; increment sector num + write offset add ax, 1 adc dx, 0 add bx, 0x20 ; loop on CX loop chslp ret %endif 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 %ifdef FAT12 ; FAT item might span over two sectors mov cx, 2 %else mov cx, 1 %endif call readf pop bx ; get lower part of cluster number pop si %ifdef FAT16 ; double sal si, 1 %endif %ifdef FAT32 ; multiply with 4 sal si, 1 sal si, 1 %endif ; make sure its within sector range and si, 0x1FF add si, buf %ifdef FAT16 ; load word from FAT lodsw xor dx, dx %endif %ifdef FAT32 ; load dword from FAT lodsw mov dx, [si] %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_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, [bp+bpb_sc] 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, 2 xor dx, dx jmp load ; 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 cmp word dx, 0x0FFF jne lloop ret main: ; Set up BP to point to BPB ; Relative addressing saves one instruction byte per access mov bp, bpb ; Save DL contents mov [bp+bpb7_dn], dl ; 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 ; restore drive number mov dl, [bp+bpb7_dn] ; restore potential partition table pop si pop ds jmp 0x7C00 ; Padding and signature times (0x1FE - ($-$$)) db 0 dw 0xAA55 buf: