diff --git a/boot/fat.asm b/boot/fat.asm index f5c156e..2b8619d 100644 --- a/boot/fat.asm +++ b/boot/fat.asm @@ -19,7 +19,7 @@ params: times bpb_size db 0 init: xor ax, ax mov ss, ax - mov sp, 0x7C00 + mov sp, ax ; save potential partition table entry push ds @@ -36,232 +36,153 @@ init: xor ax, ax %include "inc/booterr.asm" - ; offsets relative to FS -readd: ; add offset of cluster data area to DX:AX - push cx - mov di, [bp+bpb.direntries] - 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.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 + ; 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 - push bx - ; calculate CHS data - div word [bp+bpb.tracksectors] ; ax:temp = (lba / spt) - inc dx ; dx:sector = (lba % spt) + 1 - mov cl, dl ; sector number - 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 + xchg ax, bx + mov al, byte [bp+bpb.heads] + mul byte [bp+bpb.tracksectors] + xchg ax, bx - ; set up read buffer - mov es, bx - xor bx, bx - - ; call bios + ; dx:ax = lba + div word bx + xchg ax, dx + ; dx = cylinder, ax = head * tracksectors + sector + 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 - int 0x13 - jnc ($+5) - call errcll + mov bx, di + + int 0x13 + jc errjmp - 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 + add di, 0x200 + loop read 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 - %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] +rootdirsects: mov bx, [bp+bpb.direntries] mov cl, 4 - shr ax, cl - 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 + shr bx, cl ; 32 bytes per entry ret -main: ; Set up BP to point to BPB - ; Relative addressing saves one instruction byte per access - mov bp, params - ; Save DL contents +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+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 ; load root directory - call loadr + call resetbuf + call offset_rootdir + call rootdirsects + mov cx, bx + call read - ; search for first system file - mov ah, 0x04 - call loadf + ; search for file + mov bx, buf + 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 - mov dl, [bp+bpb.drivenum] + ; load fat table + call resetbuf + call offset_fat + mov cx, [bp+bpb.fatsectors] + call read - ; restore potential partition table - pop si + ; fetch cluster numbers (FAT12-specific) + 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 - jmp 0x7C00 - ; Padding and signature - times (0x1FE - ($-$$)) db 0 +err_not_found: +hlt: hlt + jmp hlt + + times (0x1F3 - ($-$$)) db 0 +filename: db "KERNEL ", "BS " dw 0xAA55 buf: