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
This commit is contained in:
Brian Palmer 2002-08-21 03:32:49 +00:00
parent d8bd5ccb4a
commit 367cfa7085
21 changed files with 633 additions and 236 deletions

View file

@ -2,6 +2,16 @@
; EXT2 Boot Sector
; Copyright (c) 2002 Brian Palmer
; [bp-0x04] Here we will store the number of sectors per track
; [bp-0x08] Here we will store the number of heads
; [bp-0x0c] Here we will store the size of the disk as the BIOS reports in CHS form
; [bp-0x10] Here we will store the number of LBA sectors read
SECTORS_PER_TRACK equ 0x04
NUMBER_OF_HEADS equ 0x08
BIOS_CHS_DRIVE_SIZE equ 0x0C
LBA_SECTORS_READ equ 0x10
EXT2_ROOT_INO equ 2
EXT2_S_IFMT equ 0f0h
@ -19,10 +29,11 @@ start:
nop
BootDrive db 0x80
SectorsPerTrack dw 63
NumberOfHeads dw 16
BiosCHSDriveSize dd (1024 * 1024 * 63)
LBASectorsRead dd 0
BootPartition db 0
;SectorsPerTrack db 63 ; Moved to [bp-SECTORS_PER_TRACK]
;NumberOfHeads dw 16 ; Moved to [bp-NUMBER_OF_HEADS]
;BiosCHSDriveSize dd (1024 * 1024 * 63) ; Moved to [bp-BIOS_CHS_DRIVE_SIZE]
;LBASectorsRead dd 0 ; Moved to [bp-LBA_SECTORS_READ]
Ext2VolumeStartSector dd 263088 ; Start sector of the ext2 volume
Ext2BlockSize dd 2 ; Block size in sectors
@ -48,7 +59,7 @@ main:
mov es,ax ; Make ES correct
mov ss,ax ; Make SS correct
mov bp,7c00h
mov sp,7c00h ; Setup a stack
mov sp,7b00h ; Setup a stack
GetDriveParameters:
@ -66,29 +77,33 @@ 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,3fh ; 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,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]
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
mov [BYTE bp-NUMBER_OF_HEADS],eax ; Save number of heads
mov [BYTE bp-SECTORS_PER_TRACK],ecx ; Save number of sectors per track
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
mov [BYTE bp-BIOS_CHS_DRIVE_SIZE],eax
LoadExtraBootCode:
; First we have to load our extra boot code at
; sector 1 into memory at [0000:7e00h]
mov eax,01h
mov cx,1
;mov eax,01h
xor eax,eax
inc eax ; Read logical sector 1, EAX now = 1
mov cx,1 ; Read one sector
mov bx,7e00h ; Read sector to [0000:7e00h]
call ReadSectors
@ -177,7 +192,7 @@ Ext2ReadInode:
; CX has number of sectors to read
ReadSectors:
add eax,DWORD [BYTE bp+Ext2VolumeStartSector] ; Add the start of the volume
cmp eax,DWORD [BYTE bp+BiosCHSDriveSize] ; Check if they are reading a sector outside CHS range
cmp eax,DWORD [BYTE bp-BIOS_CHS_DRIVE_SIZE] ; 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
@ -200,12 +215,13 @@ CheckInt13hExtensions: ; Now check if this computer supports extended read
ReadSectorsLBA:
pushad ; Save logical sector number & sector count
cmp cx,64 ; Since the LBA calls only support 0x7F sectors at a time we will limit ourselves to 64
cmp cx,byte 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 [BYTE bp+LBASectorsRead],cx
mov [BYTE bp-LBA_SECTORS_READ],cx
mov WORD [BYTE bp-LBA_SECTORS_READ+2],0
o32 push byte 0
push eax ; Put 64-bit logical block address on stack
push es ; Put transfer segment on stack
@ -225,7 +241,7 @@ ReadSectorsSetupDiskAddressPacket:
popad ; Restore sector count & logical sector number
push bx
mov ebx,DWORD [BYTE bp+LBASectorsRead]
mov ebx,DWORD [BYTE bp-LBA_SECTORS_READ]
add eax,ebx ; Increment sector to read
shl ebx,5
mov dx,es
@ -233,7 +249,7 @@ ReadSectorsSetupDiskAddressPacket:
mov es,dx
pop bx
sub cx,[BYTE bp+LBASectorsRead]
sub cx,[BYTE bp-LBA_SECTORS_READ]
jnz ReadSectorsLBA ; Read next sector
ret
@ -248,13 +264,13 @@ ReadSectorsCHS:
ReadSectorsCHSLoop:
pushad
xor edx,edx
movzx ecx,WORD [BYTE bp+SectorsPerTrack]
mov ecx,DWORD [BYTE bp-SECTORS_PER_TRACK]
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
div WORD [BYTE bp-NUMBER_OF_HEADS] ; 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
@ -410,6 +426,7 @@ LoadFreeLoader:
call Ext2ReadEntireFile ; Read freeldr.sys to 0000:8000
mov dl,[BYTE bp+BootDrive]
mov dh,[BYTE bp+BootPartition]
push byte 0 ; We loaded at 0000:8000
push WORD 8000h ; We will do a far return to 0000:8000h
retf ; Transfer control to FreeLoader
@ -437,7 +454,7 @@ Ext2ReadEntireFile:
; We will do this by rounding the
; file size up to the next block
; size and then dividing by the block size
mov eax,DWORD [bp+Ext2BlockSizeInBytes] ; Get the block size in bytes
mov eax,DWORD [BYTE bp+Ext2BlockSizeInBytes] ; Get the block size in bytes
push eax
dec eax ; Ext2BlockSizeInBytes -= 1
add eax,DWORD [es:di+4] ; Add the file size
@ -447,7 +464,7 @@ Ext2ReadEntireFile:
push eax
; Make sure the file size isn't zero
cmp eax,0
cmp eax,byte 0
jnz Ext2ReadEntireFile2
jmp PrintFileSizeError
@ -480,14 +497,14 @@ Ext2ReadEntireFile2:
; Check to see if we actually have
; blocks left to read
cmp eax,0
cmp eax,byte 0
jz Ext2ReadEntireFileDone
; Now we have read all the direct blocks in
; the inode. So now we have to read the indirect
; block and read all it's direct blocks
push eax ; Save the total block count
mov eax,DWORD [bp+Ext2InodeIndirectPointer] ; Get the indirect block pointer
mov eax,DWORD [BYTE bp+Ext2InodeIndirectPointer] ; Get the indirect block pointer
push WORD 7000h
pop es
xor bx,bx ; Set the load address to 7000:0000
@ -496,12 +513,12 @@ Ext2ReadEntireFile2:
; Now we have all the block pointers from the
; indirect block in the right location so read them in
pop eax ; Restore the total block count
mov ecx,DWORD [bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
mov ecx,DWORD [BYTE bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
call Ext2ReadDirectBlockList
; Check to see if we actually have
; blocks left to read
cmp eax,0
cmp eax,byte 0
jz Ext2ReadEntireFileDone
; Now we have read all the direct blocks from
@ -509,8 +526,8 @@ Ext2ReadEntireFile2:
; we have to read the double indirect block
; and read all it's indirect blocks
; (whew, it's a good thing I don't support triple indirect blocks)
mov [bp+Ext2BlocksLeftToRead],eax ; Save the total block count
mov eax,DWORD [bp+Ext2InodeDoubleIndirectPointer] ; Get the double indirect block pointer
mov [BYTE bp+Ext2BlocksLeftToRead],eax ; Save the total block count
mov eax,DWORD [BYTE bp+Ext2InodeDoubleIndirectPointer] ; Get the double indirect block pointer
push WORD 7800h
pop es
push es ; Save an extra copy of this value on the stack
@ -522,7 +539,7 @@ Ext2ReadEntireFile2:
Ext2ReadIndirectBlock:
mov eax,DWORD [es:di] ; Get indirect block pointer
add di,4 ; Update DI for next array index
add di,BYTE 4 ; Update DI for next array index
push es
push di
@ -533,16 +550,16 @@ Ext2ReadIndirectBlock:
; Now we have all the block pointers from the
; indirect block in the right location so read them in
mov eax,DWORD [bp+Ext2BlocksLeftToRead] ; Restore the total block count
mov ecx,DWORD [bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
mov eax,DWORD [BYTE bp+Ext2BlocksLeftToRead] ; Restore the total block count
mov ecx,DWORD [BYTE bp+Ext2PointersPerBlock] ; Get the number of block pointers that one block contains
call Ext2ReadDirectBlockList
mov [bp+Ext2BlocksLeftToRead],eax ; Save the total block count
mov [BYTE bp+Ext2BlocksLeftToRead],eax ; Save the total block count
pop di
pop es
; Check to see if we actually have
; blocks left to read
cmp eax,0
cmp eax,byte 0
jnz Ext2ReadIndirectBlock
Ext2ReadEntireFileDone:
@ -579,7 +596,7 @@ Ext2ReadDirectBlocks:
Ext2ReadDirectBlocksLoop:
mov eax,[es:di] ; Get direct block pointer from array
add di,4 ; Update DI for next array index
add di,BYTE 4 ; Update DI for next array index
push cx ; Save number of direct blocks left
push es ; Save array segment

View file

@ -42,9 +42,9 @@
BootSectorStackTop equ 0x7bf2
DataAreaStartHigh equ 0x2
DataAreaStartLow equ 0x4
BiosCHSDriveSize equ 0x6
BiosCHSDriveSizeHigh equ 0x6
BiosCHSDriveSizeLow equ 0x8
BiosCHSDriveSize equ 0x8
ReadSectorsOffset equ 0xa
ReadClusterOffset equ 0xc
PutCharsOffset equ 0xe
@ -89,6 +89,9 @@ main:
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
mov [BYTE bp+BootDrive],dl ; Save the boot drive
@ -208,22 +211,6 @@ FoundFreeLoader:
jmp 8003h
; 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
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]
call ReadSectors
ret
; Displays an error message
@ -231,10 +218,10 @@ ReadCluster:
ErrBoot:
mov si,msgFreeLdr ; FreeLdr not found message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
Reboot:
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
xor ax,ax
int 16h ; Wait for a keypress
int 19h ; Reboot
@ -254,23 +241,49 @@ Done:
; And reboots
BadBoot:
mov si,msgDiskError ; Bad boot disk message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
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
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]
;call ReadSectors
;ret
; Reads logical sectors into [ES:BX]
; DX:AX has logical sector number to read
; CX has number of sectors to read
ReadSectors:
cmp dx,WORD [BYTE bp-BiosCHSDriveSizeHigh]; Check if they are reading a sector within CHS range
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
; 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
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:
pushad ; Save logical sector number & sector count
popa
pusha ; Save logical sector number & sector count
o32 push byte 0
push dx ; Put 64-bit logical
@ -303,16 +316,13 @@ ReadSectorsLBA:
int 13h ; Call BIOS
jc BadBoot ; If the read failed then abort
add sp,0x10 ; Remove disk address packet from stack
add sp,byte 0x10 ; Remove disk address packet from stack
popad ; Restore sector count & logical sector number
popa ; Restore sector count & logical sector number
inc ax ; Increment Sector to Read
jnz NoCarry
inc dx
adc dx,byte 0
NoCarry:
mov dx,es
add dx,byte 20h ; Increment read buffer for next sector
mov es,dx
@ -327,7 +337,8 @@ NoCarry:
; CX has number of sectors to read
; CarryFlag set on error
ReadSectorsCHS:
pushad
popa
pusha
xchg ax,cx
xchg ax,dx
xor dx,dx
@ -351,7 +362,7 @@ ReadSectorsCHS:
jc BadBoot
popad
popa
inc ax ;Increment Sector to Read
jnz NoCarryCHS
inc dx
@ -370,11 +381,16 @@ NoCarryCHS:
msgDiskError db 'Disk error',0dh,0ah,0
msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
; Sorry, need the space...
;msgAnyKey db 'Press any key to restart',0dh,0ah,0
msgAnyKey db 'Press any key',0dh,0ah,0
filename db 'FREELDR SYS'
times 510-($-$$) db 0 ; Pad to 510 bytes
times 509-($-$$) db 0 ; Pad to 509 bytes
BootPartition:
db 0
BootSignature:
dw 0aa55h ; BootSector signature

View file

@ -51,6 +51,12 @@ main:
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
CheckSectorsPerFat:
cmp WORD [BYTE bp+SectorsPerFat],byte 0x00 ; Check the old 16-bit value of SectorsPerFat
@ -230,8 +236,6 @@ ReadSectorsCHSLoop:
; And reboots
PrintDiskError:
mov si,msgDiskError ; Bad boot disk message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
jmp Reboot
@ -241,10 +245,10 @@ PrintDiskError:
PrintFileSystemError:
mov si,msgFileSystemError ; FreeLdr not found message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
Reboot:
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
xor ax,ax
int 16h ; Wait for a keypress
int 19h ; Reboot
@ -268,7 +272,12 @@ 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 510-($-$$) db 0 ; Pad to 510 bytes
times 509-($-$$) db 0 ; Pad to 510 bytes
BootPartition:
db 0
BootSignature:
dw 0aa55h ; BootSector signature
@ -379,7 +388,8 @@ LoadFile:
jmp LoadFile ; Load the next cluster (if any)
LoadFileDone:
mov dl,[BYTE bp+BootDrive]
mov dl,[BYTE bp+BootDrive] ; Load boot drive into DL
mov dh,[BootPartition] ; Load boot partition into DH
xor ax,ax
push ax ; We loaded at 0000:8000
push WORD 8000h ; We will do a far return to 0000:8000h
@ -485,7 +495,7 @@ PrintFileNotFound:
jmp Reboot
msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
msgFreeLdr db 'freeldr.sys not found',0dh,0ah,0
filename db 'FREELDR SYS'
msgLoading db 'Loading FreeLoader...',0dh,0ah,0

View file

@ -330,6 +330,7 @@ get_fs_structures:
mov cx, 0xFFFF ; load the whole file
call getfssec ; get the first sector
mov dl, [DriveNo] ; dl = boot drive
mov dh, 0 ; dh = boot partition
jmp 0:0x8000 ; jump into OSLoader

View file

@ -1,3 +1,32 @@
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).
Changes in v1.7.2 (8/7/2002) (brianp)
- Fragment size must be equal to the block size

