; 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 ) ; 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 "DISKERR", 0x0A, 0x0D, 0 hlt: hlt jmp hlt ; Requires DWORD ptr and QWORD sector on the stack read: pop bp push cx mov ax, 0x10 push ax mov ah, 0x42 mov dl, 0x80 mov si, sp mov di, [si+4] int 0x13 jc err pop ax pop cx push bp ret ; Advances [clus] to next FAT entry next: ; push upper two words for sector num xor ax, ax push ax push ax ; 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 ; add reserved sector count add ax, word [rsc] adc dx, 0 ; push lower dword of sector number push dx push ax ; push ptr to target buffer push cs mov ax, buf push ax mov cx, 1 call read ; 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 ; 1x QWORD, 1x DWORD = 12 bytes add sp, 12 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 ; get number of FATs xor ch, ch mov cl, byte [fn] ; add their sizes up floop: add ax, [sf] adc dx, [sf+2] loop floop ; add reserved sector count add ax, [rsc] add dx, 0 ; push sector num QWORD xor cx, cx push cx push cx push dx push ax ; push target buffer DWORD ; dest gives the segment register mov ax, [dest] push ax push cx ; push sector count ; always an full cluster mov cx, [sc] xor ch, ch call read cmp cl, [sc] jne err xchg bx, cx mov cl, 5 sal bx, cl add [dest], bx add sp, 12 ret loadf: call readc call next cmp word [clus+2], 0x0FFF jne loadf ret main: call loadf mov ax, [dest] int 3 xor ah,ah int 0x16 int 0x19 jmp hlt ; the packing is so that it looks nice in a hexdump times (0x1E0 - ($-$$)) db 0 ; directory the kernel is in tdir: db "RDOS ", 0 ; current cluster number clus: dd 2 times (0x1F0 - ($-$$)) db 0 ; filename for the kernel tfile: db "KERNEL BS ", 0 ; segment register for data dest: dw 0x07c0 ; Padding and signature times (0x1FE - ($-$$)) db 0 dw 0xAA55 buf: