mirror of
https://github.com/reactos/reactos.git
synced 2024-07-07 21:25:05 +00:00
[FATxxx BOOTSECTORS]: Whitespace changes mainly (makes easier for diffing). No code changes.
svn path=/trunk/; revision=70428
This commit is contained in:
parent
909f7439d0
commit
6a513178c3
|
@ -43,15 +43,15 @@
|
||||||
|
|
||||||
#define BP_REL(x) [bp+x-offset start]
|
#define BP_REL(x) [bp+x-offset start]
|
||||||
|
|
||||||
DataAreaStartHigh = 2
|
DataAreaStartHigh = 2
|
||||||
DataAreaStartLow = 4
|
DataAreaStartLow = 4
|
||||||
BiosCHSDriveSizeHigh = 6
|
BiosCHSDriveSizeHigh = 6
|
||||||
BiosCHSDriveSizeLow = 8
|
BiosCHSDriveSizeLow = 8
|
||||||
BiosCHSDriveSize = 8
|
BiosCHSDriveSize = 8
|
||||||
ReadSectorsOffset = 10
|
ReadSectorsOffset = 10
|
||||||
ReadClusterOffset = 12
|
ReadClusterOffset = 12
|
||||||
PutCharsOffset = 14
|
PutCharsOffset = 14
|
||||||
BootSectorStackTop = HEX(7c00) - 16
|
BootSectorStackTop = HEX(7c00) - 16
|
||||||
|
|
||||||
|
|
||||||
// org 7c00h
|
// org 7c00h
|
||||||
|
@ -105,21 +105,21 @@ main:
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
mov ss, ax
|
mov ss, ax
|
||||||
mov bp, HEX(7c00)
|
mov bp, HEX(7c00)
|
||||||
mov sp, BootSectorStackTop // Setup a stack
|
mov sp, BootSectorStackTop // Setup a stack
|
||||||
mov ds, ax // Make DS correct
|
mov ds, ax // Make DS correct
|
||||||
mov es, ax // Make ES correct
|
mov es, ax // Make ES correct
|
||||||
|
|
||||||
cmp byte ptr BP_REL(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 GetDriveParameters
|
jne GetDriveParameters
|
||||||
|
|
||||||
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
|
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
|
||||||
|
|
||||||
|
|
||||||
GetDriveParameters:
|
GetDriveParameters:
|
||||||
mov ah, 8
|
mov ah, 8
|
||||||
mov dl, byte ptr BP_REL(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
|
||||||
|
|
||||||
// If we get here then the call to the BIOS failed
|
// If we get here then the call to the BIOS failed
|
||||||
// so just set CHS equal to the maximum addressable
|
// so just set CHS equal to the maximum addressable
|
||||||
|
@ -151,26 +151,26 @@ CalcDriveSize:
|
||||||
// Now we must find our way to the first sector of the root directory
|
// Now we must find our way to the first sector of the root directory
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
xor cx, cx
|
xor cx, cx
|
||||||
mov al, byte ptr BP_REL(NumberOfFats) // Number of fats
|
mov al, byte ptr BP_REL(NumberOfFats) // Number of fats
|
||||||
mul word ptr BP_REL(SectorsPerFat) // Times sectors per fat
|
mul word ptr BP_REL(SectorsPerFat) // Times sectors per fat
|
||||||
add ax, word ptr BP_REL(HiddenSectors)
|
add ax, word ptr BP_REL(HiddenSectors)
|
||||||
adc dx, word ptr BP_REL(HiddenSectors+2) // Add the number of hidden sectors
|
adc dx, word ptr BP_REL(HiddenSectors+2) // Add the number of hidden sectors
|
||||||
add ax, word ptr BP_REL(ReservedSectors) // Add the number of reserved sectors
|
add ax, word ptr BP_REL(ReservedSectors) // Add the number of reserved sectors
|
||||||
adc dx, cx // Add carry bit
|
adc dx, cx // Add carry bit
|
||||||
mov word ptr [bp - DataAreaStartLow], ax // Save the starting sector of the root directory
|
mov word ptr [bp - DataAreaStartLow], ax // Save the starting sector of the root directory
|
||||||
mov word ptr [bp - DataAreaStartHigh], dx // Save it in the first 4 bytes before the boot sector
|
mov word ptr [bp - DataAreaStartHigh], dx // Save it in the first 4 bytes before the boot sector
|
||||||
mov si, word ptr BP_REL(MaxRootEntries) // Get number of root dir entries in SI
|
mov si, word ptr BP_REL(MaxRootEntries) // Get number of root dir entries in SI
|
||||||
pusha // Save 32-bit logical start sector of root dir
|
pusha // Save 32-bit logical start sector of root dir
|
||||||
// DX:AX now has the number of the starting sector of the root directory
|
// DX:AX now has the number of the starting sector of the root directory
|
||||||
|
|
||||||
// Now calculate the size of the root directory
|
// Now calculate the size of the root directory
|
||||||
xor dx, dx
|
xor dx, dx
|
||||||
mov ax, 32 // Size of dir entry
|
mov ax, 32 // Size of dir entry
|
||||||
mul si // Times the number of entries
|
mul si // Times the number of entries
|
||||||
mov bx, word ptr BP_REL(BytesPerSector)
|
mov bx, word ptr BP_REL(BytesPerSector)
|
||||||
add ax, bx
|
add ax, bx
|
||||||
dec ax
|
dec ax
|
||||||
div bx // Divided by the size of a sector
|
div bx // Divided by the size of a sector
|
||||||
// AX now has the number of root directory sectors
|
// AX now has the number of root directory sectors
|
||||||
|
|
||||||
add word ptr [bp - DataAreaStartLow], ax // Add the number of sectors of the root directory to our other value
|
add word ptr [bp - DataAreaStartLow], ax // Add the number of sectors of the root directory to our other value
|
||||||
|
@ -178,49 +178,49 @@ CalcDriveSize:
|
||||||
popa // Restore root dir logical sector start to DX:AX
|
popa // Restore root dir logical sector start to DX:AX
|
||||||
|
|
||||||
LoadRootDirSector:
|
LoadRootDirSector:
|
||||||
mov bx, HEX(7e0) // We will load the root directory sector
|
mov bx, HEX(7e0) // We will load the root directory sector
|
||||||
mov es, bx // Right after the boot sector in memory
|
mov es, bx // Right after the boot sector in memory
|
||||||
xor bx, bx // We will load it to [0000:7e00h]
|
xor bx, bx // We will load it to [0000:7e00h]
|
||||||
xor cx, cx // Zero out CX
|
xor cx, cx // Zero out CX
|
||||||
inc cx // Now increment it to 1, we are reading one sector
|
inc cx // Now increment it to 1, we are reading one sector
|
||||||
xor di, di // Zero out di
|
xor di, di // Zero out di
|
||||||
push es // Save ES because it will get incremented by 20h
|
push es // Save ES because it will get incremented by 20h
|
||||||
call ReadSectors // Read the first sector of the root directory
|
call ReadSectors // Read the first sector of the root directory
|
||||||
pop es // Restore ES (ES:DI = 07E0:0000)
|
pop es // Restore ES (ES:DI = 07E0:0000)
|
||||||
|
|
||||||
SearchRootDirSector:
|
SearchRootDirSector:
|
||||||
cmp byte ptr es:[di], ch // If the first byte of the directory entry is zero then we have
|
cmp byte ptr es:[di], ch // If the first byte of the directory entry is zero then we have
|
||||||
jz ErrBoot // reached the end of the directory and FREELDR.SYS is not here so reboot
|
jz ErrBoot // reached the end of the directory and FREELDR.SYS is not here so reboot
|
||||||
pusha // Save all registers
|
pusha // Save all registers
|
||||||
mov cl, 11 // Put 11 in cl (length of filename in directory entry)
|
mov cl, 11 // Put 11 in cl (length of filename in directory entry)
|
||||||
mov si, offset filename // Put offset of filename string in DS:SI
|
mov si, offset filename // Put offset of filename string in DS:SI
|
||||||
repe cmpsb // Compare this directory entry against 'FREELDR SYS'
|
repe cmpsb // Compare this directory entry against 'FREELDR SYS'
|
||||||
popa // Restore all the registers
|
popa // Restore all the registers
|
||||||
jz FoundFreeLoader // If we found it then jump
|
jz FoundFreeLoader // If we found it then jump
|
||||||
dec si // SI holds MaxRootEntries, subtract one
|
dec si // SI holds MaxRootEntries, subtract one
|
||||||
jz ErrBoot // If we are out of root dir entries then reboot
|
jz ErrBoot // If we are out of root dir entries then reboot
|
||||||
add di, 32 // Increment DI by the size of a directory entry
|
add di, 32 // Increment DI by the size of a directory entry
|
||||||
cmp di, HEX(0200) // Compare DI to 512 (DI has offset to next dir entry, make sure we haven't gone over one sector)
|
cmp di, HEX(0200) // Compare DI to 512 (DI has offset to next dir entry, make sure we haven't gone over one sector)
|
||||||
jc SearchRootDirSector // If DI is less than 512 loop again
|
jc SearchRootDirSector // If DI is less than 512 loop again
|
||||||
jmp short LoadRootDirSector // Didn't find FREELDR.SYS in this directory sector, try again
|
jmp short LoadRootDirSector // Didn't find FREELDR.SYS in this directory sector, try again
|
||||||
|
|
||||||
FoundFreeLoader:
|
FoundFreeLoader:
|
||||||
// We found freeldr.sys on the disk
|
// We found freeldr.sys on the disk
|
||||||
// so we need to load the first 512
|
// so we need to load the first 512
|
||||||
// bytes of it to 0000:F800
|
// bytes of it to 0000:F800
|
||||||
// ES:DI has dir entry (ES:DI == 07E0:XXXX)
|
// ES:DI has dir entry (ES:DI == 07E0:XXXX)
|
||||||
mov ax, word ptr es:[di + HEX(1a)] // Get start cluster
|
mov ax, word ptr es:[di + HEX(1a)] // Get start cluster
|
||||||
push ax // Save start cluster
|
push ax // Save start cluster
|
||||||
push FREELDR_BASE / 16 // Put load segment on the stack and load it
|
push FREELDR_BASE / 16 // Put load segment on the stack and load it
|
||||||
pop es // Into ES so that we load the cluster at 0000:F800
|
pop es // Into ES so that we load the cluster at 0000:F800
|
||||||
call ReadCluster // Read the cluster
|
call ReadCluster // Read the cluster
|
||||||
pop ax // Restore start cluster of FreeLoader
|
pop ax // Restore start cluster of FreeLoader
|
||||||
|
|
||||||
// Save the addresses of needed functions so
|
// Save the addresses of needed functions so
|
||||||
// the helper code will know where to call them.
|
// the helper code will know where to call them.
|
||||||
mov word ptr [bp-ReadSectorsOffset], offset ReadSectors // Save the address of ReadSectors
|
mov word ptr [bp-ReadSectorsOffset], offset ReadSectors // Save the address of ReadSectors
|
||||||
mov word ptr [bp-ReadClusterOffset], offset ReadCluster // Save the address of ReadCluster
|
mov word ptr [bp-ReadClusterOffset], offset ReadCluster // Save the address of ReadCluster
|
||||||
mov word ptr [bp-PutCharsOffset], offset PutChars // Save the address of PutChars
|
mov word ptr [bp-PutCharsOffset], offset PutChars // Save the address of PutChars
|
||||||
|
|
||||||
// Now AX has start cluster of FreeLoader and we
|
// Now AX has start cluster of FreeLoader and we
|
||||||
// have loaded the helper code in the first 512 bytes
|
// have loaded the helper code in the first 512 bytes
|
||||||
|
@ -236,12 +236,12 @@ FoundFreeLoader:
|
||||||
// Displays an error message
|
// Displays an error message
|
||||||
// And reboots
|
// And reboots
|
||||||
ErrBoot:
|
ErrBoot:
|
||||||
mov si, offset msgFreeLdr // FreeLdr not found message
|
mov si, offset msgFreeLdr // FreeLdr not found message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
|
|
||||||
Reboot:
|
Reboot:
|
||||||
// mov si, offset msgAnyKey // Press any key message
|
// mov si, offset msgAnyKey // Press any key message
|
||||||
// call PutChars // Display it
|
// call PutChars // Display it
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int HEX(16) // Wait for a keypress
|
int HEX(16) // Wait for a keypress
|
||||||
int HEX(19) // Reboot
|
int HEX(19) // Reboot
|
||||||
|
@ -260,8 +260,8 @@ Done:
|
||||||
// Displays a bad boot message
|
// Displays a bad boot message
|
||||||
// And reboots
|
// And reboots
|
||||||
BadBoot:
|
BadBoot:
|
||||||
mov si, offset msgDiskError // Bad boot disk message
|
mov si, offset msgDiskError // Bad boot disk message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
|
|
||||||
jmp short Reboot
|
jmp short Reboot
|
||||||
|
|
||||||
|
@ -269,17 +269,17 @@ BadBoot:
|
||||||
// Reads cluster number in AX into [ES:0000]
|
// Reads cluster number in AX into [ES:0000]
|
||||||
ReadCluster:
|
ReadCluster:
|
||||||
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
||||||
dec ax // Adjust start cluster by 2
|
dec ax // Adjust start cluster by 2
|
||||||
dec ax // Because the data area starts on cluster 2
|
dec ax // Because the data area starts on cluster 2
|
||||||
xor ch, ch
|
xor ch, ch
|
||||||
mov cl, byte ptr BP_REL(SectsPerCluster)
|
mov cl, byte ptr BP_REL(SectsPerCluster)
|
||||||
mul cx // Times sectors per cluster
|
mul cx // Times sectors per cluster
|
||||||
add ax, [bp-DataAreaStartLow] // Add start of data area
|
add ax, [bp-DataAreaStartLow] // Add start of data area
|
||||||
adc dx, [bp-DataAreaStartHigh] // Now we have DX:AX with the logical start sector of OSLOADER.SYS
|
adc dx, [bp-DataAreaStartHigh] // Now we have DX:AX with the logical start sector of FREELDR.SYS
|
||||||
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
|
||||||
//mov cl,BYTE [BYTE bp+SectsPerCluster]// Sectors per cluster still in CX
|
// mov cl,BYTE [BYTE bp+SectsPerCluster]// Sectors per cluster still in CX
|
||||||
//call ReadSectors
|
// call ReadSectors
|
||||||
//ret
|
// ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -296,63 +296,63 @@ ReadSectors:
|
||||||
add ax, cx
|
add ax, cx
|
||||||
adc dx, 0
|
adc dx, 0
|
||||||
|
|
||||||
cmp dx, word ptr [bp-BiosCHSDriveSizeHigh] // Check if they are reading a sector within CHS range
|
cmp dx, word ptr [bp-BiosCHSDriveSizeHigh] // Check if they are reading a sector within CHS range
|
||||||
ja ReadSectorsLBA // No - go to the LBA routine
|
ja ReadSectorsLBA // No - go to the LBA routine
|
||||||
jb ReadSectorsCHS // Yes - go to the old CHS routine
|
jb ReadSectorsCHS // Yes - go to the old CHS routine
|
||||||
cmp ax, word ptr [bp-BiosCHSDriveSizeLow] // Check if they are reading a sector within CHS range
|
cmp ax, word ptr [bp-BiosCHSDriveSizeLow] // Check if they are reading a sector within CHS range
|
||||||
jbe ReadSectorsCHS // Yes - go to the old CHS routine
|
jbe ReadSectorsCHS // Yes - go to the old CHS routine
|
||||||
|
|
||||||
ReadSectorsLBA:
|
ReadSectorsLBA:
|
||||||
popa
|
popa
|
||||||
ReadSectorsLBALoop:
|
ReadSectorsLBALoop:
|
||||||
pusha // Save logical sector number & sector count
|
pusha // Save logical sector number & sector count
|
||||||
|
|
||||||
push 0
|
push 0
|
||||||
push 0
|
push 0
|
||||||
push dx // Put 64-bit logical
|
push dx // Put 64-bit logical
|
||||||
push ax // block address on stack
|
push ax // 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
|
||||||
push 1 // Set transfer count to 1 sector
|
push 1 // Set transfer count to 1 sector
|
||||||
push HEX(10) // Set size of packet to 10h
|
push HEX(10) // Set size of packet to 10h
|
||||||
mov si,sp // Setup disk address packet on stack
|
mov si,sp // Setup disk address packet on stack
|
||||||
|
|
||||||
// We are so totally out of space here that I am forced to
|
// We are so totally out of space here that I am forced to
|
||||||
// comment out this very beautifully written piece of code
|
// comment out this very beautifully written piece of code
|
||||||
// It would have been nice to have had this check...
|
// It would have been nice to have had this check...
|
||||||
//CheckInt13hExtensions: // Now make sure this computer supports extended reads
|
//CheckInt13hExtensions: // Now make sure this computer supports extended reads
|
||||||
// mov ah,0x41 // AH = 41h
|
// mov ah,0x41 // AH = 41h
|
||||||
// mov bx,0x55aa // BX = 55AAh
|
// mov bx,0x55aa // BX = 55AAh
|
||||||
// mov dl,[BYTE bp+BootDrive] // DL = drive (80h-FFh)
|
// mov dl,[BYTE bp+BootDrive] // DL = drive (80h-FFh)
|
||||||
// int 13h // IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
// int 13h // IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
||||||
// jc PrintDiskError // CF set on error (extensions not supported)
|
// jc PrintDiskError // CF set on error (extensions not supported)
|
||||||
// cmp bx,0xaa55 // BX = AA55h if installed
|
// cmp bx,0xaa55 // BX = AA55h if installed
|
||||||
// jne PrintDiskError
|
// jne PrintDiskError
|
||||||
// test cl,1 // CX = API subset support bitmap
|
// test cl,1 // CX = API subset support bitmap
|
||||||
// jz PrintDiskError // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
// jz PrintDiskError // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||||
|
|
||||||
|
|
||||||
// Good, we're here so the computer supports LBA disk access
|
// Good, we're here so the computer supports LBA disk access
|
||||||
// So finish the extended read
|
// So finish the extended read
|
||||||
mov dl, byte ptr BP_REL(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 BadBoot // If the read failed then abort
|
jc BadBoot // If the read failed then abort
|
||||||
|
|
||||||
add sp, 16 // Remove disk address packet from stack
|
add sp, 16 // Remove disk address packet from stack
|
||||||
|
|
||||||
popa // Restore sector count & logical sector number
|
popa // Restore sector count & logical sector number
|
||||||
|
|
||||||
inc ax // Increment Sector to Read
|
inc ax // Increment Sector to Read
|
||||||
adc dx, 0
|
adc dx, 0
|
||||||
|
|
||||||
push bx
|
push bx
|
||||||
mov bx, es
|
mov bx, es
|
||||||
add bx, HEX(20) // Increment read buffer for next sector
|
add bx, HEX(20) // Increment read buffer for next sector
|
||||||
mov es, bx
|
mov es, bx
|
||||||
pop bx
|
pop bx
|
||||||
|
|
||||||
loop ReadSectorsLBALoop // Read next sector
|
loop ReadSectorsLBALoop // Read next sector
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -370,26 +370,26 @@ ReadSectorsCHSLoop:
|
||||||
xor dx, dx
|
xor dx, dx
|
||||||
div word ptr BP_REL(SectorsPerTrack)
|
div word ptr BP_REL(SectorsPerTrack)
|
||||||
xchg ax, cx
|
xchg ax, cx
|
||||||
div word ptr BP_REL(SectorsPerTrack) // Divide logical by SectorsPerTrack
|
div word ptr BP_REL(SectorsPerTrack) // Divide logical by SectorsPerTrack
|
||||||
inc dx // Sectors numbering starts at 1 not 0
|
inc dx // Sectors numbering starts at 1 not 0
|
||||||
xchg cx, dx
|
xchg cx, dx
|
||||||
div word ptr BP_REL(NumberOfHeads) // Number of heads
|
div word ptr BP_REL(NumberOfHeads) // Number of heads
|
||||||
mov dh, dl // Head to DH, drive to DL
|
mov dh, dl // Head to DH, drive to DL
|
||||||
mov dl, byte ptr BP_REL(BootDrive) // Drive number
|
mov dl, byte ptr BP_REL(BootDrive) // Drive number
|
||||||
mov ch, al // Cylinder in CX
|
mov ch, al // Cylinder in CX
|
||||||
ror ah, 2 // Low 8 bits of cylinder in CH, high 2 bits
|
ror ah, 2 // Low 8 bits of cylinder in CH, high 2 bits
|
||||||
// in CL shifted to bits 6 & 7
|
// in CL shifted to bits 6 & 7
|
||||||
or cl, ah // Or with sector number
|
or cl, ah // Or with sector number
|
||||||
mov ax, HEX(0201)
|
mov ax, HEX(0201)
|
||||||
int HEX(13) // DISK - READ SECTORS INTO MEMORY
|
int HEX(13) // DISK - READ SECTORS INTO MEMORY
|
||||||
// AL = number of sectors to read, CH = track, CL = sector
|
// AL = number of sectors to read, CH = track, CL = sector
|
||||||
// DH = head, DL = drive, ES:BX -> buffer to fill
|
// DH = head, DL = drive, ES:BX -> buffer to fill
|
||||||
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
|
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
|
||||||
|
|
||||||
jc BadBoot
|
jc BadBoot
|
||||||
|
|
||||||
popa
|
popa
|
||||||
inc ax //Increment Sector to Read
|
inc ax // Increment Sector to Read
|
||||||
jnz NoCarryCHS
|
jnz NoCarryCHS
|
||||||
inc dx
|
inc dx
|
||||||
|
|
||||||
|
@ -400,8 +400,8 @@ NoCarryCHS:
|
||||||
add bx, HEX(20)
|
add bx, HEX(20)
|
||||||
mov es, bx
|
mov es, bx
|
||||||
pop bx
|
pop bx
|
||||||
// Increment read buffer for next sector
|
// Increment read buffer for next sector
|
||||||
loop ReadSectorsCHSLoop // Read next sector
|
loop ReadSectorsCHSLoop // Read next sector
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -409,10 +409,11 @@ NoCarryCHS:
|
||||||
msgDiskError:
|
msgDiskError:
|
||||||
.ascii "Disk error", CR, LF, NUL
|
.ascii "Disk error", CR, LF, NUL
|
||||||
msgFreeLdr:
|
msgFreeLdr:
|
||||||
.ascii "ldr not found", CR, LF, NUL
|
.ascii "Ldr not found", CR, LF, NUL
|
||||||
// Sorry, need the space...
|
// Sorry, need the space...
|
||||||
//msgAnyKey:
|
// msgAnyKey:
|
||||||
// .ascii "Press any key to restart", CR, LF, NUL
|
// .ascii "Press any key to restart", CR, LF, NUL
|
||||||
|
// .ascii "Press a key", CR, LF, NUL
|
||||||
filename:
|
filename:
|
||||||
.ascii "FREELDR SYS"
|
.ascii "FREELDR SYS"
|
||||||
|
|
||||||
|
@ -422,7 +423,7 @@ BootPartition:
|
||||||
.byte 0
|
.byte 0
|
||||||
|
|
||||||
BootSignature:
|
BootSignature:
|
||||||
.word HEX(0aa55) // BootSector signature
|
.word HEX(0aa55) // BootSector signature
|
||||||
|
|
||||||
.endcode16
|
.endcode16
|
||||||
|
|
||||||
|
|
|
@ -39,15 +39,15 @@
|
||||||
; boots dramatically.
|
; boots dramatically.
|
||||||
|
|
||||||
|
|
||||||
BootSectorStackTop equ 0x7bf2
|
BootSectorStackTop equ 0x7bf2
|
||||||
DataAreaStartHigh equ 0x2
|
DataAreaStartHigh equ 0x2
|
||||||
DataAreaStartLow equ 0x4
|
DataAreaStartLow equ 0x4
|
||||||
BiosCHSDriveSizeHigh equ 0x6
|
BiosCHSDriveSizeHigh equ 0x6
|
||||||
BiosCHSDriveSizeLow equ 0x8
|
BiosCHSDriveSizeLow equ 0x8
|
||||||
BiosCHSDriveSize equ 0x8
|
BiosCHSDriveSize equ 0x8
|
||||||
ReadSectorsOffset equ 0xa
|
ReadSectorsOffset equ 0xa
|
||||||
ReadClusterOffset equ 0xc
|
ReadClusterOffset equ 0xc
|
||||||
PutCharsOffset equ 0xe
|
PutCharsOffset equ 0xe
|
||||||
|
|
||||||
|
|
||||||
org 7c00h
|
org 7c00h
|
||||||
|
@ -84,136 +84,136 @@ main:
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
mov ss,ax
|
mov ss,ax
|
||||||
mov bp,7c00h
|
mov bp,7c00h
|
||||||
mov sp,BootSectorStackTop ; Setup a stack
|
mov sp,BootSectorStackTop ; Setup a stack
|
||||||
mov ds,ax ; Make DS correct
|
mov ds,ax ; Make DS correct
|
||||||
mov es,ax ; Make ES correct
|
mov es,ax ; Make ES correct
|
||||||
|
|
||||||
|
|
||||||
cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
|
cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
|
||||||
jne GetDriveParameters
|
jne GetDriveParameters
|
||||||
|
|
||||||
mov [BYTE bp+BootDrive],dl ; Save the boot drive
|
mov [BYTE bp+BootDrive],dl ; Save the boot drive
|
||||||
|
|
||||||
|
|
||||||
GetDriveParameters:
|
GetDriveParameters:
|
||||||
mov ah,08h
|
mov ah,08h
|
||||||
mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
|
mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
|
||||||
int 13h ; Request drive parameters from the bios
|
int 13h ; 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
|
||||||
|
|
||||||
; If we get here then the call to the BIOS failed
|
; If we get here then the call to the BIOS failed
|
||||||
; so just set CHS equal to the maximum addressable
|
; so just set CHS equal to the maximum addressable
|
||||||
; size
|
; size
|
||||||
mov cx,0ffffh
|
mov cx,0ffffh
|
||||||
mov dh,cl
|
mov dh,cl
|
||||||
|
|
||||||
CalcDriveSize:
|
CalcDriveSize:
|
||||||
; Now that we have the drive geometry
|
; Now that we have the drive geometry
|
||||||
; lets calculate the drive size
|
; lets calculate the drive size
|
||||||
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
|
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
|
||||||
mov bh,cl ; Put the high 2-bits in BH
|
mov bh,cl ; Put the high 2-bits in BH
|
||||||
shr bh,6 ; Shift them into position, now BX contains the cylinder count
|
shr bh,6 ; Shift them into position, now BX contains the cylinder count
|
||||||
and cl,3fh ; Mask off cylinder bits from sector count
|
and cl,3fh ; Mask off cylinder bits from sector count
|
||||||
; CL now contains sectors per track and DH contains head count
|
; CL now contains sectors per track and DH contains head count
|
||||||
movzx eax,dh ; Move the heads into EAX
|
movzx eax,dh ; Move the heads into EAX
|
||||||
movzx ebx,bx ; Move the cylinders into EBX
|
movzx ebx,bx ; Move the cylinders into EBX
|
||||||
movzx ecx,cl ; Move the sectors per track into ECX
|
movzx ecx,cl ; Move the sectors per track into ECX
|
||||||
inc eax ; Make it one based because the bios returns it zero based
|
inc eax ; Make it one based because the bios returns it zero based
|
||||||
inc ebx ; Make the cylinder count one based also
|
inc ebx ; Make the cylinder count one based also
|
||||||
mul ecx ; Multiply heads with the sectors per track, result in edx:eax
|
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]
|
mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
|
||||||
|
|
||||||
; We now have the total number of sectors as reported
|
; We now have the total number of sectors as reported
|
||||||
; by the bios in eax, so store it in our variable
|
; by the bios in eax, so store it in our variable
|
||||||
mov [BYTE bp-BiosCHSDriveSize],eax
|
mov [BYTE bp-BiosCHSDriveSize],eax
|
||||||
|
|
||||||
|
|
||||||
; Now we must find our way to the first sector of the root directory
|
; Now we must find our way to the first sector of the root directory
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
xor cx,cx
|
xor cx,cx
|
||||||
mov al,[BYTE bp+NumberOfFats] ; Number of fats
|
mov al,[BYTE bp+NumberOfFats] ; Number of fats
|
||||||
mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
|
mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
|
||||||
add ax,WORD [BYTE bp+HiddenSectors]
|
add ax,WORD [BYTE bp+HiddenSectors]
|
||||||
adc dx,WORD [BYTE bp+HiddenSectors+2] ; Add the number of hidden sectors
|
adc dx,WORD [BYTE bp+HiddenSectors+2] ; Add the number of hidden sectors
|
||||||
add ax,WORD [BYTE bp+ReservedSectors] ; Add the number of reserved sectors
|
add ax,WORD [BYTE bp+ReservedSectors] ; Add the number of reserved sectors
|
||||||
adc dx,cx ; Add carry bit
|
adc dx,cx ; Add carry bit
|
||||||
mov WORD [BYTE bp-DataAreaStartLow],ax ; Save the starting sector of the root directory
|
mov WORD [BYTE bp-DataAreaStartLow],ax ; Save the starting sector of the root directory
|
||||||
mov WORD [BYTE bp-DataAreaStartHigh],dx ; Save it in the first 4 bytes before the boot sector
|
mov WORD [BYTE bp-DataAreaStartHigh],dx ; Save it in the first 4 bytes before the boot sector
|
||||||
mov si,WORD [BYTE bp+MaxRootEntries] ; Get number of root dir entries in SI
|
mov si,WORD [BYTE bp+MaxRootEntries] ; Get number of root dir entries in SI
|
||||||
pusha ; Save 32-bit logical start sector of root dir
|
pusha ; Save 32-bit logical start sector of root dir
|
||||||
; DX:AX now has the number of the starting sector of the root directory
|
; DX:AX now has the number of the starting sector of the root directory
|
||||||
|
|
||||||
; Now calculate the size of the root directory
|
; Now calculate the size of the root directory
|
||||||
xor dx,dx
|
xor dx,dx
|
||||||
mov ax,0020h ; Size of dir entry
|
mov ax,0020h ; Size of dir entry
|
||||||
mul si ; Times the number of entries
|
mul si ; Times the number of entries
|
||||||
mov bx,[BYTE bp+BytesPerSector]
|
mov bx,[BYTE bp+BytesPerSector]
|
||||||
add ax,bx
|
add ax,bx
|
||||||
dec ax
|
dec ax
|
||||||
div bx ; Divided by the size of a sector
|
div bx ; Divided by the size of a sector
|
||||||
; AX now has the number of root directory sectors
|
; AX now has the number of root directory sectors
|
||||||
|
|
||||||
add [BYTE bp-DataAreaStartLow],ax ; Add the number of sectors of the root directory to our other value
|
add [BYTE bp-DataAreaStartLow],ax ; Add the number of sectors of the root directory to our other value
|
||||||
adc [BYTE bp-DataAreaStartHigh],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
|
adc [BYTE bp-DataAreaStartHigh],cx ; Now the first 4 bytes before the boot sector contain the starting sector of the data area
|
||||||
popa ; Restore root dir logical sector start to DX:AX
|
popa ; Restore root dir logical sector start to DX:AX
|
||||||
|
|
||||||
LoadRootDirSector:
|
LoadRootDirSector:
|
||||||
mov bx,7e0h ; We will load the root directory sector
|
mov bx,7e0h ; We will load the root directory sector
|
||||||
mov es,bx ; Right after the boot sector in memory
|
mov es,bx ; Right after the boot sector in memory
|
||||||
xor bx,bx ; We will load it to [0000:7e00h]
|
xor bx,bx ; We will load it to [0000:7e00h]
|
||||||
xor cx,cx ; Zero out CX
|
xor cx,cx ; Zero out CX
|
||||||
inc cx ; Now increment it to 1, we are reading one sector
|
inc cx ; Now increment it to 1, we are reading one sector
|
||||||
xor di,di ; Zero out di
|
xor di,di ; Zero out di
|
||||||
push es ; Save ES because it will get incremented by 20h
|
push es ; Save ES because it will get incremented by 20h
|
||||||
call ReadSectors ; Read the first sector of the root directory
|
call ReadSectors ; Read the first sector of the root directory
|
||||||
pop es ; Restore ES (ES:DI = 07E0:0000)
|
pop es ; Restore ES (ES:DI = 07E0:0000)
|
||||||
|
|
||||||
SearchRootDirSector:
|
SearchRootDirSector:
|
||||||
cmp [es:di],ch ; If the first byte of the directory entry is zero then we have
|
cmp [es:di],ch ; If the first byte of the directory entry is zero then we have
|
||||||
jz ErrBoot ; reached the end of the directory and FREELDR.SYS is not here so reboot
|
jz ErrBoot ; reached the end of the directory and FREELDR.SYS is not here so reboot
|
||||||
pusha ; Save all registers
|
pusha ; Save all registers
|
||||||
mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
|
mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
|
||||||
mov si,filename ; Put offset of filename string in DS:SI
|
mov si,filename ; Put offset of filename string in DS:SI
|
||||||
repe cmpsb ; Compare this directory entry against 'FREELDR SYS'
|
repe cmpsb ; Compare this directory entry against 'FREELDR SYS'
|
||||||
popa ; Restore all the registers
|
popa ; Restore all the registers
|
||||||
jz FoundFreeLoader ; If we found it then jump
|
jz FoundFreeLoader ; If we found it then jump
|
||||||
dec si ; SI holds MaxRootEntries, subtract one
|
dec si ; SI holds MaxRootEntries, subtract one
|
||||||
jz ErrBoot ; If we are out of root dir entries then reboot
|
jz ErrBoot ; If we are out of root dir entries then reboot
|
||||||
add di,BYTE +0x20 ; Increment DI by the size of a directory entry
|
add di,BYTE +0x20 ; Increment DI by the size of a directory entry
|
||||||
cmp di,0200h ; Compare DI to 512 (DI has offset to next dir entry, make sure we haven't gone over one sector)
|
cmp di,0200h ; Compare DI to 512 (DI has offset to next dir entry, make sure we haven't gone over one sector)
|
||||||
jc SearchRootDirSector ; If DI is less than 512 loop again
|
jc SearchRootDirSector ; If DI is less than 512 loop again
|
||||||
jmp short LoadRootDirSector ; Didn't find FREELDR.SYS in this directory sector, try again
|
jmp short LoadRootDirSector ; Didn't find FREELDR.SYS in this directory sector, try again
|
||||||
|
|
||||||
FoundFreeLoader:
|
FoundFreeLoader:
|
||||||
; We found freeldr.sys on the disk
|
; We found freeldr.sys on the disk
|
||||||
; so we need to load the first 512
|
; so we need to load the first 512
|
||||||
; bytes of it to 0000:8000
|
; bytes of it to 0000:8000
|
||||||
; ES:DI has dir entry (ES:DI == 07E0:XXXX)
|
; ES:DI has dir entry (ES:DI == 07E0:XXXX)
|
||||||
mov ax,WORD [es:di+1ah] ; Get start cluster
|
mov ax,WORD [es:di+1ah] ; Get start cluster
|
||||||
push ax ; Save start cluster
|
push ax ; Save start cluster
|
||||||
push WORD 800h ; Put 800h on the stack and load it
|
push WORD 800h ; Put 800h on the stack and load it
|
||||||
pop es ; Into ES so that we load the cluster at 0000:8000
|
pop es ; Into ES so that we load the cluster at 0000:8000
|
||||||
call ReadCluster ; Read the cluster
|
call ReadCluster ; Read the cluster
|
||||||
pop ax ; Restore start cluster of FreeLoader
|
pop ax ; Restore start cluster of FreeLoader
|
||||||
|
|
||||||
; Save the addresses of needed functions so
|
; Save the addresses of needed functions so
|
||||||
; the helper code will know where to call them.
|
; the helper code will know where to call them.
|
||||||
mov WORD [BYTE bp-ReadSectorsOffset],ReadSectors ; Save the address of ReadSectors
|
mov WORD [BYTE bp-ReadSectorsOffset],ReadSectors ; Save the address of ReadSectors
|
||||||
mov WORD [BYTE bp-ReadClusterOffset],ReadCluster ; Save the address of ReadCluster
|
mov WORD [BYTE bp-ReadClusterOffset],ReadCluster ; Save the address of ReadCluster
|
||||||
mov WORD [BYTE bp-PutCharsOffset],PutChars ; Save the address of PutChars
|
mov WORD [BYTE bp-PutCharsOffset],PutChars ; Save the address of PutChars
|
||||||
|
|
||||||
; Now AX has start cluster of FreeLoader and we
|
; Now AX has start cluster of FreeLoader and we
|
||||||
; have loaded the helper code in the first 512 bytes
|
; have loaded the helper code in the first 512 bytes
|
||||||
; of FreeLoader to 0000:8000. Now transfer control
|
; of FreeLoader to 0000:8000. Now transfer control
|
||||||
; to the helper code. Skip the first three bytes
|
; to the helper code. Skip the first three bytes
|
||||||
; because they contain a jump instruction to skip
|
; because they contain a jump instruction to skip
|
||||||
; over the helper code in the FreeLoader image.
|
; over the helper code in the FreeLoader image.
|
||||||
;jmp 0000:9003h
|
;jmp 0000:9003h
|
||||||
push 0 ; push segment (0x0000)
|
push 0 ; push segment (0x0000)
|
||||||
mov bx, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
|
mov bx, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
|
||||||
add bx, 0x8003 ; RVA -> VA and skip 3 bytes (jump to fathelper code)
|
add bx, 0x8003 ; RVA -> VA and skip 3 bytes (jump to fathelper code)
|
||||||
push bx ; push offset
|
push bx ; push offset
|
||||||
retf ; Transfer control to FreeLoader
|
retf ; Transfer control to FreeLoader
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,23 +248,23 @@ BadBoot:
|
||||||
mov si,msgDiskError ; Bad boot disk message
|
mov si,msgDiskError ; Bad boot disk message
|
||||||
call PutChars ; Display it
|
call PutChars ; Display it
|
||||||
|
|
||||||
jmp short Reboot
|
jmp short Reboot
|
||||||
|
|
||||||
|
|
||||||
; Reads cluster number in AX into [ES:0000]
|
; Reads cluster number in AX into [ES:0000]
|
||||||
ReadCluster:
|
ReadCluster:
|
||||||
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
||||||
dec ax ; Adjust start cluster by 2
|
dec ax ; Adjust start cluster by 2
|
||||||
dec ax ; Because the data area starts on cluster 2
|
dec ax ; Because the data area starts on cluster 2
|
||||||
xor ch,ch
|
xor ch,ch
|
||||||
mov cl,BYTE [BYTE bp+SectsPerCluster]
|
mov cl,BYTE [BYTE bp+SectsPerCluster]
|
||||||
mul cx ; Times sectors per cluster
|
mul cx ; Times sectors per cluster
|
||||||
add ax,[BYTE bp-DataAreaStartLow] ; Add start of data area
|
add ax,[BYTE bp-DataAreaStartLow] ; Add start of data area
|
||||||
adc dx,[BYTE bp-DataAreaStartHigh] ; Now we have DX:AX with the logical start sector of OSLOADER.SYS
|
adc dx,[BYTE bp-DataAreaStartHigh] ; Now we have DX:AX with the logical start sector of FREELDR.SYS
|
||||||
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
|
||||||
;mov cl,BYTE [BYTE bp+SectsPerCluster]; Sectors per cluster still in CX
|
;mov cl,BYTE [BYTE bp+SectsPerCluster]; Sectors per cluster still in CX
|
||||||
;call ReadSectors
|
;call ReadSectors
|
||||||
;ret
|
;ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,70 +273,70 @@ ReadCluster:
|
||||||
; CX has number of sectors to read
|
; CX has number of sectors to read
|
||||||
ReadSectors:
|
ReadSectors:
|
||||||
|
|
||||||
; We can't just check if the start sector is
|
; We can't just check if the start sector is
|
||||||
; in the BIOS CHS range. We have to check if
|
; in the BIOS CHS range. We have to check if
|
||||||
; the start sector + length is in that range.
|
; the start sector + length is in that range.
|
||||||
pusha
|
pusha
|
||||||
dec cx
|
dec cx
|
||||||
add ax,cx
|
add ax,cx
|
||||||
adc dx,byte 0
|
adc dx,byte 0
|
||||||
|
|
||||||
cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh] ; Check if they are reading a sector within CHS range
|
cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh] ; Check if they are reading a sector within CHS range
|
||||||
ja ReadSectorsLBA ; No - go to the LBA routine
|
ja ReadSectorsLBA ; No - go to the LBA routine
|
||||||
jb ReadSectorsCHS ; Yes - go to the old CHS routine
|
jb ReadSectorsCHS ; Yes - go to the old CHS routine
|
||||||
cmp ax,WORD [BYTE bp-BiosCHSDriveSizeLow] ; Check if they are reading a sector within CHS range
|
cmp ax,WORD [BYTE bp-BiosCHSDriveSizeLow] ; Check if they are reading a sector within CHS range
|
||||||
jbe ReadSectorsCHS ; Yes - go to the old CHS routine
|
jbe ReadSectorsCHS ; Yes - go to the old CHS routine
|
||||||
|
|
||||||
ReadSectorsLBA:
|
ReadSectorsLBA:
|
||||||
popa
|
popa
|
||||||
ReadSectorsLBALoop:
|
ReadSectorsLBALoop:
|
||||||
pusha ; Save logical sector number & sector count
|
pusha ; Save logical sector number & sector count
|
||||||
|
|
||||||
o32 push byte 0
|
o32 push byte 0
|
||||||
push dx ; Put 64-bit logical
|
push dx ; Put 64-bit logical
|
||||||
push ax ; block address on stack
|
push ax ; 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
|
||||||
push byte 1 ; Set transfer count to 1 sector
|
push byte 1 ; Set transfer count to 1 sector
|
||||||
push byte 0x10 ; Set size of packet to 10h
|
push byte 0x10 ; Set size of packet to 10h
|
||||||
mov si,sp ; Setup disk address packet on stack
|
mov si,sp ; Setup disk address packet on stack
|
||||||
|
|
||||||
; We are so totally out of space here that I am forced to
|
; We are so totally out of space here that I am forced to
|
||||||
; comment out this very beautifully written piece of code
|
; comment out this very beautifully written piece of code
|
||||||
; It would have been nice to have had this check...
|
; It would have been nice to have had this check...
|
||||||
;CheckInt13hExtensions: ; Now make sure this computer supports extended reads
|
;CheckInt13hExtensions: ; Now make sure this computer supports extended reads
|
||||||
; mov ah,0x41 ; AH = 41h
|
; mov ah,0x41 ; AH = 41h
|
||||||
; mov bx,0x55aa ; BX = 55AAh
|
; mov bx,0x55aa ; BX = 55AAh
|
||||||
; mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
|
; mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
|
||||||
; int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
; int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
||||||
; jc PrintDiskError ; CF set on error (extensions not supported)
|
; jc PrintDiskError ; CF set on error (extensions not supported)
|
||||||
; cmp bx,0xaa55 ; BX = AA55h if installed
|
; cmp bx,0xaa55 ; BX = AA55h if installed
|
||||||
; jne PrintDiskError
|
; jne PrintDiskError
|
||||||
; test cl,1 ; CX = API subset support bitmap
|
; test cl,1 ; CX = API subset support bitmap
|
||||||
; jz PrintDiskError ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
; jz PrintDiskError ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||||
|
|
||||||
|
|
||||||
; Good, we're here so the computer supports LBA disk access
|
; Good, we're here so the computer supports LBA disk access
|
||||||
; So finish the extended read
|
; So finish the extended read
|
||||||
mov dl,[BYTE bp+BootDrive] ; Drive number
|
mov dl,[BYTE bp+BootDrive] ; Drive number
|
||||||
mov ah,42h ; Int 13h, AH = 42h - Extended Read
|
mov ah,42h ; Int 13h, AH = 42h - Extended Read
|
||||||
int 13h ; Call BIOS
|
int 13h ; Call BIOS
|
||||||
jc BadBoot ; If the read failed then abort
|
jc BadBoot ; 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
|
||||||
|
|
||||||
popa ; Restore sector count & logical sector number
|
popa ; Restore sector count & logical sector number
|
||||||
|
|
||||||
inc ax ; Increment Sector to Read
|
inc ax ; Increment Sector to Read
|
||||||
adc dx,byte 0
|
adc dx,byte 0
|
||||||
|
|
||||||
push bx
|
push bx
|
||||||
mov bx,es
|
mov bx,es
|
||||||
add bx,byte 20h ; Increment read buffer for next sector
|
add bx,byte 20h ; Increment read buffer for next sector
|
||||||
mov es,bx
|
mov es,bx
|
||||||
pop bx
|
pop bx
|
||||||
|
|
||||||
loop ReadSectorsLBALoop ; Read next sector
|
loop ReadSectorsLBALoop ; Read next sector
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ ReadSectorsLBALoop:
|
||||||
; CX has number of sectors to read
|
; CX has number of sectors to read
|
||||||
; CarryFlag set on error
|
; CarryFlag set on error
|
||||||
ReadSectorsCHS:
|
ReadSectorsCHS:
|
||||||
popa
|
popa
|
||||||
ReadSectorsCHSLoop:
|
ReadSectorsCHSLoop:
|
||||||
pusha
|
pusha
|
||||||
xchg ax,cx
|
xchg ax,cx
|
||||||
|
@ -367,8 +367,8 @@ ReadSectorsCHSLoop:
|
||||||
mov ax,0201h
|
mov ax,0201h
|
||||||
int 13h ; DISK - READ SECTORS INTO MEMORY
|
int 13h ; DISK - READ SECTORS INTO MEMORY
|
||||||
; AL = number of sectors to read, CH = track, CL = sector
|
; AL = number of sectors to read, CH = track, CL = sector
|
||||||
; DH = head, DL = drive, ES:BX -> buffer to fill
|
; DH = head, DL = drive, ES:BX -> buffer to fill
|
||||||
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
|
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
|
||||||
|
|
||||||
jc BadBoot
|
jc BadBoot
|
||||||
|
|
||||||
|
@ -391,16 +391,16 @@ NoCarryCHS:
|
||||||
|
|
||||||
|
|
||||||
msgDiskError db 'Disk error',0dh,0ah,0
|
msgDiskError db 'Disk error',0dh,0ah,0
|
||||||
msgFreeLdr db 'ldr not found',0dh,0ah,0
|
msgFreeLdr db 'Ldr not found',0dh,0ah,0
|
||||||
; Sorry, need the space...
|
; Sorry, need the space...
|
||||||
;msgAnyKey db 'Press any key to restart',0dh,0ah,0
|
;msgAnyKey db 'Press any key to restart',0dh,0ah,0
|
||||||
msgAnyKey db 'Press a key',0dh,0ah,0
|
;msgAnyKey db 'Press a key',0dh,0ah,0
|
||||||
filename db 'FREELDR SYS'
|
filename db 'FREELDR SYS'
|
||||||
|
|
||||||
times 509-($-$$) db 0 ; Pad to 509 bytes
|
times 509-($-$$) db 0 ; Pad to 509 bytes
|
||||||
|
|
||||||
BootPartition:
|
BootPartition:
|
||||||
db 0
|
db 0
|
||||||
|
|
||||||
BootSignature:
|
BootSignature:
|
||||||
dw 0aa55h ; BootSector signature
|
dw 0aa55h ; BootSector signature
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* PROJECT: ReactOS Bootsector
|
* PROJECT: ReactOS Bootsector
|
||||||
* FILE: boot/freeldr/bootsect/fat32.S
|
* FILE: boot/freeldr/bootsect/fat32.S
|
||||||
* PURPOSE:
|
* PURPOSE:
|
||||||
* PROGRAMMERS: ?
|
* PROGRAMMERS: Brian Palmer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ******************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
@ -32,13 +32,13 @@ ReservedSectors:
|
||||||
NumberOfFats:
|
NumberOfFats:
|
||||||
.byte 2
|
.byte 2
|
||||||
MaxRootEntries:
|
MaxRootEntries:
|
||||||
.word 0 // Always zero for FAT32 volumes
|
.word 0 // Always zero for FAT32 volumes
|
||||||
TotalSectors:
|
TotalSectors:
|
||||||
.word 0 // Always zero for FAT32 volumes
|
.word 0 // Always zero for FAT32 volumes
|
||||||
MediaDescriptor:
|
MediaDescriptor:
|
||||||
.byte HEX(0f8)
|
.byte HEX(0f8)
|
||||||
SectorsPerFat:
|
SectorsPerFat:
|
||||||
.word 0 // Always zero for FAT32 volumes
|
.word 0 // Always zero for FAT32 volumes
|
||||||
SectorsPerTrack:
|
SectorsPerTrack:
|
||||||
.word 0
|
.word 0
|
||||||
NumberOfHeads:
|
NumberOfHeads:
|
||||||
|
@ -82,33 +82,33 @@ main:
|
||||||
xor ax,ax // Setup segment registers
|
xor ax,ax // Setup segment registers
|
||||||
mov ds,ax // Make DS correct
|
mov ds,ax // Make DS correct
|
||||||
mov es,ax // Make ES correct
|
mov es,ax // Make ES correct
|
||||||
mov ss,ax // Make SS correct
|
mov ss,ax // Make SS correct
|
||||||
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 BP_REL(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 BP_REL(BootDrive), dl // Save the boot drive
|
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
|
||||||
|
|
||||||
CheckSectorsPerFat:
|
CheckSectorsPerFat:
|
||||||
|
|
||||||
cmp word ptr BP_REL(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 dword ptr BP_REL(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 BP_REL(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 BP_REL(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
|
||||||
|
|
||||||
// If we get here then the call to the BIOS failed
|
// If we get here then the call to the BIOS failed
|
||||||
// so just set CHS equal to the maximum addressable
|
// so just set CHS equal to the maximum addressable
|
||||||
|
@ -119,18 +119,18 @@ GetDriveParameters:
|
||||||
CalcDriveSize:
|
CalcDriveSize:
|
||||||
// Now that we have the drive geometry
|
// Now that we have the drive geometry
|
||||||
// lets calculate the drive size
|
// lets calculate the drive size
|
||||||
mov bl, ch // Put the low 8-bits of the cylinder count into BL
|
mov bl, ch // Put the low 8-bits of the cylinder count into BL
|
||||||
mov bh, cl // Put the high 2-bits in BH
|
mov bh, cl // Put the high 2-bits in BH
|
||||||
shr bh, 6 // Shift them into position, now BX contains the cylinder count
|
shr bh, 6 // Shift them into position, now BX contains the cylinder count
|
||||||
and cl, HEX(3f) // Mask off cylinder bits from sector count
|
and cl, HEX(3f) // Mask off cylinder bits from sector count
|
||||||
// CL now contains sectors per track and DH contains head count
|
// CL now contains sectors per track and DH contains head count
|
||||||
movzx eax, dh // Move the heads into EAX
|
movzx eax, dh // Move the heads into EAX
|
||||||
movzx ebx, bx // Move the cylinders into EBX
|
movzx ebx, bx // Move the cylinders into EBX
|
||||||
movzx ecx, cl // Move the sectors per track into ECX
|
movzx ecx, cl // Move the sectors per track into ECX
|
||||||
inc eax // Make it one based because the bios returns it zero based
|
inc eax // Make it one based because the bios returns it zero based
|
||||||
inc ebx // Make the cylinder count one based also
|
inc ebx // Make the cylinder count one based also
|
||||||
mul ecx // Multiply heads with the sectors per track, result in edx:eax
|
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]
|
mul ebx // Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
|
||||||
|
|
||||||
// We now have the total number of sectors as reported
|
// We now have the total number of sectors as reported
|
||||||
// by the bios in eax, so store it in our variable
|
// by the bios in eax, so store it in our variable
|
||||||
|
@ -140,10 +140,10 @@ 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 BP_REL(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]
|
||||||
mov bx, HEX(7e00)
|
mov bx, HEX(7e00)
|
||||||
call ReadSectors
|
call ReadSectors
|
||||||
jmp StartSearch
|
jmp StartSearch
|
||||||
|
@ -154,64 +154,64 @@ LoadExtraBootCode:
|
||||||
// CX has number of sectors to read
|
// CX has number of sectors to read
|
||||||
ReadSectors:
|
ReadSectors:
|
||||||
push es
|
push es
|
||||||
cmp eax, dword ptr ds:[BiosCHSDriveSize] // Check if they are reading a sector outside CHS range
|
cmp eax, dword ptr ds:[BiosCHSDriveSize] // Check if they are reading a sector outside CHS range
|
||||||
jae ReadSectorsLBA // Yes - go to the LBA routine
|
jae ReadSectorsLBA // Yes - go to the LBA routine
|
||||||
// If at all possible we want to use LBA routines because
|
// If at all possible we want to use LBA routines because
|
||||||
// They are optimized to read more than 1 sector per read
|
// They are optimized to read more than 1 sector per read
|
||||||
|
|
||||||
pushad // Save logical sector number & sector count
|
pushad // Save logical sector number & sector count
|
||||||
|
|
||||||
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 BP_REL(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
|
||||||
jne ReadSectorsCHS
|
jne ReadSectorsCHS
|
||||||
test cl,1 // CX = API subset support bitmap
|
test cl,1 // CX = API subset support bitmap
|
||||||
jz ReadSectorsCHS // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
jz ReadSectorsCHS // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||||
|
|
||||||
popad // Restore sector count & logical sector number
|
popad // Restore sector count & logical sector number
|
||||||
|
|
||||||
ReadSectorsLBA:
|
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
|
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
|
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
|
mov cx, 64 // Otherwise read only 64 sectors on this loop iteration
|
||||||
|
|
||||||
ReadSectorsSetupDiskAddressPacket:
|
ReadSectorsSetupDiskAddressPacket:
|
||||||
mov word ptr ds:[LBASectorsRead],cx
|
mov word ptr ds:[LBASectorsRead],cx
|
||||||
push 0
|
push 0
|
||||||
push 0
|
push 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
|
||||||
push cx // Set transfer count
|
push cx // Set transfer count
|
||||||
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 BP_REL(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
|
||||||
|
|
||||||
add sp, 16 // Remove disk address packet from stack
|
add sp, 16 // Remove disk address packet from stack
|
||||||
|
|
||||||
popad // Restore sector count & logical sector number
|
popad // Restore sector count & logical sector number
|
||||||
|
|
||||||
push bx
|
push bx
|
||||||
mov ebx, dword ptr ds:[LBASectorsRead]
|
mov ebx, dword ptr ds:[LBASectorsRead]
|
||||||
add eax, ebx // Increment sector to read
|
add eax, ebx // Increment sector to read
|
||||||
shl ebx, 5
|
shl ebx, 5
|
||||||
mov dx, es
|
mov dx, es
|
||||||
add dx, bx // Setup read buffer for next sector
|
add dx, bx // Setup read buffer for next sector
|
||||||
mov es, dx
|
mov es, dx
|
||||||
pop bx
|
pop bx
|
||||||
|
|
||||||
sub cx, word ptr ds:[LBASectorsRead]
|
sub cx, word ptr ds:[LBASectorsRead]
|
||||||
jnz ReadSectorsLBA // Read next sector
|
jnz ReadSectorsLBA // Read next sector
|
||||||
|
|
||||||
pop es
|
pop es
|
||||||
ret
|
ret
|
||||||
|
@ -231,57 +231,57 @@ ReadSectorsCHSLoop:
|
||||||
xor edx, edx
|
xor edx, edx
|
||||||
movzx ecx, word ptr BP_REL(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 BP_REL(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 BP_REL(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
|
||||||
or cl, ah // Or with sector number
|
or cl, ah // Or with sector number
|
||||||
mov ax, HEX(0201)
|
mov ax, HEX(0201)
|
||||||
int HEX(13) // DISK - READ SECTORS INTO MEMORY
|
int HEX(13) // DISK - READ SECTORS INTO MEMORY
|
||||||
// AL = number of sectors to read, CH = track, CL = sector
|
// AL = number of sectors to read, CH = track, CL = sector
|
||||||
// DH = head, DL = drive, ES:BX -> buffer to fill
|
// DH = head, DL = drive, ES:BX -> buffer to fill
|
||||||
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
|
// 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
|
popad
|
||||||
|
|
||||||
inc eax // Increment Sector to Read
|
inc eax // Increment Sector to Read
|
||||||
|
|
||||||
mov dx, es
|
mov dx, es
|
||||||
add dx, 32 // Increment read buffer for next sector
|
add dx, 32 // Increment read buffer for next sector
|
||||||
mov es, dx
|
mov es, dx
|
||||||
|
|
||||||
loop ReadSectorsCHSLoop // Read next sector
|
loop ReadSectorsCHSLoop // Read next sector
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
// Displays a disk error message
|
// Displays a disk error message
|
||||||
// And reboots
|
// And reboots
|
||||||
PrintDiskError:
|
PrintDiskError:
|
||||||
mov si, offset msgDiskError // Bad boot disk message
|
mov si, offset msgDiskError // Bad boot disk message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
|
|
||||||
jmp Reboot
|
jmp Reboot
|
||||||
|
|
||||||
// Displays a file system error message
|
// Displays a file system error message
|
||||||
// And reboots
|
// And reboots
|
||||||
PrintFileSystemError:
|
PrintFileSystemError:
|
||||||
mov si, offset msgFileSystemError // FreeLdr not found message
|
mov si, offset msgFileSystemError // FreeLdr not found message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
|
|
||||||
Reboot:
|
Reboot:
|
||||||
mov si, offset msgAnyKey // Press any key message
|
mov si, offset msgAnyKey // Press any key message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
xor ax, ax
|
xor ax, ax
|
||||||
int HEX(16) // Wait for a keypress
|
int HEX(16) // Wait for a keypress
|
||||||
int HEX(19) // Reboot
|
int HEX(19) // Reboot
|
||||||
|
|
||||||
PutChars:
|
PutChars:
|
||||||
lodsb
|
lodsb
|
||||||
|
@ -311,7 +311,7 @@ BootPartition:
|
||||||
.byte 0
|
.byte 0
|
||||||
|
|
||||||
BootSignature:
|
BootSignature:
|
||||||
.word HEX(0aa55) // BootSector signature
|
.word HEX(0aa55) // BootSector signature
|
||||||
|
|
||||||
// End of bootsector
|
// End of bootsector
|
||||||
//
|
//
|
||||||
|
@ -330,7 +330,7 @@ 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 BP_REL(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
|
||||||
|
|
||||||
ContinueSearch:
|
ContinueSearch:
|
||||||
|
@ -339,16 +339,16 @@ ContinueSearch:
|
||||||
call ReadCluster // Read the cluster
|
call ReadCluster // Read the cluster
|
||||||
|
|
||||||
// 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 FREELDR.SYS file
|
||||||
xor bx,bx
|
xor bx,bx
|
||||||
mov bl, byte ptr BP_REL(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
|
||||||
xor di, di
|
xor di, di
|
||||||
mov si, offset filename
|
mov si, offset filename
|
||||||
mov cx, 11
|
mov cx, 11
|
||||||
repe cmpsb // Compare filenames
|
repe cmpsb // Compare filenames
|
||||||
jz FoundFile // If same we found it
|
jz FoundFile // If same we found it
|
||||||
dec bx
|
dec bx
|
||||||
jnz FindFile
|
jnz FindFile
|
||||||
|
@ -357,11 +357,11 @@ ContinueSearch:
|
||||||
FindFile:
|
FindFile:
|
||||||
mov ax, es // We didn't find it in the previous dir entry
|
mov ax, es // We didn't find it in the previous dir entry
|
||||||
add ax, 2 // So lets move to the next one
|
add ax, 2 // So lets move to the next one
|
||||||
mov es, ax // And search again
|
mov es, ax // And search again
|
||||||
xor di, di
|
xor di, di
|
||||||
mov si, offset filename
|
mov si, offset filename
|
||||||
mov cx, 11
|
mov cx, 11
|
||||||
repe cmpsb // Compare filenames
|
repe cmpsb // Compare filenames
|
||||||
jz FoundFile // If same we found it
|
jz FoundFile // If same we found it
|
||||||
dec bx // Keep searching till we run out of dir entries
|
dec bx // Keep searching till we run out of dir entries
|
||||||
jnz FindFile // Last entry?
|
jnz FindFile // Last entry?
|
||||||
|
@ -377,51 +377,51 @@ FoundFile:
|
||||||
mov si, offset msgLoading // Loading message
|
mov si, offset msgLoading // Loading message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
|
|
||||||
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+20] // 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+26] // 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
|
||||||
jnb CheckEndCluster // If so then continue
|
jnb CheckEndCluster // If so then continue
|
||||||
jmp PrintFileSystemError // If not exit with error
|
jmp PrintFileSystemError // If not exit with error
|
||||||
CheckEndCluster:
|
CheckEndCluster:
|
||||||
cmp eax, HEX(0ffffff8) // Check and see if the start cluster is and end of cluster chain indicator
|
cmp eax, HEX(0ffffff8) // Check and see if the start cluster is and end of cluster chain indicator
|
||||||
jb InitializeLoadSegment // If not then continue
|
jb InitializeLoadSegment // If not then continue
|
||||||
jmp PrintFileSystemError // If so exit with error
|
jmp PrintFileSystemError // If so exit with error
|
||||||
|
|
||||||
InitializeLoadSegment:
|
InitializeLoadSegment:
|
||||||
mov bx, FREELDR_BASE / 16
|
mov bx, FREELDR_BASE / 16
|
||||||
mov es, bx
|
mov es, bx
|
||||||
|
|
||||||
LoadFile:
|
LoadFile:
|
||||||
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
|
||||||
jae LoadFileDone // If so continue, if not then read the next one
|
jae LoadFileDone // If so continue, if not then read the next one
|
||||||
push eax
|
push eax
|
||||||
xor bx, bx // Load ROSLDR starting at 0000:8000h
|
xor bx, bx // Load ROSLDR starting at 0000:8000h
|
||||||
push es
|
push es
|
||||||
call ReadCluster
|
call ReadCluster
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
xor bx, bx
|
xor bx, bx
|
||||||
mov bl, byte ptr BP_REL(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
|
||||||
mov es, ax
|
mov es, ax
|
||||||
|
|
||||||
pop eax
|
pop eax
|
||||||
push es
|
push es
|
||||||
call GetFatEntry // Get the next entry
|
call GetFatEntry // Get the next entry
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
jmp LoadFile // Load the next cluster (if any)
|
jmp LoadFile // Load the next cluster (if any)
|
||||||
|
|
||||||
LoadFileDone:
|
LoadFileDone:
|
||||||
mov dl, byte ptr BP_REL(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
|
||||||
|
|
||||||
/* Transfer execution to the bootloader */
|
/* Transfer execution to the bootloader */
|
||||||
ljmp16 0, FREELDR_BASE
|
ljmp16 0, FREELDR_BASE
|
||||||
|
@ -431,43 +431,43 @@ LoadFileDone:
|
||||||
// On return EAX has FAT entry for that cluster
|
// On return EAX has FAT entry for that cluster
|
||||||
GetFatEntry:
|
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 BP_REL(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 BP_REL(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 BP_REL(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
|
||||||
and ecx,ebx // FAT Offset Within Sector = ECX % BytesPerSector
|
and ecx,ebx // FAT Offset Within Sector = ECX % BytesPerSector
|
||||||
// EAX holds logical FAT sector number
|
// EAX holds logical FAT sector number
|
||||||
// ECX holds FAT entry offset
|
// ECX holds FAT entry offset
|
||||||
|
|
||||||
// Now we have to check the extended flags
|
// Now we have to check the extended flags
|
||||||
// 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 BP_REL(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 BP_REL(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 BP_REL(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
|
||||||
|
|
||||||
LoadFatSector:
|
LoadFatSector:
|
||||||
push ecx
|
push ecx
|
||||||
|
|
||||||
mov bx, HEX(9000) // We will load it to [9000:0000h]
|
mov bx, HEX(9000) // We will load it to [9000:0000h]
|
||||||
mov es, bx
|
mov es, bx
|
||||||
|
|
||||||
// EAX holds logical FAT sector number
|
// EAX holds logical FAT sector number
|
||||||
|
@ -482,18 +482,18 @@ LoadFatSector:
|
||||||
|
|
||||||
LoadFatSectorAlreadyLoaded:
|
LoadFatSectorAlreadyLoaded:
|
||||||
pop ecx
|
pop ecx
|
||||||
mov eax, dword ptr es:[ecx] // Get FAT entry
|
mov eax, dword ptr es:[ecx] // Get FAT entry
|
||||||
and eax, HEX(0fffffff) // Mask off reserved bits
|
and eax, HEX(0fffffff) // Mask off reserved bits
|
||||||
|
|
||||||
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
|
||||||
.long HEX(0ffffffff) // 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]
|
||||||
ReadCluster:
|
ReadCluster:
|
||||||
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors//
|
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
||||||
|
|
||||||
dec eax
|
dec eax
|
||||||
dec eax
|
dec eax
|
||||||
|
@ -508,7 +508,7 @@ ReadCluster:
|
||||||
add eax, ebx
|
add eax, ebx
|
||||||
add eax, dword ptr BP_REL(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 BP_REL(SectsPerCluster)
|
movzx cx, byte ptr BP_REL(SectsPerCluster)
|
||||||
call ReadSectors
|
call ReadSectors
|
||||||
|
@ -517,10 +517,10 @@ ReadCluster:
|
||||||
// Displays a file not found error message
|
// Displays a file not found error message
|
||||||
// And reboots
|
// And reboots
|
||||||
PrintFileNotFound:
|
PrintFileNotFound:
|
||||||
mov si, offset msgFreeLdr // FreeLdr not found message
|
mov si, offset msgFreeLdr // FreeLdr not found message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
mov si, offset msgAnyKey // Press any key message
|
mov si, offset msgAnyKey // Press any key message
|
||||||
call PutChars // Display it
|
call PutChars // Display it
|
||||||
|
|
||||||
jmp Reboot
|
jmp Reboot
|
||||||
|
|
||||||
|
|
|
@ -12,109 +12,109 @@ start:
|
||||||
jmp short main
|
jmp short main
|
||||||
nop
|
nop
|
||||||
|
|
||||||
OEMName db 'FrLdr1.0'
|
OEMName db 'FrLdr1.0'
|
||||||
BytesPerSector dw 512
|
BytesPerSector dw 512
|
||||||
SectsPerCluster db 0
|
SectsPerCluster db 0
|
||||||
ReservedSectors dw 32
|
ReservedSectors dw 32
|
||||||
NumberOfFats db 2
|
NumberOfFats db 2
|
||||||
MaxRootEntries dw 0 ; Always zero for FAT32 volumes
|
MaxRootEntries dw 0 ; Always zero for FAT32 volumes
|
||||||
TotalSectors dw 0 ; Always zero for FAT32 volumes
|
TotalSectors dw 0 ; Always zero for FAT32 volumes
|
||||||
MediaDescriptor db 0f8h
|
MediaDescriptor db 0f8h
|
||||||
SectorsPerFat dw 0 ; Always zero for FAT32 volumes
|
SectorsPerFat dw 0 ; Always zero for FAT32 volumes
|
||||||
SectorsPerTrack dw 0
|
SectorsPerTrack dw 0
|
||||||
NumberOfHeads dw 0
|
NumberOfHeads dw 0
|
||||||
HiddenSectors dd 0
|
HiddenSectors dd 0
|
||||||
TotalSectorsBig dd 0
|
TotalSectorsBig dd 0
|
||||||
; FAT32 Inserted Info
|
; FAT32 Inserted Info
|
||||||
SectorsPerFatBig dd 0
|
SectorsPerFatBig dd 0
|
||||||
ExtendedFlags dw 0
|
ExtendedFlags dw 0
|
||||||
FSVersion dw 0
|
FSVersion dw 0
|
||||||
RootDirStartCluster dd 0
|
RootDirStartCluster dd 0
|
||||||
FSInfoSector dw 0
|
FSInfoSector dw 0
|
||||||
BackupBootSector dw 6
|
BackupBootSector dw 6
|
||||||
Reserved1 times 12 db 0
|
Reserved1 times 12 db 0
|
||||||
; End FAT32 Inserted Info
|
; End FAT32 Inserted Info
|
||||||
BootDrive db 0
|
BootDrive db 0
|
||||||
Reserved db 0
|
Reserved db 0
|
||||||
ExtendSig db 29h
|
ExtendSig db 29h
|
||||||
SerialNumber dd 00000000h
|
SerialNumber dd 00000000h
|
||||||
VolumeLabel db 'NO NAME '
|
VolumeLabel db 'NO NAME '
|
||||||
FileSystem db 'FAT32 '
|
FileSystem db 'FAT32 '
|
||||||
|
|
||||||
main:
|
main:
|
||||||
xor ax,ax ; Setup segment registers
|
xor ax,ax ; Setup segment registers
|
||||||
mov ds,ax ; Make DS correct
|
mov ds,ax ; Make DS correct
|
||||||
mov es,ax ; Make ES correct
|
mov es,ax ; Make ES correct
|
||||||
mov ss,ax ; Make SS correct
|
mov ss,ax ; Make SS correct
|
||||||
mov bp,7c00h
|
mov bp,7c00h
|
||||||
mov sp,7c00h ; Setup a stack
|
mov sp,7c00h ; Setup a stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
|
cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
|
||||||
jne CheckSectorsPerFat
|
jne CheckSectorsPerFat
|
||||||
|
|
||||||
mov [BYTE bp+BootDrive],dl ; Save the boot drive
|
mov [BYTE bp+BootDrive],dl ; Save the boot drive
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CheckSectorsPerFat:
|
CheckSectorsPerFat:
|
||||||
cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat
|
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
|
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 DWORD [BYTE bp+MaxRootEntries],byte 0x00; by comparing the DWORD at offset MaxRootEntries to zero
|
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
|
jnz CheckFailed ; If it is non-zero then exit with an error
|
||||||
CheckFileSystemVersion:
|
CheckFileSystemVersion:
|
||||||
cmp WORD [BYTE bp+FSVersion],byte 0x00 ; Check the file system version word
|
cmp WORD [BYTE bp+FSVersion],byte 0x00 ; 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,0800h
|
mov ax,0800h
|
||||||
mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
|
mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
|
||||||
int 13h ; Request drive parameters from the bios
|
int 13h ; 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
|
||||||
|
|
||||||
; If we get here then the call to the BIOS failed
|
; If we get here then the call to the BIOS failed
|
||||||
; so just set CHS equal to the maximum addressable
|
; so just set CHS equal to the maximum addressable
|
||||||
; size
|
; size
|
||||||
mov cx,0ffffh
|
mov cx,0ffffh
|
||||||
mov dh,cl
|
mov dh,cl
|
||||||
|
|
||||||
CalcDriveSize:
|
CalcDriveSize:
|
||||||
; Now that we have the drive geometry
|
; Now that we have the drive geometry
|
||||||
; lets calculate the drive size
|
; lets calculate the drive size
|
||||||
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
|
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
|
||||||
mov bh,cl ; Put the high 2-bits in BH
|
mov bh,cl ; Put the high 2-bits in BH
|
||||||
shr bh,6 ; Shift them into position, now BX contains the cylinder count
|
shr bh,6 ; Shift them into position, now BX contains the cylinder count
|
||||||
and cl,3fh ; Mask off cylinder bits from sector count
|
and cl,3fh ; Mask off cylinder bits from sector count
|
||||||
; CL now contains sectors per track and DH contains head count
|
; CL now contains sectors per track and DH contains head count
|
||||||
movzx eax,dh ; Move the heads into EAX
|
movzx eax,dh ; Move the heads into EAX
|
||||||
movzx ebx,bx ; Move the cylinders into EBX
|
movzx ebx,bx ; Move the cylinders into EBX
|
||||||
movzx ecx,cl ; Move the sectors per track into ECX
|
movzx ecx,cl ; Move the sectors per track into ECX
|
||||||
inc eax ; Make it one based because the bios returns it zero based
|
inc eax ; Make it one based because the bios returns it zero based
|
||||||
inc ebx ; Make the cylinder count one based also
|
inc ebx ; Make the cylinder count one based also
|
||||||
mul ecx ; Multiply heads with the sectors per track, result in edx:eax
|
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]
|
mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
|
||||||
|
|
||||||
; We now have the total number of sectors as reported
|
; We now have the total number of sectors as reported
|
||||||
; by the bios in eax, so store it in our variable
|
; by the bios in eax, so store it in our variable
|
||||||
mov [BiosCHSDriveSize],eax
|
mov [BiosCHSDriveSize],eax
|
||||||
|
|
||||||
|
|
||||||
LoadExtraBootCode:
|
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,0eh
|
mov eax,0eh
|
||||||
add eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors
|
add eax,DWORD [BYTE bp+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]
|
||||||
mov bx,7e00h
|
mov bx,7e00h
|
||||||
call ReadSectors
|
call ReadSectors
|
||||||
jmp StartSearch
|
jmp StartSearch
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,110 +122,110 @@ LoadExtraBootCode:
|
||||||
; EAX has logical sector number to read
|
; EAX has logical sector number to read
|
||||||
; CX has number of sectors to read
|
; CX has number of sectors to read
|
||||||
ReadSectors:
|
ReadSectors:
|
||||||
cmp eax,DWORD [BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
|
cmp eax,DWORD [BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
|
||||||
jae ReadSectorsLBA ; Yes - go to the LBA routine
|
jae ReadSectorsLBA ; Yes - go to the LBA routine
|
||||||
; If at all possible we want to use LBA routines because
|
; If at all possible we want to use LBA routines because
|
||||||
; They are optimized to read more than 1 sector per read
|
; They are optimized to read more than 1 sector per read
|
||||||
|
|
||||||
pushad ; Save logical sector number & sector count
|
pushad ; Save logical sector number & sector count
|
||||||
|
|
||||||
CheckInt13hExtensions: ; Now check if this computer supports extended reads
|
CheckInt13hExtensions: ; Now check if this computer supports extended reads
|
||||||
mov ah,0x41 ; AH = 41h
|
mov ah,0x41 ; AH = 41h
|
||||||
mov bx,0x55aa ; BX = 55AAh
|
mov bx,0x55aa ; BX = 55AAh
|
||||||
mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
|
mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
|
||||||
int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
int 13h ; 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,0xaa55 ; BX = AA55h if installed
|
cmp bx,0xaa55 ; BX = AA55h if installed
|
||||||
jne ReadSectorsCHS
|
jne ReadSectorsCHS
|
||||||
test cl,1 ; CX = API subset support bitmap
|
test cl,1 ; CX = API subset support bitmap
|
||||||
jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||||
|
|
||||||
popad ; Restore sector count & logical sector number
|
popad ; Restore sector count & logical sector number
|
||||||
|
|
||||||
ReadSectorsLBA:
|
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
|
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
|
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
|
mov cx,64 ; Otherwise read only 64 sectors on this loop iteration
|
||||||
|
|
||||||
ReadSectorsSetupDiskAddressPacket:
|
ReadSectorsSetupDiskAddressPacket:
|
||||||
mov [LBASectorsRead],cx
|
mov [LBASectorsRead],cx
|
||||||
o32 push byte 0
|
o32 push byte 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
|
||||||
push cx ; Set transfer count
|
push cx ; Set transfer count
|
||||||
push byte 0x10 ; Set size of packet to 10h
|
push byte 0x10 ; 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 bp+BootDrive] ; Drive number
|
mov dl,[BYTE bp+BootDrive] ; Drive number
|
||||||
mov ah,42h ; Int 13h, AH = 42h - Extended Read
|
mov ah,42h ; Int 13h, AH = 42h - Extended Read
|
||||||
int 13h ; Call BIOS
|
int 13h ; Call BIOS
|
||||||
jc PrintDiskError ; If the read failed then abort
|
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
|
push bx
|
||||||
mov ebx,DWORD [LBASectorsRead]
|
mov ebx,DWORD [LBASectorsRead]
|
||||||
add eax,ebx ; Increment sector to read
|
add eax,ebx ; Increment sector to read
|
||||||
shl ebx,5
|
shl ebx,5
|
||||||
mov dx,es
|
mov dx,es
|
||||||
add dx,bx ; Setup read buffer for next sector
|
add dx,bx ; Setup read buffer for next sector
|
||||||
mov es,dx
|
mov es,dx
|
||||||
pop bx
|
pop bx
|
||||||
|
|
||||||
sub cx,[LBASectorsRead]
|
sub cx,[LBASectorsRead]
|
||||||
jnz ReadSectorsLBA ; Read next sector
|
jnz ReadSectorsLBA ; Read next sector
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
LBASectorsRead:
|
LBASectorsRead:
|
||||||
dd 0
|
dd 0
|
||||||
|
|
||||||
|
|
||||||
; Reads logical sectors into [ES:BX]
|
; Reads logical sectors into [ES:BX]
|
||||||
; EAX has logical sector number to read
|
; EAX has logical sector number to read
|
||||||
; CX has number of sectors to read
|
; CX has number of sectors to read
|
||||||
ReadSectorsCHS:
|
ReadSectorsCHS:
|
||||||
popad ; Get logical sector number & sector count off stack
|
popad ; Get logical sector number & sector count off stack
|
||||||
|
|
||||||
ReadSectorsCHSLoop:
|
ReadSectorsCHSLoop:
|
||||||
pushad
|
pushad
|
||||||
xor edx,edx
|
xor edx,edx
|
||||||
movzx ecx,WORD [BYTE bp+SectorsPerTrack]
|
movzx ecx,WORD [BYTE bp+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 [BYTE bp+NumberOfHeads] ; Divide logical by number of heads
|
div WORD [BYTE bp+NumberOfHeads] ; Divide logical by number of heads
|
||||||
mov dh,dl ; Head in DH
|
mov dh,dl ; Head in DH
|
||||||
mov dl,[BYTE bp+BootDrive] ; Drive number in DL
|
mov dl,[BYTE bp+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
|
||||||
or cl,ah ; Or with sector number
|
or cl,ah ; Or with sector number
|
||||||
mov ax,0201h
|
mov ax,0201h
|
||||||
int 13h ; DISK - READ SECTORS INTO MEMORY
|
int 13h ; DISK - READ SECTORS INTO MEMORY
|
||||||
; AL = number of sectors to read, CH = track, CL = sector
|
; AL = number of sectors to read, CH = track, CL = sector
|
||||||
; DH = head, DL = drive, ES:BX -> buffer to fill
|
; DH = head, DL = drive, ES:BX -> buffer to fill
|
||||||
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
|
; 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
|
popad
|
||||||
|
|
||||||
inc eax ; Increment Sector to Read
|
inc eax ; Increment Sector to Read
|
||||||
|
|
||||||
mov dx,es
|
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
|
mov es,dx
|
||||||
|
|
||||||
loop ReadSectorsCHSLoop ; Read next sector
|
loop ReadSectorsCHSLoop ; Read next sector
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -235,23 +235,23 @@ ReadSectorsCHSLoop:
|
||||||
; Displays a disk error message
|
; Displays a disk error message
|
||||||
; And reboots
|
; And reboots
|
||||||
PrintDiskError:
|
PrintDiskError:
|
||||||
mov si,msgDiskError ; Bad boot disk message
|
mov si,msgDiskError ; Bad boot disk message
|
||||||
call PutChars ; Display it
|
call PutChars ; Display it
|
||||||
|
|
||||||
jmp Reboot
|
jmp Reboot
|
||||||
|
|
||||||
; 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,msgFileSystemError ; FreeLdr not found message
|
||||||
call PutChars ; Display it
|
call PutChars ; Display it
|
||||||
|
|
||||||
Reboot:
|
Reboot:
|
||||||
mov si,msgAnyKey ; Press any key message
|
mov si,msgAnyKey ; Press any key message
|
||||||
call PutChars ; Display it
|
call PutChars ; Display it
|
||||||
xor ax,ax
|
xor ax,ax
|
||||||
int 16h ; Wait for a keypress
|
int 16h ; Wait for a keypress
|
||||||
int 19h ; Reboot
|
int 19h ; Reboot
|
||||||
|
|
||||||
PutChars:
|
PutChars:
|
||||||
lodsb
|
lodsb
|
||||||
|
@ -268,14 +268,14 @@ Done:
|
||||||
|
|
||||||
BiosCHSDriveSize dd 0
|
BiosCHSDriveSize dd 0
|
||||||
|
|
||||||
msgDiskError db 'Disk error',0dh,0ah,0
|
msgDiskError db 'Disk error',0dh,0ah,0
|
||||||
msgFileSystemError db 'File system error',0dh,0ah,0
|
msgFileSystemError db 'File system error',0dh,0ah,0
|
||||||
msgAnyKey db 'Press any key to restart',0dh,0ah,0
|
msgAnyKey db 'Press any key to restart',0dh,0ah,0
|
||||||
|
|
||||||
times 509-($-$$) db 0 ; Pad to 509 bytes
|
times 509-($-$$) db 0 ; Pad to 509 bytes
|
||||||
|
|
||||||
BootPartition:
|
BootPartition:
|
||||||
db 0
|
db 0
|
||||||
|
|
||||||
BootSignature:
|
BootSignature:
|
||||||
dw 0aa55h ; BootSector signature
|
dw 0aa55h ; BootSector signature
|
||||||
|
@ -295,22 +295,22 @@ 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 [BYTE bp+RootDirStartCluster]
|
mov eax,DWORD [BYTE bp+RootDirStartCluster]
|
||||||
cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
|
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
|
jb ContinueSearch ; If not continue, if so then we didn't find freeldr.sys
|
||||||
jmp PrintFileNotFound
|
jmp PrintFileNotFound
|
||||||
ContinueSearch:
|
ContinueSearch:
|
||||||
mov bx,2000h
|
mov bx,2000h
|
||||||
mov es,bx ; Read cluster to [2000:0000h]
|
mov es,bx ; Read cluster to [2000:0000h]
|
||||||
call ReadCluster ; Read the cluster
|
call ReadCluster ; Read the cluster
|
||||||
|
|
||||||
|
|
||||||
; 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 FREELDR.SYS file
|
||||||
xor bx,bx
|
xor bx,bx
|
||||||
mov bl,[BYTE bp+SectsPerCluster]
|
mov bl,[BYTE bp+SectsPerCluster]
|
||||||
shl bx,4 ; BX = BX * 512 / 32
|
shl bx,4 ; BX = BX * 512 / 32
|
||||||
mov ax,2000h ; We loaded at 2000:0000
|
mov ax,2000h ; We loaded at 2000:0000
|
||||||
mov es,ax
|
mov es,ax
|
||||||
xor di,di
|
xor di,di
|
||||||
mov si,filename
|
mov si,filename
|
||||||
|
@ -333,157 +333,157 @@ FindFile:
|
||||||
dec bx ; Keep searching till we run out of dir entries
|
dec bx ; Keep searching till we run out of dir entries
|
||||||
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 [BYTE bp+RootDirStartCluster]
|
mov eax,DWORD [BYTE bp+RootDirStartCluster]
|
||||||
call GetFatEntry
|
call GetFatEntry
|
||||||
mov [BYTE bp+RootDirStartCluster],eax
|
mov [BYTE bp+RootDirStartCluster],eax
|
||||||
jmp StartSearch
|
jmp StartSearch
|
||||||
|
|
||||||
FoundFile:
|
FoundFile:
|
||||||
|
|
||||||
; Display "Loading FreeLoader..." message
|
; Display "Loading FreeLoader..." message
|
||||||
mov si,msgLoading ; Loading message
|
mov si,msgLoading ; Loading message
|
||||||
call PutChars ; Display it
|
call PutChars ; Display it
|
||||||
|
|
||||||
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 [es:di+14h] ; Get start cluster high word
|
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
|
mov ax,WORD [es:di+1ah] ; 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
|
||||||
jnb CheckEndCluster ; If so then continue
|
jnb CheckEndCluster ; If so then continue
|
||||||
jmp PrintFileSystemError ; If not exit with error
|
jmp PrintFileSystemError ; If not exit with error
|
||||||
CheckEndCluster:
|
CheckEndCluster:
|
||||||
cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator
|
cmp eax,0ffffff8h ; Check and see if the start cluster is and end of cluster chain indicator
|
||||||
jb InitializeLoadSegment ; If not then continue
|
jb InitializeLoadSegment ; If not then continue
|
||||||
jmp PrintFileSystemError ; If so exit with error
|
jmp PrintFileSystemError ; If so exit with error
|
||||||
|
|
||||||
InitializeLoadSegment:
|
InitializeLoadSegment:
|
||||||
mov bx,800h
|
mov bx,800h
|
||||||
mov es,bx
|
mov es,bx
|
||||||
|
|
||||||
LoadFile:
|
LoadFile:
|
||||||
cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
|
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
|
jae LoadFileDone ; If so continue, if not then read the next one
|
||||||
push eax
|
push eax
|
||||||
xor bx,bx ; Load ROSLDR starting at 0000:8000h
|
xor bx,bx ; Load ROSLDR starting at 0000:8000h
|
||||||
push es
|
push es
|
||||||
call ReadCluster
|
call ReadCluster
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
xor bx,bx
|
xor bx,bx
|
||||||
mov bl,[BYTE bp+SectsPerCluster]
|
mov bl,[BYTE bp+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
|
||||||
mov es,ax
|
mov es,ax
|
||||||
|
|
||||||
pop eax
|
pop eax
|
||||||
push es
|
push es
|
||||||
call GetFatEntry ; Get the next entry
|
call GetFatEntry ; Get the next entry
|
||||||
pop es
|
pop es
|
||||||
|
|
||||||
jmp LoadFile ; Load the next cluster (if any)
|
jmp LoadFile ; Load the next cluster (if any)
|
||||||
|
|
||||||
LoadFileDone:
|
LoadFileDone:
|
||||||
mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
|
mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
|
||||||
mov dh,[BootPartition] ; Load boot partition into DH
|
mov dh,[BootPartition] ; Load boot partition into DH
|
||||||
|
|
||||||
push 0 ; push segment (0x0000)
|
push 0 ; push segment (0x0000)
|
||||||
mov eax, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
|
mov eax, [0x8000 + 0xA8] ; load the RVA of the EntryPoint into eax
|
||||||
add eax, 0x8000 ; RVA -> VA
|
add eax, 0x8000 ; RVA -> VA
|
||||||
push ax ; push offset
|
push ax ; push offset
|
||||||
retf ; Transfer control to FreeLoader
|
retf ; Transfer control to FreeLoader
|
||||||
|
|
||||||
; Returns the FAT entry for a given cluster number
|
; Returns the FAT entry for a given cluster number
|
||||||
; On entry EAX has cluster number
|
; On entry EAX has cluster number
|
||||||
; On return EAX has FAT entry for that cluster
|
; On return EAX has FAT entry for that cluster
|
||||||
GetFatEntry:
|
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 [BYTE bp+BytesPerSector]
|
movzx ebx,WORD [BYTE bp+BytesPerSector]
|
||||||
push ebx
|
push ebx
|
||||||
div ebx ; FAT Sector Number = EAX / BytesPerSector
|
div ebx ; FAT Sector Number = EAX / BytesPerSector
|
||||||
movzx ebx,WORD [BYTE bp+ReservedSectors]
|
movzx ebx,WORD [BYTE bp+ReservedSectors]
|
||||||
add eax,ebx ; FAT Sector Number += ReservedSectors
|
add eax,ebx ; FAT Sector Number += ReservedSectors
|
||||||
mov ebx,DWORD [BYTE bp+HiddenSectors]
|
mov ebx,DWORD [BYTE bp+HiddenSectors]
|
||||||
add eax,ebx ; FAT Sector Number += HiddenSectors
|
add eax,ebx ; FAT Sector Number += HiddenSectors
|
||||||
pop ebx
|
pop ebx
|
||||||
dec ebx
|
dec ebx
|
||||||
and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
|
and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
|
||||||
; EAX holds logical FAT sector number
|
; EAX holds logical FAT sector number
|
||||||
; ECX holds FAT entry offset
|
; ECX holds FAT entry offset
|
||||||
|
|
||||||
; Now we have to check the extended flags
|
; Now we have to check the extended flags
|
||||||
; 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 [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx
|
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
|
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
|
jz LoadFatSector ; If fat is mirrored then skip fat calcs
|
||||||
cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats
|
cmp bl,[BYTE bp+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,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
|
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
|
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
|
||||||
|
|
||||||
LoadFatSector:
|
LoadFatSector:
|
||||||
push ecx
|
push ecx
|
||||||
; EAX holds logical FAT sector number
|
; EAX holds logical FAT sector number
|
||||||
; Check if we have already loaded it
|
; Check if we have already loaded it
|
||||||
cmp eax,DWORD [FatSectorInCache]
|
cmp eax,DWORD [FatSectorInCache]
|
||||||
je LoadFatSectorAlreadyLoaded
|
je LoadFatSectorAlreadyLoaded
|
||||||
|
|
||||||
mov DWORD [FatSectorInCache],eax
|
mov DWORD [FatSectorInCache],eax
|
||||||
mov bx,9000h
|
mov bx,9000h
|
||||||
mov es,bx
|
mov es,bx
|
||||||
xor bx,bx ; We will load it to [9000:0000h]
|
xor bx,bx ; We will load it to [9000:0000h]
|
||||||
mov cx,1
|
mov cx,1
|
||||||
call ReadSectors
|
call ReadSectors
|
||||||
|
|
||||||
LoadFatSectorAlreadyLoaded:
|
LoadFatSectorAlreadyLoaded:
|
||||||
mov bx,9000h
|
mov bx,9000h
|
||||||
mov es,bx
|
mov es,bx
|
||||||
pop ecx
|
pop ecx
|
||||||
mov eax,DWORD [es:ecx] ; Get FAT entry
|
mov eax,DWORD [es:ecx] ; Get FAT entry
|
||||||
and eax,0fffffffh ; Mask off reserved bits
|
and eax,0fffffffh ; Mask off reserved bits
|
||||||
|
|
||||||
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
|
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]
|
; Reads cluster number in EAX into [ES:0000]
|
||||||
ReadCluster:
|
ReadCluster:
|
||||||
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
||||||
|
|
||||||
dec eax
|
dec eax
|
||||||
dec eax
|
dec eax
|
||||||
xor edx,edx
|
xor edx,edx
|
||||||
movzx ebx,BYTE [BYTE bp+SectsPerCluster]
|
movzx ebx,BYTE [BYTE bp+SectsPerCluster]
|
||||||
mul ebx
|
mul ebx
|
||||||
push eax
|
push eax
|
||||||
xor edx,edx
|
xor edx,edx
|
||||||
movzx eax,BYTE [BYTE bp+NumberOfFats]
|
movzx eax,BYTE [BYTE bp+NumberOfFats]
|
||||||
mul DWORD [BYTE bp+SectorsPerFatBig]
|
mul DWORD [BYTE bp+SectorsPerFatBig]
|
||||||
movzx ebx,WORD [BYTE bp+ReservedSectors]
|
movzx ebx,WORD [BYTE bp+ReservedSectors]
|
||||||
add eax,ebx
|
add eax,ebx
|
||||||
add eax,DWORD [BYTE bp+HiddenSectors]
|
add eax,DWORD [BYTE bp+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 [BYTE bp+SectsPerCluster]
|
movzx cx,BYTE [BYTE bp+SectsPerCluster]
|
||||||
call ReadSectors
|
call ReadSectors
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
; Displays a file not found error message
|
; Displays a file not found error message
|
||||||
|
@ -494,7 +494,7 @@ PrintFileNotFound:
|
||||||
mov si,msgAnyKey ; Press any key message
|
mov si,msgAnyKey ; Press any key message
|
||||||
call PutChars ; Display it
|
call PutChars ; Display it
|
||||||
|
|
||||||
jmp Reboot
|
jmp Reboot
|
||||||
|
|
||||||
msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
|
msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
|
||||||
filename db 'FREELDR SYS'
|
filename db 'FREELDR SYS'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS Bootsector
|
* PROJECT: ReactOS Bootsector
|
||||||
* FILE: boot/freeldr/bootsect/fatx.S
|
* FILE: boot/freeldr/bootsect/faty.S
|
||||||
* PURPOSE: Combined FAT16 and FAT32 boot sector
|
* PURPOSE: Combined FAT12, FAT16 and FAT32 boot sector
|
||||||
* PROGRAMMERS: Brian Palmer
|
* PROGRAMMERS: Brian Palmer
|
||||||
* Timo Kreuzer
|
* Timo Kreuzer
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue