Fix the "portable" version of the fat32 bootsector
Its now mostly identical to the one we currently use, only a few encoding differences

svn path=/trunk/; revision=52147
This commit is contained in:
Timo Kreuzer 2011-06-08 12:45:56 +00:00
parent af201a5b6a
commit 8d5976819d

View file

@ -10,6 +10,8 @@
#include <asm.inc> #include <asm.inc>
#define BP_REL(x) [bp+x-offset start]
.code16 .code16
//ORG HEX(7c00) //ORG HEX(7c00)
@ -21,59 +23,59 @@ start:
OEMName: OEMName:
.ASCII "FrLdr1.0" .ASCII "FrLdr1.0"
BytesPerSector: BytesPerSector:
dw 512 .word 512
SectsPerCluster: SectsPerCluster:
db 0 .byte 0
ReservedSectors: ReservedSectors:
dw 32 .word 32
NumberOfFats: NumberOfFats:
db 2 .byte 2
MaxRootEntries: MaxRootEntries:
dw 0 // Always zero for FAT32 volumes .word 0 // Always zero for FAT32 volumes
TotalSectors: TotalSectors:
dw 0 // Always zero for FAT32 volumes .word 0 // Always zero for FAT32 volumes
MediaDescriptor: MediaDescriptor:
db HEX(0f8) .byte HEX(0f8)
SectorsPerFat: SectorsPerFat:
dw 0 // Always zero for FAT32 volumes .word 0 // Always zero for FAT32 volumes
SectorsPerTrack: SectorsPerTrack:
dw 0 .word 0
NumberOfHeads: NumberOfHeads:
dw 0 .word 0
HiddenSectors: HiddenSectors:
dd 0 .long 0
TotalSectorsBig: TotalSectorsBig:
dd 0 .long 0
// FAT32 Inserted Info // FAT32 Inserted Info
SectorsPerFatBig: SectorsPerFatBig:
dd 0 .long 0
ExtendedFlags: ExtendedFlags:
dw 0 .word 0
FSVersion: FSVersion:
dw 0 .word 0
RootDirStartCluster: RootDirStartCluster:
dd 0 .long 0
FSInfoSector: FSInfoSector:
dw 0 .word 0
BackupBootSector: BackupBootSector:
dw 6 .word 6
Reserved1: Reserved1:
db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
// End FAT32 Inserted Info // End FAT32 Inserted Info
BootDrive: BootDrive:
db 0 .byte 0
Reserved: Reserved:
db 0 .byte 0
ExtendSig: ExtendSig:
db HEX(29) .byte HEX(29)
SerialNumber: SerialNumber:
dd 0 .long 0
VolumeLabel: VolumeLabel:
db "NO NAME " .ascii "NO NAME "
FileSystem: FileSystem:
db "FAT32 " .ascii "FAT32 "
main: main:
xor ax,ax // Setup segment registers xor ax,ax // Setup segment registers
@ -83,27 +85,27 @@ main:
mov bp, HEX(7c00) mov bp, HEX(7c00)
mov sp, HEX(7c00) // Setup a stack mov sp, HEX(7c00) // Setup a stack
cmp byte ptr ds:[BootDrive], HEX(0ff) // If they have specified a boot drive then use it cmp byte ptr BP_REL(BootDrive), HEX(0ff) // If they have specified a boot drive then use it
jne CheckSectorsPerFat jne CheckSectorsPerFat
mov byte ptr ds:[BootDrive], dl // Save the boot drive mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
CheckSectorsPerFat: CheckSectorsPerFat:
cmp word ptr [SectorsPerFat], 0 // Check the old 16-bit value of SectorsPerFat cmp word ptr BP_REL(SectorsPerFat), 0 // Check the old 16-bit value of SectorsPerFat
jnz CheckFailed // If it is non-zero then exit with an error jnz CheckFailed // If it is non-zero then exit with an error
CheckTotalSectors: // Check the old 16-bit value of TotalSectors & MaxRootEntries CheckTotalSectors: // Check the old 16-bit value of TotalSectors & MaxRootEntries
cmp word ptr [MaxRootEntries], 0// by comparing the DWORD at offset MaxRootEntries to zero cmp dword ptr BP_REL(MaxRootEntries), 0// by comparing the DWORD at offset MaxRootEntries to zero
jnz CheckFailed // If it is non-zero then exit with an error jnz CheckFailed // If it is non-zero then exit with an error
CheckFileSystemVersion: CheckFileSystemVersion:
cmp word ptr [FSVersion], 0 // Check the file system version word cmp word ptr BP_REL(FSVersion), 0 // Check the file system version word
jna GetDriveParameters // It is zero, so continue jna GetDriveParameters // It is zero, so continue
CheckFailed: CheckFailed:
jmp PrintFileSystemError // If it is not zero then exit with an error jmp PrintFileSystemError // If it is not zero then exit with an error
GetDriveParameters: GetDriveParameters:
mov ax, HEX(0800) mov ax, HEX(0800)
mov dl, byte ptr [BootDrive] // Get boot drive in dl mov dl, byte ptr BP_REL(BootDrive) // Get boot drive in dl
int HEX(13) // Request drive parameters from the bios int HEX(13) // Request drive parameters from the bios
jnc CalcDriveSize // If the call succeeded then calculate the drive size jnc CalcDriveSize // If the call succeeded then calculate the drive size
@ -137,7 +139,7 @@ LoadExtraBootCode:
// First we have to load our extra boot code at // First we have to load our extra boot code at
// sector 14 into memory at [0000:7e00h] // sector 14 into memory at [0000:7e00h]
mov eax, HEX(0e) mov eax, HEX(0e)
add eax, dword ptr ds:[HiddenSectors] // Add the number of hidden sectors add eax, dword ptr BP_REL(HiddenSectors) // Add the number of hidden sectors
mov cx, 1 mov cx, 1
xor bx, bx xor bx, bx
mov es, bx // Read sector to [0000:7e00h] mov es, bx // Read sector to [0000:7e00h]
@ -160,7 +162,7 @@ ReadSectors:
CheckInt13hExtensions: // Now check if this computer supports extended reads CheckInt13hExtensions: // Now check if this computer supports extended reads
mov ah, HEX(41) // AH = 41h mov ah, HEX(41) // AH = 41h
mov bx, HEX(55aa) // BX = 55AAh mov bx, HEX(55aa) // BX = 55AAh
mov dl, byte ptr ds:[BootDrive] // DL = drive (80h-FFh) mov dl, byte ptr BP_REL(BootDrive) // DL = drive (80h-FFh)
int HEX(13) // IBM/MS INT 13 Extensions - INSTALLATION CHECK int HEX(13) // IBM/MS INT 13 Extensions - INSTALLATION CHECK
jc ReadSectorsCHS // CF set on error (extensions not supported) jc ReadSectorsCHS // CF set on error (extensions not supported)
cmp bx, HEX(0aa55) // BX = AA55h if installed cmp bx, HEX(0aa55) // BX = AA55h if installed
@ -179,7 +181,7 @@ ReadSectorsLBA:
ReadSectorsSetupDiskAddressPacket: ReadSectorsSetupDiskAddressPacket:
mov word ptr ds:[LBASectorsRead],cx mov word ptr ds:[LBASectorsRead],cx
push 0 push 0 // push large 0 ?
push eax // Put 64-bit logical block address on stack push eax // Put 64-bit logical block address on stack
push es // Put transfer segment on stack push es // Put transfer segment on stack
push bx // Put transfer offset on stack push bx // Put transfer offset on stack
@ -187,7 +189,7 @@ ReadSectorsSetupDiskAddressPacket:
push 16 // Set size of packet to 10h push 16 // Set size of packet to 10h
mov si, sp // Setup disk address packet on stack mov si, sp // Setup disk address packet on stack
mov dl, byte ptr ds:[BootDrive] // Drive number mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
int HEX(13) // Call BIOS int HEX(13) // Call BIOS
jc PrintDiskError // If the read failed then abort jc PrintDiskError // If the read failed then abort
@ -211,7 +213,7 @@ ReadSectorsSetupDiskAddressPacket:
ret ret
LBASectorsRead: LBASectorsRead:
dd 0 .long 0
// Reads logical sectors into [ES:BX] // Reads logical sectors into [ES:BX]
@ -223,15 +225,15 @@ ReadSectorsCHS:
ReadSectorsCHSLoop: ReadSectorsCHSLoop:
pushad pushad
xor edx, edx xor edx, edx
movzx ecx, word ptr ds:[SectorsPerTrack] movzx ecx, word ptr BP_REL(SectorsPerTrack)
div ecx // Divide logical by SectorsPerTrack div ecx // Divide logical by SectorsPerTrack
inc dl // Sectors numbering starts at 1 not 0 inc dl // Sectors numbering starts at 1 not 0
mov cl, dl // Sector in CL mov cl, dl // Sector in CL
mov edx, eax mov edx, eax
shr edx, 16 shr edx, 16
div word ptr ds:[NumberOfHeads] // Divide logical by number of heads div word ptr BP_REL(NumberOfHeads) // Divide logical by number of heads
mov dh, dl // Head in DH mov dh, dl // Head in DH
mov dl, byte ptr ds:[BootDrive] // Drive number in DL mov dl, byte ptr BP_REL(BootDrive) // Drive number in DL
mov ch, al // Cylinder in CX mov ch, al // Cylinder in CX
ror ah, 1 // Low 8 bits of cylinder in CH, high 2 bits ror ah, 1 // Low 8 bits of cylinder in CH, high 2 bits
ror ah, 1 // in CL shifted to bits 6 & 7 ror ah, 1 // in CL shifted to bits 6 & 7
@ -267,7 +269,7 @@ PrintDiskError:
// Displays a file system error message // Displays a file system error message
// And reboots // And reboots
PrintFileSystemError: PrintFileSystemError:
mov si,msgFileSystemError // FreeLdr not found message mov si, offset msgFileSystemError // FreeLdr not found message
call PutChars // Display it call PutChars // Display it
Reboot: Reboot:
@ -286,27 +288,26 @@ PutChars:
int HEX(10) int HEX(10)
jmp short PutChars jmp short PutChars
Done: Done:
retn ret
BiosCHSDriveSize: BiosCHSDriveSize:
dd 0 .long 0
msgDiskError: msgDiskError:
db "Disk error", 13, 10, 0 .asciz "Disk error\r\n"
msgFileSystemError: msgFileSystemError:
db "File system error", 13, 10, 0 .asciz "File system error\r\n"
msgAnyKey: msgAnyKey:
db "Press any key to restart", 13, 10, 0 .asciz "Press any key to restart\r\n"
// times 509-($-$$) db 0 // Pad to 509 bytes
.org 509 // Pad to 509 bytes .org 509 // Pad to 509 bytes
BootPartition: BootPartition:
db 0 .byte 0
BootSignature: BootSignature:
dw 0aa55h // BootSector signature .word HEX(0aa55) // BootSector signature
// End of bootsector // End of bootsector
// //
@ -323,7 +324,7 @@ BootSignature:
StartSearch: StartSearch:
// Now we must get the first cluster of the root directory // Now we must get the first cluster of the root directory
mov eax, dword ptr ds:[RootDirStartCluster] mov eax, dword ptr BP_REL(RootDirStartCluster)
cmp eax, HEX(0ffffff8) // Check to see if this is the last cluster in the chain cmp eax, HEX(0ffffff8) // Check to see if this is the last cluster in the chain
jb ContinueSearch // If not continue, if so then we didn't find freeldr.sys jb ContinueSearch // If not continue, if so then we didn't find freeldr.sys
jmp PrintFileNotFound jmp PrintFileNotFound
@ -336,7 +337,7 @@ ContinueSearch:
// Now we have to find our way through the root directory to // Now we have to find our way through the root directory to
// The OSLOADER.SYS file // The OSLOADER.SYS file
xor bx,bx xor bx,bx
mov bl, byte ptr ds:[SectsPerCluster] mov bl, byte ptr BP_REL(SectsPerCluster)
shl bx, 4 // BX = BX * 512 / 32 shl bx, 4 // BX = BX * 512 / 32
mov ax, HEX(2000) // We loaded at 2000:0000 mov ax, HEX(2000) // We loaded at 2000:0000
mov es, ax mov es, ax
@ -362,9 +363,9 @@ FindFile:
jnz FindFile // Last entry? jnz FindFile // Last entry?
// Get the next root dir cluster and try again until we run out of clusters // Get the next root dir cluster and try again until we run out of clusters
mov eax, dword ptr ds:[RootDirStartCluster] mov eax, dword ptr BP_REL(RootDirStartCluster)
call GetFatEntry call GetFatEntry
mov dword ptr ds:[RootDirStartCluster], eax mov dword ptr BP_REL(RootDirStartCluster), eax
jmp StartSearch jmp StartSearch
FoundFile: FoundFile:
@ -374,9 +375,9 @@ FoundFile:
xor di, di // ES:DI has dir entry xor di, di // ES:DI has dir entry
xor dx, dx xor dx, dx
mov ax, word ptr es:[di+14h] // Get start cluster high word mov ax, word ptr es:[di+20] // Get start cluster high word
shl eax, 16 shl eax, 16
mov ax, word ptr es:[di+1ah] // Get start cluster low word mov ax, word ptr es:[di+26] // Get start cluster low word
CheckStartCluster: CheckStartCluster:
cmp eax, 2 // Check and see if the start cluster starts at cluster 2 or above cmp eax, 2 // Check and see if the start cluster starts at cluster 2 or above
@ -401,7 +402,7 @@ LoadFile:
pop es pop es
xor bx, bx xor bx, bx
mov bl, byte ptr ds:[SectsPerCluster] mov bl, byte ptr BP_REL(SectsPerCluster)
shl bx, 5 // BX = BX * 512 / 16 shl bx, 5 // BX = BX * 512 / 16
mov ax, es // Increment the load address by mov ax, es // Increment the load address by
add ax, bx // The size of a cluster add ax, bx // The size of a cluster
@ -415,7 +416,7 @@ LoadFile:
jmp LoadFile // Load the next cluster (if any) jmp LoadFile // Load the next cluster (if any)
LoadFileDone: LoadFileDone:
mov dl, byte ptr ds:[BootDrive] // Load boot drive into DL mov dl, byte ptr BP_REL(BootDrive) // Load boot drive into DL
mov dh, byte ptr ds:[BootPartition] // Load boot partition into DH mov dh, byte ptr ds:[BootPartition] // Load boot partition into DH
push 0 // push segment (0x0000) push 0 // push segment (0x0000)
@ -432,12 +433,12 @@ GetFatEntry:
shl eax, 2 // EAX = EAX * 4 (since FAT32 entries are 4 bytes) shl eax, 2 // EAX = EAX * 4 (since FAT32 entries are 4 bytes)
mov ecx, eax // Save this for later in ECX mov ecx, eax // Save this for later in ECX
xor edx, edx xor edx, edx
movzx ebx, word ptr ds:[BytesPerSector] movzx ebx, word ptr BP_REL(BytesPerSector)
push ebx push ebx
div ebx // FAT Sector Number = EAX / BytesPerSector div ebx // FAT Sector Number = EAX / BytesPerSector
movzx ebx, word ptr ds:[ReservedSectors] movzx ebx, word ptr BP_REL(ReservedSectors)
add eax, ebx // FAT Sector Number += ReservedSectors add eax, ebx // FAT Sector Number += ReservedSectors
mov ebx, dword ptr ds:[HiddenSectors] mov ebx, dword ptr BP_REL(HiddenSectors)
add eax, ebx // FAT Sector Number += HiddenSectors add eax, ebx // FAT Sector Number += HiddenSectors
pop ebx pop ebx
dec ebx dec ebx
@ -449,15 +450,15 @@ GetFatEntry:
// to see which FAT is the active one // to see which FAT is the active one
// and use it, or if they are mirrored then // and use it, or if they are mirrored then
// no worries // no worries
movzx ebx, word ptr ds:[ExtendedFlags] // Get extended flags and put into ebx movzx ebx, word ptr BP_REL(ExtendedFlags) // Get extended flags and put into ebx
and bx, HEX(0f) // Mask off upper 8 bits, now we have active fat in bl and bx, HEX(0f) // Mask off upper 8 bits, now we have active fat in bl
jz LoadFatSector // If fat is mirrored then skip fat calcs jz LoadFatSector // If fat is mirrored then skip fat calcs
cmp bl, byte ptr ds:[NumberOfFats] // Compare bl to number of fats cmp bl, byte ptr BP_REL(NumberOfFats) // Compare bl to number of fats
jb GetActiveFatOffset jb GetActiveFatOffset
jmp PrintFileSystemError // If bl is bigger than numfats exit with error jmp PrintFileSystemError // If bl is bigger than numfats exit with error
GetActiveFatOffset: GetActiveFatOffset:
push eax // Save logical FAT sector number push eax // Save logical FAT sector number
mov eax, dword ptr ds:[SectorsPerFatBig] // Get the number of sectors occupied by one fat in eax mov eax, dword ptr BP_REL(SectorsPerFatBig) // Get the number of sectors occupied by one fat in eax
mul ebx // Multiplied by the active FAT index we have in ebx mul ebx // Multiplied by the active FAT index we have in ebx
pop edx // Get logical FAT sector number pop edx // Get logical FAT sector number
add eax, edx // Add the current FAT sector offset add eax, edx // Add the current FAT sector offset
@ -486,7 +487,7 @@ LoadFatSectorAlreadyLoaded:
ret ret
FatSectorInCache: // This variable tells us which sector we currently have in memory FatSectorInCache: // This variable tells us which sector we currently have in memory
dd 0ffffffffh // There is no need to re-read the same sector if we don't have to .long HEX(0ffffffff) // There is no need to re-read the same sector if we don't have to
// Reads cluster number in EAX into [ES:0000] // Reads cluster number in EAX into [ES:0000]
@ -496,19 +497,19 @@ ReadCluster:
dec eax dec eax
dec eax dec eax
xor edx, edx xor edx, edx
movzx ebx, byte ptr ds:[SectsPerCluster] movzx ebx, byte ptr BP_REL(SectsPerCluster)
mul ebx mul ebx
push eax push eax
xor edx, edx xor edx, edx
movzx eax, byte ptr ds:[NumberOfFats] movzx eax, byte ptr BP_REL(NumberOfFats)
mul dword ptr ds:[SectorsPerFatBig] mul dword ptr BP_REL(SectorsPerFatBig)
movzx ebx, word ptr ds:[ReservedSectors] movzx ebx, word ptr BP_REL(ReservedSectors)
add eax, ebx add eax, ebx
add eax, dword ptr ds:[HiddenSectors] add eax, dword ptr BP_REL(HiddenSectors)
pop ebx pop ebx
add eax, ebx // EAX now contains the logical sector number of the cluster add eax, ebx // EAX now contains the logical sector number of the cluster
xor bx, bx // We will load it to [ES:0000], ES loaded before function call xor bx, bx // We will load it to [ES:0000], ES loaded before function call
movzx cx, byte ptr ds:[SectsPerCluster] movzx cx, byte ptr BP_REL(SectsPerCluster)
call ReadSectors call ReadSectors
ret ret
@ -523,15 +524,15 @@ PrintFileNotFound:
jmp Reboot jmp Reboot
msgFreeLdr: msgFreeLdr:
db "freeldr.sys not found", 13, 10, 0 .asciz "freeldr.sys not found\r\n"
filename: filename:
db "FREELDR SYS" .ascii "FREELDR SYS"
msgLoading: msgLoading:
db "Loading FreeLoader...", 13, 10, 0 .asciz "Loading FreeLoader...\r\n"
//times 1022-($-$$) db 0 // Pad to 1022 bytes .org 1022 // Pad to 1022 bytes
dw 0aa55h // BootSector signature .word HEX(0aa55) // BootSector signature
.endcode16 .endcode16