[FATxxx BOOTSECTORS]: Whitespace changes mainly (makes easier for diffing). No code changes.

svn path=/trunk/; revision=70428
This commit is contained in:
Hermès Bélusca-Maïto 2015-12-26 20:13:27 +00:00
parent 909f7439d0
commit 6a513178c3
5 changed files with 703 additions and 702 deletions

View file

@ -43,15 +43,15 @@
#define BP_REL(x) [bp+x-offset start]
DataAreaStartHigh = 2
DataAreaStartLow = 4
BiosCHSDriveSizeHigh = 6
BiosCHSDriveSizeLow = 8
BiosCHSDriveSize = 8
ReadSectorsOffset = 10
ReadClusterOffset = 12
PutCharsOffset = 14
BootSectorStackTop = HEX(7c00) - 16
DataAreaStartHigh = 2
DataAreaStartLow = 4
BiosCHSDriveSizeHigh = 6
BiosCHSDriveSizeLow = 8
BiosCHSDriveSize = 8
ReadSectorsOffset = 10
ReadClusterOffset = 12
PutCharsOffset = 14
BootSectorStackTop = HEX(7c00) - 16
// org 7c00h
@ -105,21 +105,21 @@ main:
xor ax, ax
mov ss, ax
mov bp, HEX(7c00)
mov sp, BootSectorStackTop // Setup a stack
mov ds, ax // Make DS correct
mov es, ax // Make ES correct
mov sp, BootSectorStackTop // Setup a stack
mov ds, ax // Make DS 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
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
GetDriveParameters:
mov ah, 8
mov dl, byte ptr BP_REL(BootDrive) // Get boot drive in dl
int HEX(13) // Request drive parameters from the bios
jnc CalcDriveSize // If the call succeeded then calculate the drive size
mov dl, byte ptr BP_REL(BootDrive) // Get boot drive in dl
int HEX(13) // Request drive parameters from the bios
jnc CalcDriveSize // If the call succeeded then calculate the drive size
// If we get here then the call to the BIOS failed
// so just set CHS equal to the maximum addressable
@ -151,26 +151,26 @@ CalcDriveSize:
// Now we must find our way to the first sector of the root directory
xor ax, ax
xor cx, cx
mov al, byte ptr BP_REL(NumberOfFats) // Number of fats
mul word ptr BP_REL(SectorsPerFat) // Times sectors per fat
mov al, byte ptr BP_REL(NumberOfFats) // Number of fats
mul word ptr BP_REL(SectorsPerFat) // Times sectors per fat
add ax, word ptr BP_REL(HiddenSectors)
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
adc dx, cx // Add carry bit
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 si, word ptr BP_REL(MaxRootEntries) // Get number of root dir entries in SI
pusha // Save 32-bit logical start sector of root dir
add ax, word ptr BP_REL(ReservedSectors) // Add the number of reserved sectors
adc dx, cx // Add carry bit
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 si, word ptr BP_REL(MaxRootEntries) // Get number of root dir entries in SI
pusha // Save 32-bit logical start sector of root dir
// DX:AX now has the number of the starting sector of the root directory
// Now calculate the size of the root directory
xor dx, dx
mov ax, 32 // Size of dir entry
mul si // Times the number of entries
mov ax, 32 // Size of dir entry
mul si // Times the number of entries
mov bx, word ptr BP_REL(BytesPerSector)
add ax, bx
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
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
LoadRootDirSector:
mov bx, HEX(7e0) // We will load the root directory sector
mov es, bx // Right after the boot sector in memory
xor bx, bx // We will load it to [0000:7e00h]
xor cx, cx // Zero out CX
inc cx // Now increment it to 1, we are reading one sector
xor di, di // Zero out di
push es // Save ES because it will get incremented by 20h
call ReadSectors // Read the first sector of the root directory
pop es // Restore ES (ES:DI = 07E0:0000)
mov bx, HEX(7e0) // We will load the root directory sector
mov es, bx // Right after the boot sector in memory
xor bx, bx // We will load it to [0000:7e00h]
xor cx, cx // Zero out CX
inc cx // Now increment it to 1, we are reading one sector
xor di, di // Zero out di
push es // Save ES because it will get incremented by 20h
call ReadSectors // Read the first sector of the root directory
pop es // Restore ES (ES:DI = 07E0:0000)
SearchRootDirSector:
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
pusha // Save all registers
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
repe cmpsb // Compare this directory entry against 'FREELDR SYS'
popa // Restore all the registers
jz FoundFreeLoader // If we found it then jump
dec si // SI holds MaxRootEntries, subtract one
jz ErrBoot // If we are out of root dir entries then reboot
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)
jc SearchRootDirSector // If DI is less than 512 loop again
jmp short LoadRootDirSector // Didn't find FREELDR.SYS in this directory sector, try again
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
pusha // Save all registers
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
repe cmpsb // Compare this directory entry against 'FREELDR SYS'
popa // Restore all the registers
jz FoundFreeLoader // If we found it then jump
dec si // SI holds MaxRootEntries, subtract one
jz ErrBoot // If we are out of root dir entries then reboot
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)
jc SearchRootDirSector // If DI is less than 512 loop again
jmp short LoadRootDirSector // Didn't find FREELDR.SYS in this directory sector, try again
FoundFreeLoader:
// We found freeldr.sys on the disk
// so we need to load the first 512
// bytes of it to 0000:F800
// ES:DI has dir entry (ES:DI == 07E0:XXXX)
mov ax, word ptr es:[di + HEX(1a)] // Get start cluster
push ax // Save start cluster
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
call ReadCluster // Read the cluster
pop ax // Restore start cluster of FreeLoader
mov ax, word ptr es:[di + HEX(1a)] // Get start cluster
push ax // Save start cluster
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
call ReadCluster // Read the cluster
pop ax // Restore start cluster of FreeLoader
// Save the addresses of needed functions so
// 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-ReadClusterOffset], offset ReadCluster // Save the address of ReadCluster
mov word ptr [bp-PutCharsOffset], offset PutChars // Save the address of PutChars
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-PutCharsOffset], offset PutChars // Save the address of PutChars
// Now AX has start cluster of FreeLoader and we
// have loaded the helper code in the first 512 bytes
@ -236,12 +236,12 @@ FoundFreeLoader:
// Displays an error message
// And reboots
ErrBoot:
mov si, offset msgFreeLdr // FreeLdr not found message
call PutChars // Display it
mov si, offset msgFreeLdr // FreeLdr not found message
call PutChars // Display it
Reboot:
// mov si, offset msgAnyKey // Press any key message
// call PutChars // Display it
// mov si, offset msgAnyKey // Press any key message
// call PutChars // Display it
xor ax, ax
int HEX(16) // Wait for a keypress
int HEX(19) // Reboot
@ -260,8 +260,8 @@ Done:
// Displays a bad boot message
// And reboots
BadBoot:
mov si, offset msgDiskError // Bad boot disk message
call PutChars // Display it
mov si, offset msgDiskError // Bad boot disk message
call PutChars // Display it
jmp short Reboot
@ -269,17 +269,17 @@ BadBoot:
// Reads cluster number in AX into [ES:0000]
ReadCluster:
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
dec ax // Adjust start cluster by 2
dec ax // Because the data area starts on cluster 2
dec ax // Adjust start cluster by 2
dec ax // Because the data area starts on cluster 2
xor ch, ch
mov cl, byte ptr BP_REL(SectsPerCluster)
mul cx // Times sectors per cluster
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
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
//call ReadSectors
//ret
mul cx // Times sectors per cluster
add ax, [bp-DataAreaStartLow] // Add start of data area
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
// mov cl,BYTE [BYTE bp+SectsPerCluster]// Sectors per cluster still in CX
// call ReadSectors
// ret
@ -296,63 +296,63 @@ ReadSectors:
add ax, cx
adc dx, 0
cmp dx, word ptr [bp-BiosCHSDriveSizeHigh] // Check if they are reading a sector within CHS range
ja ReadSectorsLBA // No - go to the LBA 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
jbe ReadSectorsCHS // Yes - go to the old CHS routine
cmp dx, word ptr [bp-BiosCHSDriveSizeHigh] // Check if they are reading a sector within CHS range
ja ReadSectorsLBA // No - go to the LBA 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
jbe ReadSectorsCHS // Yes - go to the old CHS routine
ReadSectorsLBA:
popa
ReadSectorsLBALoop:
pusha // Save logical sector number & sector count
pusha // Save logical sector number & sector count
push 0
push 0
push dx // Put 64-bit logical
push ax // block address on stack
push es // Put transfer segment on stack
push bx // Put transfer offset on stack
push 1 // Set transfer count to 1 sector
push HEX(10) // Set size of packet to 10h
mov si,sp // Setup disk address packet on stack
push dx // Put 64-bit logical
push ax // block address on stack
push es // Put transfer segment on stack
push bx // Put transfer offset on stack
push 1 // Set transfer count to 1 sector
push HEX(10) // Set size of packet to 10h
mov si,sp // Setup disk address packet on stack
// We are so totally out of space here that I am forced to
// comment out this very beautifully written piece of code
// It would have been nice to have had this check...
//CheckInt13hExtensions: // Now make sure this computer supports extended reads
// mov ah,0x41 // AH = 41h
// mov bx,0x55aa // BX = 55AAh
// mov dl,[BYTE bp+BootDrive] // DL = drive (80h-FFh)
// int 13h // IBM/MS INT 13 Extensions - INSTALLATION CHECK
// jc PrintDiskError // CF set on error (extensions not supported)
// cmp bx,0xaa55 // BX = AA55h if installed
// jne PrintDiskError
// test cl,1 // CX = API subset support bitmap
// jz PrintDiskError // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
//CheckInt13hExtensions: // Now make sure this computer supports extended reads
// mov ah,0x41 // AH = 41h
// mov bx,0x55aa // BX = 55AAh
// mov dl,[BYTE bp+BootDrive] // DL = drive (80h-FFh)
// int 13h // IBM/MS INT 13 Extensions - INSTALLATION CHECK
// jc PrintDiskError // CF set on error (extensions not supported)
// cmp bx,0xaa55 // BX = AA55h if installed
// jne PrintDiskError
// test cl,1 // CX = API subset support bitmap
// 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
// So finish the extended read
mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
int HEX(13) // Call BIOS
jc BadBoot // If the read failed then abort
// Good, we're here so the computer supports LBA disk access
// So finish the extended read
mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
int HEX(13) // Call BIOS
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
push bx
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
pop bx
loop ReadSectorsLBALoop // Read next sector
loop ReadSectorsLBALoop // Read next sector
ret
@ -370,26 +370,26 @@ ReadSectorsCHSLoop:
xor dx, dx
div word ptr BP_REL(SectorsPerTrack)
xchg ax, cx
div word ptr BP_REL(SectorsPerTrack) // Divide logical by SectorsPerTrack
inc dx // Sectors numbering starts at 1 not 0
div word ptr BP_REL(SectorsPerTrack) // Divide logical by SectorsPerTrack
inc dx // Sectors numbering starts at 1 not 0
xchg cx, dx
div word ptr BP_REL(NumberOfHeads) // Number of heads
mov dh, dl // Head to DH, drive to DL
mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ch, al // Cylinder in CX
ror ah, 2 // Low 8 bits of cylinder in CH, high 2 bits
// in CL shifted to bits 6 & 7
or cl, ah // Or with sector number
div word ptr BP_REL(NumberOfHeads) // Number of heads
mov dh, dl // Head to DH, drive to DL
mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ch, al // Cylinder in CX
ror ah, 2 // Low 8 bits of cylinder in CH, high 2 bits
// in CL shifted to bits 6 & 7
or cl, ah // Or with sector number
mov ax, HEX(0201)
int HEX(13) // DISK - READ SECTORS INTO MEMORY
// AL = number of sectors to read, CH = track, CL = sector
// DH = head, DL = drive, ES:BX -> buffer to fill
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
// DH = head, DL = drive, ES:BX -> buffer to fill
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
jc BadBoot
popa
inc ax //Increment Sector to Read
inc ax // Increment Sector to Read
jnz NoCarryCHS
inc dx
@ -400,8 +400,8 @@ NoCarryCHS:
add bx, HEX(20)
mov es, bx
pop bx
// Increment read buffer for next sector
loop ReadSectorsCHSLoop // Read next sector
// Increment read buffer for next sector
loop ReadSectorsCHSLoop // Read next sector
ret
@ -409,10 +409,11 @@ NoCarryCHS:
msgDiskError:
.ascii "Disk error", CR, LF, NUL
msgFreeLdr:
.ascii "ldr not found", CR, LF, NUL
.ascii "Ldr not found", CR, LF, NUL
// Sorry, need the space...
//msgAnyKey:
// msgAnyKey:
// .ascii "Press any key to restart", CR, LF, NUL
// .ascii "Press a key", CR, LF, NUL
filename:
.ascii "FREELDR SYS"
@ -422,7 +423,7 @@ BootPartition:
.byte 0
BootSignature:
.word HEX(0aa55) // BootSector signature
.word HEX(0aa55) // BootSector signature
.endcode16

