; 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