jmp short main
nop
-OEMName db 'FrLdr1.0'
-BytesPerSector dw 512
-SectsPerCluster db 0
-ReservedSectors dw 32
-NumberOfFats db 2
-MaxRootEntries dw 0 ; Always zero for FAT32 volumes
-TotalSectors dw 0 ; Always zero for FAT32 volumes
-MediaDescriptor db 0f8h
-SectorsPerFat dw 0 ; Always zero for FAT32 volumes
-SectorsPerTrack dw 0
-NumberOfHeads dw 0
-HiddenSectors dd 0
-TotalSectorsBig dd 0
+OEMName db 'FrLdr1.0'
+BytesPerSector dw 512
+SectsPerCluster db 0
+ReservedSectors dw 32
+NumberOfFats db 2
+MaxRootEntries dw 0 ; Always zero for FAT32 volumes
+TotalSectors dw 0 ; Always zero for FAT32 volumes
+MediaDescriptor db 0f8h
+SectorsPerFat dw 0 ; Always zero for FAT32 volumes
+SectorsPerTrack dw 0
+NumberOfHeads dw 0
+HiddenSectors dd 0
+TotalSectorsBig dd 0
; FAT32 Inserted Info
-SectorsPerFatBig dd 0
-ExtendedFlags dw 0
-FSVersion dw 0
-RootDirStartCluster dd 0
-FSInfoSector dw 0
-BackupBootSector dw 6
-Reserved1 times 12 db 0
+SectorsPerFatBig dd 0
+ExtendedFlags dw 0
+FSVersion dw 0
+RootDirStartCluster dd 0
+FSInfoSector dw 0
+BackupBootSector dw 6
+Reserved1 times 12 db 0
; End FAT32 Inserted Info
-BootDrive db 0
-Reserved db 0
-ExtendSig db 29h
-SerialNumber dd 00000000h
-VolumeLabel db 'NO NAME '
-FileSystem db 'FAT32 '
+BootDrive db 0
+Reserved db 0
+ExtendSig db 29h
+SerialNumber dd 00000000h
+VolumeLabel db 'NO NAME '
+FileSystem db 'FAT32 '
main:
xor ax,ax ; Setup segment registers
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
- mov ss,ax ; Make SS correct
- mov bp,7c00h
+ mov ss,ax ; Make SS correct
+ mov bp,7c00h
mov sp,7c00h ; Setup a stack
- cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
- jne CheckSectorsPerFat
+ cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
+ jne CheckSectorsPerFat
- mov [BYTE bp+BootDrive],dl ; Save the boot drive
+ mov [BYTE bp+BootDrive],dl ; Save the boot drive
CheckSectorsPerFat:
- cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat
- jnz CheckFailed ; If it is non-zero then exit with an error
-CheckTotalSectors: ; Check the old 16-bit value of TotalSectors & MaxRootEntries
- cmp DWORD [BYTE bp+MaxRootEntries],byte 0x00; by comparing the DWORD at offset MaxRootEntries to zero
- jnz CheckFailed ; If it is non-zero then exit with an error
+ cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat
+ jnz CheckFailed ; If it is non-zero then exit with an error
+CheckTotalSectors: ; Check the old 16-bit value of TotalSectors & MaxRootEntries
+ cmp DWORD [BYTE bp+MaxRootEntries],byte 0x00; by comparing the DWORD at offset MaxRootEntries to zero
+ jnz CheckFailed ; If it is non-zero then exit with an error
CheckFileSystemVersion:
- cmp WORD [BYTE bp+FSVersion],byte 0x00 ; Check the file system version word
- jna GetDriveParameters ; It is zero, so continue
+ cmp WORD [BYTE bp+FSVersion],byte 0x00 ; Check the file system version word
+ jna GetDriveParameters ; It is zero, so continue
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:
- mov ax,0800h
- mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
- int 13h ; Request drive parameters from the bios
- jnc CalcDriveSize ; If the call succeeded then calculate the drive size
+ mov ax,0800h
+ mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
+ int 13h ; Request drive parameters from the bios
+ jnc CalcDriveSize ; If the call succeeded then calculate the drive size
- ; If we get here then the call to the BIOS failed
- ; so just set CHS equal to the maximum addressable
- ; size
- mov cx,0ffffh
- mov dh,cl
+ ; If we get here then the call to the BIOS failed
+ ; so just set CHS equal to the maximum addressable
+ ; size
+ mov cx,0ffffh
+ mov dh,cl
CalcDriveSize:
- ; Now that we have the drive geometry
- ; lets calculate the drive size
- mov bl,ch ; Put the low 8-bits of the cylinder count into BL
- mov bh,cl ; Put the high 2-bits in BH
- shr bh,6 ; Shift them into position, now BX contains the cylinder count
- and cl,3fh ; Mask off cylinder bits from sector count
- ; CL now contains sectors per track and DH contains head count
- movzx eax,dh ; Move the heads into EAX
- movzx ebx,bx ; Move the cylinders into EBX
- movzx ecx,cl ; Move the sectors per track into ECX
- inc eax ; Make it one based because the bios returns it zero based
- inc ebx ; Make the cylinder count one based also
- mul ecx ; Multiply heads with the sectors per track, result in edx:eax
- mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
-
- ; We now have the total number of sectors as reported
- ; by the bios in eax, so store it in our variable
- mov [BiosCHSDriveSize],eax
+ ; Now that we have the drive geometry
+ ; lets calculate the drive size
+ mov bl,ch ; Put the low 8-bits of the cylinder count into BL
+ mov bh,cl ; Put the high 2-bits in BH
+ shr bh,6 ; Shift them into position, now BX contains the cylinder count
+ and cl,3fh ; Mask off cylinder bits from sector count
+ ; CL now contains sectors per track and DH contains head count
+ movzx eax,dh ; Move the heads into EAX
+ movzx ebx,bx ; Move the cylinders into EBX
+ movzx ecx,cl ; Move the sectors per track into ECX
+ inc eax ; Make it one based because the bios returns it zero based
+ inc ebx ; Make the cylinder count one based also
+ mul ecx ; Multiply heads with the sectors per track, result in edx:eax
+ mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
+
+ ; We now have the total number of sectors as reported
+ ; by the bios in eax, so store it in our variable
+ mov [BiosCHSDriveSize],eax
LoadExtraBootCode:
- ; First we have to load our extra boot code at
- ; sector 14 into memory at [0000:7e00h]
- mov eax,0eh
- add eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors
- mov cx,1
+ ; First we have to load our extra boot code at
+ ; sector 14 into memory at [0000:7e00h]
+ mov eax,0eh
+ add eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors
+ mov cx,1
xor bx,bx
- mov es,bx ; Read sector to [0000:7e00h]
- mov bx,7e00h
- call ReadSectors
- jmp StartSearch
+ mov es,bx ; Read sector to [0000:7e00h]
+ mov bx,7e00h
+ call ReadSectors
+ jmp StartSearch
; EAX has logical sector number to read
; CX has number of sectors to read
ReadSectors:
- cmp eax,DWORD [BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
- jae ReadSectorsLBA ; Yes - go to the LBA routine
- ; If at all possible we want to use LBA routines because
- ; They are optimized to read more than 1 sector per read
-
- pushad ; Save logical sector number & sector count
-
-CheckInt13hExtensions: ; Now check if this computer supports extended reads
- mov ah,0x41 ; AH = 41h
- mov bx,0x55aa ; BX = 55AAh
- mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
- int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
- jc ReadSectorsCHS ; CF set on error (extensions not supported)
- cmp bx,0xaa55 ; BX = AA55h if installed
- jne ReadSectorsCHS
- test cl,1 ; CX = API subset support bitmap
- jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
-
- popad ; Restore sector count & logical sector number
+ push es
+ cmp eax,DWORD [BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
+ jae ReadSectorsLBA ; Yes - go to the LBA routine
+ ; If at all possible we want to use LBA routines because
+ ; They are optimized to read more than 1 sector per read
+
+ pushad ; Save logical sector number & sector count
+
+CheckInt13hExtensions: ; Now check if this computer supports extended reads
+ mov ah,0x41 ; AH = 41h
+ mov bx,0x55aa ; BX = 55AAh
+ mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
+ int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
+ jc ReadSectorsCHS ; CF set on error (extensions not supported)
+ cmp bx,0xaa55 ; BX = AA55h if installed
+ jne ReadSectorsCHS
+ test cl,1 ; CX = API subset support bitmap
+ jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
+
+ popad ; Restore sector count & logical sector number
ReadSectorsLBA:
- pushad ; Save logical sector number & sector count
+ pushad ; Save logical sector number & sector count
- cmp cx,64 ; Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
- jbe ReadSectorsSetupDiskAddressPacket ; If we are reading less than 65 sectors then just do the read
- mov cx,64 ; Otherwise read only 64 sectors on this loop iteration
+ cmp cx,64 ; Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
+ jbe ReadSectorsSetupDiskAddressPacket ; If we are reading less than 65 sectors then just do the read
+ mov cx,64 ; Otherwise read only 64 sectors on this loop iteration
ReadSectorsSetupDiskAddressPacket:
- mov [LBASectorsRead],cx
- o32 push byte 0
- push eax ; Put 64-bit logical block address on stack
- push es ; Put transfer segment on stack
- push bx ; Put transfer offset on stack
- push cx ; Set transfer count
- push byte 0x10 ; Set size of packet to 10h
- mov si,sp ; Setup disk address packet on stack
+ mov [LBASectorsRead],cx
+ o32 push byte 0
+ push eax ; Put 64-bit logical block address on stack
+ push es ; Put transfer segment on stack
+ push bx ; Put transfer offset on stack
+ push cx ; Set transfer count
+ push byte 0x10 ; Set size of packet to 10h
+ mov si,sp ; Setup disk address packet on stack
- mov dl,[BYTE bp+BootDrive] ; Drive number
- mov ah,42h ; Int 13h, AH = 42h - Extended Read
- int 13h ; Call BIOS
- jc PrintDiskError ; If the read failed then abort
+ mov dl,[BYTE bp+BootDrive] ; Drive number
+ mov ah,42h ; Int 13h, AH = 42h - Extended Read
+ int 13h ; Call BIOS
+ jc PrintDiskError ; If the read failed then abort
- add sp,byte 0x10 ; Remove disk address packet from stack
+ add sp,byte 0x10 ; Remove disk address packet from stack
- popad ; Restore sector count & logical sector number
+ popad ; Restore sector count & logical sector number
- push bx
- mov ebx,DWORD [LBASectorsRead]
- add eax,ebx ; Increment sector to read
- shl ebx,5
+ push bx
+ mov ebx,DWORD [LBASectorsRead]
+ add eax,ebx ; Increment sector to read
+ shl ebx,5
mov dx,es
- add dx,bx ; Setup read buffer for next sector
+ add dx,bx ; Setup read buffer for next sector
mov es,dx
- pop bx
+ pop bx
- sub cx,[LBASectorsRead]
- jnz ReadSectorsLBA ; Read next sector
+ sub cx,[LBASectorsRead]
+ jnz ReadSectorsLBA ; Read next sector
+ pop es
ret
LBASectorsRead:
- dd 0
+ dd 0
; Reads logical sectors into [ES:BX]
; EAX has logical sector number to read
; CX has number of sectors to read
ReadSectorsCHS:
- popad ; Get logical sector number & sector count off stack
+ popad ; Get logical sector number & sector count off stack
ReadSectorsCHSLoop:
pushad
xor edx,edx
- movzx ecx,WORD [BYTE bp+SectorsPerTrack]
- div ecx ; Divide logical by SectorsPerTrack
- inc dl ; Sectors numbering starts at 1 not 0
- mov cl,dl ; Sector in CL
- mov edx,eax
- shr edx,16
- div WORD [BYTE bp+NumberOfHeads] ; Divide logical by number of heads
- mov dh,dl ; Head in DH
- mov dl,[BYTE bp+BootDrive] ; Drive number in DL
- mov ch,al ; Cylinder in CX
- ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
- ror ah,1 ; in CL shifted to bits 6 & 7
- or cl,ah ; Or with sector number
+ movzx ecx,WORD [BYTE bp+SectorsPerTrack]
+ div ecx ; Divide logical by SectorsPerTrack
+ inc dl ; Sectors numbering starts at 1 not 0
+ mov cl,dl ; Sector in CL
+ mov edx,eax
+ shr edx,16
+ div WORD [BYTE bp+NumberOfHeads] ; Divide logical by number of heads
+ mov dh,dl ; Head in DH
+ mov dl,[BYTE bp+BootDrive] ; Drive number in DL
+ mov ch,al ; Cylinder in CX
+ ror ah,1 ; Low 8 bits of cylinder in CH, high 2 bits
+ ror ah,1 ; in CL shifted to bits 6 & 7
+ or cl,ah ; Or with sector number
mov ax,0201h
int 13h ; DISK - READ SECTORS INTO MEMORY
; AL = number of sectors to read, CH = track, CL = sector
- ; DH = head, DL = drive, ES:BX -> buffer to fill
- ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
+ ; DH = head, DL = drive, ES:BX -> buffer to fill
+ ; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
- jc PrintDiskError ; If the read failed then abort
+ jc PrintDiskError ; If the read failed then abort
popad
- inc eax ; Increment Sector to Read
+ inc eax ; Increment Sector to Read
mov dx,es
- add dx,byte 20h ; Increment read buffer for next sector
+ add dx,byte 20h ; Increment read buffer for next sector
mov es,dx
- loop ReadSectorsCHSLoop ; Read next sector
+ loop ReadSectorsCHSLoop ; Read next sector
- ret
+ ret
; Displays a disk error message
; And reboots
PrintDiskError:
- mov si,msgDiskError ; Bad boot disk message
- call PutChars ; Display it
+ mov si,msgDiskError ; Bad boot disk message
+ call PutChars ; Display it
- jmp Reboot
+ jmp Reboot
; Displays a file system error message
; And reboots
PrintFileSystemError:
- mov si,msgFileSystemError ; FreeLdr not found message
- call PutChars ; Display it
+ mov si,msgFileSystemError ; FreeLdr not found message
+ call PutChars ; Display it
Reboot:
- mov si,msgAnyKey ; Press any key message
- call PutChars ; Display it
- xor ax,ax
- int 16h ; Wait for a keypress
- int 19h ; Reboot
+ mov si,msgAnyKey ; Press any key message
+ call PutChars ; Display it
+ xor ax,ax
+ int 16h ; Wait for a keypress
+ int 19h ; Reboot
PutChars:
lodsb
BiosCHSDriveSize dd 0
-msgDiskError db 'Disk error',0dh,0ah,0
-msgFileSystemError db 'File system error',0dh,0ah,0
-msgAnyKey db 'Press any key to restart',0dh,0ah,0
+msgDiskError db 'Disk error',0dh,0ah,0
+msgFileSystemError db 'File system error',0dh,0ah,0
+msgAnyKey db 'Press any key to restart',0dh,0ah,0
times 509-($-$$) db 0 ; Pad to 509 bytes
BootPartition:
- db 0
+ db 0
BootSignature:
dw 0aa55h ; BootSector signature
-
+
; End of bootsector
;
StartSearch:
; Now we must get the first cluster of the root directory
- mov eax,DWORD [BYTE bp+RootDirStartCluster]
- cmp eax,0ffffff8h ; 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
- jmp PrintFileNotFound
+ mov eax,DWORD [BYTE bp+RootDirStartCluster]
+ cmp eax,0ffffff8h ; 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
+ jmp PrintFileNotFound
ContinueSearch:
mov bx,2000h
- mov es,bx ; Read cluster to [2000:0000h]
+ mov es,bx ; Read cluster to [2000:0000h]
call ReadCluster ; Read the cluster
; Now we have to find our way through the root directory to
- ; The OSLOADER.SYS file
- xor bx,bx
+ ; The FREELDR.SYS file
+ xor bx,bx
mov bl,[BYTE bp+SectsPerCluster]
- shl bx,4 ; BX = BX * 512 / 32
- mov ax,2000h ; We loaded at 2000:0000
+ shl bx,4 ; BX = BX * 512 / 32
+ mov ax,2000h ; We loaded at 2000:0000
mov es,ax
xor di,di
mov si,filename
add ax,2 ; So lets move to the next one
mov es,ax ; And search again
xor di,di
- mov si,filename
+ mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx ; Keep searching till we run out of dir entries
jnz FindFile ; Last entry?
- ; Get the next root dir cluster and try again until we run out of clusters
- mov eax,DWORD [BYTE bp+RootDirStartCluster]
- call GetFatEntry
- mov [BYTE bp+RootDirStartCluster],eax
+ ; Get the next root dir cluster and try again until we run out of clusters
+ mov eax,DWORD [BYTE bp+RootDirStartCluster]
+ call GetFatEntry
+ mov [BYTE bp+RootDirStartCluster],eax
jmp StartSearch
FoundFile:
+ ; Display "Loading FreeLoader..." message
+ mov si,msgLoading ; Loading message
+ call PutChars ; Display it
- ; Display "Loading FreeLoader..." message
- mov si,msgLoading ; Loading message
- call PutChars ; Display it
-
- xor di,di ; ES:DI has dir entry
+ xor di,di ; ES:DI has dir entry
xor dx,dx
mov ax,WORD [es:di+14h] ; Get start cluster high word
- shl eax,16
+ shl eax,16
mov ax,WORD [es:di+1ah] ; Get start cluster low word
CheckStartCluster:
- cmp eax,2 ; Check and see if the start cluster starts at cluster 2 or above
- jnb CheckEndCluster ; If so then continue
- jmp PrintFileSystemError ; If not exit with error
+ cmp eax,2 ; Check and see if the start cluster starts at cluster 2 or above
+ jnb CheckEndCluster ; If so then continue
+ jmp PrintFileSystemError ; If not exit with error
CheckEndCluster:
- cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator
- jb InitializeLoadSegment ; If not then continue
- jmp PrintFileSystemError ; If so exit with error
+ cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator
+ jb InitializeLoadSegment ; If not then continue
+ jmp PrintFileSystemError ; If so exit with error
InitializeLoadSegment:
- mov bx,800h
+ mov bx,0F80h ; FREELDR_BASE / 16
mov es,bx
LoadFile:
- cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
- jae LoadFileDone ; If so continue, if not then read the next one
- push eax
- xor bx,bx ; Load ROSLDR starting at 0000:8000h
- push es
- call ReadCluster
- pop es
-
- xor bx,bx
+ cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
+ jae LoadFileDone ; If so continue, if not then read the next one
+ push eax
+ xor bx,bx ; Load ROSLDR starting at 0000:F800h
+ push es
+ call ReadCluster
+ pop es
+
+ xor bx,bx
mov bl,[BYTE bp+SectsPerCluster]
- shl bx,5 ; BX = BX * 512 / 16
- mov ax,es ; Increment the load address by
- add ax,bx ; The size of a cluster
- mov es,ax
+ shl bx,5 ; BX = BX * 512 / 16
+ mov ax,es ; Increment the load address by
+ add ax,bx ; The size of a cluster
+ mov es,ax
- pop eax
- push es
- call GetFatEntry ; Get the next entry
- pop es
+ pop eax
+ push es
+ call GetFatEntry ; Get the next entry
+ pop es
- jmp LoadFile ; Load the next cluster (if any)
+ jmp LoadFile ; Load the next cluster (if any)
LoadFileDone:
- mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
- mov dh,[BootPartition] ; Load boot partition into DH
+ mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
+ mov dh,[BootPartition] ; Load boot partition into DH
- push 0 ; push segment (0x0000)
- mov eax, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
- add eax, 0x8000 ; RVA -> VA
- push ax ; push offset
- retf ; Transfer control to FreeLoader
+ ; Transfer execution to the bootloader
+ ;ljmp16 0, FREELDR_BASE
+ db 0EAh
+ dw 0F800h
+ dw 0
; Returns the FAT entry for a given cluster number
; On entry EAX has cluster number
; On return EAX has FAT entry for that cluster
GetFatEntry:
- shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
- mov ecx,eax ; Save this for later in ECX
- xor edx,edx
- movzx ebx,WORD [BYTE bp+BytesPerSector]
- push ebx
- div ebx ; FAT Sector Number = EAX / BytesPerSector
- movzx ebx,WORD [BYTE bp+ReservedSectors]
- add eax,ebx ; FAT Sector Number += ReservedSectors
- mov ebx,DWORD [BYTE bp+HiddenSectors]
- add eax,ebx ; FAT Sector Number += HiddenSectors
- pop ebx
- dec ebx
- and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
- ; EAX holds logical FAT sector number
- ; ECX holds FAT entry offset
-
- ; Now we have to check the extended flags
- ; to see which FAT is the active one
- ; and use it, or if they are mirrored then
- ; no worries
- movzx ebx,WORD [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx
- and bx,0x0f ; Mask off upper 8 bits, now we have active fat in bl
- jz LoadFatSector ; If fat is mirrored then skip fat calcs
- cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats
- jb GetActiveFatOffset
- jmp PrintFileSystemError ; If bl is bigger than numfats exit with error
+ shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
+ mov ecx,eax ; Save this for later in ECX
+ xor edx,edx
+ movzx ebx,WORD [BYTE bp+BytesPerSector]
+ push ebx
+ div ebx ; FAT Sector Number = EAX / BytesPerSector
+ movzx ebx,WORD [BYTE bp+ReservedSectors]
+ add eax,ebx ; FAT Sector Number += ReservedSectors
+ mov ebx,DWORD [BYTE bp+HiddenSectors]
+ add eax,ebx ; FAT Sector Number += HiddenSectors
+ pop ebx
+ dec ebx
+ and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
+ ; EAX holds logical FAT sector number
+ ; ECX holds FAT entry offset
+
+ ; Now we have to check the extended flags
+ ; to see which FAT is the active one
+ ; and use it, or if they are mirrored then
+ ; no worries
+ movzx ebx,WORD [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx
+ and bx,0x0f ; Mask off upper 8 bits, now we have active fat in bl
+ jz LoadFatSector ; If fat is mirrored then skip fat calcs
+ cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats
+ jb GetActiveFatOffset
+ jmp PrintFileSystemError ; If bl is bigger than numfats exit with error
GetActiveFatOffset:
- push eax ; Save logical FAT sector number
- mov eax,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
- mul ebx ; Multiplied by the active FAT index we have in ebx
- pop edx ; Get logical FAT sector number
- add eax,edx ; Add the current FAT sector offset
+ push eax ; Save logical FAT sector number
+ mov eax,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
+ mul ebx ; Multiplied by the active FAT index we have in ebx
+ pop edx ; Get logical FAT sector number
+ add eax,edx ; Add the current FAT sector offset
LoadFatSector:
- push ecx
- ; EAX holds logical FAT sector number
- ; Check if we have already loaded it
- cmp eax,DWORD [FatSectorInCache]
- je LoadFatSectorAlreadyLoaded
-
- mov DWORD [FatSectorInCache],eax
- mov bx,9000h
- mov es,bx
- xor bx,bx ; We will load it to [9000:0000h]
- mov cx,1
- call ReadSectors
+ push ecx
+
+ mov bx, 9000h ; We will load it to [9000:0000h]
+ mov es, bx
+
+ ; EAX holds logical FAT sector number
+ ; Check if we have already loaded it
+ cmp eax,DWORD [FatSectorInCache]
+ je LoadFatSectorAlreadyLoaded
+
+ mov DWORD [FatSectorInCache],eax
+ xor bx,bx
+ mov cx,1
+ call ReadSectors
LoadFatSectorAlreadyLoaded:
- mov bx,9000h
- mov es,bx
- pop ecx
- mov eax,DWORD [es:ecx] ; Get FAT entry
- and eax,0fffffffh ; Mask off reserved bits
+ pop ecx
+ mov eax,DWORD [es:ecx] ; Get FAT entry
+ and eax,0fffffffh ; Mask off reserved bits
- ret
+ ret
-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
+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
; Reads cluster number in EAX into [ES:0000]
ReadCluster:
- ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
-
- dec eax
- dec eax
- xor edx,edx
- movzx ebx,BYTE [BYTE bp+SectsPerCluster]
- mul ebx
- push eax
- xor edx,edx
- movzx eax,BYTE [BYTE bp+NumberOfFats]
- mul DWORD [BYTE bp+SectorsPerFatBig]
- movzx ebx,WORD [BYTE bp+ReservedSectors]
- add eax,ebx
- add eax,DWORD [BYTE bp+HiddenSectors]
- pop ebx
- 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
- movzx cx,BYTE [BYTE bp+SectsPerCluster]
- call ReadSectors
- ret
+ ; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
+
+ dec eax
+ dec eax
+ xor edx,edx
+ movzx ebx,BYTE [BYTE bp+SectsPerCluster]
+ mul ebx
+ push eax
+ xor edx,edx
+ movzx eax,BYTE [BYTE bp+NumberOfFats]
+ mul DWORD [BYTE bp+SectorsPerFatBig]
+ movzx ebx,WORD [BYTE bp+ReservedSectors]
+ add eax,ebx
+ add eax,DWORD [BYTE bp+HiddenSectors]
+ pop ebx
+ 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
+ movzx cx,BYTE [BYTE bp+SectsPerCluster]
+ call ReadSectors
+ ret
; Displays a file not found error message
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
- jmp Reboot
+ jmp Reboot
msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
filename db 'FREELDR SYS'