Re: FAT32 Bootloader Problem
Posted: Wed Dec 05, 2012 9:05 am
FAT in FAT32 can be too large. I'm using 1 sector FAT cache. I'm reading root directory sector-by-sector until I have found required file records.
The Place to Start for Operating System Developers
http://f.osdev.org/
Code: Select all
BITS 16
ORG 0x7C00
Start:
jmp Skip
nop
;*********************************************
; OEM Parameter block, FAT 12/16/32
; I dont use the values from this particular example
; They are here for reference!
;*********************************************
bOemName db "MollenOS" ;8 Bytes
; /* FAT 12/16 BIOS Parameter Block starts here */
wBlockSize dw 0
bSecPerClus db 0
wReservedSecs dw 0
bNumFats db 0
wRootEntries dw 0
wSectors16 dw 0
bMediaType db 0
wFATSz16 dw 0
wSecPerTrack dw 0
wNumHeads dw 0
lSecCache dd 0 ;lHiddenSecs
lSectors32 dd 0
;**********************************************
; Extended BIOS Parameter Block
;**********************************************
lFATSz32 dd 0
wExtFlags dw 0 ; Bits 0-3 = Active FAT, 7 = !FAT mirroring
wFSVer dw 0
lRootCluster dd 0
wFSInfo dw 0
wBkBootSec dw 0
BytesPerCluster dd 0 ;Reserved1
CurrentCluster dd 0 ;Reserved2
lDataSector dd 0 ;Reserved3
bDriveNum db 0
bReserved db 0
bBootSig db 0
lVolSerial dd 0xDEADF007
szVolLabel db "MollenOS V1"
bSysID db "COPYHERE"
Skip:
; -------------------- Adjust segment registers --------------------------------;
cli
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; -------------------- Create Stack (0000 - FFFF) ------------------------------;
mov ax, 0x0000
mov ss, ax
mov sp, 0xFFFF
sti
; -------------------- Display load message ------------------------------------;
mov si, msgLoading
call Print
; -------------------- Start loading KRNLDR.SYS --------------------------------;
; Preparations
mov ax, WORD[wBlockSize] ; calculate starting address of the fat cache, in order to put it directly after the rootdir cache
mul WORD[bSecPerClus] ; size of a cluster = bytesPerSec * SecPerCluster
mov WORD[wBytesPerCluster], ax ; store
add ax, 0x0200 ; first byte after the rootdir cache = 0x0200 (bootcode) + size of a cluster
mov WORD[wFatCacheStart], ax ; move to the ram
mov al, BYTE[bNumFats]
mul DWORD[lFATSz32]
add eax, DWORD[wReservedSecs]
mov DWORD[dDataSector], eax
mov ax, WORD[bSecPerClus]
mov WORD[DAP.wSectorsToRead], ax ; tell the DAP to read 1 Cluster
mov WORD[DAP.wSegment], ds ; store the actual Segment
mov BYTE[bBootDrive], dl ; move starting-drive (in this case: usb stick) to the ram
; --- STEP 1 (Root Dir Stuff) ---
xor eax, eax
mov eax, DWORD[lRootCluster] ; get the starting cluster of the root dir
mul DWORD[bSecPerClus] ; multiply it by the number of Sectors per Cluster in order to get the absolute starting sector of the cluster
mov DWORD[DAP.dSecStart], eax ; push it to the DAP
xor ax, ax
mov ax, WORD[wRootDirCacheStart] ; tell the DAP (BIOS INTERRUPT 13h) to store the cluster at 0x7C00:0x0200 (directyl above the bootcode)
mov WORD[DAP.wOffset], ax
call ReadCluster ; Read the cluster
mov si, msgDone
call Print
;TODO
; --------------------- End loading KRNLDR.SYS ----------------------------------;
; --------------------- jump to KRNLDR.SYS --------------------------------------;
;TODO
cli
hlt
Print:
lodsb ; get next character
or al, al ; check, if null-terminator
jz PrintDone ; yes? -> printing done
mov ah, 0eh ; no? -> print the character
int 10h ; call BIOS
jmp Print ; repeat until null-terminator found
PrintDone:
ret ; printing done, so return
; ------ Read one Cluster to memory ----------- ;
; Input: DAP ;
; DAP.wSegment:DAP.wOffset = memory location ;
; DAP.dSecStart = starting sector of cluster ;
; --------------------------------------------- ;
ReadCluster:
.MAIN
mov di, 0x0005 ; 5 times retry
.CLUSTERLOOP
mov ah, 42h ; Extended read sectors function
mov si, DAP
mov dl, [bBootDrive]
int 13h
jnc .SUCCESS ; no error? -> cluster loaded successfully
xor ax, ax ; error? -> reset disk
int 13h
dec di
jnz .CLUSTERLOOP
mov si, msgFailure ; still an error? -> Loading the Cluster failed, print "Failure" and halt the System
call Print
int 18h
cli
hlt
.SUCCESS
ret ; Successfully read the cluster, so return
; ------------------------ Variables ---------------------------------------------;
bBootDrive db 0
wFatCacheStart dw 0
wRootDirCacheStart dw 0x0200
wBytesPerCluster dw 0
dDataSector dd 0
dActualCluster dd 0
KRNLDR db "KRNLDR SYS"
msgLoading db "Loading Boot Image...", 0x00
msgDone db "Done", 0x0D, 0x0A, 0x00
msgFailure db "Failure", 0x0D, 0x0A, 0x00
; ------------------------ Structs ------------------------------------------------;
DAP: db 16,0
.wSectorsToRead: dw 1 ; Number of sectors to read (read size of OS)
.wOffset: dw 0 ; Offset
.wSegment: dw 0x7C00 ; Segment (note: not segment:offset because of little endianes)
.dUnused: dd 0 ; the absolute number of the starting sector is 64 bits, i only need 32, so this is unused
.dSecStart: dd 0
TIMES 510-($-$$) DB 0
DW 0xAA55
Code: Select all
.dUnused:
dd 0 ; the absolute number of the starting sector is 64 bits, i only need 32, so this is unused
.dSecStart:
dd 0
StartRootSector = DataStart + (SrartRootCluster-2)*SectorsPerClusterSo what is the start of the root dir?
My smile tells that no.And is it right what i've done with the dunused and dsecatart in the dap?