View file

@ -48,6 +48,9 @@ EXTERN(RealEntryPoint)
/* Store the boot drive */
movb %dl,(_BootDrive)
/* Store the boot partition */
movb %dh,(_BootPartition)
/* GO! */
call _BootMain
@ -291,3 +294,6 @@ rmode_idtptr:
EXTERN(_BootDrive)
.long 0
EXTERN(_BootPartition)
.long 0

View file

@ -14,9 +14,9 @@ bits 16
BootSectorStackTop equ 0x7bf2
DataAreaStartHigh equ 0x2
DataAreaStartLow equ 0x4
BiosCHSDriveSize equ 0x6
BiosCHSDriveSizeHigh equ 0x6
BiosCHSDriveSizeLow equ 0x8
BiosCHSDriveSize equ 0x8
ReadSectorsOffset equ 0xa
ReadClusterOffset equ 0xc
PutCharsOffset equ 0xe
@ -40,6 +40,8 @@ ExtendSig equ 38
SerialNumber equ 39
VolumeLabel equ 43
FileSystem equ 54
BootPartition equ 0x7dfd
; This code will be stored in the first 512 bytes
@ -120,6 +122,7 @@ LoadFile5:
LoadFile_Done:
mov dl,BYTE [BYTE bp+BootDrive] ; Load the boot drive into DL
mov dh,[BootPartition] ; Load the boot partition into DH
push WORD 0x0000
push WORD 0x8000 ; We will do a far return to 0000:8000h
retf ; Transfer control to ROSLDR

View file

@ -66,6 +66,10 @@
movl %eax,i386_DR2
movl %dr3,%eax
movl %eax,i386_DR3
movl %dr6,%eax
movl %eax,i386_DR6
movl %dr7,%eax
movl %eax,i386_DR7
sgdt i386_GDTR
sidt i386_IDTR
sldt i386_LDTR
@ -115,6 +119,10 @@
movl %eax,i386_DR2
movl %dr3,%eax
movl %eax,i386_DR3
movl %dr6,%eax
movl %eax,i386_DR6
movl %dr7,%eax
movl %eax,i386_DR7
sgdt i386_GDTR
sidt i386_IDTR
sldt i386_LDTR
@ -214,6 +222,10 @@ i386_DR2_Text:
.asciz " DR2: "
i386_DR3_Text:
.asciz " DR3: "
i386_DR6_Text:
.asciz " DR6: "
i386_DR7_Text:
.asciz " DR7: "
i386_GDTR_Text:
.asciz " GDTR Base: "
i386_IDTR_Text:
@ -280,6 +292,10 @@ i386_DR2:
.long 0
i386_DR3:
.long 0
i386_DR6:
.long 0
i386_DR7:
.long 0
i386_GDTR:
.word 0
.long 0
@ -379,6 +395,18 @@ i386CommonExceptionHandler:
call i386PrintText
movl i386_DR3,%eax
call i386PrintHexDword // Display DR3
incl i386_ScreenPosY
movl $55,i386_ScreenPosX
movl $i386_DR6_Text,%esi
call i386PrintText
movl i386_DR6,%eax
call i386PrintHexDword // Display DR6
incl i386_ScreenPosY
movl $55,i386_ScreenPosX
movl $i386_DR7_Text,%esi
call i386PrintText
movl i386_DR7,%eax
call i386PrintHexDword // Display DR7
movl $0,i386_ScreenPosX
incl i386_ScreenPosY
incl i386_ScreenPosY
@ -759,3 +787,210 @@ EXTERN(i386MachineCheck)
movl $i386MachineCheckText,i386ExceptionDescriptionText
jmp i386CommonExceptionHandler
/************************************************************************
* DEBUGGING SUPPORT FUNCTIONS
************************************************************************/
EXTERN(_INSTRUCTION_BREAKPOINT1)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr0
movl %dr7,%eax
andl $0xfff0ffff,%eax
orl $0x00000303,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_READWRITE_BREAKPOINT1)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr0
movl %dr7,%eax
andl $0xfff0ffff,%eax
orl $0x00030303,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_WRITE_BREAKPOINT1)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr0
movl %dr7,%eax
andl $0xfff0ffff,%eax
orl $0x00010303,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_INSTRUCTION_BREAKPOINT2)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr1
movl %dr7,%eax
andl $0xff0fffff,%eax
orl $0x0000030c,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_READWRITE_BREAKPOINT2)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr1
movl %dr7,%eax
andl $0xff0fffff,%eax
orl $0x0030030c,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_WRITE_BREAKPOINT2)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr1
movl %dr7,%eax
andl $0xff0fffff,%eax
orl $0x0010030c,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_INSTRUCTION_BREAKPOINT3)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr2
movl %dr7,%eax
andl $0xf0ffffff,%eax
orl $0x00000330,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_READWRITE_BREAKPOINT3)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr2
movl %dr7,%eax
andl $0xf0ffffff,%eax
orl $0x03000330,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_WRITE_BREAKPOINT3)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr2
movl %dr7,%eax
andl $0xf0ffffff,%eax
orl $0x01000330,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_INSTRUCTION_BREAKPOINT4)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr3
movl %dr7,%eax
andl $0x0fffffff,%eax
orl $0x000003c0,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_READWRITE_BREAKPOINT4)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr3
movl %dr7,%eax
andl $0x0fffffff,%eax
orl $0x300003c0,%eax
movl %eax,%dr7
popl %eax
ret
EXTERN(_MEMORY_WRITE_BREAKPOINT4)
.code32
pushl %eax
movl 8(%esp),%eax
movl %eax,%dr3
movl %dr7,%eax
andl $0x0fffffff,%eax
orl $0x100003c0,%eax
movl %eax,%dr7
popl %eax
ret