View file

@ -39,15 +39,15 @@
; boots dramatically.
BootSectorStackTop equ 0x7bf2
DataAreaStartHigh equ 0x2
DataAreaStartLow equ 0x4
BiosCHSDriveSizeHigh equ 0x6
BiosCHSDriveSizeLow equ 0x8
BiosCHSDriveSize equ 0x8
ReadSectorsOffset equ 0xa
ReadClusterOffset equ 0xc
PutCharsOffset equ 0xe
BootSectorStackTop equ 0x7bf2
DataAreaStartHigh equ 0x2
DataAreaStartLow equ 0x4
BiosCHSDriveSizeHigh equ 0x6
BiosCHSDriveSizeLow equ 0x8
BiosCHSDriveSize equ 0x8
ReadSectorsOffset equ 0xa
ReadClusterOffset equ 0xc
PutCharsOffset equ 0xe
org 7c00h
@ -84,136 +84,136 @@ main:
xor ax,ax
mov ss,ax
mov bp,7c00h
mov sp,BootSectorStackTop ; Setup a stack
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
mov sp,BootSectorStackTop ; Setup a stack
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
jne GetDriveParameters
cmp BYTE [BYTE bp+BootDrive],BYTE 0xff ; If they have specified a boot drive then use it
jne GetDriveParameters
mov [BYTE bp+BootDrive],dl ; Save the boot drive
mov [BYTE bp+BootDrive],dl ; Save the boot drive
GetDriveParameters:
mov ah,08h
mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
int 13h ; Request drive parameters from the bios
jnc CalcDriveSize ; If the call succeeded then calculate the drive size
mov ah,08h
mov dl,[BYTE bp+BootDrive] ; Get boot drive in dl
int 13h ; Request drive parameters from the bios
jnc CalcDriveSize ; If the call succeeded then calculate the drive size
; If we get here then the call to the BIOS failed
; so just set CHS equal to the maximum addressable
; size
mov cx,0ffffh
mov dh,cl
; If we get here then the call to the BIOS failed
; so just set CHS equal to the maximum addressable
; size
mov cx,0ffffh
mov dh,cl
CalcDriveSize:
; Now that we have the drive geometry
; lets calculate the drive size
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
mov bh,cl ; Put the high 2-bits in BH
shr bh,6 ; Shift them into position, now BX contains the cylinder count
and cl,3fh ; Mask off cylinder bits from sector count
; CL now contains sectors per track and DH contains head count
movzx eax,dh ; Move the heads into EAX
movzx ebx,bx ; Move the cylinders into EBX
movzx ecx,cl ; Move the sectors per track into ECX
inc eax ; Make it one based because the bios returns it zero based
inc ebx ; Make the cylinder count one based also
mul ecx ; Multiply heads with the sectors per track, result in edx:eax
mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
; Now that we have the drive geometry
; lets calculate the drive size
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
mov bh,cl ; Put the high 2-bits in BH
shr bh,6 ; Shift them into position, now BX contains the cylinder count
and cl,3fh ; Mask off cylinder bits from sector count
; CL now contains sectors per track and DH contains head count
movzx eax,dh ; Move the heads into EAX
movzx ebx,bx ; Move the cylinders into EBX
movzx ecx,cl ; Move the sectors per track into ECX
inc eax ; Make it one based because the bios returns it zero based
inc ebx ; Make the cylinder count one based also
mul ecx ; Multiply heads with the sectors per track, result in edx:eax
mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
; We now have the total number of sectors as reported
; by the bios in eax, so store it in our variable
mov [BYTE bp-BiosCHSDriveSize],eax
; We now have the total number of sectors as reported
; by the bios in eax, so store it in our variable
mov [BYTE bp-BiosCHSDriveSize],eax
; Now we must find our way to the first sector of the root directory
xor ax,ax
xor cx,cx
mov al,[BYTE bp+NumberOfFats] ; Number of fats
mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
xor cx,cx
mov al,[BYTE bp+NumberOfFats] ; Number of fats
mul WORD [BYTE bp+SectorsPerFat] ; Times sectors per fat
add ax,WORD [BYTE bp+HiddenSectors]
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
adc dx,cx ; Add carry bit
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 si,WORD [BYTE bp+MaxRootEntries] ; Get number of root dir entries in SI
pusha ; Save 32-bit logical start sector of root dir
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
adc dx,cx ; Add carry bit
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 si,WORD [BYTE bp+MaxRootEntries] ; Get number of root dir entries in SI
pusha ; Save 32-bit logical start sector of root dir
; DX:AX now has the number of the starting sector of the root directory
; Now calculate the size of the root directory
xor dx,dx
mov ax,0020h ; Size of dir entry
mul si ; Times the number of entries
xor dx,dx
mov ax,0020h ; Size of dir entry
mul si ; Times the number of entries
mov bx,[BYTE bp+BytesPerSector]
add ax,bx
dec ax
div bx ; Divided by the size of a sector
; AX now has the number of root directory sectors
div bx ; Divided by the size of a sector
; 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
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
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
popa ; Restore root dir logical sector start to DX:AX
LoadRootDirSector:
mov bx,7e0h ; We will load the root directory sector
mov es,bx ; Right after the boot sector in memory
xor bx,bx ; We will load it to [0000:7e00h]
xor cx,cx ; Zero out CX
inc cx ; Now increment it to 1, we are reading one sector
xor di,di ; Zero out di
push es ; Save ES because it will get incremented by 20h
call ReadSectors ; Read the first sector of the root directory
pop es ; Restore ES (ES:DI = 07E0:0000)
mov bx,7e0h ; We will load the root directory sector
mov es,bx ; Right after the boot sector in memory
xor bx,bx ; We will load it to [0000:7e00h]
xor cx,cx ; Zero out CX
inc cx ; Now increment it to 1, we are reading one sector
xor di,di ; Zero out di
push es ; Save ES because it will get incremented by 20h
call ReadSectors ; Read the first sector of the root directory
pop es ; Restore ES (ES:DI = 07E0:0000)
SearchRootDirSector:
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
pusha ; Save all registers
mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
mov si,filename ; Put offset of filename string in DS:SI
repe cmpsb ; Compare this directory entry against 'FREELDR SYS'
popa ; Restore all the registers
jz FoundFreeLoader ; If we found it then jump
dec si ; SI holds MaxRootEntries, subtract one
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
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
jmp short LoadRootDirSector ; Didn't find FREELDR.SYS in this directory sector, try again
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
pusha ; Save all registers
mov cl,0xb ; Put 11 in cl (length of filename in directory entry)
mov si,filename ; Put offset of filename string in DS:SI
repe cmpsb ; Compare this directory entry against 'FREELDR SYS'
popa ; Restore all the registers
jz FoundFreeLoader ; If we found it then jump
dec si ; SI holds MaxRootEntries, subtract one
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
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
jmp short LoadRootDirSector ; Didn't find FREELDR.SYS in this directory sector, try again
FoundFreeLoader:
; We found freeldr.sys on the disk
; so we need to load the first 512
; bytes of it to 0000:8000
; We found freeldr.sys on the disk
; so we need to load the first 512
; bytes of it to 0000:8000
; ES:DI has dir entry (ES:DI == 07E0:XXXX)
mov ax,WORD [es:di+1ah] ; Get start cluster
push ax ; Save start cluster
push WORD 800h ; Put 800h on the stack and load it
pop es ; Into ES so that we load the cluster at 0000:8000
call ReadCluster ; Read the cluster
pop ax ; Restore start cluster of FreeLoader
mov ax,WORD [es:di+1ah] ; Get start cluster
push ax ; Save start cluster
push WORD 800h ; Put 800h on the stack and load it
pop es ; Into ES so that we load the cluster at 0000:8000
call ReadCluster ; Read the cluster
pop ax ; Restore start cluster of FreeLoader
; Save the addresses of needed functions so
; the helper code will know where to call them.
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-PutCharsOffset],PutChars ; Save the address of PutChars
; Save the addresses of needed functions so
; the helper code will know where to call them.
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-PutCharsOffset],PutChars ; Save the address of PutChars
; Now AX has start cluster of FreeLoader and we
; have loaded the helper code in the first 512 bytes
; of FreeLoader to 0000:8000. Now transfer control
; to the helper code. Skip the first three bytes
; because they contain a jump instruction to skip
; over the helper code in the FreeLoader image.
;jmp 0000:9003h
push 0 ; push segment (0x0000)
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)
push bx ; push offset
retf ; Transfer control to FreeLoader
; Now AX has start cluster of FreeLoader and we
; have loaded the helper code in the first 512 bytes
; of FreeLoader to 0000:8000. Now transfer control
; to the helper code. Skip the first three bytes
; because they contain a jump instruction to skip
; over the helper code in the FreeLoader image.
;jmp 0000:9003h
push 0 ; push segment (0x0000)
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)
push bx ; push offset
retf ; Transfer control to FreeLoader
@ -248,23 +248,23 @@ BadBoot:
mov si,msgDiskError ; Bad boot disk message
call PutChars ; Display it
jmp short Reboot
jmp short Reboot
; Reads cluster number in AX into [ES:0000]
ReadCluster:
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
dec ax ; Adjust start cluster by 2
dec ax ; Because the data area starts on cluster 2
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
dec ax ; Adjust start cluster by 2
dec ax ; Because the data area starts on cluster 2
xor ch,ch
mov cl,BYTE [BYTE bp+SectsPerCluster]
mul cx ; Times sectors per cluster
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
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
;call ReadSectors
;ret
mul cx ; Times sectors per cluster
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 FREELDR.SYS
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
;call ReadSectors
;ret
@ -272,71 +272,71 @@ ReadCluster:
; DX:AX has logical sector number to read
; CX has number of sectors to read
ReadSectors:
; We can't just check if the start sector is
; in the BIOS CHS range. We have to check if
; the start sector + length is in that range.
pusha
dec cx
add ax,cx
adc dx,byte 0
; We can't just check if the start sector is
; in the BIOS CHS range. We have to check if
; the start sector + length is in that range.
pusha
dec cx
add ax,cx
adc dx,byte 0
cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh] ; Check if they are reading a sector within CHS range
ja ReadSectorsLBA ; No - go to the LBA 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
jbe ReadSectorsCHS ; Yes - go to the old CHS routine
cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh] ; Check if they are reading a sector within CHS range
ja ReadSectorsLBA ; No - go to the LBA 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
jbe ReadSectorsCHS ; Yes - go to the old CHS routine
ReadSectorsLBA:
popa
popa
ReadSectorsLBALoop:
pusha ; Save logical sector number & sector count
pusha ; Save logical sector number & sector count
o32 push byte 0
push dx ; Put 64-bit logical
push ax ; block address on stack
push es ; Put transfer segment on stack
push bx ; Put transfer offset on stack
push byte 1 ; Set transfer count to 1 sector
push byte 0x10 ; Set size of packet to 10h
mov si,sp ; Setup disk address packet on stack
o32 push byte 0
push dx ; Put 64-bit logical
push ax ; block address on stack
push es ; Put transfer segment on stack
push bx ; Put transfer offset on stack
push byte 1 ; Set transfer count to 1 sector
push byte 0x10 ; Set size of packet to 10h
mov si,sp ; Setup disk address packet on stack
; We are so totally out of space here that I am forced to
; comment out this very beautifully written piece of code
; It would have been nice to have had this check...
;CheckInt13hExtensions: ; Now make sure this computer supports extended reads
; mov ah,0x41 ; AH = 41h
; mov bx,0x55aa ; BX = 55AAh
; mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
; int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
; jc PrintDiskError ; CF set on error (extensions not supported)
; cmp bx,0xaa55 ; BX = AA55h if installed
; jne PrintDiskError
; test cl,1 ; CX = API subset support bitmap
; jz PrintDiskError ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
;CheckInt13hExtensions: ; Now make sure this computer supports extended reads
; mov ah,0x41 ; AH = 41h
; mov bx,0x55aa ; BX = 55AAh
; mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
; int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
; jc PrintDiskError ; CF set on error (extensions not supported)
; cmp bx,0xaa55 ; BX = AA55h if installed
; jne PrintDiskError
; test cl,1 ; CX = API subset support bitmap
; 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
; So finish the extended read
mov dl,[BYTE bp+BootDrive] ; Drive number
mov ah,42h ; Int 13h, AH = 42h - Extended Read
int 13h ; Call BIOS
jc BadBoot ; If the read failed then abort
; Good, we're here so the computer supports LBA disk access
; So finish the extended read
mov dl,[BYTE bp+BootDrive] ; Drive number
mov ah,42h ; Int 13h, AH = 42h - Extended Read
int 13h ; Call BIOS
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
adc dx,byte 0
inc ax ; Increment Sector to Read
adc dx,byte 0
push bx
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
pop bx
loop ReadSectorsLBALoop ; Read next sector
loop ReadSectorsLBALoop ; Read next sector
ret
@ -346,7 +346,7 @@ ReadSectorsLBALoop:
; CX has number of sectors to read
; CarryFlag set on error
ReadSectorsCHS:
popa
popa
ReadSectorsCHSLoop:
pusha
xchg ax,cx
@ -367,8 +367,8 @@ ReadSectorsCHSLoop:
mov ax,0201h
int 13h ; DISK - READ SECTORS INTO MEMORY
; AL = number of sectors to read, CH = track, CL = sector
; DH = head, DL = drive, ES:BX -> buffer to fill
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
; DH = head, DL = drive, ES:BX -> buffer to fill
; Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
jc BadBoot
@ -391,16 +391,16 @@ NoCarryCHS:
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...
;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'
times 509-($-$$) db 0 ; Pad to 509 bytes
BootPartition:
db 0
db 0
BootSignature:
dw 0aa55h ; BootSector signature

