2001-07-06 22:05:05 +00:00
|
|
|
; FAT32.ASM
|
2001-05-15 03:50:25 +00:00
|
|
|
; FAT32 Boot Sector
|
2002-04-16 06:11:08 +00:00
|
|
|
; Copyright (c) 1998, 2000, 2001, 2002 Brian Palmer
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2002-04-16 06:11:08 +00:00
|
|
|
org 7c00h
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
segment .text
|
|
|
|
|
|
|
|
bits 16
|
|
|
|
|
|
|
|
start:
|
|
|
|
jmp short main
|
|
|
|
nop
|
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
OEMName db 'FrLdr1.0'
|
2001-05-15 03:50:25 +00:00
|
|
|
BytesPerSector dw 512
|
2001-11-15 07:48:33 +00:00
|
|
|
SectsPerCluster db 0
|
2001-07-06 22:05:05 +00:00
|
|
|
ReservedSectors dw 32
|
2001-05-15 03:50:25 +00:00
|
|
|
NumberOfFats db 2
|
2001-07-06 22:05:05 +00:00
|
|
|
MaxRootEntries dw 0 ; Always zero for FAT32 volumes
|
|
|
|
TotalSectors dw 0 ; Always zero for FAT32 volumes
|
2001-05-15 03:50:25 +00:00
|
|
|
MediaDescriptor db 0f8h
|
2001-07-06 22:05:05 +00:00
|
|
|
SectorsPerFat dw 0 ; Always zero for FAT32 volumes
|
2001-11-15 07:48:33 +00:00
|
|
|
SectorsPerTrack dw 0
|
|
|
|
NumberOfHeads dw 0
|
2001-05-15 03:50:25 +00:00
|
|
|
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
|
|
|
|
; End FAT32 Inserted Info
|
|
|
|
BootDrive db 0
|
|
|
|
Reserved db 0
|
|
|
|
ExtendSig db 29h
|
|
|
|
SerialNumber dd 00000000h
|
2001-07-06 22:05:05 +00:00
|
|
|
VolumeLabel db 'NO NAME '
|
2001-05-15 03:50:25 +00:00
|
|
|
FileSystem db 'FAT32 '
|
|
|
|
|
|
|
|
main:
|
2002-04-16 06:11:08 +00:00
|
|
|
xor ax,ax ; Setup segment registers
|
2001-05-15 03:50:25 +00:00
|
|
|
mov ds,ax ; Make DS correct
|
|
|
|
mov es,ax ; Make ES correct
|
2001-11-15 07:48:33 +00:00
|
|
|
mov ss,ax ; Make SS correct
|
2002-04-16 06:11:08 +00:00
|
|
|
mov bp,7c00h
|
|
|
|
mov sp,7c00h ; Setup a stack
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
|
|
|
|
|
Changes in v1.7.4 (8/20/2002) (brianp)
- Boot sector code now reports to freeldr.sys the partition
that it was installed on. This is specified by a byte
value in the boot sector code. By default the boot partition
is set to zero which indicates the active (bootable)
partition, unless the installer sets the value to non-zero.
If FreeLoader is installed on a partition other than
the active (bootable) partition then the installer must
set this byte to that partition number. Otherwise
FreeLoader will not be able to find freeldr.ini.
- i386trap.S: Added debug macros BREAKPOINT(),
INSTRUCTION_BREAKPOINTX(), MEMORY_READWRITE_BREAKPOINTX(), &
MEMORY_WRITE_BREAKPOINTX().
- partition.c (DiskGetPartitionEntry): Add the relative offset
of the extended partition to the partitions start sector.
- ext2.c (Ext2ReadBlockPointerList, Ext2CopyIndirectBlockPointers,
Ext2CopyDoubleIndirectBlockPointers, Ext2CopyTripleIndirectBlockPointers):
Rewrote the block pointer functions so they actually work.
- ini_init.c (IniFileInitialize, IniOpenIniFile): Looks for freeldr.ini
on both the active (bootable) partition and the partition
passed in from the boot sector code.
- meminit.c (MmInitializeMemoryManager, MmFixupSystemMemoryMap,
MmGetEndAddressOfAnyMemory, MmGetAddressablePageCountIncludingHoles,
MmInitPageLookupTable): Fixed bug that would cause FreeLoader to
have an off-by-one error when accessing the last entry in the
page lookup table on systems with 4GB of memory (or memory mapped
at the end of the address space).
svn path=/trunk/; revision=3372
2002-08-21 03:32:49 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
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
|
|
|
|
CheckFileSystemVersion:
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
; If we get here then the call to the BIOS failed
|
|
|
|
; so just set CHS equal to the maximum addressable
|
|
|
|
; size
|
|
|
|
mov cx,0ffffh
|
|
|
|
mov dh,cl
|
|
|
|
|
|
|
|
CalcDriveSize:
|
|
|
|
; Now that we have the drive geometry
|
|
|
|
; lets calculate the drive size
|
|
|
|
mov bl,ch ; Put the low 8-bits of the cylinder count into BL
|
|
|
|
mov bh,cl ; Put the high 2-bits in BH
|
|
|
|
shr bh,6 ; Shift them into position, now BX contains the cylinder count
|
|
|
|
and cl,3fh ; Mask off cylinder bits from sector count
|
|
|
|
; CL now contains sectors per track and DH contains head count
|
|
|
|
movzx eax,dh ; Move the heads into EAX
|
|
|
|
movzx ebx,bx ; Move the cylinders into EBX
|
|
|
|
movzx ecx,cl ; Move the sectors per track into ECX
|
|
|
|
inc eax ; Make it one based because the bios returns it zero based
|
|
|
|
inc ebx ; Make the cylinder count one based also
|
|
|
|
mul ecx ; Multiply heads with the sectors per track, result in edx:eax
|
|
|
|
mul ebx ; Multiply the cylinders with (heads * sectors) [stored in edx:eax already]
|
|
|
|
|
|
|
|
; We now have the total number of sectors as reported
|
|
|
|
; by the bios in eax, so store it in our variable
|
|
|
|
mov [BiosCHSDriveSize],eax
|
|
|
|
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
LoadExtraBootCode:
|
2001-05-15 03:50:25 +00:00
|
|
|
; First we have to load our extra boot code at
|
2002-04-16 06:11:08 +00:00
|
|
|
; sector 14 into memory at [0000:7e00h]
|
2001-11-15 07:48:33 +00:00
|
|
|
mov eax,0eh
|
|
|
|
add eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors
|
2001-05-15 03:50:25 +00:00
|
|
|
mov cx,1
|
2002-04-16 06:11:08 +00:00
|
|
|
xor bx,bx
|
|
|
|
mov es,bx ; Read sector to [0000:7e00h]
|
|
|
|
mov bx,7e00h
|
2001-05-15 03:50:25 +00:00
|
|
|
call ReadSectors
|
2001-07-06 22:05:05 +00:00
|
|
|
jmp StartSearch
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; Reads logical sectors into [ES:BX]
|
2001-11-15 07:48:33 +00:00
|
|
|
; EAX has logical sector number to read
|
2001-05-15 03:50:25 +00:00
|
|
|
; CX has number of sectors to read
|
|
|
|
ReadSectors:
|
2002-06-11 05:41:45 +00:00
|
|
|
cmp eax,DWORD [BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
|
|
|
|
jae ReadSectorsLBA ; Yes - go to the LBA routine
|
|
|
|
; If at all possible we want to use LBA routines because
|
|
|
|
; They are optimized to read more than 1 sector per read
|
|
|
|
|
|
|
|
pushad ; Save logical sector number & sector count
|
|
|
|
|
|
|
|
CheckInt13hExtensions: ; Now check if this computer supports extended reads
|
|
|
|
mov ah,0x41 ; AH = 41h
|
|
|
|
mov bx,0x55aa ; BX = 55AAh
|
|
|
|
mov dl,[BYTE bp+BootDrive] ; DL = drive (80h-FFh)
|
|
|
|
int 13h ; IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
|
|
|
jc ReadSectorsCHS ; CF set on error (extensions not supported)
|
|
|
|
cmp bx,0xaa55 ; BX = AA55h if installed
|
|
|
|
jne ReadSectorsCHS
|
|
|
|
test cl,1 ; CX = API subset support bitmap
|
|
|
|
jz ReadSectorsCHS ; Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
|
|
|
|
|
|
|
popad ; Restore sector count & logical sector number
|
2001-11-15 07:48:33 +00:00
|
|
|
|
|
|
|
ReadSectorsLBA:
|
|
|
|
pushad ; Save logical sector number & sector count
|
|
|
|
|
2002-06-11 05:41:45 +00:00
|
|
|
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
|
2001-11-15 07:48:33 +00:00
|
|
|
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
|
2002-06-11 05:41:45 +00:00
|
|
|
push cx ; Set transfer count
|
2001-11-15 07:48:33 +00:00
|
|
|
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
|
|
|
|
|
2002-08-09 17:34:24 +00:00
|
|
|
add sp,byte 0x10 ; Remove disk address packet from stack
|
2001-11-15 07:48:33 +00:00
|
|
|
|
|
|
|
popad ; Restore sector count & logical sector number
|
|
|
|
|
2002-08-09 17:34:24 +00:00
|
|
|
push bx
|
|
|
|
mov ebx,DWORD [LBASectorsRead]
|
2002-06-11 05:41:45 +00:00
|
|
|
add eax,ebx ; Increment sector to read
|
2002-08-09 17:34:24 +00:00
|
|
|
shl ebx,5
|
2001-11-15 07:48:33 +00:00
|
|
|
mov dx,es
|
2002-06-11 05:41:45 +00:00
|
|
|
add dx,bx ; Setup read buffer for next sector
|
2001-11-15 07:48:33 +00:00
|
|
|
mov es,dx
|
2002-08-09 17:34:24 +00:00
|
|
|
pop bx
|
2001-11-15 07:48:33 +00:00
|
|
|
|
2002-06-11 05:41:45 +00:00
|
|
|
sub cx,[LBASectorsRead]
|
|
|
|
jnz ReadSectorsLBA ; Read next sector
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
LBASectorsRead:
|
2002-08-09 17:34:24 +00:00
|
|
|
dd 0
|
2001-11-15 07:48:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
; Reads logical sectors into [ES:BX]
|
|
|
|
; EAX has logical sector number to read
|
|
|
|
; CX has number of sectors to read
|
|
|
|
ReadSectorsCHS:
|
2002-06-11 05:41:45 +00:00
|
|
|
popad ; Get logical sector number & sector count off stack
|
|
|
|
|
|
|
|
ReadSectorsCHSLoop:
|
2001-11-15 07:48:33 +00:00
|
|
|
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
|
|
|
|
mov ax,0201h
|
|
|
|
int 13h ; DISK - READ SECTORS INTO MEMORY
|
2001-05-15 03:50:25 +00:00
|
|
|
; 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
|
2001-07-06 22:05:05 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
jc PrintDiskError ; If the read failed then abort
|
2001-07-06 22:05:05 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
popad
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
inc eax ; Increment Sector to Read
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
mov dx,es
|
|
|
|
add dx,byte 20h ; Increment read buffer for next sector
|
|
|
|
mov es,dx
|
|
|
|
|
2002-06-11 05:41:45 +00:00
|
|
|
loop ReadSectorsCHSLoop ; Read next sector
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
ret
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
; Displays a disk error message
|
2001-05-15 03:50:25 +00:00
|
|
|
; And reboots
|
2001-11-15 07:48:33 +00:00
|
|
|
PrintDiskError:
|
|
|
|
mov si,msgDiskError ; Bad boot disk message
|
|
|
|
call PutChars ; Display it
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
jmp Reboot
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
; Displays a file system error message
|
2001-05-15 03:50:25 +00:00
|
|
|
; And reboots
|
2001-11-15 07:48:33 +00:00
|
|
|
PrintFileSystemError:
|
|
|
|
mov si,msgFileSystemError ; FreeLdr not found message
|
|
|
|
call PutChars ; Display it
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
Reboot:
|
Changes in v1.7.4 (8/20/2002) (brianp)
- Boot sector code now reports to freeldr.sys the partition
that it was installed on. This is specified by a byte
value in the boot sector code. By default the boot partition
is set to zero which indicates the active (bootable)
partition, unless the installer sets the value to non-zero.
If FreeLoader is installed on a partition other than
the active (bootable) partition then the installer must
set this byte to that partition number. Otherwise
FreeLoader will not be able to find freeldr.ini.
- i386trap.S: Added debug macros BREAKPOINT(),
INSTRUCTION_BREAKPOINTX(), MEMORY_READWRITE_BREAKPOINTX(), &
MEMORY_WRITE_BREAKPOINTX().
- partition.c (DiskGetPartitionEntry): Add the relative offset
of the extended partition to the partitions start sector.
- ext2.c (Ext2ReadBlockPointerList, Ext2CopyIndirectBlockPointers,
Ext2CopyDoubleIndirectBlockPointers, Ext2CopyTripleIndirectBlockPointers):
Rewrote the block pointer functions so they actually work.
- ini_init.c (IniFileInitialize, IniOpenIniFile): Looks for freeldr.ini
on both the active (bootable) partition and the partition
passed in from the boot sector code.
- meminit.c (MmInitializeMemoryManager, MmFixupSystemMemoryMap,
MmGetEndAddressOfAnyMemory, MmGetAddressablePageCountIncludingHoles,
MmInitPageLookupTable): Fixed bug that would cause FreeLoader to
have an off-by-one error when accessing the last entry in the
page lookup table on systems with 4GB of memory (or memory mapped
at the end of the address space).
svn path=/trunk/; revision=3372
2002-08-21 03:32:49 +00:00
|
|
|
mov si,msgAnyKey ; Press any key message
|
|
|
|
call PutChars ; Display it
|
2001-05-15 03:50:25 +00:00
|
|
|
xor ax,ax
|
2001-11-15 07:48:33 +00:00
|
|
|
int 16h ; Wait for a keypress
|
|
|
|
int 19h ; Reboot
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
PutChars:
|
|
|
|
lodsb
|
|
|
|
or al,al
|
|
|
|
jz short Done
|
|
|
|
mov ah,0eh
|
|
|
|
mov bx,07h
|
|
|
|
int 10h
|
|
|
|
jmp short PutChars
|
|
|
|
Done:
|
|
|
|
retn
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
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
|
2001-05-15 03:50:25 +00:00
|
|
|
|
2002-11-24 19:10:06 +00:00
|
|
|
times 509-($-$$) db 0 ; Pad to 509 bytes
|
Changes in v1.7.4 (8/20/2002) (brianp)
- Boot sector code now reports to freeldr.sys the partition
that it was installed on. This is specified by a byte
value in the boot sector code. By default the boot partition
is set to zero which indicates the active (bootable)
partition, unless the installer sets the value to non-zero.
If FreeLoader is installed on a partition other than
the active (bootable) partition then the installer must
set this byte to that partition number. Otherwise
FreeLoader will not be able to find freeldr.ini.
- i386trap.S: Added debug macros BREAKPOINT(),
INSTRUCTION_BREAKPOINTX(), MEMORY_READWRITE_BREAKPOINTX(), &
MEMORY_WRITE_BREAKPOINTX().
- partition.c (DiskGetPartitionEntry): Add the relative offset
of the extended partition to the partitions start sector.
- ext2.c (Ext2ReadBlockPointerList, Ext2CopyIndirectBlockPointers,
Ext2CopyDoubleIndirectBlockPointers, Ext2CopyTripleIndirectBlockPointers):
Rewrote the block pointer functions so they actually work.
- ini_init.c (IniFileInitialize, IniOpenIniFile): Looks for freeldr.ini
on both the active (bootable) partition and the partition
passed in from the boot sector code.
- meminit.c (MmInitializeMemoryManager, MmFixupSystemMemoryMap,
MmGetEndAddressOfAnyMemory, MmGetAddressablePageCountIncludingHoles,
MmInitPageLookupTable): Fixed bug that would cause FreeLoader to
have an off-by-one error when accessing the last entry in the
page lookup table on systems with 4GB of memory (or memory mapped
at the end of the address space).
svn path=/trunk/; revision=3372
2002-08-21 03:32:49 +00:00
|
|
|
|
|
|
|
BootPartition:
|
|
|
|
db 0
|
|
|
|
|
|
|
|
BootSignature:
|
2001-05-15 03:50:25 +00:00
|
|
|
dw 0aa55h ; BootSector signature
|
|
|
|
|
|
|
|
|
|
|
|
; End of bootsector
|
|
|
|
;
|
|
|
|
; Now starts the extra boot code that we will store
|
|
|
|
; at sector 14 on a FAT32 volume
|
|
|
|
;
|
|
|
|
; To remain multi-boot compatible with other operating
|
|
|
|
; systems we must not overwrite anything other than
|
|
|
|
; the bootsector which means we will have to use
|
|
|
|
; a different sector like 14 to store our extra boot code
|
|
|
|
|
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
|
|
|
|
StartSearch:
|
|
|
|
; Now we must get the first cluster of the root directory
|
2001-11-15 07:48:33 +00:00
|
|
|
mov eax,DWORD [BYTE bp+RootDirStartCluster]
|
2001-07-06 22:05:05 +00:00
|
|
|
cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
|
2001-11-15 07:48:33 +00:00
|
|
|
jb ContinueSearch ; If not continue, if so then we didn't find freeldr.sys
|
|
|
|
jmp PrintFileNotFound
|
2001-07-06 22:05:05 +00:00
|
|
|
ContinueSearch:
|
2002-06-06 05:58:37 +00:00
|
|
|
mov bx,2000h
|
|
|
|
mov es,bx ; Read cluster to [2000:0000h]
|
2001-07-06 22:05:05 +00:00
|
|
|
call ReadCluster ; Read the cluster
|
|
|
|
|
|
|
|
|
|
|
|
; Now we have to find our way through the root directory to
|
|
|
|
; The OSLOADER.SYS file
|
|
|
|
xor bx,bx
|
2001-11-15 07:48:33 +00:00
|
|
|
mov bl,[BYTE bp+SectsPerCluster]
|
2001-07-06 22:05:05 +00:00
|
|
|
shl bx,4 ; BX = BX * 512 / 32
|
2002-06-06 05:58:37 +00:00
|
|
|
mov ax,2000h ; We loaded at 2000:0000
|
2001-07-06 22:05:05 +00:00
|
|
|
mov es,ax
|
|
|
|
xor di,di
|
|
|
|
mov si,filename
|
|
|
|
mov cx,11
|
|
|
|
rep cmpsb ; Compare filenames
|
|
|
|
jz FoundFile ; If same we found it
|
|
|
|
dec bx
|
|
|
|
jnz FindFile
|
2001-11-15 07:48:33 +00:00
|
|
|
jmp PrintFileNotFound
|
2001-07-06 22:05:05 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
xor di,di
|
|
|
|
mov si,filename
|
|
|
|
mov cx,11
|
|
|
|
rep cmpsb ; Compare filenames
|
|
|
|
jz FoundFile ; If same we found it
|
|
|
|
dec bx ; Keep searching till we run out of dir entries
|
|
|
|
jnz FindFile ; Last entry?
|
|
|
|
|
|
|
|
; Get the next root dir cluster and try again until we run out of clusters
|
2001-11-15 07:48:33 +00:00
|
|
|
mov eax,DWORD [BYTE bp+RootDirStartCluster]
|
2001-07-06 22:05:05 +00:00
|
|
|
call GetFatEntry
|
2001-11-15 07:48:33 +00:00
|
|
|
mov [BYTE bp+RootDirStartCluster],eax
|
2001-07-06 22:05:05 +00:00
|
|
|
jmp StartSearch
|
|
|
|
|
|
|
|
FoundFile:
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
; Display "Loading FreeLoader..." message
|
|
|
|
mov si,msgLoading ; Loading message
|
|
|
|
call PutChars ; Display it
|
|
|
|
|
|
|
|
xor di,di ; ES:DI has dir entry
|
2001-07-06 22:05:05 +00:00
|
|
|
xor dx,dx
|
|
|
|
mov ax,WORD [es:di+14h] ; Get start cluster high word
|
|
|
|
shl eax,16
|
|
|
|
mov ax,WORD [es:di+1ah] ; Get start cluster low word
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
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
|
|
|
|
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
|
|
|
|
|
|
|
|
InitializeLoadSegment:
|
2002-04-16 06:11:08 +00:00
|
|
|
mov bx,800h
|
2001-07-06 22:05:05 +00:00
|
|
|
mov es,bx
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
LoadFile:
|
2001-07-06 22:05:05 +00:00
|
|
|
cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
|
2001-11-15 07:48:33 +00:00
|
|
|
jae LoadFileDone ; If so continue, if not then read the next one
|
2001-07-06 22:05:05 +00:00
|
|
|
push eax
|
2002-04-16 06:11:08 +00:00
|
|
|
xor bx,bx ; Load ROSLDR starting at 0000:8000h
|
2001-07-06 22:05:05 +00:00
|
|
|
push es
|
|
|
|
call ReadCluster
|
|
|
|
pop es
|
|
|
|
|
|
|
|
xor bx,bx
|
2001-11-15 07:48:33 +00:00
|
|
|
mov bl,[BYTE bp+SectsPerCluster]
|
2001-07-06 22:05:05 +00:00
|
|
|
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
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
jmp LoadFile ; Load the next cluster (if any)
|
2001-07-06 22:05:05 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
LoadFileDone:
|
Changes in v1.7.4 (8/20/2002) (brianp)
- Boot sector code now reports to freeldr.sys the partition
that it was installed on. This is specified by a byte
value in the boot sector code. By default the boot partition
is set to zero which indicates the active (bootable)
partition, unless the installer sets the value to non-zero.
If FreeLoader is installed on a partition other than
the active (bootable) partition then the installer must
set this byte to that partition number. Otherwise
FreeLoader will not be able to find freeldr.ini.
- i386trap.S: Added debug macros BREAKPOINT(),
INSTRUCTION_BREAKPOINTX(), MEMORY_READWRITE_BREAKPOINTX(), &
MEMORY_WRITE_BREAKPOINTX().
- partition.c (DiskGetPartitionEntry): Add the relative offset
of the extended partition to the partitions start sector.
- ext2.c (Ext2ReadBlockPointerList, Ext2CopyIndirectBlockPointers,
Ext2CopyDoubleIndirectBlockPointers, Ext2CopyTripleIndirectBlockPointers):
Rewrote the block pointer functions so they actually work.
- ini_init.c (IniFileInitialize, IniOpenIniFile): Looks for freeldr.ini
on both the active (bootable) partition and the partition
passed in from the boot sector code.
- meminit.c (MmInitializeMemoryManager, MmFixupSystemMemoryMap,
MmGetEndAddressOfAnyMemory, MmGetAddressablePageCountIncludingHoles,
MmInitPageLookupTable): Fixed bug that would cause FreeLoader to
have an off-by-one error when accessing the last entry in the
page lookup table on systems with 4GB of memory (or memory mapped
at the end of the address space).
svn path=/trunk/; revision=3372
2002-08-21 03:32:49 +00:00
|
|
|
mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
|
|
|
|
mov dh,[BootPartition] ; Load boot partition into DH
|
2001-07-06 22:05:05 +00:00
|
|
|
|
[FREELDR]
Convert freeldr and setupldr to PE format.
Previously freeldr was a raw binary file, which made handling by the bootsector very easy, but it disqualified it from proper debugging with gdb using symbols. This is possible with having unstripped PE files.
As we don't have any space to do proper PE loading from the bootsector (I already had to trim some strings to get enough space for the new jump code), we need to make sure, that the PE file doesn't contain a .bss section, which is achieved by a linker script. The next thing is to make sure, we don't have any symbols in the output file, because they would make freeldr too big to be loaded into memory and they are useless anyway. On the other hand we like to keep the symbols in the .nostrip.sys files if requested, as this is the primary purpose. This is in theory not a problem, as we could simply strip the file at the end, but binutils throw a monkey wrench in our plans: both strip and objcopy disrespect the file alignment and create unaligned sections, that don't naturally match their VAs. This is solved by hacking rbuild to do invoke ld 2 times, one time without and one time with the symbols (if requested).
Now the bootsectors also got some changes: instead of jumping to the loading address (0x8000) they get the address of the entry point from the image optional header. This is slightly simplified, by assuming the NtHeader begins at offset 0xE0. This finally allows source level debugging of freeldr with gdb.
svn path=/trunk/; revision=48124
2010-07-19 23:18:31 +00:00
|
|
|
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
|
2001-07-06 22:05:05 +00:00
|
|
|
|
2001-05-15 03:50:25 +00:00
|
|
|
; 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:
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
|
|
|
|
mov ecx,eax ; Save this for later in ECX
|
2001-05-15 03:50:25 +00:00
|
|
|
xor edx,edx
|
2001-11-15 07:48:33 +00:00
|
|
|
movzx ebx,WORD [BYTE bp+BytesPerSector]
|
2001-05-15 03:50:25 +00:00
|
|
|
push ebx
|
2001-11-15 07:48:33 +00:00
|
|
|
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
|
2001-05-15 03:50:25 +00:00
|
|
|
pop ebx
|
|
|
|
dec ebx
|
2001-11-15 07:48:33 +00:00
|
|
|
and ecx,ebx ; FAT Offset Within Sector = ECX % BytesPerSector
|
|
|
|
; EAX holds logical FAT sector number
|
|
|
|
; ECX holds FAT entry offset
|
|
|
|
|
|
|
|
; Now we have to check the extended flags
|
|
|
|
; to see which FAT is the active one
|
|
|
|
; and use it, or if they are mirrored then
|
|
|
|
; no worries
|
|
|
|
movzx ebx,WORD [BYTE bp+ExtendedFlags] ; Get extended flags and put into ebx
|
|
|
|
and bx,0x0f ; Mask off upper 8 bits, now we have active fat in bl
|
|
|
|
jz LoadFatSector ; If fat is mirrored then skip fat calcs
|
|
|
|
cmp bl,[BYTE bp+NumberOfFats] ; Compare bl to number of fats
|
|
|
|
jb GetActiveFatOffset
|
|
|
|
jmp PrintFileSystemError ; If bl is bigger than numfats exit with error
|
|
|
|
GetActiveFatOffset:
|
|
|
|
push eax ; Save logical FAT sector number
|
|
|
|
mov eax,[BYTE bp+SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
|
|
|
|
mul ebx ; Multiplied by the active FAT index we have in ebx
|
|
|
|
pop edx ; Get logical FAT sector number
|
|
|
|
add eax,edx ; Add the current FAT sector offset
|
|
|
|
|
|
|
|
LoadFatSector:
|
2001-05-15 03:50:25 +00:00
|
|
|
push ecx
|
2001-11-15 07:48:33 +00:00
|
|
|
; EAX holds logical FAT sector number
|
2002-06-11 16:58:31 +00:00
|
|
|
; Check if we have already loaded it
|
|
|
|
cmp eax,DWORD [FatSectorInCache]
|
|
|
|
je LoadFatSectorAlreadyLoaded
|
|
|
|
|
|
|
|
mov DWORD [FatSectorInCache],eax
|
2001-05-15 03:50:25 +00:00
|
|
|
mov bx,7000h
|
|
|
|
mov es,bx
|
2001-11-15 07:48:33 +00:00
|
|
|
xor bx,bx ; We will load it to [7000:0000h]
|
2001-05-15 03:50:25 +00:00
|
|
|
mov cx,1
|
|
|
|
call ReadSectors
|
2002-06-11 16:58:31 +00:00
|
|
|
|
|
|
|
LoadFatSectorAlreadyLoaded:
|
2001-05-15 03:50:25 +00:00
|
|
|
mov bx,7000h
|
|
|
|
mov es,bx
|
|
|
|
pop ecx
|
2001-11-15 07:48:33 +00:00
|
|
|
mov eax,DWORD [es:ecx] ; Get FAT entry
|
|
|
|
and eax,0fffffffh ; Mask off reserved bits
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
ret
|
|
|
|
|
2002-06-11 16:58:31 +00:00
|
|
|
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
|
|
|
|
|
2001-05-15 03:50:25 +00:00
|
|
|
|
|
|
|
; Reads cluster number in EAX into [ES:0000]
|
|
|
|
ReadCluster:
|
|
|
|
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
|
|
|
|
|
|
|
|
dec eax
|
|
|
|
dec eax
|
|
|
|
xor edx,edx
|
2001-11-15 07:48:33 +00:00
|
|
|
movzx ebx,BYTE [BYTE bp+SectsPerCluster]
|
2001-05-15 03:50:25 +00:00
|
|
|
mul ebx
|
|
|
|
push eax
|
|
|
|
xor edx,edx
|
2001-11-15 07:48:33 +00:00
|
|
|
movzx eax,BYTE [BYTE bp+NumberOfFats]
|
|
|
|
mul DWORD [BYTE bp+SectorsPerFatBig]
|
|
|
|
movzx ebx,WORD [BYTE bp+ReservedSectors]
|
2001-05-15 03:50:25 +00:00
|
|
|
add eax,ebx
|
2001-11-15 07:48:33 +00:00
|
|
|
add eax,DWORD [BYTE bp+HiddenSectors]
|
2001-05-15 03:50:25 +00:00
|
|
|
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
|
2001-11-15 07:48:33 +00:00
|
|
|
movzx cx,BYTE [BYTE bp+SectsPerCluster]
|
2001-05-15 03:50:25 +00:00
|
|
|
call ReadSectors
|
|
|
|
ret
|
|
|
|
|
2001-07-06 22:05:05 +00:00
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
; Displays a file not found error message
|
|
|
|
; And reboots
|
|
|
|
PrintFileNotFound:
|
|
|
|
mov si,msgFreeLdr ; FreeLdr not found message
|
|
|
|
call PutChars ; Display it
|
|
|
|
mov si,msgAnyKey ; Press any key message
|
|
|
|
call PutChars ; Display it
|
|
|
|
|
|
|
|
jmp Reboot
|
|
|
|
|
Changes in v1.7.4 (8/20/2002) (brianp)
- Boot sector code now reports to freeldr.sys the partition
that it was installed on. This is specified by a byte
value in the boot sector code. By default the boot partition
is set to zero which indicates the active (bootable)
partition, unless the installer sets the value to non-zero.
If FreeLoader is installed on a partition other than
the active (bootable) partition then the installer must
set this byte to that partition number. Otherwise
FreeLoader will not be able to find freeldr.ini.
- i386trap.S: Added debug macros BREAKPOINT(),
INSTRUCTION_BREAKPOINTX(), MEMORY_READWRITE_BREAKPOINTX(), &
MEMORY_WRITE_BREAKPOINTX().
- partition.c (DiskGetPartitionEntry): Add the relative offset
of the extended partition to the partitions start sector.
- ext2.c (Ext2ReadBlockPointerList, Ext2CopyIndirectBlockPointers,
Ext2CopyDoubleIndirectBlockPointers, Ext2CopyTripleIndirectBlockPointers):
Rewrote the block pointer functions so they actually work.
- ini_init.c (IniFileInitialize, IniOpenIniFile): Looks for freeldr.ini
on both the active (bootable) partition and the partition
passed in from the boot sector code.
- meminit.c (MmInitializeMemoryManager, MmFixupSystemMemoryMap,
MmGetEndAddressOfAnyMemory, MmGetAddressablePageCountIncludingHoles,
MmInitPageLookupTable): Fixed bug that would cause FreeLoader to
have an off-by-one error when accessing the last entry in the
page lookup table on systems with 4GB of memory (or memory mapped
at the end of the address space).
svn path=/trunk/; revision=3372
2002-08-21 03:32:49 +00:00
|
|
|
msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
|
2001-11-15 07:48:33 +00:00
|
|
|
filename db 'FREELDR SYS'
|
2001-07-06 22:05:05 +00:00
|
|
|
msgLoading db 'Loading FreeLoader...',0dh,0ah,0
|
|
|
|
|
2001-11-15 07:48:33 +00:00
|
|
|
|
|
|
|
times 1022-($-$$) db 0 ; Pad to 1022 bytes
|
|
|
|
|
2001-05-15 03:50:25 +00:00
|
|
|
dw 0aa55h ; BootSector signature
|