View file

@ -34,7 +34,7 @@ VOID DiskError(PUCHAR ErrorString)
{
UCHAR ErrorCodeString[80];
sprintf(ErrorCodeString, "%s\nError Code: 0x%lx", ErrorString, BiosInt13GetLastErrorCode());
sprintf(ErrorCodeString, "%s\nError Code: 0x%x", ErrorString, BiosInt13GetLastErrorCode());
DbgPrint((DPRINT_DISK, "%s\n", ErrorCodeString));

View file

@ -130,6 +130,7 @@ BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABL
MASTER_BOOT_RECORD MasterBootRecord;
PARTITION_TABLE_ENTRY ExtendedPartitionTableEntry;
U32 ExtendedPartitionNumber;
U32 ExtendedPartitionRelativeOffset;
U32 Index;
// Read master boot record
@ -158,6 +159,11 @@ BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABL
ExtendedPartitionNumber = PartitionNumber - 5;
// Set the initial relative starting sector to 0
// This is because extended partition starting
// sectors a numbered relative to their parent
ExtendedPartitionRelativeOffset = 0;
for (Index=0; Index<=ExtendedPartitionNumber; Index++)
{
// Get the extended partition table entry
@ -166,8 +172,11 @@ BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABL
return FALSE;
}
// Adjust the relative starting sector of the partition
ExtendedPartitionRelativeOffset += ExtendedPartitionTableEntry.SectorCountBeforePartition;
// Read the partition boot record
if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionTableEntry.SectorCountBeforePartition, &MasterBootRecord))
if (!DiskReadBootRecord(DriveNumber, ExtendedPartitionRelativeOffset, &MasterBootRecord))
{
return FALSE;
}
@ -177,6 +186,9 @@ BOOL DiskGetPartitionEntry(U32 DriveNumber, U32 PartitionNumber, PPARTITION_TABL
{
return FALSE;
}
// Now correct the start sector of the partition
PartitionTableEntry->SectorCountBeforePartition += ExtendedPartitionRelativeOffset;
}
// When we get here we should have the correct entry

View file