View file

@ -3,7 +3,7 @@
* PROJECT: ReactOS Bootsector
* FILE: boot/freeldr/bootsect/fat32.S
* PURPOSE:
* PROGRAMMERS: ?
* PROGRAMMERS: Brian Palmer
*/
/* INCLUDES ******************************************************************/
@ -32,13 +32,13 @@ ReservedSectors:
NumberOfFats:
.byte 2
MaxRootEntries:
.word 0 // Always zero for FAT32 volumes
.word 0 // Always zero for FAT32 volumes
TotalSectors:
.word 0 // Always zero for FAT32 volumes
.word 0 // Always zero for FAT32 volumes
MediaDescriptor:
.byte HEX(0f8)
SectorsPerFat:
.word 0 // Always zero for FAT32 volumes
.word 0 // Always zero for FAT32 volumes
SectorsPerTrack:
.word 0
NumberOfHeads:
@ -82,33 +82,33 @@ main:
xor ax,ax // Setup segment registers
mov ds,ax // Make DS correct
mov es,ax // Make ES correct
mov ss,ax // Make SS correct
mov ss,ax // Make SS correct
mov bp, HEX(7c00)
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
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
mov byte ptr BP_REL(BootDrive), dl // Save the boot drive
CheckSectorsPerFat:
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
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
jnz CheckFailed // If it is non-zero then exit with an error
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
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
jnz CheckFailed // If it is non-zero then exit with an error
CheckFileSystemVersion:
cmp word ptr BP_REL(FSVersion), 0 // Check the file system version word
jna GetDriveParameters // It is zero, so continue
cmp word ptr BP_REL(FSVersion), 0 // Check the file system version word
jna GetDriveParameters // It is zero, so continue
CheckFailed:
jmp PrintFileSystemError // If it is not zero then exit with an error
jmp PrintFileSystemError // If it is not zero then exit with an error
GetDriveParameters:
mov ax, HEX(0800)
mov dl, byte ptr BP_REL(BootDrive) // Get boot drive in dl
int HEX(13) // Request drive parameters from the bios
jnc CalcDriveSize // If the call succeeded then calculate the drive size
mov dl, byte ptr BP_REL(BootDrive) // Get boot drive in dl
int HEX(13) // Request drive parameters from the bios
jnc CalcDriveSize // If the call succeeded then calculate the drive size
// If we get here then the call to the BIOS failed
// so just set CHS equal to the maximum addressable
@ -119,18 +119,18 @@ GetDriveParameters:
CalcDriveSize:
// Now that we have the drive geometry
// lets calculate the drive size
mov bl, ch // Put the low 8-bits of the cylinder count into BL
mov bh, cl // Put the high 2-bits in BH
shr bh, 6 // Shift them into position, now BX contains the cylinder count
and cl, HEX(3f) // Mask off cylinder bits from sector count
mov bl, ch // Put the low 8-bits of the cylinder count into BL
mov bh, cl // Put the high 2-bits in BH
shr bh, 6 // Shift them into position, now BX contains the cylinder count
and cl, HEX(3f) // Mask off cylinder bits from sector count
// CL now contains sectors per track and DH contains head count
movzx eax, dh // Move the heads into EAX
movzx ebx, bx // Move the cylinders into EBX
movzx ecx, cl // Move the sectors per track into ECX
inc eax // Make it one based because the bios returns it zero based
inc ebx // Make the cylinder count one based also
mul ecx // Multiply heads with the sectors per track, result in edx:eax
mul ebx // Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
movzx eax, dh // Move the heads into EAX
movzx ebx, bx // Move the cylinders into EBX
movzx ecx, cl // Move the sectors per track into ECX
inc eax // Make it one based because the bios returns it zero based
inc ebx // Make the cylinder count one based also
mul ecx // Multiply heads with the sectors per track, result in edx:eax
mul ebx // Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
// We now have the total number of sectors as reported
// by the bios in eax, so store it in our variable
@ -140,10 +140,10 @@ LoadExtraBootCode:
// First we have to load our extra boot code at
// sector 14 into memory at [0000:7e00h]
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
xor bx, bx
mov es, bx // Read sector to [0000:7e00h]
mov es, bx // Read sector to [0000:7e00h]
mov bx, HEX(7e00)
call ReadSectors
jmp StartSearch
@ -154,64 +154,64 @@ LoadExtraBootCode:
// CX has number of sectors to read
ReadSectors:
push es
cmp eax, dword ptr ds:[BiosCHSDriveSize] // Check if they are reading a sector outside CHS range
jae ReadSectorsLBA // Yes - go to the LBA routine
cmp eax, dword ptr ds:[BiosCHSDriveSize] // Check if they are reading a sector outside CHS range
jae ReadSectorsLBA // Yes - go to the LBA routine
// If at all possible we want to use LBA routines because
// They are optimized to read more than 1 sector per read
pushad // Save logical sector number & sector count
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 bx, HEX(55aa) // BX = 55AAh
mov dl, byte ptr BP_REL(BootDrive) // DL = drive (80h-FFh)
mov bx, HEX(55aa) // BX = 55AAh
mov dl, byte ptr BP_REL(BootDrive) // DL = drive (80h-FFh)
int HEX(13) // IBM/MS INT 13 Extensions - INSTALLATION CHECK
jc ReadSectorsCHS // CF set on error (extensions not supported)
cmp bx, HEX(0aa55) // BX = AA55h if installed
jc ReadSectorsCHS // CF set on error (extensions not supported)
cmp bx, HEX(0aa55) // BX = AA55h if installed
jne ReadSectorsCHS
test cl,1 // CX = API subset support bitmap
jz ReadSectorsCHS // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
test cl,1 // CX = API subset support bitmap
jz ReadSectorsCHS // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
popad // Restore sector count & logical sector number
popad // Restore sector count & logical sector number
ReadSectorsLBA:
pushad // Save logical sector number & sector count
pushad // Save logical sector number & sector count
cmp cx, 64 // Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
jbe ReadSectorsSetupDiskAddressPacket // If we are reading less than 65 sectors then just do the read
mov cx, 64 // Otherwise read only 64 sectors on this loop iteration
cmp cx, 64 // Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
jbe ReadSectorsSetupDiskAddressPacket // If we are reading less than 65 sectors then just do the read
mov cx, 64 // Otherwise read only 64 sectors on this loop iteration
ReadSectorsSetupDiskAddressPacket:
mov word ptr ds:[LBASectorsRead],cx
push 0
push 0
push eax // Put 64-bit logical block address on stack
push es // Put transfer segment on stack
push bx // Put transfer offset on stack
push cx // Set transfer count
push 16 // Set size of packet to 10h
mov si, sp // Setup disk address packet on stack
push es // Put transfer segment on stack
push bx // Put transfer offset on stack
push cx // Set transfer count
push 16 // Set size of packet to 10h
mov si, sp // Setup disk address packet on stack
mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
int HEX(13) // Call BIOS
jc PrintDiskError // If the read failed then abort
mov dl, byte ptr BP_REL(BootDrive) // Drive number
mov ah, HEX(42) // Int 13h, AH = 42h - Extended Read
int HEX(13) // Call BIOS
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
mov ebx, dword ptr ds:[LBASectorsRead]
add eax, ebx // Increment sector to read
add eax, ebx // Increment sector to read
shl ebx, 5
mov dx, es
add dx, bx // Setup read buffer for next sector
add dx, bx // Setup read buffer for next sector
mov es, dx
pop bx
sub cx, word ptr ds:[LBASectorsRead]
jnz ReadSectorsLBA // Read next sector
jnz ReadSectorsLBA // Read next sector
pop es
ret
@ -231,57 +231,57 @@ ReadSectorsCHSLoop:
xor edx, edx
movzx ecx, word ptr BP_REL(SectorsPerTrack)
div ecx // Divide logical by SectorsPerTrack
inc dl // Sectors numbering starts at 1 not 0
mov cl, dl // Sector in CL
inc dl // Sectors numbering starts at 1 not 0
mov cl, dl // Sector in CL
mov edx, eax
shr edx, 16
div word ptr BP_REL(NumberOfHeads) // Divide logical by number of heads
mov dh, dl // Head in DH
mov dl, byte ptr BP_REL(BootDrive) // Drive number in DL
mov ch, al // Cylinder in CX
ror ah, 1 // Low 8 bits of cylinder in CH, high 2 bits
ror ah, 1 // in CL shifted to bits 6 & 7
or cl, ah // Or with sector number
div word ptr BP_REL(NumberOfHeads) // Divide logical by number of heads
mov dh, dl // Head in DH
mov dl, byte ptr BP_REL(BootDrive) // Drive number in DL
mov ch, al // Cylinder in CX
ror ah, 1 // Low 8 bits of cylinder in CH, high 2 bits
ror ah, 1 // in CL shifted to bits 6 & 7
or cl, ah // Or with sector number
mov ax, HEX(0201)
int HEX(13) // DISK - READ SECTORS INTO MEMORY
// AL = number of sectors to read, CH = track, CL = sector
// DH = head, DL = drive, ES:BX -> buffer to fill
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
// DH = head, DL = drive, ES:BX -> buffer to fill
// Return: CF set on error, AH = status (see AH=01h), AL = number of sectors read
jc PrintDiskError // If the read failed then abort
jc PrintDiskError // If the read failed then abort
popad
inc eax // Increment Sector to Read
mov dx, es
add dx, 32 // Increment read buffer for next sector
add dx, 32 // Increment read buffer for next sector
mov es, dx
loop ReadSectorsCHSLoop // Read next sector
loop ReadSectorsCHSLoop // Read next sector
ret
// Displays a disk error message
// And reboots
PrintDiskError:
mov si, offset msgDiskError // Bad boot disk message
call PutChars // Display it
mov si, offset msgDiskError // Bad boot disk message
call PutChars // Display it
jmp Reboot
// Displays a file system error message
// And reboots
PrintFileSystemError:
mov si, offset msgFileSystemError // FreeLdr not found message
call PutChars // Display it
mov si, offset msgFileSystemError // FreeLdr not found message
call PutChars // Display it
Reboot:
mov si, offset msgAnyKey // Press any key message
call PutChars // Display it
mov si, offset msgAnyKey // Press any key message
call PutChars // Display it
xor ax, ax
int HEX(16) // Wait for a keypress
int HEX(19) // Reboot
int HEX(16) // Wait for a keypress
int HEX(19) // Reboot
PutChars:
lodsb
@ -311,7 +311,7 @@ BootPartition:
.byte 0
BootSignature:
.word HEX(0aa55) // BootSector signature
.word HEX(0aa55) // BootSector signature
// End of bootsector
//
@ -330,7 +330,7 @@ StartSearch:
// Now we must get the first cluster of the root directory
mov eax, dword ptr BP_REL(RootDirStartCluster)
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
ContinueSearch:
@ -339,16 +339,16 @@ ContinueSearch:
call ReadCluster // Read the cluster
// Now we have to find our way through the root directory to
// The OSLOADER.SYS file
// The FREELDR.SYS file
xor bx,bx
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 es, ax
xor di, di
mov si, offset filename
mov cx, 11
repe cmpsb // Compare filenames
repe cmpsb // Compare filenames
jz FoundFile // If same we found it
dec bx
jnz FindFile
@ -357,11 +357,11 @@ ContinueSearch:
FindFile:
mov ax, es // We didn't find it in the previous dir entry
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
mov si, offset filename
mov cx, 11
repe cmpsb // Compare filenames
repe cmpsb // Compare filenames
jz FoundFile // If same we found it
dec bx // Keep searching till we run out of dir entries
jnz FindFile // Last entry?
@ -377,51 +377,51 @@ FoundFile:
mov si, offset msgLoading // Loading message
call PutChars // Display it
xor di, di // ES:DI has dir entry
xor di, di // ES:DI has dir entry
xor dx, dx
mov ax, word ptr es:[di+20] // Get start cluster high word
mov ax, word ptr es:[di+20] // Get start cluster high word
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:
cmp eax, 2 // Check and see if the start cluster starts at cluster 2 or above
jnb CheckEndCluster // If so then continue
jmp PrintFileSystemError // If not exit with error
cmp eax, 2 // Check and see if the start cluster starts at cluster 2 or above
jnb CheckEndCluster // If so then continue
jmp PrintFileSystemError // If not exit with error
CheckEndCluster:
cmp eax, HEX(0ffffff8) // Check and see if the start cluster is and end of cluster chain indicator
jb InitializeLoadSegment // If not then continue
jmp PrintFileSystemError // If so exit with error
cmp eax, HEX(0ffffff8) // Check and see if the start cluster is and end of cluster chain indicator
jb InitializeLoadSegment // If not then continue
jmp PrintFileSystemError // If so exit with error
InitializeLoadSegment:
mov bx, FREELDR_BASE / 16
mov es, bx
LoadFile:
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
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
push eax
xor bx, bx // Load ROSLDR starting at 0000:8000h
xor bx, bx // Load ROSLDR starting at 0000:8000h
push es
call ReadCluster
pop es
xor bx, bx
mov bl, byte ptr BP_REL(SectsPerCluster)
shl bx, 5 // BX = BX * 512 / 16
mov ax, es // Increment the load address by
add ax, bx // The size of a cluster
shl bx, 5 // BX = BX * 512 / 16
mov ax, es // Increment the load address by
add ax, bx // The size of a cluster
mov es, ax
pop eax
push es
call GetFatEntry // Get the next entry
call GetFatEntry // Get the next entry
pop es
jmp LoadFile // Load the next cluster (if any)
jmp LoadFile // Load the next cluster (if any)
LoadFileDone:
mov dl, byte ptr BP_REL(BootDrive) // Load boot drive into DL
mov dh, byte ptr ds:[BootPartition] // Load boot partition into DH
mov dl, byte ptr BP_REL(BootDrive) // Load boot drive into DL
mov dh, byte ptr ds:[BootPartition] // Load boot partition into DH
/* Transfer execution to the bootloader */
ljmp16 0, FREELDR_BASE
@ -431,43 +431,43 @@ LoadFileDone:
// On return EAX has FAT entry for that cluster
GetFatEntry:
shl eax, 2 // EAX = EAX * 4 (since FAT32 entries are 4 bytes)
mov ecx, eax // Save this for later in ECX
shl eax, 2 // EAX = EAX * 4 (since FAT32 entries are 4 bytes)
mov ecx, eax // Save this for later in ECX
xor edx, edx
movzx ebx, word ptr BP_REL(BytesPerSector)
push ebx
div ebx // FAT Sector Number = EAX / BytesPerSector
div ebx // FAT Sector Number = EAX / BytesPerSector
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)
add eax, ebx // FAT Sector Number += HiddenSectors
add eax, ebx // FAT Sector Number += HiddenSectors
pop ebx
dec ebx
and ecx,ebx // FAT Offset Within Sector = ECX % BytesPerSector
// EAX holds logical FAT sector number
// ECX holds FAT entry offset
and ecx,ebx // FAT Offset Within Sector = ECX % BytesPerSector
// EAX holds logical FAT sector number
// ECX holds FAT entry offset
// Now we have to check the extended flags
// to see which FAT is the active one
// and use it, or if they are mirrored then
// no worries
movzx ebx, word 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
jz LoadFatSector // If fat is mirrored then skip fat calcs
cmp bl, byte ptr BP_REL(NumberOfFats) // Compare bl to number of fats
// Now we have to check the extended flags
// to see which FAT is the active one
// and use it, or if they are mirrored then
// no worries
movzx ebx, word 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
jz LoadFatSector // If fat is mirrored then skip fat calcs
cmp bl, byte ptr BP_REL(NumberOfFats) // Compare bl to number of fats
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:
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
mul ebx // Multiplied by the active FAT index we have in ebx
pop edx // Get logical FAT sector number
add eax, edx // Add the current FAT sector offset
push eax // Save logical FAT sector number
mov eax, 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
pop edx // Get logical FAT sector number
add eax, edx // Add the current FAT sector offset
LoadFatSector:
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
// EAX holds logical FAT sector number
@ -482,18 +482,18 @@ LoadFatSector:
LoadFatSectorAlreadyLoaded:
pop ecx
mov eax, dword ptr es:[ecx] // Get FAT entry
and eax, HEX(0fffffff) // Mask off reserved bits
mov eax, dword ptr es:[ecx] // Get FAT entry
and eax, HEX(0fffffff) // Mask off reserved bits
ret
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
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
// Reads cluster number in EAX into [ES:0000]
ReadCluster:
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors//
// StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
dec eax
dec eax
@ -508,7 +508,7 @@ ReadCluster:
add eax, ebx
add eax, dword ptr BP_REL(HiddenSectors)
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
movzx cx, byte ptr BP_REL(SectsPerCluster)
call ReadSectors
@ -517,10 +517,10 @@ ReadCluster:
// Displays a file not found error message
// And reboots
PrintFileNotFound:
mov si, offset msgFreeLdr // FreeLdr not found message
call PutChars // Display it
mov si, offset msgAnyKey // Press any key message
call PutChars // Display it
mov si, offset msgFreeLdr // FreeLdr not found message
call PutChars // Display it
mov si, offset msgAnyKey // Press any key message
call PutChars // Display it
jmp Reboot

View file

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

View file

@ -1,8 +1,8 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Bootsector
* FILE: boot/freeldr/bootsect/fatx.S
* PURPOSE: Combined FAT16 and FAT32 boot sector
* FILE: boot/freeldr/bootsect/faty.S
* PURPOSE: Combined FAT12, FAT16 and FAT32 boot sector
* PROGRAMMERS: Brian Palmer
* Timo Kreuzer
*/