@ -25,9 +25,9 @@
#include <bootmgr.h>
#include <fs.h>
// Variable BootDrive moved to asmcode.S
// Variables BootDrive & BootPartition moved to asmcode.S
//U32 BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
U32 BootPartition = 0; // Boot Partition, 1-4
//U32 BootPartition = 0; // Boot Partition, 1-4
VOID BootMain(VOID)
{
@ -38,6 +38,8 @@ VOID BootMain(VOID)
DebugInit();
#endif
DbgPrint((DPRINT_WARNING, "BootMain() called. BootDrive = 0x%x BootPartition = %d\n", BootDrive, BootPartition));
if (!MmInitializeMemoryManager())
{
printf("Press any key to reboot.\n");

View file

@ -149,7 +149,7 @@ FILE* Ext2OpenFile(PUCHAR FileName)
FullPath[Index] = '\0';
// Concatenate the symbolic link
strcat(FullPath, "/");
strcat(FullPath, Index == 0 ? "" : "/");
strcat(FullPath, SymLinkPath);
}
@ -353,7 +353,7 @@ BOOL Ext2ReadFile(FILE *FileHandle, U64 BytesToRead, U64* BytesRead, PVOID Buffe
U32 LengthInBlock;
U32 NumberOfBlocks;
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadFile() BytesToRead = %d Buffer = 0x%x\n", BytesToRead, Buffer));
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadFile() BytesToRead = %d Buffer = 0x%x\n", (U32)BytesToRead, Buffer));
if (BytesRead != NULL)
{
@ -843,13 +843,23 @@ BOOL Ext2ReadBlock(U32 BlockNumber, PVOID Buffer)
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber, Buffer));
// Make sure its a valid block
if ((BlockNumber < 1) || (BlockNumber > Ext2SuperBlock->s_blocks_count))
if (BlockNumber > Ext2SuperBlock->s_blocks_count)
{
sprintf(ErrorString, "Error reading block %d - block out of range.", BlockNumber);
FileSystemError(ErrorString);
return FALSE;
}
// Check to see if this is a sparse block
if (BlockNumber == 0)
{
DbgPrint((DPRINT_FILESYSTEM, "Block is part of a sparse file. Zeroing input buffer.\n"));
RtlZeroMemory(Buffer, Ext2BlockSizeInBytes);
return TRUE;
}
return Ext2ReadVolumeSectors(Ext2DriveNumber, (U64)BlockNumber * Ext2BlockSizeInSectors, Ext2BlockSizeInSectors, Buffer);
}
@ -996,16 +1006,20 @@ U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode)
U64 FileSize;
U32 BlockCount;
U32* BlockList;
U32 CurrentBlockInList;
U32 CurrentBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2ReadBlockPointerList()\n"));
// Get the file size and round it up
// Get the number of blocks this file occupies
// I would just use Inode->i_blocks but it
// doesn't seem to be the number of blocks
// the file size corresponds to, but instead
// it is much bigger.
//BlockCount = Inode->i_blocks;
FileSize = Ext2GetInodeFileSize(Inode);
FileSize = ROUND_UP(FileSize, Ext2BlockSizeInBytes);
// Calculate the number of blocks this file occupies
BlockCount = FileSize / Ext2BlockSizeInBytes;
BlockCount = (FileSize / Ext2BlockSizeInBytes);
// Allocate the memory for the block list
BlockList = MmAllocateMemory(BlockCount * sizeof(U32));
@ -1014,75 +1028,43 @@ U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode)
return NULL;
}
// Copy the direct blocks
for (CurrentBlock=0; CurrentBlock<BlockCount; CurrentBlock++)
{
if (CurrentBlock > 11)
{
break;
}
RtlZeroMemory(BlockList, BlockCount * sizeof(U32));
CurrentBlockInList = 0;
BlockList[CurrentBlock] = Inode->i_block[CurrentBlock];
// Copy the direct block pointers
for (CurrentBlock=0; CurrentBlockInList<BlockCount && CurrentBlock<EXT3_NDIR_BLOCKS; CurrentBlock++)
{
BlockList[CurrentBlockInList] = Inode->i_block[CurrentBlock];
CurrentBlockInList++;
}
BlockCount -= CurrentBlock;
// Copy the indirect blocks
if (BlockCount > 0)
// Copy the indirect block pointers
if (CurrentBlockInList < BlockCount)
{
if (!Ext2CopyIndirectBlockPointers(Inode->i_block[12], BlockCount, &BlockList[CurrentBlock]))
if (!Ext2CopyIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->i_block[EXT3_IND_BLOCK]))
{
MmFreeMemory(BlockList);
return NULL;
}
CurrentBlock += (Ext2BlockSizeInBytes / sizeof(U32));
if (BlockCount >= (Ext2BlockSizeInBytes / sizeof(U32)))
{
BlockCount -= (Ext2BlockSizeInBytes / sizeof(U32));
}
else
{
BlockCount = 0;
return FALSE;
}
}
// Copy the double-indirect blocks
if (BlockCount > 0)
// Copy the double indirect block pointers
if (CurrentBlockInList < BlockCount)
{
if (!Ext2CopyIndirectBlockPointers(Inode->i_block[12], BlockCount, &BlockList[CurrentBlock]))
if (!Ext2CopyDoubleIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->i_block[EXT3_DIND_BLOCK]))
{
MmFreeMemory(BlockList);
return NULL;
}
CurrentBlock += (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32));
if (BlockCount >= (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32)))
{
BlockCount -= (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32));
}
else
{
BlockCount = 0;
return FALSE;
}
}
// Copy the triple-indirect blocks
if (BlockCount > 0)
// Copy the triple indirect block pointers
if (CurrentBlockInList < BlockCount)
{
if (!Ext2CopyIndirectBlockPointers(Inode->i_block[12], BlockCount, &BlockList[CurrentBlock]))
if (!Ext2CopyTripleIndirectBlockPointers(BlockList, &CurrentBlockInList, BlockCount, Inode->i_block[EXT3_TIND_BLOCK]))
{
MmFreeMemory(BlockList);
return NULL;
}
CurrentBlock += (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32));
if (BlockCount >= (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32)))
{
BlockCount -= (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32));
}
else
{
BlockCount = 0;
return FALSE;
}
}
@ -1101,91 +1083,96 @@ U64 Ext2GetInodeFileSize(PEXT2_INODE Inode)
}
}
BOOL Ext2CopyIndirectBlockPointers(U32 IndirectBlock, U32 BlockCount, U32* BlockList)
BOOL Ext2CopyIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 IndirectBlock)
{
U32* BlockBuffer = (U32*)FILESYSBUFFER;
U32 CurrentBlock;
U32 BlockPointersPerBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyIndirectBlockPointers()\n"));
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyIndirectBlockPointers() BlockCount = %d\n", BlockCount));
BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(U32);
if (!Ext2ReadBlock(IndirectBlock, BlockBuffer))
{
return FALSE;
}
for (CurrentBlock=0; CurrentBlock<BlockCount; CurrentBlock++)
for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
{
BlockList[CurrentBlock] = BlockBuffer[CurrentBlock];
if (CurrentBlock >= ((Ext2BlockSizeInBytes / sizeof(U32)) - 1))
{
break;
}
BlockList[(*CurrentBlockInList)] = BlockBuffer[CurrentBlock];
(*CurrentBlockInList)++;
}
return TRUE;
}
BOOL Ext2CopyDoubleIndirectBlockPointers(U32 DoubleIndirectBlock, U32 BlockCount, U32* BlockList)
BOOL Ext2CopyDoubleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 DoubleIndirectBlock)
{
U32* BlockBuffer = (U32*)FILESYSBUFFER;
U32 CurrentIndirectBlock;
U32* BlockBuffer;
U32 CurrentBlock;
U32 BlockPointersPerBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyDoubleIndirectBlockPointers()\n"));
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyDoubleIndirectBlockPointers() BlockCount = %d\n", BlockCount));
BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(U32);
BlockBuffer = (U32*)MmAllocateMemory(Ext2BlockSizeInBytes);
if (BlockBuffer == NULL)
{
return FALSE;
}
if (!Ext2ReadBlock(DoubleIndirectBlock, BlockBuffer))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
for (CurrentIndirectBlock=0,CurrentBlock=0; CurrentBlock<BlockCount; CurrentIndirectBlock++)
for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
{
if (!Ext2CopyIndirectBlockPointers(BlockBuffer[CurrentIndirectBlock], BlockCount, &BlockList[CurrentBlock]))
if (!Ext2CopyIndirectBlockPointers(BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
CurrentBlock += (Ext2BlockSizeInBytes / sizeof(U32));
BlockCount -= (Ext2BlockSizeInBytes / sizeof(U32));
if (CurrentIndirectBlock >= ((Ext2BlockSizeInBytes / sizeof(U32)) - 1))
{
break;
}
}
MmFreeMemory(BlockBuffer);
return TRUE;
}
BOOL Ext2CopyTripleIndirectBlockPointers(U32 TripleIndirectBlock, U32 BlockCount, U32* BlockList)
BOOL Ext2CopyTripleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 TripleIndirectBlock)
{
U32* BlockBuffer = (U32*)FILESYSBUFFER;
U32 CurrentIndirectBlock;
U32* BlockBuffer;
U32 CurrentBlock;
U32 BlockPointersPerBlock;
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyTripleIndirectBlockPointers()\n"));
DbgPrint((DPRINT_FILESYSTEM, "Ext2CopyTripleIndirectBlockPointers() BlockCount = %d\n", BlockCount));
BlockPointersPerBlock = Ext2BlockSizeInBytes / sizeof(U32);
BlockBuffer = (U32*)MmAllocateMemory(Ext2BlockSizeInBytes);
if (BlockBuffer == NULL)
{
return FALSE;
}
if (!Ext2ReadBlock(TripleIndirectBlock, BlockBuffer))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
for (CurrentIndirectBlock=0,CurrentBlock=0; CurrentBlock<BlockCount; CurrentIndirectBlock++)
for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
{
if (!Ext2CopyDoubleIndirectBlockPointers(BlockBuffer[CurrentIndirectBlock], BlockCount, &BlockList[CurrentBlock]))
if (!Ext2CopyDoubleIndirectBlockPointers(BlockList, CurrentBlockInList, BlockCount, BlockBuffer[CurrentBlock]))
{
MmFreeMemory(BlockBuffer);
return FALSE;
}
CurrentBlock += (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32));
BlockCount -= (Ext2BlockSizeInBytes / sizeof(U32)) * (Ext2BlockSizeInBytes / sizeof(U32));
if (CurrentIndirectBlock >= ((Ext2BlockSizeInBytes / sizeof(U32)) - 1))
{
break;
}
}
MmFreeMemory(BlockBuffer);
return TRUE;
}

View file

@ -653,7 +653,7 @@ typedef struct ext3_dir_entry_2 EXT2_DIR_ENTRY, *PEXT2_DIR_ENTRY;
#define EXT2_S_IFLNK 0xA000 // Symbolic link
#define EXT2_S_IFSOCK 0xC000 // Socket
#define FAST_SYMLINK_MAX_NAME_SIZE 60
#define FAST_SYMLINK_MAX_NAME_SIZE (EXT3_N_BLOCKS * sizeof(U32)) /* 60 bytes */
typedef struct
{
@ -690,8 +690,8 @@ BOOL Ext2ReadInode(U32 Inode, PEXT2_INODE InodeBuffer);
BOOL Ext2ReadGroupDescriptor(U32 Group, PEXT2_GROUP_DESC GroupBuffer);
U32* Ext2ReadBlockPointerList(PEXT2_INODE Inode);
U64 Ext2GetInodeFileSize(PEXT2_INODE Inode);
BOOL Ext2CopyIndirectBlockPointers(U32 IndirectBlock, U32 BlockCount, U32* BlockList);
BOOL Ext2CopyDoubleIndirectBlockPointers(U32 DoubleIndirectBlock, U32 BlockCount, U32* BlockList);
BOOL Ext2CopyTripleIndirectBlockPointers(U32 TripleIndirectBlock, U32 BlockCount, U32* BlockList);
BOOL Ext2CopyIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 IndirectBlock);
BOOL Ext2CopyDoubleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 DoubleIndirectBlock);
BOOL Ext2CopyTripleIndirectBlockPointers(U32* BlockList, U32* CurrentBlockInList, U32 BlockCount, U32 TripleIndirectBlock);
#endif // #defined __EXT2_H

View file

@ -43,6 +43,33 @@
#define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d(%s)\n", __FILE__, __LINE__, __FUNCTION__); DebugPrint _x_ ; for (;;); }
#define DbgDumpBuffer(_x_, _y_, _z_) DebugDumpBuffer(_x_, _y_, _z_)
#ifdef __i386__
// Debugging support functions:
//
// BREAKPOINT() - Inserts an "int 3" instruction
// INSTRUCTION_BREAKPOINTX(x) - Enters exception handler right before instruction at address "x" is executed
// MEMORY_READWRITE_BREAKPOINTX(x) - Enters exception handler when a read or write occurs at address "x"
// MEMORY_WRITE_BREAKPOINTX(x) - Enters exception handler when a write occurs at address "x"
//
// You may have as many BREAKPOINT()'s as you like but you may only
// have up to four of any of the others.
#define BREAKPOINT() __asm__ ("int $3");
void INSTRUCTION_BREAKPOINT1(unsigned long addr);
void MEMORY_READWRITE_BREAKPOINT1(unsigned long addr);
void MEMORY_WRITE_BREAKPOINT1(unsigned long addr);
void INSTRUCTION_BREAKPOINT2(unsigned long addr);
void MEMORY_READWRITE_BREAKPOINT2(unsigned long addr);
void MEMORY_WRITE_BREAKPOINT2(unsigned long addr);
void INSTRUCTION_BREAKPOINT3(unsigned long addr);
void MEMORY_READWRITE_BREAKPOINT3(unsigned long addr);
void MEMORY_WRITE_BREAKPOINT3(unsigned long addr);
void INSTRUCTION_BREAKPOINT4(unsigned long addr);
void MEMORY_READWRITE_BREAKPOINT4(unsigned long addr);
void MEMORY_WRITE_BREAKPOINT4(unsigned long addr);
#endif // defined __i386__
#else
#define DbgPrint(_x_)

View file

@ -29,10 +29,8 @@
typedef struct
{
U32 BaseAddressLow;
U32 BaseAddressHigh;
U32 LengthLow;
U32 LengthHigh;
U64 BaseAddress;
U64 Length;
U32 Type;
U32 Reserved;
} PACKED BIOS_MEMORY_MAP, *PBIOS_MEMORY_MAP;

View file

@ -22,7 +22,7 @@
/* just some stuff */
#define VERSION "FreeLoader v1.7.2"
#define VERSION "FreeLoader v1.7.4"
#define COPYRIGHT "Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>"
#define AUTHOR_EMAIL "<brianp@sginet.com>"
#define BY_AUTHOR "by Brian Palmer"
@ -36,7 +36,7 @@
//
#define FREELOADER_MAJOR_VERSION 1
#define FREELOADER_MINOR_VERSION 7
#define FREELOADER_PATCH_VERSION 2
#define FREELOADER_PATCH_VERSION 4
PUCHAR GetFreeLoaderVersionString(VOID);

View file

@ -21,6 +21,7 @@
#define __INI_H
#include <rtl.h>
#include <fs.h>
#define INI_FILE_COMMENT_CHAR ';'
@ -55,6 +56,8 @@ typedef struct
extern PINI_SECTION IniFileSectionListHead;
extern U32 IniFileSectionListCount;
PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber);
BOOL IniParseFile(PUCHAR IniFileData, U32 IniFileSize);
U32 IniGetNextLineSize(PUCHAR IniFileData, U32 IniFileSize, U32 CurrentOffset);
U32 IniGetNextLine(PUCHAR IniFileData, U32 IniFileSize, PUCHAR Buffer, U32 BufferSize, U32 CurrentOffset);

View file

@ -32,18 +32,28 @@ BOOL IniFileInitialize(VOID)
U32 FreeLoaderIniFileSize;
BOOL Success;
// Open the boot drive for file access
if (!OpenDiskDrive(BootDrive, 0))
// Open freeldr.ini
// BootDrive & BootPartition are passed
// in from the boot sector code in the
// DL & DH registers.
Freeldr_Ini = IniOpenIniFile(BootDrive, BootPartition);
// If we couldn't open freeldr.ini on the partition
// they specified in the boot sector then try
// opening the active (boot) partition.
if ((Freeldr_Ini == NULL) && (BootPartition != 0))
{
printf("Error opening boot drive for file access.\n");
BootPartition = 0;
Freeldr_Ini = IniOpenIniFile(BootDrive, BootPartition);
return FALSE;
}
// Try to open freeldr.ini or fail
Freeldr_Ini = OpenFile("freeldr.ini");
if (Freeldr_Ini == NULL)
{
printf("FREELDR.INI not found.\nYou need to re-install FreeLoader.\n");
printf("Error opening freeldr.ini or file not found.\n");
printf("You need to re-install FreeLoader.\n");
return FALSE;
}
@ -54,7 +64,7 @@ BOOL IniFileInitialize(VOID)
// If we are out of memory then return FALSE
if (FreeLoaderIniFileData == NULL)
{
printf("Out of memory while loading FREELDR.INI.\n");
printf("Out of memory while loading freeldr.ini.\n");
CloseFile(Freeldr_Ini);
return FALSE;
}
@ -76,3 +86,27 @@ BOOL IniFileInitialize(VOID)
return Success;
}
PFILE IniOpenIniFile(U8 BootDriveNumber, U8 BootPartitionNumber)
{
PFILE IniFileHandle; // File handle for freeldr.ini
if (!OpenDiskDrive(BootDriveNumber, BootPartitionNumber))
{
if (BootPartitionNumber == 0)
{
printf("Error opening active (bootable) partition on boot drive 0x%x for file access.\n", BootDriveNumber);
}
else
{
printf("Error opening partition %d on boot drive 0x%x for file access.\n", BootPartitionNumber, BootDriveNumber);
}
return NULL;
}
// Try to open freeldr.ini
IniFileHandle = OpenFile("freeldr.ini");
return IniFileHandle;
}

View file

@ -105,6 +105,7 @@ VOID LoadAndBootBootSector(PUCHAR OperatingSystemName)
// still think the motor is on and this will
// result in a read error.
//StopFloppyMotor();
//DisableA20();
ChainLoadBiosBootSectorCode();
}
@ -174,6 +175,7 @@ VOID LoadAndBootPartition(PUCHAR OperatingSystemName)
// still think the motor is on and this will
// result in a read error.
//StopFloppyMotor();
//DisableA20();
ChainLoadBiosBootSectorCode();
}
@ -226,5 +228,6 @@ VOID LoadAndBootDrive(PUCHAR OperatingSystemName)
// still think the motor is on and this will
// result in a read error.
//StopFloppyMotor();
//DisableA20();
ChainLoadBiosBootSectorCode();
}

View file

@ -22,13 +22,17 @@
#define __MEM_H
#ifdef __i386__
#define MM_PAGE_SIZE 4096
#endif // defined __i386__
typedef struct
{
U32 PageAllocated; // Zero = free, non-zero = allocated
U32 PageAllocationLength; // Number of pages allocated (or zero if this isn't the first page in the chain)
} PAGE_LOOKUP_TABLE_ITEM, *PPAGE_LOOKUP_TABLE_ITEM;
} PACKED PAGE_LOOKUP_TABLE_ITEM, *PPAGE_LOOKUP_TABLE_ITEM;
//
// Define this to 1 if you want the entire contents

View file

@ -67,12 +67,6 @@ BOOL MmInitializeMemoryManager(VOID)
ExtendedMemorySize = GetExtendedMemorySize();
ConventionalMemorySize = GetConventionalMemorySize();
// If we got the system memory map then fixup invalid entries
if (BiosMemoryMapEntryCount != 0)
{
MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount);
}
#ifdef DEBUG
// Dump the system memory map
if (BiosMemoryMapEntryCount != 0)
@ -80,17 +74,23 @@ BOOL MmInitializeMemoryManager(VOID)
DbgPrint((DPRINT_MEMORY, "System Memory Map (Base Address, Length, Type):\n"));
for (Index=0; Index<BiosMemoryMapEntryCount; Index++)
{
DbgPrint((DPRINT_MEMORY, "%x%x\t %x%x\t %s\n", BiosMemoryMap[Index].BaseAddressHigh, BiosMemoryMap[Index].BaseAddressLow, BiosMemoryMap[Index].LengthHigh, BiosMemoryMap[Index].LengthLow, MmGetSystemMemoryMapTypeString(BiosMemoryMap[Index].Type)));
DbgPrint((DPRINT_MEMORY, "%x%x\t %x%x\t %s\n", BiosMemoryMap[Index].BaseAddress, BiosMemoryMap[Index].Length, MmGetSystemMemoryMapTypeString(BiosMemoryMap[Index].Type)));
}
}
else
{
DbgPrint((DPRINT_MEMORY, "GetBiosMemoryMap() not supported.\n"));
}
#endif
DbgPrint((DPRINT_MEMORY, "Extended memory size: %d KB\n", ExtendedMemorySize));
DbgPrint((DPRINT_MEMORY, "Conventional memory size: %d KB\n", ConventionalMemorySize));
#endif
// If we got the system memory map then fixup invalid entries
if (BiosMemoryMapEntryCount != 0)
{
MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount);
}
// Since I don't feel like writing two sets of routines
// one to handle the BiosMemoryMap structure and another
@ -99,10 +99,8 @@ BOOL MmInitializeMemoryManager(VOID)
// extended memory size if GetBiosMemoryMap() fails.
if (BiosMemoryMapEntryCount == 0)
{
BiosMemoryMap[0].BaseAddressLow = 0x100000; // Start at 1MB
BiosMemoryMap[0].BaseAddressHigh = 0;
BiosMemoryMap[0].LengthLow = ExtendedMemorySize * 1024;
BiosMemoryMap[0].LengthHigh = 0;
BiosMemoryMap[0].BaseAddress = 0x100000; // Start at 1MB
BiosMemoryMap[0].Length = ExtendedMemorySize * 1024;
BiosMemoryMap[0].Type = MEMTYPE_USABLE;
BiosMemoryMapEntryCount = 1;
}
@ -153,18 +151,18 @@ U32 MmGetPageNumberFromAddress(PVOID Address)
PVOID MmGetEndAddressOfAnyMemory(BIOS_MEMORY_MAP BiosMemoryMap[32], U32 MapCount)
{
U32 MaxStartAddressSoFar;
U64 EndAddressOfMemory;
U64 MaxStartAddressSoFar;
U64 EndAddressOfMemory;
U32 Index;
MaxStartAddressSoFar = 0;
EndAddressOfMemory = 0;
for (Index=0; Index<MapCount; Index++)
{
if (MaxStartAddressSoFar < BiosMemoryMap[Index].BaseAddressLow)
if (MaxStartAddressSoFar < BiosMemoryMap[Index].BaseAddress)
{
MaxStartAddressSoFar = BiosMemoryMap[Index].BaseAddressLow;
EndAddressOfMemory = ((U64)MaxStartAddressSoFar + (U64)BiosMemoryMap[Index].LengthLow);
MaxStartAddressSoFar = BiosMemoryMap[Index].BaseAddress;
EndAddressOfMemory = (MaxStartAddressSoFar + BiosMemoryMap[Index].Length);
if (EndAddressOfMemory > 0xFFFFFFFF)
{
EndAddressOfMemory = 0xFFFFFFFF;
@ -180,8 +178,23 @@ PVOID MmGetEndAddressOfAnyMemory(BIOS_MEMORY_MAP BiosMemoryMap[32], U32 MapCount
U32 MmGetAddressablePageCountIncludingHoles(BIOS_MEMORY_MAP BiosMemoryMap[32], U32 MapCount)
{
U32 PageCount;
U64 EndAddress;
PageCount = MmGetPageNumberFromAddress(MmGetEndAddressOfAnyMemory(BiosMemoryMap, MapCount));
EndAddress = (U64)(U32)MmGetEndAddressOfAnyMemory(BiosMemoryMap, MapCount);
// Since MmGetEndAddressOfAnyMemory() won't
// return addresses higher than 0xFFFFFFFF
// then we need to adjust the end address
// to 0x100000000 so we don't get an
// off-by-one error
if (EndAddress >= 0xFFFFFFFF)
{
EndAddress = 0x100000000;
DbgPrint((DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returned 0xFFFFFFFF, correcting to be 0x100000000.\n"));
}
PageCount = (EndAddress / MM_PAGE_SIZE);
DbgPrint((DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning %d\n", PageCount));
@ -207,9 +220,9 @@ PVOID MmFindLocationForPageLookupTable(BIOS_MEMORY_MAP BiosMemoryMap[32], U32 Ma
{
// If this is usable memory with a big enough length
// then we'll put our page lookup table here
if (TempBiosMemoryMap[Index].Type == MEMTYPE_USABLE && TempBiosMemoryMap[Index].LengthLow >= PageLookupTableSize)
if (TempBiosMemoryMap[Index].Type == MEMTYPE_USABLE && TempBiosMemoryMap[Index].Length >= PageLookupTableSize)
{
PageLookupTableAddress = (PVOID)(TempBiosMemoryMap[Index].BaseAddressLow + (TempBiosMemoryMap[Index].LengthLow - PageLookupTableSize));
PageLookupTableAddress = (PVOID)(U32)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize));
break;
}
}
@ -231,7 +244,7 @@ VOID MmSortBiosMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32], U32 MapCount)
{
for (Index=0; Index<(MapCount-1); Index++)
{
if (BiosMemoryMap[Index].BaseAddressLow > BiosMemoryMap[Index+1].BaseAddressLow)
if (BiosMemoryMap[Index].BaseAddress > BiosMemoryMap[Index+1].BaseAddress)
{
TempMapItem = BiosMemoryMap[Index];
BiosMemoryMap[Index] = BiosMemoryMap[Index+1];
@ -260,8 +273,8 @@ VOID MmInitPageLookupTable(PVOID PageLookupTable, U32 TotalPageCount, BIOS_MEMOR
for (Index=0; Index<MapCount; Index++)
{
MemoryMapStartPage = MmGetPageNumberFromAddress((PVOID)BiosMemoryMap[Index].BaseAddressLow);
MemoryMapEndPage = MmGetPageNumberFromAddress((PVOID)(BiosMemoryMap[Index].BaseAddressLow + BiosMemoryMap[Index].LengthLow - 1));
MemoryMapStartPage = MmGetPageNumberFromAddress((PVOID)(U32)BiosMemoryMap[Index].BaseAddress);
MemoryMapEndPage = MmGetPageNumberFromAddress((PVOID)(U32)(BiosMemoryMap[Index].BaseAddress + BiosMemoryMap[Index].Length - 1));
MemoryMapPageCount = (MemoryMapEndPage - MemoryMapStartPage) + 1;
MemoryMapPageAllocated = (BiosMemoryMap[Index].Type == MEMTYPE_USABLE) ? 0 : BiosMemoryMap[Index].Type;
DbgPrint((DPRINT_MEMORY, "Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryMapStartPage, MemoryMapPageCount));
@ -286,9 +299,14 @@ VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, U32 StartPage, U32 PageCoun
for (Index=StartPage; Index<(StartPage+PageCount); Index++)
{
if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16)))
{
DbgPrint((DPRINT_MEMORY, "Index = %d StartPage = %d PageCount = %d\n", Index, StartPage, PageCount));
}
RealPageLookupTable[Index].PageAllocated = PageAllocated;
RealPageLookupTable[Index].PageAllocationLength = PageAllocated ? 1 : 0;
}
DbgPrint((DPRINT_MEMORY, "MmMarkPagesInLookupTable() Done\n"));
}
VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, U32 StartPage, U32 PageCount)
@ -360,14 +378,14 @@ VOID MmFixupSystemMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32], U32* MapCount)
{
int Index;
int Index2;
U64 RealLength;
// Loop through each entry in the array
for (Index=0; Index<*MapCount; Index++)
{
// If the base address for this entry starts at
// or above 4G then remove this entry
if (BiosMemoryMap[Index].BaseAddressHigh != 0)
// If the entry type isn't usable then remove
// it from the memory map (this will help reduce
// the size of our lookup table)
if (BiosMemoryMap[Index].Type != 0)
{
// Slide every entry after this down one
for (Index2=Index; Index2<(*MapCount - 1); Index2++)
@ -377,14 +395,6 @@ VOID MmFixupSystemMemoryMap(BIOS_MEMORY_MAP BiosMemoryMap[32], U32* MapCount)
(*MapCount)--;
Index--;
}
// If the base address plus the length for this entry
// extends beyond 4G then truncate this entry
RealLength = BiosMemoryMap[Index].BaseAddressLow + BiosMemoryMap[Index].LengthLow;
if ((BiosMemoryMap[Index].LengthHigh != 0) || (RealLength > 0xFFFFFFFF))
{
BiosMemoryMap[Index].LengthLow = 0xFFFFFFFF - BiosMemoryMap[Index].BaseAddressLow;
}
}
}