BIOS Int 13h Extensions Support

New .ini file format (sort of) - changed some parameter names, etc.
More efficient .ini file parsing code
More efficient use of memory, smaller image file
Total rewrite of file system code (the old stuff sucked)
VFAT Long File Names now supported!
ReactOS is the only boot type supported currently, disabled all others (temporarily)

svn path=/trunk/; revision=2372
This commit is contained in:
Brian Palmer 2001-11-15 07:48:33 +00:00
parent 709cd514ab
commit 3662f1f720
34 changed files with 3659 additions and 1730 deletions

View file

@ -71,9 +71,20 @@
[FREELOADER]
MessageLine=Welcome to FreeLoader!
MessageLine=Copyright (c) 2000 by Brian Palmer <brianp@sginet.com>
MessageLine=Copyright (c) 2001 by Brian Palmer <brianp@sginet.com>
MessageLine=
MessageBox=Edit your FREELDR.INI file to change your boot settings.
OS=ReactOS (HD)
OS=ReactOS (Floppy)
#OS=ReactOS (Debug)
#OS=Linux
OS=3« Floppy (A:)
OS=Microsoft Windows (C:)
OS=Drive D:
DefaultOS=ReactOS (Floppy)
TimeOut=10
[Display]
TitleText=Boot Menu
StatusBarColor=Cyan
StatusBarTextColor=Black
@ -89,18 +100,11 @@ MenuColor=Blue
TextColor=Yellow
SelectedTextColor=Black
SelectedColor=Gray
OS=ReactOS (HD)
OS=ReactOS (Floppy)
#OS=ReactOS (Debug)
#OS=Linux
OS=3« Floppy (A:)
OS=Microsoft Windows (C:)
OS=Drive D:
#TimeOut=0
# Load ReactOS from harddisk (drive C:)
# - does not work on large harddisks
[ReactOS (HD)]
Name="ReactOS (HardDrive)"
BootType=ReactOS
SystemPath=multi(0)disk(0)rdisk(0)partition(1)\reactos
Options=/DEBUGPORT=SCREEN
@ -110,14 +114,16 @@ Driver=VFATFS.SYS
# Load ReactOS from floppy (drive A:)
[ReactOS (Floppy)]
Name="ReactOS (Floppy)"
BootType=ReactOS
SystemPath=multi(0)disk(0)fdisk(0)
Options=/DEBUGPORT=SCREEN
Kernel=NTOSKRNL.EXE
Driver=IDE.SYS
Driver=VFATFS.SYS
Kernel=\reactos\NTOSKRNL.EXE
Driver=\reactos\IDE.SYS
Driver=\reactos\VFATFS.SYS
#[ReactOS (Debug)]
#Name="ReactOS (Debug)"
#BootType=ReactOS
#BootDrive=0
#Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=19200
@ -126,20 +132,24 @@ Driver=VFATFS.SYS
#Driver=\DRIVERS\VFATFS.SYS
#[Linux]
#Name="Linux"
# Linux boot type not implemented yet
#BootType=Partition
#BootDrive=0x80
#BootPartition=2
[3« Floppy (A:)]
Name="3« Floppy (A:)"
BootType=Drive
BootDrive=0
[Microsoft Windows (C:)]
Name="Microsoft Windows (C:)"
BootType=Drive
BootDrive=0x80
[Drive D:]
Name="Drive D:"
BootType=Partition
BootDrive=0x81
BootPartition=1

View file

@ -18,13 +18,13 @@
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
export NASM_CMD = nasm
export MAKE = make
export MAKE = make
.PHONY : bootsect freeldr install clean

View file

@ -17,13 +17,12 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
export NASM_CMD = nasm
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
export NASM_CMD = nasm
.PHONY : clean

View file

@ -256,7 +256,7 @@ Done:
msgDiskError db 'Disk error',0dh,0ah,0
msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
msgAnyKey db 'Press any key to continue.',0dh,0ah,0
msgAnyKey db 'Press any key to restart',0dh,0ah,0
filename db 'FREELDR SYS'
times 510-($-$$) db 0 ; Pad to 510 bytes
@ -272,11 +272,34 @@ filename db 'FREELDR SYS'
LoadFile:
push ax ; First save AX - the start cluster of freeldr.sys
; Lets save the contents of the screen
; from B800:0000 to 9000:8000
push ds
mov ax,0b800h
mov ds,ax
xor si,si
mov ax,9800h
mov es,ax
xor di,di
mov cx,2000 ; Copy 2000 characters [words] (screen is 80x25)
rep movsw ; 2 bytes a character (one is the attribute byte)
pop ds
mov ah,03h ; AH = 03h
xor bx,bx ; BH = video page
int 10h ; BIOS Int 10h Func 3 - Read Cursor Position and Size
mov [es:di],dx ; DH = row, DL = column
; Display "Loading FreeLoader..." message
push ax
mov si,msgLoading ; Loading message
call PutChars ; Display it
pop ax
mov si,msgLoading ; Loading message
call PutChars ; Display it
pop ax ; Restore AX
; AX has start cluster of freeldr.sys
push ax

View file

@ -2,7 +2,8 @@
; FAT32 Boot Sector
; Copyright (c) 1998, 2000, 2001 Brian Palmer
org 7c00h
;org 7c00h
org 0
segment .text
@ -14,15 +15,15 @@ start:
OEMName db 'FrLdr1.0'
BytesPerSector dw 512
SectsPerCluster db 1
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 18
NumberOfHeads dw 2
SectorsPerTrack dw 0
NumberOfHeads dw 0
HiddenSectors dd 0
TotalSectorsBig dd 0
; FAT32 Inserted Info
@ -44,122 +45,209 @@ FileSystem db 'FAT32 '
main:
cli
cld
; Lets copy ourselves from 0000:7c00 to 9000:0000
; and transfer control to the new code
xor ax,ax
mov ds,ax
mov si,7c00h
mov ax,9000h
mov es,ax
xor di,di
mov cx,512
rep movsb
jmp 0x9000:RealMain
; Now we are executing at 9000:xxxx
; We are now free to load freeldr.sys at 0000:7e00
RealMain:
xor ax,ax
mov ss,ax
mov sp,7c00h ; Setup a stack
mov bp,ax
mov sp,ax ; Setup a stack
mov ax,cs ; Setup segment registers
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
mov ss,ax ; Make SS correct
sti ; Enable ints now
mov [BootDrive],dl ; Save the boot drive
xor ax,ax ; Zero out AX
cmp word [TotalSectors],byte 0x00 ; Check the old 16-bit value of TotalSectors
jnz ErrBoot ; If it is non-zero then exit with an error
cmp word [FSVersion],byte 0x00 ; Check the file system version word
ja ErrBoot ; If it is not zero then exit with an error
; Reset disk controller
int 13h
jnc LoadExtraBootCode
jmp BadBoot ; Reset failed...
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
LoadExtraBootCode:
; First we have to load our extra boot code at
; sector 14 into memory at [0000:7e00h]
xor dx,dx
mov ax,0eh
add ax,WORD [HiddenSectors]
adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors
; sector 14 into memory at [9000:0200h]
mov eax,0eh
add eax,DWORD [BYTE bp+HiddenSectors] ; Add the number of hidden sectors
mov cx,1
mov bx,7e0h
mov es,bx ; Read sector to [0000:7e00h]
xor bx,bx
mov bx,9000h
mov es,bx ; Read sector to [9000:0200h]
mov bx,0200h
call ReadSectors
jmp StartSearch
; Reads logical sectors into [ES:BX]
; 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 within CHS range
jbe ReadSectorsCHS ; Yes - go to the old CHS routine
ReadSectorsLBA:
pushad ; Save logical sector number & sector count
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 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
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 PrintDiskError ; If the read failed then abort
add sp,0x10 ; Remove disk address packet from stack
popad ; Restore sector count & logical sector number
inc eax ; Increment sector to read
mov dx,es
add dx,byte 20h ; Increment read buffer for next sector
mov es,dx
loop ReadSectorsLBA ; Read next sector
ret
; Reads logical sectors into [ES:BX]
; DX:AX has logical sector number to read
; EAX has logical sector number to read
; CX has number of sectors to read
; CarryFlag set on error
ReadSectors:
push ax
push dx
push cx
xchg ax,cx
xchg ax,dx
xor dx,dx
div WORD [SectorsPerTrack]
xchg ax,cx
div WORD [SectorsPerTrack] ; Divide logical by SectorsPerTrack
inc dx ; Sectors numbering starts at 1 not 0
xchg cx,dx
div WORD [NumberOfHeads] ; Number of heads
mov dh,dl ; Head to DH, drive to DL
mov dl,[BootDrive] ; Drive number
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
ReadSectorsCHS:
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
; 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
jc BadBoot
jc PrintDiskError ; If the read failed then abort
pop cx
pop dx
pop ax
inc ax ;Increment Sector to Read
jnz NoCarry
inc dx
popad
inc eax ; Increment Sector to Read
NoCarry:
push bx
mov bx,es
add bx,byte 20h
mov es,bx
pop bx
; Increment read buffer for next sector
loop ReadSectors ; Read next sector
mov dx,es
add dx,byte 20h ; Increment read buffer for next sector
mov es,dx
loop ReadSectorsCHS ; Read next sector
ret
; Displays a bad boot message
; Displays a disk error message
; 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
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
; Displays an error message
; Displays a file system error message
; And reboots
ErrBoot:
mov si,msgFreeLdr ; FreeLdr not found message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
PrintFileSystemError:
mov si,msgFileSystemError ; FreeLdr not found message
call PutChars ; Display it
mov si,msgAnyKey ; Press any key message
call PutChars ; Display it
Reboot:
xor ax,ax
int 16h ; Wait for a keypress
int 19h ; Reboot
int 16h ; Wait for a keypress
int 19h ; Reboot
PutChars:
lodsb
@ -172,10 +260,13 @@ PutChars:
Done:
retn
msgDiskError db 'Disk error',0dh,0ah,0
msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
msgAnyKey db 'Press any key to continue.',0dh,0ah,0
filename db 'FREELDR SYS'
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
times 510-($-$$) db 0 ; Pad to 510 bytes
dw 0aa55h ; BootSector signature
@ -190,29 +281,27 @@ filename db 'FREELDR SYS'
; 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
;
; Note: Win2k uses sector 12 for this purpose
StartSearch:
; Now we must get the first cluster of the root directory
mov eax,DWORD [RootDirStartCluster]
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 BadBoot
jmp ErrBoot
jb ContinueSearch ; If not continue, if so then we didn't find freeldr.sys
jmp PrintFileNotFound
ContinueSearch:
mov bx,800h
mov es,bx ; Read cluster to [0000:8000h]
mov bx,7e0h
mov es,bx ; Read cluster to [0000:7e00h]
call ReadCluster ; Read the cluster
; Now we have to find our way through the root directory to
; The OSLOADER.SYS file
xor bx,bx
mov bl,[SectsPerCluster]
mov bl,[BYTE bp+SectsPerCluster]
shl bx,4 ; BX = BX * 512 / 32
mov ax,800h ; We loaded at 0800:0000
mov ax,7e0h ; We loaded at 07e0:0000
mov es,ax
xor di,di
mov si,filename
@ -221,7 +310,7 @@ ContinueSearch:
jz FoundFile ; If same we found it
dec bx
jnz FindFile
jmp ErrBoot
jmp PrintFileNotFound
FindFile:
mov ax,es ; We didn't find it in the previous dir entry
@ -236,36 +325,67 @@ FindFile:
jnz FindFile ; Last entry?
; Get the next root dir cluster and try again until we run out of clusters
mov eax,DWORD [RootDirStartCluster]
mov eax,DWORD [BYTE bp+RootDirStartCluster]
call GetFatEntry
mov [RootDirStartCluster],eax
mov [BYTE bp+RootDirStartCluster],eax
jmp StartSearch
FoundFile:
; Display "Loading FreeLoader..." message
mov si,msgLoading ; Loading message
call PutChars ; Display it
xor di,di ; ES:DI has dir entry
; Lets save the contents of the screen
; from B800:0000 to 9000:8000
pushad
mov ax,0b800h
mov ds,ax
xor si,si
mov ax,9800h
mov es,ax
xor di,di
mov cx,2000 ; Copy 2000 characters (screen is 80x25)
rep movsw ; 2 bytes a character (one is the attribute byte)
mov ah,03h ; AH = 03h
xor bx,bx ; BH = video page
int 10h ; BIOS Int 10h Func 3 - Read Cursor Position and Size
mov [es:di],dx ; DH = row, DL = column
; Display "Loading FreeLoader..." message
mov si,msgLoading ; Loading message
call PutChars ; Display it
popad
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
mov ax,WORD [es:di+1ah] ; Get start cluster low word
mov bx,800h
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:
mov bx,7e0h
mov es,bx
FoundFile2:
LoadFile:
cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
jae FoundFile3 ; If so continue, if not then read then next one
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:7e00h
push es
call ReadCluster
pop es
xor bx,bx
mov bl,[SectsPerCluster]
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
@ -276,14 +396,13 @@ FoundFile2:
call GetFatEntry ; Get the next entry
pop es
jmp FoundFile2 ; Load the next cluster (if any)
jmp LoadFile ; Load the next cluster (if any)
FoundFile3:
mov dl,[BootDrive]
xor ax,ax
push ax
mov ax,8000h
push ax ; We will do a far return to 0000:8000h
LoadFileDone:
mov dl,[BYTE bp+BootDrive]
xor ax,ax ; We loaded at 0000:7e00 but the entry point is 0000:8000
push ax ; because the first 512 bytes is fat helper code
push WORD 8000h ; We will do a far return to 0000:8000h
retf ; Transfer control to ROSLDR
@ -292,57 +411,52 @@ FoundFile3:
; 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 [BytesPerSector]
movzx ebx,WORD [BYTE bp+BytesPerSector]
push ebx
div ebx ; FAT Sector Number = EAX / BytesPerSector
movzx ebx,WORD [ReservedSectors]
add eax,ebx ; FAT Sector Number += ReservedSectors
mov ebx,DWORD [HiddenSectors]
add eax,ebx ; FAT Sector Number += HiddenSectors
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
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 [ExtendedFlags] ; Get extended flags and put into ebx
and bx,0x0f ; Mask off upper 8 bits
jz GetFatEntry2 ; If fat is mirrored then skip fat calcs
cmp bl,[NumberOfFats] ; Compare bl to number of fats
jc GetFatEntry1
jmp ErrBoot ; If bl is bigger than numfats exit with error
GetFatEntry1:
mov edx,eax ; Put logical FAT sector number in edx
mov eax,[SectorsPerFatBig] ; Get the number of sectors occupied by one fat in eax
mul ebx ; Multiplied by the active FAT index we have in ebx
add eax,edx ; Add the current FAT sector 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
GetFatEntry2:
LoadFatSector:
push ecx
ror eax,16
mov dx,ax
ror eax,16
; DX:AX holds logical FAT sector number
; EAX holds logical FAT sector number
mov bx,7000h
mov es,bx
xor bx,bx ; We will load it to [7000:0000h]
xor bx,bx ; We will load it to [7000:0000h]
mov cx,1
call ReadSectors
jnc GetFatEntry3
jmp BadBoot
GetFatEntry3:
mov bx,7000h
mov es,bx
pop ecx
mov eax,DWORD [es:ecx] ; Get FAT entry
and eax,0fffffffh ; Mask off reserved bits
mov eax,DWORD [es:ecx] ; Get FAT entry
and eax,0fffffffh ; Mask off reserved bits
ret
@ -354,27 +468,38 @@ ReadCluster:
dec eax
dec eax
xor edx,edx
movzx ebx,BYTE [SectsPerCluster]
movzx ebx,BYTE [BYTE bp+SectsPerCluster]
mul ebx
push eax
xor edx,edx
movzx eax,BYTE [NumberOfFats]
mul DWORD [SectorsPerFatBig]
movzx ebx,WORD [ReservedSectors]
movzx eax,BYTE [BYTE bp+NumberOfFats]
mul DWORD [BYTE bp+SectorsPerFatBig]
movzx ebx,WORD [BYTE bp+ReservedSectors]
add eax,ebx
add eax,DWORD [HiddenSectors]
add eax,DWORD [BYTE bp+HiddenSectors]
pop ebx
add eax,ebx ; EAX now contains the logical sector number of the cluster
ror eax,16
mov dx,ax
ror eax,16
xor bx,bx ; We will load it to [ES:0000], ES loaded before function call
movzx cx,BYTE [SectsPerCluster]
movzx cx,BYTE [BYTE bp+SectsPerCluster]
call ReadSectors
ret
times 998-($-$$) db 0 ; Pad to 998 bytes
; 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
msgFreeLdr db 'FREELDR.SYS not found',0dh,0ah,0
filename db 'FREELDR SYS'
msgLoading db 'Loading FreeLoader...',0dh,0ah,0
times 1022-($-$$) db 0 ; Pad to 1022 bytes
dw 0aa55h ; BootSector signature

View file

@ -25,17 +25,17 @@ export RM = cmd /C del
export CP = cmd /C copy
#FLAGS = -Wall -nostdinc -fno-builtin
#FLAGS = -Wall -fno-builtin -DDEBUG
FLAGS = -Wall -fno-builtin
FLAGS = -Wall -fno-builtin -DDEBUG
#FLAGS = -Wall -fno-builtin
# asmcode.o has to be first in the link line because it contains the startup code
OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
OBJS = asmcode.a asmcode.o mb.o boot.o freeldr.o stdlib.o fs.a fs.o fat.o \
reactos.o tui.o menu.o miscboot.o options.o linux.o multiboot.o arcname.o \
mem.o memory.o debug.o parseini.o
ASM_OBJS = asmcode.o mb.o boot.o mem.o
C_OBJS = freeldr.o stdlib.o fs.a reactos.o tui.o menu.o miscboot.o options.o linux.o \
multiboot.o
C_OBJS2 = arcname.o memory.o debug.o parseini.o rs232.o portio.o
C_OBJS2 = arcname.o memory.o debug.o parseini.o rs232.o portio.o oslist.o
.PHONY : clean
@ -66,14 +66,14 @@ freeldr.o: freeldr.c freeldr.h stdlib.h fs.h reactos.h tui.h asmcode.h menu.h mi
stdlib.o: stdlib.c freeldr.h stdlib.h Makefile
$(CC) $(FLAGS) -o stdlib.o -c stdlib.c
fs.a: fs.o fs_fat.o Makefile
$(LD) -r -o fs.a fs.o fs_fat.o
fs.a: fs.o fat.o Makefile
$(LD) -r -o fs.a fs.o fat.o
fs.o: fs.c freeldr.h fs.h stdlib.h tui.h asmcode.h Makefile
$(CC) $(FLAGS) -o fs.o -c fs.c
fs_fat.o: fs_fat.c freeldr.h fs.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o fs_fat.o -c fs_fat.c
fat.o: fat.c fat.h freeldr.h fs.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o fat.o -c fat.c
reactos.o: reactos.c freeldr.h reactos.h stdlib.h fs.h tui.h multiboot.h Makefile
$(CC) $(FLAGS) -o reactos.o -c reactos.c
@ -123,6 +123,9 @@ rs232.o: rs232.c rs232.h Makefile
portio.o: portio.c portio.h Makefile
$(CC) $(FLAGS) -o portio.o -c portio.c
oslist.o: oslist.c oslist.h Makefile
$(CC) $(FLAGS) -o oslist.o -c oslist.c
clean:
$(RM) *.o
$(RM) *.a

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -376,10 +376,8 @@ EXTERN(_gotoxy)
ret
/*
* int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer);
* BOOL BiosInt13Read(ULONG Drive, ULONG Head, ULONG Track, ULONG Sector, ULONG SectorCount, PVOID Buffer);
*/
_biosdisk_cmd:
.long 0
_biosdisk_drive:
.long 0
_biosdisk_head:
@ -396,7 +394,7 @@ _biosdisk_retval:
.long 0
_biosdisk_retrycount:
.byte 0
EXTERN(_biosdisk)
EXTERN(_BiosInt13Read)
.code32
push %ebp
@ -408,18 +406,16 @@ EXTERN(_biosdisk)
/* Get parameters */
movl 0x1c(%esp),%eax
movl %eax,_biosdisk_cmd
movl 0x20(%esp),%eax
movl %eax,_biosdisk_drive
movl 0x24(%esp),%eax
movl 0x20(%esp),%eax
movl %eax,_biosdisk_head
movl 0x28(%esp),%eax
movl 0x24(%esp),%eax
movl %eax,_biosdisk_track
movl 0x2c(%esp),%eax
movl 0x28(%esp),%eax
movl %eax,_biosdisk_sector
movl 0x30(%esp),%eax
movl 0x2c(%esp),%eax
movl %eax,_biosdisk_nsects
movl 0x34(%esp),%eax
movl 0x30(%esp),%eax
movl %eax,_biosdisk_buffer
call switch_to_real
@ -429,9 +425,11 @@ EXTERN(_biosdisk)
movb $3,_biosdisk_retrycount // Set the retry count to 3
_biosdisk_read:
movw $SCRATCHSEG,%ax // Load ES with 7000
movw %ax,%es // and BX with 0
movw $SCRATCHOFF,%bx // so that the sector gets loaded to 7000:0000
movl _biosdisk_buffer,%eax // Get buffer address in eax
shrl $4,%eax // Make linear address into segment
movw %ax,%es // Load ES with segment
movl _biosdisk_buffer,%ebx // and BX with offset
andl $0x0f,%ebx // so that data gets loaded to [ES:BX]
movb _biosdisk_sector,%cl // Get the sector in CL
movw _biosdisk_track,%ax // Cylinder in AX
movb %al,%ch // Now put it in CH
@ -487,17 +485,6 @@ _biosdisk_done:
.code32
/* Copy the sector contents from 7000:0000 to the buffer */
cld
movl $SCRATCHAREA,%esi
movl _biosdisk_buffer,%edi
movl _biosdisk_nsects,%eax
movl $0x100,%ebx
mull %ebx
movl %eax,%ecx
rep
movsw
movl _biosdisk_retval,%eax // Get return value
//movl $1,%eax
@ -509,6 +496,176 @@ _biosdisk_done:
pop %ebp
ret
/*
* BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer);
*/
_disk_address_packet:
_packet_size:
.byte 0x10
_packet_reserved:
.byte 0
_packet_sector_count:
.word 0
_packet_transfer_buffer_segment:
.word 0
_packet_transfer_buffer_offset:
.word 0
_packet_lba_sector_number:
.quad 0
_packet_64bit_flat_address:
.quad 0
_int13_extended_drive:
.long 0
_int13_extended_sector_count:
.long 0
_int13_extended_retval:
.long 0
_int13_extended_retrycount:
.byte 0
EXTERN(_BiosInt13ReadExtended)
.code32
push %ebp
push %esi
push %edi
push %ebx
push %ecx
push %edx
/* Get parameters */
movl 0x1c(%esp),%eax
movl %eax,_int13_extended_drive
movl 0x20(%esp),%eax
movl %eax,_packet_lba_sector_number
movl 0x24(%esp),%eax
movw %ax,_packet_sector_count
movl %eax,_int13_extended_sector_count
movl 0x28(%esp),%eax // Get buffer address in eax
shrl $4,%eax // Make linear address into segment
movw %ax,_packet_transfer_buffer_segment // Save segment
movl 0x28(%esp),%eax // Get buffer address in eax
andl $0x0f,%eax // Make linear address into offset
movw %ax,_packet_transfer_buffer_offset // Save offset
call switch_to_real
.code16
pushw %es // Save this just in case
movb $3,_int13_extended_retrycount // Set the retry count to 3
_int13_extended_read:
movb _int13_extended_drive,%dl // Get the drive
movb $42,%ah // BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
movw $_disk_address_packet,%si // DS:SI -> disk address packet
int $0x13 // Read sectors
movb $1,%al // Set the return value to be one (will be set to zero later if needed)
jc _int13_extended_error // Jump if error (CF = 1 on error)
movl _int13_extended_sector_count,%eax // Get the sector count in eax
cmpw _packet_sector_count,%ax // See how many sectors we actually read (returned in disk address packet sector count)
jne _int13_extended_error // Jump if not equal
jmp _int13_extended_done
_int13_extended_error:
cmpb $0x11,%ah // Check and see if it was a corrected ECC error
je _int13_extended_done // If so then the data is still good, if not fail
movb _int13_extended_retrycount,%al // Get the current retry count
decb %al // Decrement it
movb %al,_int13_extended_retrycount // Save it
cmpb $0,%al // Is it zero?
jz _int13_extended_zero // Yes, return zero
movb $0,%ah // BIOS int 0x13, function 0 - Reset Disk System
movb _int13_extended_drive,%dl // Get the drive
int $0x13 // Reset the disk system
jmp _int13_extended_read // Try reading again
_int13_extended_zero:
movb $0,%al // We will return zero
_int13_extended_done:
movzbl %al,%eax // Put the number of sectors read into EAX
movl %eax,_int13_extended_retval // Save it as the return value
popw %es // Restore ES
call switch_to_prot
.code32
movl _int13_extended_retval,%eax // Get return value
//movl $1,%eax
pop %edx
pop %ecx
pop %ebx
pop %edi
pop %esi
pop %ebp
ret
/*
* BOOL BiosInt13ExtensionsSupported(ULONG Drive);
*/
_int13_extension_check_drive:
.long 0
_int13_extension_check_retval:
.long 0
EXTERN(_BiosInt13ExtensionsSupported)
.code32
push %ebp
push %esi
push %edi
push %ebx
push %ecx
push %edx
/* Get parameters */
movl 0x1c(%esp),%eax
movl %eax,_int13_extension_check_drive
call switch_to_real
.code16
// Now make sure this computer supports extended reads
movb $0x41,%ah // AH = 41h
movw $0x55aa,%bx // BX = 55AAh
movb _int13_extension_check_drive,%dl // DL = drive (80h-FFh)
int $0x13 // IBM/MS INT 13 Extensions - INSTALLATION CHECK
jc _int13_extension_check_error // CF set on error (extensions not supported)
cmpw $0x55aa,%bx // BX = AA55h if installed
jne _int13_extension_check_error
testb $1,%cl // CX = API subset support bitmap
jz _int13_extension_check_error // Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
// If we get here then we passed all the int13 extension tests
movl $1,_int13_extension_check_retval // Set return value to TRUE
jmp _int13_extension_check_done
_int13_extension_check_error:
movl $0,_int13_extension_check_retval // The tests failed so return FALSE
_int13_extension_check_done:
call switch_to_prot
.code32
movl _int13_extension_check_retval,%eax // Get return value
pop %edx
pop %ecx
pop %ebx
pop %edi
pop %esi
pop %ebp
ret
/*
* int getyear(void);
*/
@ -996,7 +1153,7 @@ EXTERN(_get_heads)
jmp _get_heads_done
_get_heads_error:
movl $0x0e,_biosdisk_retval
movl $0xff,_biosdisk_retval
_get_heads_done:
@ -1049,7 +1206,7 @@ EXTERN(_get_cylinders)
jmp _get_cylinders_done
_get_cylinders_error:
movl $0x00,_biosdisk_retval
movl $0xff,_biosdisk_retval
_get_cylinders_done:
@ -1098,7 +1255,7 @@ EXTERN(_get_sectors)
jmp _get_sectors_done
_get_sectors_error:
movl $0x00,_biosdisk_retval
movl $0xff,_biosdisk_retval
_get_sectors_done:

View file

@ -39,18 +39,13 @@
#define NR_TASKS 128 /* Space reserved in the GDT for TSS descriptors */
#define STACK16ADDR 0x7000 /* The 16-bit stack top will be at 0000:7000 */
#define STACK32ADDR 0x60000 /* The 32-bit stack top will be at 6000:0000, or 0x60000 */
#define STACK32ADDR 0xA0000 /* The 32-bit stack top will be at 9000:FFFF, or 0x9FFFF */
#define FILESYSADDR 0x80000 /* The filesystem data address will be at 8000:0000, or 0x80000 */
#define DISKREADBUFFER 0x90000 /* Buffer to store data read in from the disk via the BIOS */
#define FATCLUSTERBUF 0x60000 /* The fat filesystem's cluster buffer */
#define SCREENBUFFER 0x68000 /* The screen contents will be saved here */
#define FREELDRINIADDR 0x6C000 /* The freeldr.ini load address will be at 6000:C000, or 0x6C000 */
#define SCRATCHSEG 0x7000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */
#define SCRATCHOFF 0x0000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */
#define SCRATCHAREA 0x70000 /* The 512-byte fixed scratch area will be at 7000:0000, or 0x70000 */
#define SCREENBUFFER 0x98000 /* The screen contents will be saved here */
#define SCREENXCOORD 0x98FA0 /* Address of the byte that contains the current column of the cursor */
#define SCREENYCOORD 0x98FA1 /* Address of the byte that contains the current row of the cursor */
/* Makes "x" a global variable or label */
#define EXTERN(x) .global x; x:

View file

@ -22,20 +22,26 @@
#include "stdlib.h"
#include "rs232.h"
#include "parseini.h"
#include "portio.h"
#ifdef DEBUG
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY;
ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | DPRINT_UI;
#define SCREEN 0
#define RS232 1
#define SCREEN 0
#define RS232 1
#define BOCHS 2
#define COM1 1
#define COM2 2
#define COM3 3
#define COM4 4
#define COM1 1
#define COM2 2
#define COM3 3
#define COM4 4
ULONG DebugPort = RS232; //SCREEN;
#define BOCHS_OUTPUT_PORT 0xe9
//ULONG DebugPort = RS232;
//ULONG DebugPort = SCREEN;
ULONG DebugPort = BOCHS;
ULONG ComPort = COM1;
ULONG BaudRate = 19200;
@ -47,13 +53,30 @@ VOID DebugInit(VOID)
}
}
void DebugPrint(ULONG Mask, char *format, ...)
VOID DebugPrintChar(UCHAR Character)
{
if (DebugPort == RS232)
{
Rs232PortPutByte(Character);
if (Character == '\n')
{
Rs232PortPutByte('\r');
}
}
else if (DebugPort == BOCHS)
{
WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character);
}
else
{
putchar(Character);
}
}
VOID DebugPrint(ULONG Mask, char *format, ...)
{
int *dataptr = (int *) &format;
char c, *ptr, str[16];
char buffer[512];
char *p = buffer;
int i;
// Mask out unwanted debug messages
if (!(Mask & DebugPrintMask))
@ -65,60 +88,50 @@ void DebugPrint(ULONG Mask, char *format, ...)
while ((c = *(format++)))
{
if (c != '%')
{
*p = c;
p++;
}
else
switch (c = *(format++))
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
ptr = str;
while (*ptr)
if (c != '%')
{
*p = *(ptr++);
p++;
DebugPrintChar(c);
}
break;
case 'c':
*p = (*(dataptr++))&0xff;
p++;
break;
case 's':
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++)))
else
{
*p = c;
p++;
}
break;
}
}
*p=0;
if (DebugPort == RS232)
{
for (i=0; buffer[i] != 0; i++)
{
Rs232PortPutByte(buffer[i]);
if (buffer[i] == '\n')
switch (c = *(format++))
{
Rs232PortPutByte('\r');
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
ptr = str;
while (*ptr)
{
DebugPrintChar(*(ptr++));
}
break;
case 'c':
DebugPrintChar((*(dataptr++))&0xff);
break;
case 's':
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++)))
{
DebugPrintChar(c);
}
break;
}
}
}
else
if (DebugPort == SCREEN)
{
print(buffer);
//getch();
}
}
#endif // defined DEBUG

View file

@ -23,39 +23,22 @@
#ifdef DEBUG
#define DPRINT_WARNING 0x00000001 // OR this with DebugPrintMask to enable debugger messages and other misc stuff
#define DPRINT_MEMORY 0x00000002 // OR this with DebugPrintMask to enable memory management messages
#define DPRINT_WARNING 0x00000001 // OR this with DebugPrintMask to enable debugger messages and other misc stuff
#define DPRINT_MEMORY 0x00000002 // OR this with DebugPrintMask to enable memory management messages
#define DPRINT_FILESYSTEM 0x00000004 // OR this with DebugPrintMask to enable file system messages
#define DPRINT_INIFILE 0x00000008 // OR this with DebugPrintMask to enable .ini file messages
#define DPRINT_UI 0x00000010 // OR this with DebugPrintMask to enable user interface messages
VOID DebugInit(VOID);
void DebugPrint(ULONG Mask, char *format, ...);
VOID DebugInit(VOID);
VOID DebugPrint(ULONG Mask, char *format, ...);
#define BugCheck0(format) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format); \
for (;;); \
}
#define DbgPrint(_x_) DebugPrint _x_
#define BugCheck(_x_) { DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); DebugPrint _x_ ; for (;;); }
#define BugCheck1(format, arg1) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format, arg1); \
for (;;); \
}
#else
#define BugCheck2(format, arg1, arg2) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format, arg1, arg2); \
for (;;); \
}
#define BugCheck3(format, arg1, arg2, arg3) \
{ \
DebugPrint(DPRINT_WARNING, "Fatal Error: %s:%d\n", __FILE__, __LINE__); \
DebugPrint(DPRINT_WARNING, format, arg1, arg2, arg3); \
for (;;); \
}
#define DbgPrint(_x_)
#define BugCheck(_x_)
#endif // defined DEBUG

1163
freeldr/freeldr/fat.c Normal file

File diff suppressed because it is too large Load diff

179
freeldr/freeldr/fat.h Normal file
View file

@ -0,0 +1,179 @@
/*
* FreeLoader
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __FAT_H
#define __FAT_H
typedef struct _FAT_BOOTSECTOR
{
BYTE JumpBoot[3]; // Jump instruction to boot code
UCHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
WORD BytesPerSector; // Bytes per sector
BYTE SectorsPerCluster; // Number of sectors in a cluster
WORD ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
BYTE NumberOfFats; // Number of FAT tables
WORD RootDirEntries; // Number of root directory entries (fat12/16)
WORD TotalSectors; // Number of total sectors on the drive, 16-bit
BYTE MediaDescriptor; // Media descriptor byte
WORD SectorsPerFat; // Sectors per FAT table (fat12/16)
WORD SectorsPerTrack; // Number of sectors in a track
WORD NumberOfHeads; // Number of heads on the disk
DWORD HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
DWORD TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
BYTE DriveNumber; // Int 0x13 drive number (e.g. 0x80)
BYTE Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
BYTE BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
DWORD VolumeSerialNumber; // Volume serial number
UCHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
UCHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT "
BYTE BootCodeAndData[448]; // The remainder of the boot sector
WORD BootSectorMagic; // 0xAA55
} PACKED FAT_BOOTSECTOR, *PFAT_BOOTSECTOR;
typedef struct _FAT32_BOOTSECTOR
{
BYTE JumpBoot[3]; // Jump instruction to boot code
UCHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes
WORD BytesPerSector; // Bytes per sector
BYTE SectorsPerCluster; // Number of sectors in a cluster
WORD ReservedSectors; // Reserved sectors, usually 1 (the bootsector)
BYTE NumberOfFats; // Number of FAT tables
WORD RootDirEntries; // Number of root directory entries (fat12/16)
WORD TotalSectors; // Number of total sectors on the drive, 16-bit
BYTE MediaDescriptor; // Media descriptor byte
WORD SectorsPerFat; // Sectors per FAT table (fat12/16)
WORD SectorsPerTrack; // Number of sectors in a track
WORD NumberOfHeads; // Number of heads on the disk
DWORD HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
DWORD TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume
DWORD SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0
WORD ExtendedFlags; // Extended flags (fat32)
WORD FileSystemVersion; // File system version (fat32)
DWORD RootDirStartCluster; // Starting cluster of the root directory (fat32)
WORD FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1.
WORD BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6.
BYTE Reserved[12]; // Reserved for future expansion
BYTE DriveNumber; // Int 0x13 drive number (e.g. 0x80)
BYTE Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.
BYTE BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.
DWORD VolumeSerialNumber; // Volume serial number
UCHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory
UCHAR FileSystemType[8]; // Always set to the string "FAT32 "
BYTE BootCodeAndData[420]; // The remainder of the boot sector
WORD BootSectorMagic; // 0xAA55
} PACKED FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR;
/*
* Structure of MSDOS directory entry
*/
typedef struct //_DIRENTRY
{
UCHAR FileName[11]; /* Filename + extension */
UINT8 Attr; /* File attributes */
UINT8 ReservedNT; /* Reserved for use by Windows NT */
UINT8 TimeInTenths; /* Millisecond stamp at file creation */
UINT16 CreateTime; /* Time file was created */
UINT16 CreateDate; /* Date file was created */
UINT16 LastAccessDate; /* Date file was last accessed */
UINT16 ClusterHigh; /* High word of this entry's start cluster */
UINT16 Time; /* Time last modified */
UINT16 Date; /* Date last modified */
UINT16 ClusterLow; /* First cluster number low word */
UINT32 Size; /* File size */
} PACKED DIRENTRY, * PDIRENTRY;
typedef struct
{
UINT8 SequenceNumber; /* Sequence number for slot */
WCHAR Name0_4[5]; /* First 5 characters in name */
UINT8 EntryAttributes; /* Attribute byte */
UINT8 Reserved; /* Always 0 */
UINT8 AliasChecksum; /* Checksum for 8.3 alias */
WCHAR Name5_10[6]; /* 6 more characters in name */
UINT16 StartCluster; /* Starting cluster number */
WCHAR Name11_12[2]; /* Last 2 characters in name */
} PACKED LFN_DIRENTRY, * PLFN_DIRENTRY;
typedef struct
{
ULONG FileSize; // File size
ULONG FilePointer; // File pointer
PUINT32 FileFatChain; // File fat chain array
} FAT_FILE_INFO, * PFAT_FILE_INFO;
BOOL FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartHead, ULONG VolumeStartTrack, ULONG VolumeStartSector, ULONG FatFileSystemType);
PVOID FatBufferDirectory(UINT32 DirectoryStartCluster, PUINT32 EntryCountPointer, BOOL RootDirectory);
BOOL FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, UINT32 EntryCount, PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
BOOL FatLookupFile(PUCHAR FileName, PFAT_FILE_INFO FatFileInfoPointer);
ULONG FatGetNumPathParts(PUCHAR Path);
VOID FatGetFirstNameFromPath(PUCHAR Buffer, PUCHAR Path);
void FatParseShortFileName(PUCHAR Buffer, PDIRENTRY DirEntry);
DWORD FatGetFatEntry(DWORD nCluster);
FILE* FatOpenFile(PUCHAR FileName);
UINT32 FatCountClustersInChain(UINT32 StartCluster);
PUINT32 FatGetClusterChainArray(UINT32 StartCluster);
BOOL FatReadCluster(ULONG ClusterNumber, PVOID Buffer);
BOOL FatReadClusterChain(ULONG StartClusterNumber, ULONG NumberOfClusters, PVOID Buffer);
BOOL FatReadPartialCluster(ULONG ClusterNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer);
BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
ULONG FatGetFileSize(FILE *FileHandle);
VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
ULONG FatGetFilePointer(FILE *FileHandle);
/*BOOL FatLookupFile(char *file, PFAT_STRUCT pFatStruct);
int FatGetNumPathParts(char *name);
BOOL FatGetFirstNameFromPath(char *buffer, char *name);
void FatParseFileName(char *buffer, char *name);
DWORD FatGetFatEntry(DWORD nCluster);
int FatReadCluster(DWORD nCluster, char *cBuffer);
int FatRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer);
int Fatfseek(PFAT_STRUCT pFatStruct, DWORD offset);
FILE* FatOpenFile(PUCHAR FileName);
BOOL FatReadFile(FILE *FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
ULONG FatGetFileSize(FILE *FileHandle);
VOID FatSetFilePointer(FILE *FileHandle, ULONG NewFilePointer);
ULONG FatGetFilePointer(FILE *FileHandle);*/
#define EOF -1
#define ATTR_NORMAL 0x00
#define ATTR_READONLY 0x01
#define ATTR_HIDDEN 0x02
#define ATTR_SYSTEM 0x04
#define ATTR_VOLUMENAME 0x08
#define ATTR_DIRECTORY 0x10
#define ATTR_ARCHIVE 0x20
#define ATTR_LONG_NAME (ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUMENAME)
#define FAT12 1
#define FAT16 2
#define FAT32 3
#endif // #defined __FAT_H

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -29,41 +29,42 @@
#include "memory.h"
#include "parseini.h"
#include "debug.h"
#include "oslist.h"
// Variable BootDrive moved to asmcode.S
//ULONG BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
ULONG BootPartition = 0; // Boot Partition, 1-4
BOOL UserInterfaceUp = FALSE; // Tells us if the user interface is displayed
//ULONG BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
ULONG BootPartition = 0; // Boot Partition, 1-4
PUCHAR ScreenBuffer = (PUCHAR)(SCREENBUFFER); // Save buffer for screen contents
int CursorXPos = 0; // Cursor's X Position
int CursorYPos = 0; // Cursor's Y Position
PUCHAR ScreenBuffer = (PUCHAR)(SCREENBUFFER); // Save buffer for screen contents
ULONG CursorXPos = 0; // Cursor's X Position
ULONG CursorYPos = 0; // Cursor's Y Position
OSTYPE OSList[16];
int nNumOS = 0;
ULONG GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], ULONG OperatingSystemCount);
LONG GetTimeOut(VOID);
int nTimeOut = -1; // Time to wait for the user before booting
void BootMain(void)
VOID BootMain(VOID)
{
int i;
char name[1024];
char value[1024];
int nOSToBoot;
ULONG Idx;
UCHAR SettingName[80];
UCHAR SettingValue[80];
ULONG SectionId;
ULONG OperatingSystemCount;
PUCHAR *OperatingSystemSectionNames;
PUCHAR *OperatingSystemDisplayNames;
ULONG DefaultOperatingSystem;
LONG TimeOut;
ULONG SelectedOperatingSystem;
enable_a20();
SaveScreen(ScreenBuffer);
CursorXPos = wherex();
CursorYPos = wherey();
printf("Loading FreeLoader...\n");
CursorXPos = (ULONG) *((PUCHAR)(SCREENXCOORD));
CursorYPos = (ULONG) *((PUCHAR)(SCREENYCOORD));
#ifdef DEBUG
DebugInit();
#endif
InitMemoryManager((PVOID)0x100000, 0x20000);
InitMemoryManager( (PVOID) 0x20000 /* BaseAddress */, 0x70000 /* Length */);
if (!ParseIniFile())
{
@ -72,39 +73,63 @@ void BootMain(void)
return;
}
clrscr();
hidecursor();
// Draw the backdrop and title box
DrawBackdrop();
UserInterfaceUp = TRUE;
if (nNumOS == 0)
if (!OpenSection("FreeLoader", &SectionId))
{
DrawStatusText(" Press ENTER to reboot");
MessageBox("Error: there were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
clrscr();
showcursor();
RestoreScreen(ScreenBuffer);
printf("Section [FreeLoader] not found in freeldr.ini.\n");
getch();
return;
}
DrawStatusText(" Press ENTER to continue");
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems("FREELOADER"); i++)
if (!InitUserInterface())
{
ReadSectionSettingByNumber("FREELOADER", i, name, value);
if (stricmp(name, "MessageBox") == 0)
MessageBox(value);
if (stricmp(name, "MessageLine") == 0)
MessageLine(value);
printf("Press any key to reboot.\n");
getch();
return;
}
if (!InitOperatingSystemList(&OperatingSystemSectionNames, &OperatingSystemDisplayNames, &OperatingSystemCount))
{
MessageBox("Press ENTER to reboot.\n");
goto reboot;
}
if (OperatingSystemCount == 0)
{
MessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
goto reboot;
}
DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemSectionNames, OperatingSystemCount);
TimeOut = GetTimeOut();
//
// Find all the message box settings and run them
//
for (Idx=0; Idx<GetNumSectionItems(SectionId); Idx++)
{
ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
if (stricmp(SettingName, "MessageBox") == 0)
{
MessageBox(SettingValue);
}
else if (stricmp(SettingName, "MessageLine") == 0)
{
MessageLine(SettingValue);
}
}
for (;;)
{
nOSToBoot = RunMenu();
if (!DisplayMenu(OperatingSystemDisplayNames, OperatingSystemCount, DefaultOperatingSystem, TimeOut, &SelectedOperatingSystem))
{
MessageBox("Press ENTER to reboot.\n");
return;
}
switch (OSList[nOSToBoot].nOSType)
LoadAndBootReactOS(OperatingSystemSectionNames[SelectedOperatingSystem]);
/*switch (OSList[nOSToBoot].nOSType)
{
case OSTYPE_REACTOS:
LoadAndBootReactOS(OSList[nOSToBoot].name);
@ -121,13 +146,67 @@ void BootMain(void)
case OSTYPE_DRIVE:
LoadAndBootDrive(nOSToBoot);
break;
}
DrawBackdrop();
}*/
}
MessageBox("Press any key to reboot.");
reboot:
RestoreScreen(ScreenBuffer);
showcursor();
gotoxy(CursorXPos, CursorYPos);
return;
}
ULONG GetDefaultOperatingSystem(PUCHAR OperatingSystemList[], ULONG OperatingSystemCount)
{
UCHAR DefaultOSText[80];
ULONG SectionId;
ULONG DefaultOS;
ULONG Idx;
if (!OpenSection("FreeLoader", &SectionId))
{
return 0;
}
if (ReadSectionSettingByName(SectionId, "DefaultOS", DefaultOSText, 80))
{
for (Idx=0; Idx<OperatingSystemCount; Idx++)
{
if (stricmp(DefaultOSText, OperatingSystemList[Idx]) == 0)
{
DefaultOS = Idx;
break;
}
}
}
else
{
DefaultOS = 0;
}
return DefaultOS;
}
LONG GetTimeOut(VOID)
{
UCHAR TimeOutText[20];
ULONG TimeOut;
ULONG SectionId;
if (!OpenSection("FreeLoader", &SectionId))
{
return -1;
}
if (ReadSectionSettingByName(SectionId, "TimeOut", TimeOutText, 20))
{
TimeOut = atoi(TimeOutText);
}
else
{
TimeOut = -1;
}
return TimeOut;
}

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -54,33 +54,27 @@
#define PWORD WORD *
#define VOID void
#define PVOID VOID*
#define INT8 char
#define UINT8 unsigned char
#define INT16 short
#define UINT16 unsigned short
#define INT32 long
#define UINT32 unsigned long
#define PUINT32 UINT32 *
#define INT64 long long
#define UINT64 unsigned long long
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define OSTYPE_REACTOS 1
#define OSTYPE_LINUX 2
#define OSTYPE_BOOTSECTOR 3
#define OSTYPE_PARTITION 4
#define OSTYPE_DRIVE 5
typedef struct
{
char name[260];
int nOSType; // ReactOS or Linux or a bootsector, etc.
} OSTYPE, *POSTYPE;
#define PACKED __attribute__((packed))
extern ULONG BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
extern ULONG BootPartition; // Boot Partition, 1-4
extern BOOL UserInterfaceUp; // Tells us if the user interface is displayed
extern PUCHAR ScreenBuffer; // Save buffer for screen contents
extern int CursorXPos; // Cursor's X Position
extern int CursorYPos; // Cursor's Y Position
extern OSTYPE OSList[16]; // The OS list
extern int nNumOS; // Number of OSes listed
extern int nTimeOut; // Time to wait for the user before booting
extern ULONG CursorXPos; // Cursor's X Position
extern ULONG CursorYPos; // Cursor's Y Position
void BootMain(void);

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -19,251 +19,238 @@
#include "freeldr.h"
#include "fs.h"
#include "fat.h"
#include "stdlib.h"
#include "tui.h"
#include "asmcode.h"
#define FS_DO_ERROR(s) \
{ \
if (UserInterfaceUp) \
MessageBox(s); \
else \
{ \
printf(s); \
printf("\nPress any key\n"); \
getch(); \
} \
}
#include "debug.h"
int nSectorBuffered = -1; // Tells us which sector was read into SectorBuffer[]
/////////////////////////////////////////////////////////////////////////////////////////////
// DATA
/////////////////////////////////////////////////////////////////////////////////////////////
BYTE SectorBuffer[512]; // 512 byte buffer space for read operations, ReadOneSector reads to here
GEOMETRY DriveGeometry;
ULONG VolumeHiddenSectors;
ULONG CurrentlyOpenDriveNumber;
ULONG FileSystemType = 0; // Type of filesystem on boot device, set by OpenDiskDrive()
int FSType = NULL; // Type of filesystem on boot device, set by OpenDiskDrive()
/////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
char *pFileSysData = (char *)(FILESYSADDR); // Load address for filesystem data
char *pFat32FATCacheIndex = (char *)(FILESYSADDR); // Load address for filesystem data
BOOL OpenDiskDrive(int nDrive, int nPartition)
VOID FileSystemError(PUCHAR ErrorString)
{
int num_bootable_partitions = 0;
int boot_partition = 0;
int partition_type = 0;
int head, sector, cylinder;
int offset;
DbgPrint((DPRINT_FILESYSTEM, "%s\n", ErrorString));
// Check and see if it is a floppy drive
if (nDrive < 0x80)
if (UserInterfaceUp)
{
// Read boot sector
if (!biosdisk(_DISK_READ, nDrive, 0, 0, 1, 1, SectorBuffer))
{
FS_DO_ERROR("Disk Read Error");
return FALSE;
}
// Check for validity
if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
{
FS_DO_ERROR("Invalid boot sector magic (0xaa55)");
return FALSE;
}
MessageBox(ErrorString);
}
else
{
// Read master boot record
if (!biosdisk(_DISK_READ, nDrive, 0, 0, 1, 1, SectorBuffer))
printf("%s", ErrorString);
printf("\nPress any key\n");
getch();
}
}
/*
*
* BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
*
* This function is called to open a disk drive for file access.
* It must be called before any of the file functions will work.
* It takes two parameters:
*
* Drive: The BIOS drive number of the disk to open
* Partition: This is zero for floppy drives.
* If the disk is a hard disk then this specifies
* The partition number to open (1 - 4)
* If it is zero then it opens the active (bootable) partition
*
*/
BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber)
{
ULONG BootablePartitionCount = 0;
ULONG BootPartition = 0;
ULONG PartitionStartHead;
ULONG PartitionStartSector;
ULONG PartitionStartCylinder;
MASTER_BOOT_RECORD DriveMasterBootRecord;
DbgPrint((DPRINT_FILESYSTEM, "OpenDiskDrive() DriveNumber: 0x%x PartitionNumber: 0x%x\n", DriveNumber, PartitionNumber));
CurrentlyOpenDriveNumber = DriveNumber;
//
// Check and see if it is a floppy drive
// If so then just assume FAT12 file system type
//
if (DriveNumber < 0x80)
{
DbgPrint((DPRINT_FILESYSTEM, "Drive is a floppy diskette drive. Assuming FAT12 file system.\n"));
FileSystemType = FS_FAT;
return FatOpenVolume(DriveNumber, 0, 0, 1, FAT12);
}
//
// Read master boot record
//
if (!BiosInt13Read(DriveNumber, 0, 0, 1, 1, &DriveMasterBootRecord))
{
FileSystemError("Disk read error.");
return FALSE;
}
#ifdef DEBUG
DbgPrint((DPRINT_FILESYSTEM, "Drive is a hard disk, dumping partition table:\n"));
DbgPrint((DPRINT_FILESYSTEM, "sizeof(MASTER_BOOT_RECORD) = 0x%x.\n", sizeof(MASTER_BOOT_RECORD)));
for (BootPartition=0; BootPartition<4; BootPartition++)
{
DbgPrint((DPRINT_FILESYSTEM, "-------------------------------------------\n"));
DbgPrint((DPRINT_FILESYSTEM, "Partition %d\n", (BootPartition + 1)));
DbgPrint((DPRINT_FILESYSTEM, "BootIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].BootIndicator));
DbgPrint((DPRINT_FILESYSTEM, "StartHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartHead));
DbgPrint((DPRINT_FILESYSTEM, "StartSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartSector));
DbgPrint((DPRINT_FILESYSTEM, "StartCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].StartCylinder));
DbgPrint((DPRINT_FILESYSTEM, "SystemIndicator: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SystemIndicator));
DbgPrint((DPRINT_FILESYSTEM, "EndHead: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndHead));
DbgPrint((DPRINT_FILESYSTEM, "EndSector (Plus 2 cylinder bits): 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndSector));
DbgPrint((DPRINT_FILESYSTEM, "EndCylinder: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].EndCylinder));
DbgPrint((DPRINT_FILESYSTEM, "SectorCountBeforePartition: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].SectorCountBeforePartition));
DbgPrint((DPRINT_FILESYSTEM, "PartitionSectorCount: 0x%x\n", DriveMasterBootRecord.PartitionTable[BootPartition].PartitionSectorCount));
}
#endif // defined DEBUG
//
// Check the partition table magic value
//
if (DriveMasterBootRecord.MasterBootRecordMagic != 0xaa55)
{
FileSystemError("Invalid partition table magic (0xaa55)");
return FALSE;
}
if (PartitionNumber == 0)
{
//
// Count the bootable partitions
//
if (DriveMasterBootRecord.PartitionTable[0].BootIndicator == 0x80)
{
FS_DO_ERROR("Disk Read Error");
return FALSE;
BootablePartitionCount++;
BootPartition = 1;
}
if (DriveMasterBootRecord.PartitionTable[1].BootIndicator == 0x80)
{
BootablePartitionCount++;
BootPartition = 2;
}
if (DriveMasterBootRecord.PartitionTable[2].BootIndicator == 0x80)
{
BootablePartitionCount++;
BootPartition = 3;
}
if (DriveMasterBootRecord.PartitionTable[3].BootIndicator == 0x80)
{
BootablePartitionCount++;
BootPartition = 4;
}
// Check for validity
if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
//
// Make sure there was only one bootable partition
//
if (BootablePartitionCount != 1)
{
FS_DO_ERROR("Invalid partition table magic (0xaa55)");
FileSystemError("Too many bootable partitions or none found.");
return FALSE;
}
if (nPartition == 0)
{
// Check for bootable partitions
if (SectorBuffer[0x1BE] == 0x80)
num_bootable_partitions++;
if (SectorBuffer[0x1CE] == 0x80)
{
num_bootable_partitions++;
boot_partition = 1;
}
if (SectorBuffer[0x1DE] == 0x80)
{
num_bootable_partitions++;
boot_partition = 2;
}
if (SectorBuffer[0x1EE] == 0x80)
{
num_bootable_partitions++;
boot_partition = 3;
}
// Make sure there was only one bootable partition
if (num_bootable_partitions > 1)
{
FS_DO_ERROR("Too many boot partitions");
return FALSE;
}
offset = 0x1BE + (boot_partition * 0x10);
}
else
offset = 0x1BE + ((nPartition-1) * 0x10);
partition_type = SectorBuffer[offset + 4];
// Check for valid partition
if (partition_type == 0)
{
FS_DO_ERROR("Invalid boot partition");
return FALSE;
}
head = SectorBuffer[offset + 1];
sector = (SectorBuffer[offset + 2] & 0x3F);
cylinder = SectorBuffer[offset + 3];
if (SectorBuffer[offset + 2] & 0x80)
cylinder += 0x200;
if (SectorBuffer[offset + 2] & 0x40)
cylinder += 0x100;
// Read partition boot sector
if (!biosdisk(_DISK_READ, nDrive, head, cylinder, sector, 1, SectorBuffer))
{
FS_DO_ERROR("Disk Read Error");
return FALSE;
}
// Check for validity
if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)//(SectorBuffer[0x1FE] != 0x55) || (SectorBuffer[0x1FF] != 0xAA))
{
FS_DO_ERROR("Invalid boot sector magic (0xaa55)");
return FALSE;
//
// We found the boot partition, so set the partition number
//
PartitionNumber = BootPartition;
}
}
//
// Right now the partition number is one-based
// and we need zero based
//
PartitionNumber--;
// Reset data
nBytesPerSector = 0;
nSectorsPerCluster = 0;
nReservedSectors = 0;
nNumberOfFATs = 0;
nRootDirEntries = 0;
nTotalSectors16 = 0;
nSectorsPerFAT16 = 0;
nSectorsPerTrack = 0;
nNumberOfHeads = 0;
nHiddenSectors = 0;
nTotalSectors32 = 0;
nSectorsPerFAT32 = 0;
nExtendedFlags = 0;
nFileSystemVersion = 0;
nRootDirStartCluster = 0;
nRootDirSectorStart = 0;
nDataSectorStart = 0;
nSectorsPerFAT = 0;
nRootDirSectors = 0;
nTotalSectors = 0;
nNumberOfClusters = 0;
// Get data
memcpy(&nBytesPerSector, SectorBuffer + BPB_BYTESPERSECTOR, 2);
memcpy(&nSectorsPerCluster, SectorBuffer + BPB_SECTORSPERCLUSTER, 1);
memcpy(&nReservedSectors, SectorBuffer + BPB_RESERVEDSECTORS, 2);
memcpy(&nNumberOfFATs, SectorBuffer + BPB_NUMBEROFFATS, 1);
memcpy(&nRootDirEntries, SectorBuffer + BPB_ROOTDIRENTRIES, 2);
memcpy(&nTotalSectors16, SectorBuffer + BPB_TOTALSECTORS16, 2);
memcpy(&nSectorsPerFAT16, SectorBuffer + BPB_SECTORSPERFAT16, 2);
memcpy(&nSectorsPerTrack, SectorBuffer + BPB_SECTORSPERTRACK, 2);
memcpy(&nNumberOfHeads, SectorBuffer + BPB_NUMBEROFHEADS, 2);
memcpy(&nHiddenSectors, SectorBuffer + BPB_HIDDENSECTORS, 4);
memcpy(&nTotalSectors32, SectorBuffer + BPB_TOTALSECTORS32, 4);
memcpy(&nSectorsPerFAT32, SectorBuffer + BPB_SECTORSPERFAT32, 4);
memcpy(&nExtendedFlags, SectorBuffer + BPB_EXTENDEDFLAGS32, 2);
memcpy(&nFileSystemVersion, SectorBuffer + BPB_FILESYSTEMVERSION32, 2);
memcpy(&nRootDirStartCluster, SectorBuffer + BPB_ROOTDIRSTARTCLUSTER32, 4);
// Calc some stuff
if (nTotalSectors16 != 0)
nTotalSectors = nTotalSectors16;
else
nTotalSectors = nTotalSectors32;
if (nSectorsPerFAT16 != 0)
nSectorsPerFAT = nSectorsPerFAT16;
else
nSectorsPerFAT = nSectorsPerFAT32;
nRootDirSectorStart = (nNumberOfFATs * nSectorsPerFAT) + nReservedSectors;
nRootDirSectors = ((nRootDirEntries * 32) + (nBytesPerSector - 1)) / nBytesPerSector;
nDataSectorStart = nReservedSectors + (nNumberOfFATs * nSectorsPerFAT) + nRootDirSectors;
nNumberOfClusters = (nTotalSectors - nDataSectorStart) / nSectorsPerCluster;
// Determine FAT type
if (nNumberOfClusters < 4085)
//
// Check for valid partition
//
if (DriveMasterBootRecord.PartitionTable[PartitionNumber].SystemIndicator == PARTITION_ENTRY_UNUSED)
{
/* Volume is FAT12 */
nFATType = FAT12;
}
else if (nNumberOfClusters < 65525)
{
/* Volume is FAT16 */
nFATType = FAT16;
}
else
{
/* Volume is FAT32 */
nFATType = FAT32;
// Check version
// we only work with version 0
if (*((WORD*)(SectorBuffer + BPB_FILESYSTEMVERSION32)) != 0)
{
FS_DO_ERROR("Error: FreeLoader is too old to work with this FAT32 filesystem.\nPlease update FreeLoader.");
return FALSE;
}
FileSystemError("Invalid partition.");
return FALSE;
}
FSType = FS_FAT;
PartitionStartHead = DriveMasterBootRecord.PartitionTable[PartitionNumber].StartHead;
PartitionStartSector = DriveMasterBootRecord.PartitionTable[PartitionNumber].StartSector & 0x3F;
PartitionStartCylinder = MAKE_CYLINDER(
DriveMasterBootRecord.PartitionTable[PartitionNumber].StartCylinder,
DriveMasterBootRecord.PartitionTable[PartitionNumber].StartSector);
// Buffer the FAT table if it is small enough
if ((FSType == FS_FAT) && (nFATType == FAT12))
DbgPrint((DPRINT_FILESYSTEM, "PartitionStartHead: %d\n", PartitionStartHead));
DbgPrint((DPRINT_FILESYSTEM, "PartitionStartSector: %d\n", PartitionStartSector));
DbgPrint((DPRINT_FILESYSTEM, "PartitionStartCylinder: %d\n", PartitionStartCylinder));
DbgPrint((DPRINT_FILESYSTEM, "PartitionNumber: %d\n", PartitionNumber));
switch (DriveMasterBootRecord.PartitionTable[PartitionNumber].SystemIndicator)
{
if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData))
return FALSE;
}
else if ((FSType == FS_FAT) && (nFATType == FAT16))
{
if (!ReadMultipleSectors(nReservedSectors, nSectorsPerFAT, pFileSysData))
return FALSE;
}
else if ((FSType == FS_FAT) && (nFATType == FAT32))
{
// The FAT table is too big to be buffered so
// we will initialize our cache and cache it
// on demand
for (offset=0; offset<256; offset++)
((int*)pFat32FATCacheIndex)[offset] = -1;
case PARTITION_FAT_12:
FileSystemType = FS_FAT;
return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT12);
case PARTITION_FAT_16:
case PARTITION_HUGE:
case PARTITION_XINT13:
FileSystemType = FS_FAT;
return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT16);
case PARTITION_FAT32:
case PARTITION_FAT32_XINT13:
FileSystemType = FS_FAT;
return FatOpenVolume(DriveNumber, PartitionStartHead, PartitionStartCylinder, PartitionStartSector, FAT32);
default:
FileSystemType = 0;
FileSystemError("Unsupported file system.");
return FALSE;
}
return TRUE;
}
BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
VOID SetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector)
{
BOOL bRetVal;
DriveGeometry.Cylinders = Cylinders;
DriveGeometry.Heads = Heads;
DriveGeometry.Sectors = Sectors;
DriveGeometry.BytesPerSector = BytesPerSector;
DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.Cylinders: %d\n", DriveGeometry.Cylinders));
DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.Heads: %d\n", DriveGeometry.Heads));
DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.Sectors: %d\n", DriveGeometry.Sectors));
DbgPrint((DPRINT_FILESYSTEM, "DriveGeometry.BytesPerSector: %d\n", DriveGeometry.BytesPerSector));
}
VOID SetVolumeProperties(ULONG HiddenSectors)
{
VolumeHiddenSectors = HiddenSectors;
}
BOOL ReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{
/*BOOL bRetVal;
int PhysicalSector;
int PhysicalHead;
int PhysicalTrack;
@ -292,7 +279,7 @@ BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
nNum = nNumberOfSectors;
}
bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
bRetVal = biosdisk(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
if (!bRetVal)
{
@ -303,124 +290,203 @@ BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
pBuffer += (nNum * 512);
nNumberOfSectors -= nNum;
nSect += nNum;
}
}*/
return TRUE;
}
ULONG CurrentSector;
PVOID RealBuffer = Buffer;
BOOL ReadOneSector(int nSect)
{
BOOL bRetVal;
int PhysicalSector;
int PhysicalHead;
int PhysicalTrack;
nSectorBuffered = nSect;
nSect += nHiddenSectors;
PhysicalSector = 1 + (nSect % nSectorsPerTrack);
PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, 1, SectorBuffer);
if (!bRetVal)
for (CurrentSector=SectorNumber; CurrentSector<(SectorNumber + SectorCount); CurrentSector++)
{
FS_DO_ERROR("Disk Error");
return FALSE;
}
return TRUE;
}
BOOL OpenFile(char *filename, FILE *pFile)
{
switch(FSType)
{
case FS_FAT:
if(!FATOpenFile(filename, &(pFile->fat)))
if (!ReadLogicalSector(CurrentSector, RealBuffer) )
{
return FALSE;
pFile->filesize = pFile->fat.dwSize;
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
return FALSE;
break;
}
RealBuffer += DriveGeometry.BytesPerSector;
}
return TRUE;
}
BOOL ReadLogicalSector(ULONG SectorNumber, PVOID Buffer)
{
ULONG PhysicalSector;
ULONG PhysicalHead;
ULONG PhysicalTrack;
DbgPrint((DPRINT_FILESYSTEM, "ReadLogicalSector() SectorNumber: %d Buffer: 0x%x\n", SectorNumber, Buffer));
SectorNumber += VolumeHiddenSectors;
PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
//DbgPrint((DPRINT_FILESYSTEM, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
if (PhysicalHead >= DriveGeometry.Heads)
{
BugCheck((DPRINT_FILESYSTEM, "PhysicalHead >= DriveGeometry.Heads\nPhysicalHead = %d\nDriveGeometry.Heads = %d\n", PhysicalHead, DriveGeometry.Heads));
}
if (PhysicalTrack >= DriveGeometry.Cylinders)
{
BugCheck((DPRINT_FILESYSTEM, "PhysicalTrack >= DriveGeometry.Cylinders\nPhysicalTrack = %d\nDriveGeometry.Cylinders = %d\n", PhysicalTrack, DriveGeometry.Cylinders));
}
if (PhysicalSector > DriveGeometry.Sectors)
{
BugCheck((DPRINT_FILESYSTEM, "PhysicalSector > DriveGeometry.Sectors\nPhysicalSector = %d\nDriveGeometry.Sectors = %d\n", PhysicalSector, DriveGeometry.Sectors));
}
if ((CurrentlyOpenDriveNumber >= 0x80) &&
(BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber)) &&
(SectorNumber > (DriveGeometry.Cylinders * DriveGeometry.Heads * DriveGeometry.Sectors)))
{
DbgPrint((DPRINT_FILESYSTEM, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", CurrentlyOpenDriveNumber, BiosInt13ExtensionsSupported(CurrentlyOpenDriveNumber) ? "TRUE" : "FALSE"));
if ( !BiosInt13ReadExtended(CurrentlyOpenDriveNumber, SectorNumber, 1, Buffer) )
{
FileSystemError("Disk read error.");
return FALSE;
}
}
else
{
if ( !BiosInt13Read(CurrentlyOpenDriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, 1, Buffer) )
{
FileSystemError("Disk read error.");
return FALSE;
}
}
return TRUE;
}
PFILE OpenFile(PUCHAR FileName)
{
PFILE FileHandle = NULL;
//
// Print status message
//
DbgPrint((DPRINT_FILESYSTEM, "Opening file '%s'...\n", FileName));
//
// Check file system type and pass off to appropriate handler
//
if (FileSystemType == FS_FAT)
{
FileHandle = FatOpenFile(FileName);
}
else
{
FileSystemError("Error: Unknown filesystem.");
}
#ifdef DEBUG
//
// Check return value
//
if (FileHandle != NULL)
{
DbgPrint((DPRINT_FILESYSTEM, "OpenFile() succeeded. FileHandle: 0x%x\n", FileHandle));
}
else
{
DbgPrint((DPRINT_FILESYSTEM, "OpenFile() failed.\n"));
}
#endif // defined DEBUG
return FileHandle;
}
VOID CloseFile(PFILE FileHandle)
{
}
/*
* ReadFile()
* returns number of bytes read or EOF
*/
int ReadFile(FILE *pFile, int count, void *buffer)
BOOL ReadFile(PFILE FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer)
{
switch(FSType)
//
// Set the number of bytes read equal to zero
//
if (BytesRead !=NULL)
{
*BytesRead = 0;
}
switch (FileSystemType)
{
case FS_FAT:
return FATRead(&(pFile->fat), count, buffer);
return FatReadFile(FileHandle, BytesToRead, BytesRead, Buffer);
default:
FS_DO_ERROR("Error: Unknown filesystem.");
return EOF;
FileSystemError("Unknown file system.");
return FALSE;
}
return FALSE;
}
ULONG GetFileSize(PFILE FileHandle)
{
switch (FileSystemType)
{
case FS_FAT:
return FatGetFileSize(FileHandle);
default:
FileSystemError("Unknown file system.");
break;
}
return 0;
}
DWORD GetFileSize(FILE *pFile)
VOID SetFilePointer(PFILE FileHandle, ULONG NewFilePointer)
{
return pFile->filesize;
}
DWORD Rewind(FILE *pFile)
{
switch (FSType)
switch (FileSystemType)
{
case FS_FAT:
pFile->fat.dwCurrentCluster = pFile->fat.dwStartCluster;
pFile->fat.dwCurrentReadOffset = 0;
FatSetFilePointer(FileHandle, NewFilePointer);
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
FileSystemError("Unknown file system.");
break;
}
}
ULONG GetFilePointer(PFILE FileHandle)
{
switch (FileSystemType)
{
case FS_FAT:
return FatGetFilePointer(FileHandle);
break;
default:
FileSystemError("Unknown file system.");
break;
}
return pFile->filesize;
return 0;
}
int feof(FILE *pFile)
BOOL IsEndOfFile(PFILE FileHandle)
{
switch (FSType)
if (GetFilePointer(FileHandle) >= GetFileSize(FileHandle))
{
case FS_FAT:
if (pFile->fat.dwCurrentReadOffset >= pFile->fat.dwSize)
return TRUE;
else
return FALSE;
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
return TRUE;
break;
}
return TRUE;
}
int fseek(FILE *pFile, DWORD offset)
{
switch (FSType)
else
{
case FS_FAT:
return FATfseek(&(pFile->fat), offset);
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
break;
return FALSE;
}
return -1;
}

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,148 +17,89 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __FS_FAT_H
#define __FS_FAT_H
#ifndef __FS_H
#define __FS_H
// Bootsector BPB defines
#define BPB_JMPBOOT 0
#define BPB_OEMNAME 3
#define BPB_BYTESPERSECTOR 11
#define BPB_SECTORSPERCLUSTER 13
#define BPB_RESERVEDSECTORS 14
#define BPB_NUMBEROFFATS 16
#define BPB_ROOTDIRENTRIES 17
#define BPB_TOTALSECTORS16 19
#define BPB_MEDIADESCRIPTOR 21
#define BPB_SECTORSPERFAT16 22
#define BPB_SECTORSPERTRACK 24
#define BPB_NUMBEROFHEADS 26
#define BPB_HIDDENSECTORS 28
#define BPB_TOTALSECTORS32 32
// Fat12/16 extended BPB defines
#define BPB_DRIVENUMBER16 36
#define BPB_RESERVED16_1 37
#define BPB_BOOTSIGNATURE16 38
#define BPB_VOLUMESERIAL16 39
#define BPB_VOLUMELABEL16 43
#define BPB_FILESYSTEMTYPE16 54
// Fat32 extended BPB defines
#define BPB_SECTORSPERFAT32 36
#define BPB_EXTENDEDFLAGS32 40
#define BPB_FILESYSTEMVERSION32 42
#define BPB_ROOTDIRSTARTCLUSTER32 44
#define BPB_FILESYSTEMINFOSECTOR32 48
#define BPB_BACKUPBOOTSECTOR32 50
#define BPB_RESERVED32_1 52
#define BPB_DRIVENUMBER32 64
#define BPB_RESERVED32_2 65
#define BPB_BOOTSIGNATURE32 66
#define BPB_VOLUMESERIAL32 67
#define BPB_VOLUMELABEL32 71
#define BPB_FILESYSTEMTYPE32 82
/*
* Structure of MSDOS directory entry
*/
typedef struct //_DIRENTRY
//
// Define the structure of a partition table entry
//
typedef struct _PARTITION_TABLE_ENTRY
{
BYTE cFileName[11]; /* Filename + extension */
BYTE cAttr; /* File attributes */
BYTE cReserved[10]; /* Reserved area */
WORD wTime; /* Time last modified */
WORD wData; /* Date last modified */
WORD wCluster; /* First cluster number */
DWORD dwSize; /* File size */
} DIRENTRY, * PDIRENTRY;
BYTE BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only)
BYTE StartHead; // Beginning head number
BYTE StartSector; // Beginning sector (2 high bits of cylinder #)
BYTE StartCylinder; // Beginning cylinder# (low order bits of cylinder #)
BYTE SystemIndicator; // System indicator
BYTE EndHead; // Ending head number
BYTE EndSector; // Ending sector (2 high bits of cylinder #)
BYTE EndCylinder; // Ending cylinder# (low order bits of cylinder #)
DWORD SectorCountBeforePartition; // Number of sectors preceding the partition
DWORD PartitionSectorCount; // Number of sectors in the partition
/*
* Structure of internal file control block
*/
typedef struct //_FCB
} PACKED PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
//
// This macro will return the cylinder when you pass it a cylinder/sector
// pair where the high 2 bits of the cylinder are stored in the sector byte
//
#define MAKE_CYLINDER(cylinder, sector) ( cylinder + ((((WORD)sector) & 0xC0) << 2) )
//
// Define the structure of the master boot record
//
typedef struct _MASTER_BOOT_RECORD
{
BYTE cAttr; /* Open attributes */
BYTE cSector; /* Sector within cluster */
PDIRENTRY pDirptr; /* Pointer to directory entry */
WORD wDirSector; /* Directory sector */
WORD wFirstCluster; /* First cluster in file */
WORD wLastCluster; /* Last cluster read/written */
WORD wNextCluster; /* Next cluster to read/write */
WORD wOffset; /* Read/Write offset within sector */
DWORD dwSize; /* File size */
BYTE cBuffer[512]; /* Data transfer buffer */
} FCB, * PFCB;
BYTE MasterBootRecordCodeAndData[0x1be];
PARTITION_TABLE_ENTRY PartitionTable[4];
WORD MasterBootRecordMagic;
typedef struct //_FAT_STRUCT
} PACKED MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
//
// Partition type defines
//
#define PARTITION_ENTRY_UNUSED 0x00 // Entry unused
#define PARTITION_FAT_12 0x01 // 12-bit FAT entries
#define PARTITION_XENIX_1 0x02 // Xenix
#define PARTITION_XENIX_2 0x03 // Xenix
#define PARTITION_FAT_16 0x04 // 16-bit FAT entries
#define PARTITION_EXTENDED 0x05 // Extended partition entry
#define PARTITION_HUGE 0x06 // Huge partition MS-DOS V4
#define PARTITION_IFS 0x07 // IFS Partition
#define PARTITION_OS2BOOTMGR 0x0A // OS/2 Boot Manager/OPUS/Coherent swap
#define PARTITION_FAT32 0x0B // FAT32
#define PARTITION_FAT32_XINT13 0x0C // FAT32 using extended int13 services
#define PARTITION_XINT13 0x0E // Win95 partition using extended int13 services
#define PARTITION_XINT13_EXTENDED 0x0F // Same as type 5 but uses extended int13 services
#define PARTITION_PREP 0x41 // PowerPC Reference Platform (PReP) Boot Partition
#define PARTITION_LDM 0x42 // Logical Disk Manager partition
#define PARTITION_UNIX 0x63 // Unix
typedef struct _GEOMETRY
{
DWORD dwStartCluster; // File's starting cluster
DWORD dwCurrentCluster; // Current read cluster number
DWORD dwSize; // File size
DWORD dwCurrentReadOffset;// Amount of data already read
} FAT_STRUCT, * PFAT_STRUCT;
ULONG Cylinders;
ULONG Heads;
ULONG Sectors;
ULONG BytesPerSector;
typedef struct //_FILE
{
//DIRENTRY de;
//FCB fcb;
FAT_STRUCT fat;
unsigned long filesize;
} FILE;
} GEOMETRY, *PGEOMETRY;
extern int nSectorBuffered; // Tells us which sector was read into SectorBuffer[]
extern BYTE SectorBuffer[512]; // 512 byte buffer space for read operations, ReadOneSector reads to here
#define FILE VOID
#define PFILE FILE *
extern int nFATType;
extern DWORD nBytesPerSector; // Bytes per sector
extern DWORD nSectorsPerCluster; // Number of sectors in a cluster
extern DWORD nReservedSectors; // Reserved sectors, usually 1 (the bootsector)
extern DWORD nNumberOfFATs; // Number of FAT tables
extern DWORD nRootDirEntries; // Number of root directory entries (fat12/16)
extern DWORD nTotalSectors16; // Number of total sectors on the drive, 16-bit
extern DWORD nSectorsPerFAT16; // Sectors per FAT table (fat12/16)
extern DWORD nSectorsPerTrack; // Number of sectors in a track
extern DWORD nNumberOfHeads; // Number of heads on the disk
extern DWORD nHiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
extern DWORD nTotalSectors32; // Number of total sectors on the drive, 32-bit
extern DWORD nSectorsPerFAT32; // Sectors per FAT table (fat32)
extern DWORD nExtendedFlags; // Extended flags (fat32)
extern DWORD nFileSystemVersion; // File system version (fat32)
extern DWORD nRootDirStartCluster; // Starting cluster of the root directory (fat32)
extern DWORD nRootDirSectorStart; // Starting sector of the root directory (fat12/16)
extern DWORD nDataSectorStart; // Starting sector of the data area
extern DWORD nSectorsPerFAT; // Sectors per FAT table
extern DWORD nRootDirSectors; // Number of sectors of the root directory (fat32)
extern DWORD nTotalSectors; // Total sectors on the drive
extern DWORD nNumberOfClusters; // Number of clusters on the drive
extern int FSType; // Type of filesystem on boot device, set by OpenDiskDrive()
extern char *pFileSysData; // Load address for filesystem data
extern char *pFat32FATCacheIndex; // Load address for filesystem data
BOOL OpenDiskDrive(int nDrive, int nPartition); // Opens the disk drive device for reading
BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer);// Reads a sector from the open device
BOOL ReadOneSector(int nSect); // Reads one sector from the open device
BOOL OpenFile(char *filename, FILE *pFile); // Opens a file
int ReadFile(FILE *pFile, int count, void *buffer); // Reads count bytes from pFile into buffer
DWORD GetFileSize(FILE *pFile);
DWORD Rewind(FILE *pFile); // Rewinds a file and returns it's size
int feof(FILE *pFile);
int fseek(FILE *pFILE, DWORD offset);
BOOL FATLookupFile(char *file, PFAT_STRUCT pFatStruct);
int FATGetNumPathParts(char *name);
BOOL FATGetFirstNameFromPath(char *buffer, char *name);
void FATParseFileName(char *buffer, char *name);
DWORD FATGetFATEntry(DWORD nCluster);
BOOL FATOpenFile(char *szFileName, PFAT_STRUCT pFatStruct);
int FATReadCluster(DWORD nCluster, char *cBuffer);
int FATRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer);
int FATfseek(PFAT_STRUCT pFatStruct, DWORD offset);
VOID FileSystemError(PUCHAR ErrorString);
BOOL OpenDiskDrive(ULONG DriveNumber, ULONG PartitionNumber);
VOID SetDriveGeometry(ULONG Cylinders, ULONG Heads, ULONG Sectors, ULONG BytesPerSector);
VOID SetVolumeProperties(ULONG HiddenSectors);
BOOL ReadMultipleLogicalSectors(ULONG SectorNumber, ULONG SectorCount, PVOID Buffer);
BOOL ReadLogicalSector(ULONG SectorNumber, PVOID Buffer);
PFILE OpenFile(PUCHAR FileName);
VOID CloseFile(PFILE FileHandle);
BOOL ReadFile(PFILE FileHandle, ULONG BytesToRead, PULONG BytesRead, PVOID Buffer);
ULONG GetFileSize(PFILE FileHandle);
VOID SetFilePointer(PFILE FileHandle, ULONG NewFilePointer);
ULONG GetFilePointer(PFILE FileHandle);
BOOL IsEndOfFile(PFILE FileHandle);
#define EOF -1
@ -179,4 +120,4 @@ int FATfseek(PFAT_STRUCT pFatStruct, DWORD offset);
#define FAT16 2
#define FAT32 3
#endif // #defined __FS_FAT_H
#endif // #defined __FS_H

View file

@ -1,541 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "freeldr.h"
#include "fs.h"
#include "stdlib.h"
#include "tui.h"
#include "asmcode.h"
int nFATType = FAT12;
DWORD nBytesPerSector; // Bytes per sector
DWORD nSectorsPerCluster; // Number of sectors in a cluster
DWORD nReservedSectors; // Reserved sectors, usually 1 (the bootsector)
DWORD nNumberOfFATs; // Number of FAT tables
DWORD nRootDirEntries; // Number of root directory entries (fat12/16)
DWORD nTotalSectors16; // Number of total sectors on the drive, 16-bit
DWORD nSectorsPerFAT16; // Sectors per FAT table (fat12/16)
DWORD nSectorsPerTrack; // Number of sectors in a track
DWORD nNumberOfHeads; // Number of heads on the disk
DWORD nHiddenSectors; // Hidden sectors (sectors before the partition start like the partition table)
DWORD nTotalSectors32; // Number of total sectors on the drive, 32-bit
DWORD nSectorsPerFAT32; // Sectors per FAT table (fat32)
DWORD nExtendedFlags; // Extended flags (fat32)
DWORD nFileSystemVersion; // File system version (fat32)
DWORD nRootDirStartCluster; // Starting cluster of the root directory (fat32)
DWORD nRootDirSectorStart; // Starting sector of the root directory (fat12/16)
DWORD nDataSectorStart; // Starting sector of the data area
DWORD nSectorsPerFAT; // Sectors per FAT table
DWORD nRootDirSectors; // Number of sectors of the root directory (fat32)
DWORD nTotalSectors; // Total sectors on the drive
DWORD nNumberOfClusters; // Number of clusters on the drive
BOOL FATReadRootDirectoryEntry(int nDirEntry, void *pDirEntryBuf)
{
DWORD nDirEntrySector;
int nOffsetWithinSector;
nDirEntrySector = nRootDirSectorStart + ((nDirEntry * 32) / nBytesPerSector);
if (!ReadOneSector(nDirEntrySector))
return FALSE;
nOffsetWithinSector = (nDirEntry * 32) % nBytesPerSector;
memcpy(pDirEntryBuf, SectorBuffer + nOffsetWithinSector, 32);
if (*((char *)pDirEntryBuf) == 0x05)
*((char *)pDirEntryBuf) = 0xE5;
return TRUE;
}
BOOL FATReadDirectoryEntry(DWORD nDirStartCluster, int nDirEntry, void *pDirEntryBuf)
{
DWORD nRealDirCluster;
int nSectorWithinCluster;
int nOffsetWithinSector;
int nSectorToRead;
int i;
i = (nDirEntry * 32) / (nSectorsPerCluster * nBytesPerSector);
//if ((nDirEntry * 32) % (nSectorsPerCluster * nBytesPerSector))
// i++;
for (nRealDirCluster = nDirStartCluster; i; i--)
nRealDirCluster = FATGetFATEntry(nRealDirCluster);
nSectorWithinCluster = ((nDirEntry * 32) % (nSectorsPerCluster * nBytesPerSector)) / nBytesPerSector;
nSectorToRead = ((nRealDirCluster - 2) * nSectorsPerCluster) + nDataSectorStart + nSectorWithinCluster;
if (!ReadOneSector(nSectorToRead))
return FALSE;
nOffsetWithinSector = (nDirEntry * 32) % nBytesPerSector;
memcpy(pDirEntryBuf, SectorBuffer + nOffsetWithinSector, 32);
if (*((char *)pDirEntryBuf) == 0x05)
*((char *)pDirEntryBuf) = 0xE5;
return TRUE;
}
/*
* FATLookupFile()
* This function searches the file system for the
* specified filename and fills in a FAT_STRUCT structure
* with info describing the file, etc. returns true
* if the file exists or false otherwise
*/
BOOL FATLookupFile(char *file, PFAT_STRUCT pFatStruct)
{
int i, j;
int numparts;
char filename[12];
BYTE direntry[32];
int nNumDirEntries;
FAT_STRUCT fatstruct;
BOOL bFound;
DWORD cluster;
memset(pFatStruct, 0, sizeof(FAT_STRUCT));
// Check and see if the first character is '\' and remove it if so
if (*file == '\\')
file++;
// Figure out how many sub-directories we are nested in
numparts = FATGetNumPathParts(file);
// Loop once for each part
for (i=0; i<numparts; i++)
{
// Make filename compatible with MSDOS dir entry
if (!FATGetFirstNameFromPath(filename, file))
return FALSE;
// Advance to the next part of the path
for (; (*file != '\\') && (*file != '\0'); file++);
file++;
// If we didn't find the correct sub-directory the fail
if ((i != 0) && !bFound)
return FALSE;
bFound = FALSE;
// Check if we are pulling from the root directory of a fat12/fat16 disk
if ((i == 0) && ((nFATType == FAT12) || (nFATType == FAT16)))
nNumDirEntries = nRootDirEntries;
else if ((i == 0) && (nFATType == FAT32))
{
cluster = nRootDirStartCluster;
fatstruct.dwSize = nSectorsPerCluster * nBytesPerSector;
while((cluster = FATGetFATEntry(cluster)) < 0x0FFFFFF8)
fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
fatstruct.dwStartCluster = nRootDirStartCluster;
nNumDirEntries = fatstruct.dwSize / 32;
}
else
nNumDirEntries = fatstruct.dwSize / 32;
// Loop through each directory entry
for (j=0; j<nNumDirEntries; j++)
{
// Read the entry
if ((i == 0) && ((nFATType == FAT12) || (nFATType == FAT16)))
{
if (!FATReadRootDirectoryEntry(j, direntry))
return FALSE;
}
else
{
if (!FATReadDirectoryEntry(fatstruct.dwStartCluster, j, direntry))
return FALSE;
}
if (memcmp(direntry, filename, 11) == 0)
{
fatstruct.dwStartCluster = 0;
fatstruct.dwCurrentCluster = 0;
memcpy(&fatstruct.dwStartCluster, direntry + 26, sizeof(WORD));
memcpy(&fatstruct.dwCurrentCluster, direntry + 20, sizeof(WORD));
fatstruct.dwStartCluster += (fatstruct.dwCurrentCluster * 0x10000);
if (direntry[11] & ATTR_DIRECTORY)
{
fatstruct.dwSize = nSectorsPerCluster * nBytesPerSector;
cluster = fatstruct.dwStartCluster;
switch (nFATType)
{
case FAT12:
while((cluster = FATGetFATEntry(cluster)) < 0xFF8)
fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
break;
case FAT16:
while((cluster = FATGetFATEntry(cluster)) < 0xFFF8)
fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
break;
case FAT32:
while((cluster = FATGetFATEntry(cluster)) < 0x0FFFFFF8)
fatstruct.dwSize += nSectorsPerCluster * nBytesPerSector;
break;
}
}
// If we have more parts to go and this isn't a directory then fail
if ((i < (numparts-1)) && !(direntry[11] & ATTR_DIRECTORY))
return FALSE;
// If this is supposed to be a file and it is a directory then fail
if ((i == (numparts-1)) && (direntry[11] & ATTR_DIRECTORY))
return FALSE;
bFound = TRUE;
break;
}
}
}
if(!bFound)
return FALSE;
memcpy(&pFatStruct->dwStartCluster, direntry + 26, sizeof(WORD));
memcpy(&pFatStruct->dwCurrentCluster, direntry + 20, sizeof(WORD));
pFatStruct->dwStartCluster += (pFatStruct->dwCurrentCluster * 0x10000);
pFatStruct->dwCurrentCluster = pFatStruct->dwStartCluster;
memcpy(&pFatStruct->dwSize, direntry + 28, sizeof(DWORD));
pFatStruct->dwCurrentReadOffset = 0;
return TRUE;
}
/*
* FATGetNumPathParts()
* This function parses a path in the form of dir1\dir2\file1.ext
* and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext)
*/
int FATGetNumPathParts(char *name)
{
int i, num;
for(i=0,num=0; i<(int)strlen(name); i++)
{
if(name[i] == '\\')
num++;
}
num++;
return num;
}
/*
* FATGetFirstNameFromPath()
* This function parses a path in the form of dir1\dir2\file1.ext
* and puts the first name of the path (e.g. "dir1") in buffer
* compatible with the MSDOS directory structure
*/
BOOL FATGetFirstNameFromPath(char *buffer, char *name)
{
int i;
char temp[260];
// Copy all the characters up to the end of the
// string or until we hit a '\' character
// and put them in temp
for(i=0; i<(int)strlen(name); i++)
{
if(name[i] == '\\')
break;
else
temp[i] = name[i];
}
temp[i] = 0;
// If the filename is too long then fail
if(strlen(temp) > 12)
return FALSE;
FATParseFileName(buffer, temp);
return TRUE;
}
/*
* FATParseFileName()
* This function parses "name" which is in the form of file.ext
* and puts it in "buffer" in the form of "FILE EXT" which
* is compatible with the MSDOS directory structure
*/
void FATParseFileName(char *buffer, char *name)
{
int i, j;
i = 0;
j = 0;
while(i < 8)
buffer[i++] = (name[j] && (name[j] != '.')) ? toupper(name[j++]) : ' ';
if(name[j] == '.')
j++;
while(i < 11)
buffer[i++] = name[j] ? toupper(name[j++]) : ' ';
buffer[i] = 0;
}
/*
* FATGetFATEntry()
* returns the FAT entry for a given cluster number
*/
DWORD FATGetFATEntry(DWORD nCluster)
{
DWORD fat;
int FATOffset;
int ThisFATSecNum;
int ThisFATEntOffset;
int Idx;
BOOL bEntryFound;
switch(nFATType)
{
case FAT12:
FATOffset = nCluster + (nCluster / 2);
ThisFATSecNum = (FATOffset / nBytesPerSector);
ThisFATEntOffset = (FATOffset % nBytesPerSector);
fat = *((WORD *) (pFileSysData + (ThisFATSecNum * nBytesPerSector) + ThisFATEntOffset));
if (nCluster & 0x0001)
fat = fat >> 4; /* Cluster number is ODD */
else
fat = fat & 0x0FFF; /* Cluster number is EVEN */
return fat;
break;
case FAT16:
FATOffset = (nCluster * 2);
//ThisFATSecNum = nReservedSectors + (FATOffset / nBytesPerSector);
//ThisFATEntOffset = (FATOffset % nBytesPerSector);
//if (!ReadOneSector(ThisFATSecNum))
// return NULL;
//fat = *((WORD *) &SectorBuffer[ThisFATEntOffset]);
fat = *((WORD *) (pFileSysData + FATOffset));
return fat;
break;
case FAT32:
//if (!ReadOneSector(ThisFATSecNum))
// return NULL;
//fat = *((DWORD *) &SectorBuffer[ThisFATEntOffset]) & 0x0FFFFFFF;
//return fat;
// This code manages the fat32 fat table entry cache
// The cache is at address FILESYSADDR which is 128k in size
// The first two sectors will contain an array of DWORDs that
// Specify what fat sector is cached. The first two DWORDs
// should be zero.
FATOffset = (nCluster * 4);
ThisFATSecNum = nReservedSectors + (FATOffset / nBytesPerSector);
ThisFATEntOffset = (FATOffset % nBytesPerSector);
// Now we go through our cache and see if we already have the sector cached
bEntryFound = FALSE;
for (Idx=2; Idx<256; Idx++)
{
if (((int*)pFat32FATCacheIndex)[Idx] == ThisFATSecNum)
{
bEntryFound = TRUE;
break;
}
}
if (bEntryFound)
{
// Get the fat entry
fat = (*((DWORD *) (pFat32FATCacheIndex +
(Idx * nBytesPerSector) + ThisFATEntOffset))) & 0x0FFFFFFF;
}
else
{
if (!ReadOneSector(ThisFATSecNum))
return NULL;
// Move each sector down in the cache to make room for new sector
for (Idx=255; Idx>2; Idx--)
{
memcpy(pFat32FATCacheIndex + (Idx * nBytesPerSector), pFat32FATCacheIndex + ((Idx - 1) * nBytesPerSector), nBytesPerSector);
((int*)pFat32FATCacheIndex)[Idx] = ((int*)pFat32FATCacheIndex)[Idx - 1];
}
// Insert it into the cache
memcpy(pFat32FATCacheIndex + (2 * nBytesPerSector), SectorBuffer, nBytesPerSector);
((int*)pFat32FATCacheIndex)[2] = ThisFATSecNum;
// Get the fat entry
fat = (*((DWORD *) (pFat32FATCacheIndex +
(2 * nBytesPerSector) + ThisFATEntOffset))) & 0x0FFFFFFF;
}
return fat;
break;
}
return NULL;
}
/*
* FATOpenFile()
* Tries to open the file 'name' and returns true or false
* for success and failure respectively
*/
BOOL FATOpenFile(char *szFileName, PFAT_STRUCT pFatStruct)
{
if(!FATLookupFile(szFileName, pFatStruct))
return FALSE;
/* Fill in file control information */
pFatStruct->dwCurrentCluster = pFatStruct->dwStartCluster;
pFatStruct->dwCurrentReadOffset = 0;
return TRUE;
}
/*
* FATReadCluster()
* Reads the specified cluster into memory
* and returns the number of bytes read
*/
int FATReadCluster(DWORD nCluster, char *cBuffer)
{
int nStartSector;
nStartSector = ((nCluster - 2) * nSectorsPerCluster) + nDataSectorStart;
ReadMultipleSectors(nStartSector, nSectorsPerCluster, cBuffer);
return (nSectorsPerCluster * nBytesPerSector);
}
/*
* FATRead()
* Reads nNumBytes from open file and
* returns the number of bytes read
*/
int FATRead(PFAT_STRUCT pFatStruct, int nNumBytes, char *cBuffer)
{
int nSectorWithinCluster;
int nOffsetWithinSector;
int nOffsetWithinCluster;
int nNum;
int nBytesRead = 0;
// If all the data is read return zero
if (pFatStruct->dwCurrentReadOffset >= pFatStruct->dwSize)
return 0;
// If they are trying to read more than there is to read
// then adjust the amount to read
if ((pFatStruct->dwCurrentReadOffset + nNumBytes) > pFatStruct->dwSize)
nNumBytes = pFatStruct->dwSize - pFatStruct->dwCurrentReadOffset;
while (nNumBytes)
{
// Check and see if the read offset is aligned to a cluster boundary
// if so great, if not then read the rest of the current cluster
if ((pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector)) != 0)
{
nSectorWithinCluster = ((pFatStruct->dwCurrentReadOffset / nBytesPerSector) % nSectorsPerCluster);
nOffsetWithinSector = (pFatStruct->dwCurrentReadOffset % nBytesPerSector);
nOffsetWithinCluster = (pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector));
// Read the cluster into the scratch area
FATReadCluster(pFatStruct->dwCurrentCluster, (char *)FATCLUSTERBUF);
nNum = (nSectorsPerCluster * nBytesPerSector) - (pFatStruct->dwCurrentReadOffset % (nSectorsPerCluster * nBytesPerSector));
if (nNumBytes >= nNum)
{
memcpy(cBuffer, (char *)(FATCLUSTERBUF + nOffsetWithinCluster), nNum);
nBytesRead += nNum;
cBuffer += nNum;
pFatStruct->dwCurrentReadOffset += nNum;
pFatStruct->dwCurrentCluster = FATGetFATEntry(pFatStruct->dwCurrentCluster);
nNumBytes -= nNum;
}
else
{
memcpy(cBuffer, (char *)(FATCLUSTERBUF + nOffsetWithinCluster), nNumBytes);
nBytesRead += nNumBytes;
cBuffer += nNumBytes;
pFatStruct->dwCurrentReadOffset += nNumBytes;
nNumBytes -= nNumBytes;
}
}
else
{
// Read the cluster into the scratch area
FATReadCluster(pFatStruct->dwCurrentCluster, (char *)FATCLUSTERBUF);
nNum = (nSectorsPerCluster * nBytesPerSector);
if (nNumBytes >= nNum)
{
memcpy(cBuffer, (char *)(FATCLUSTERBUF), nNum);
nBytesRead += nNum;
cBuffer += nNum;
pFatStruct->dwCurrentReadOffset += nNum;
pFatStruct->dwCurrentCluster = FATGetFATEntry(pFatStruct->dwCurrentCluster);
nNumBytes -= nNum;
}
else
{
memcpy(cBuffer, (char *)(FATCLUSTERBUF), nNumBytes);
nBytesRead += nNumBytes;
cBuffer += nNumBytes;
pFatStruct->dwCurrentReadOffset += nNumBytes;
nNumBytes -= nNumBytes;
}
}
}
return nBytesRead;
}
int FATfseek(PFAT_STRUCT pFatStruct, DWORD offset)
{
DWORD cluster;
int numclusters;
numclusters = offset / (nSectorsPerCluster * nBytesPerSector);
for (cluster=pFatStruct->dwStartCluster; numclusters > 0; numclusters--)
cluster = FATGetFATEntry(cluster);
pFatStruct->dwCurrentCluster = cluster;
pFatStruct->dwCurrentReadOffset = offset;
return 0;
}

View file

@ -28,7 +28,7 @@
void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line)
{
FILE file;
/*FILE file;
char temp[260];
char bootsector[512];
char setup[2048];
@ -97,5 +97,5 @@ void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToLinuxBootCode();
JumpToLinuxBootCode();*/
}

View file

@ -21,6 +21,15 @@
#include "memory.h"
#include "stdlib.h"
#include "debug.h"
#include "tui.h"
//
// Define this to 1 if you want the entire contents
// of the memory allocation bitmap displayed
// when a chunk is allocated or freed
//
#define DUMP_MEM_MAP_ON_VERIFY 0
#define MEM_BLOCK_SIZE 256
@ -39,6 +48,7 @@ PMEMBLOCK HeapMemBlockArray = NULL;
ULONG AllocationCount = 0;
VOID VerifyHeap(VOID);
VOID DumpMemoryAllocMap(VOID);
VOID IncrementAllocationCount(VOID);
VOID DecrementAllocationCount(VOID);
VOID MemAllocTest(VOID);
@ -66,7 +76,7 @@ VOID InitMemoryManager(PVOID BaseAddress, ULONG Length)
ZeroMemory(HeapMemBlockArray, (HeapMemBlockCount * sizeof(MEMBLOCK)));
#ifdef DEBUG
DebugPrint(DPRINT_MEMORY, "Memory Manager initialized. BaseAddress = 0x%x Length = 0x%x. %d blocks in heap.\n", BaseAddress, Length, HeapMemBlockCount);
DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. BaseAddress = 0x%x Length = 0x%x. %d blocks in heap.\n", BaseAddress, Length, HeapMemBlockCount));
//MemAllocTest();
#endif
}
@ -78,9 +88,11 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
ULONG NumFree;
PVOID MemPointer;
#ifdef DEBUG
VerifyHeap();
#endif DEBUG
if (NumberOfBytes == 0)
{
DbgPrint((DPRINT_MEMORY, "AllocateMemory() called for 0 bytes. Returning NULL.\n"));
return NULL;
}
// Find out how many blocks it will take to
// satisfy this allocation
@ -116,6 +128,8 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
// then return NULL
if (NumFree < BlocksNeeded)
{
DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", NumberOfBytes, AllocationCount));
MessageBox("Memory allocation failed: out of memory.");
return NULL;
}
@ -135,7 +149,8 @@ PVOID AllocateMemory(ULONG NumberOfBytes)
#ifdef DEBUG
IncrementAllocationCount();
DebugPrint(DPRINT_MEMORY, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocationCount: %d\n", NumberOfBytes, BlocksNeeded, Idx, AllocationCount);
DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocCount: %d\n", NumberOfBytes, BlocksNeeded, Idx, AllocationCount));
VerifyHeap();
#endif DEBUG
// Now return the pointer
@ -149,12 +164,11 @@ VOID FreeMemory(PVOID MemBlock)
ULONG Idx;
#ifdef DEBUG
VerifyHeap();
// Make sure we didn't get a bogus pointer
if ((MemBlock < HeapBaseAddress) || (MemBlock > (HeapBaseAddress + HeapLengthInBytes)))
{
BugCheck1("Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock);
BugCheck((DPRINT_MEMORY, "Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock));
}
#endif DEBUG
@ -167,7 +181,7 @@ VOID FreeMemory(PVOID MemBlock)
// Make sure we didn't get a bogus pointer
if ((BlockCount < 1) || (BlockCount > HeapMemBlockCount))
{
BugCheck1("Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray[BlockNumber].BlocksAllocated);
BugCheck((DPRINT_MEMORY, "Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray[BlockNumber].BlocksAllocated));
}
#endif
@ -181,7 +195,8 @@ VOID FreeMemory(PVOID MemBlock)
#ifdef DEBUG
DecrementAllocationCount();
DebugPrint(DPRINT_MEMORY, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount, BlockNumber, AllocationCount);
DbgPrint((DPRINT_MEMORY, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount, BlockNumber, AllocationCount));
VerifyHeap();
#endif DEBUG
}
@ -192,6 +207,11 @@ VOID VerifyHeap(VOID)
ULONG Idx2;
ULONG Count;
if (DUMP_MEM_MAP_ON_VERIFY)
{
DumpMemoryAllocMap();
}
// Loop through the array and verify that
// everything is kosher
for (Idx=0; Idx<HeapMemBlockCount; Idx++)
@ -203,7 +223,7 @@ VOID VerifyHeap(VOID)
// had better have a length that is within range
if ((HeapMemBlockArray[Idx].BlocksAllocated < 1) || (HeapMemBlockArray[Idx].BlocksAllocated > (HeapMemBlockCount - Idx)))
{
BugCheck1("Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray[Idx].BlocksAllocated);
BugCheck((DPRINT_MEMORY, "Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray[Idx].BlocksAllocated));
}
// Now go through and verify that the rest of
@ -216,30 +236,60 @@ VOID VerifyHeap(VOID)
// Make sure it's allocated
if (HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE)
{
BugCheck0("Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n");
BugCheck((DPRINT_MEMORY, "Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n"));
}
// Make sure the length is zero
if (HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0)
{
BugCheck0("Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n");
BugCheck((DPRINT_MEMORY, "Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n"));
}
}
// Move on to the next run
Idx += Count;
Idx += (Count - 1);
}
else
{
// Nope, not allocated so make sure the length is zero
if (HeapMemBlockArray[Idx].BlocksAllocated != 0)
{
BugCheck0("Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n");
BugCheck((DPRINT_MEMORY, "Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n"));
}
}
}
}
VOID DumpMemoryAllocMap(VOID)
{
ULONG Idx;
DbgPrint((DPRINT_MEMORY, "----------- Memory Allocation Bitmap -----------\n"));
for (Idx=0; Idx<HeapMemBlockCount; Idx++)
{
if ((Idx % 32) == 0)
{
DbgPrint((DPRINT_MEMORY, "\n%x:\t", (Idx * 256)));
}
else if ((Idx % 4) == 0)
{
DbgPrint((DPRINT_MEMORY, " "));
}
if (HeapMemBlockArray[Idx].MemBlockAllocated)
{
DbgPrint((DPRINT_MEMORY, "X"));
}
else
{
DbgPrint((DPRINT_MEMORY, "*"));
}
}
DbgPrint((DPRINT_MEMORY, "\n"));
}
VOID IncrementAllocationCount(VOID)
{
AllocationCount++;
@ -266,6 +316,8 @@ VOID MemAllocTest(VOID)
getch();
MemPtr3 = AllocateMemory(4096);
printf("MemPtr3: 0x%x\n", (int)MemPtr3);
DumpMemoryAllocMap();
VerifyHeap();
getch();
FreeMemory(MemPtr2);

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -22,171 +22,384 @@
#include "tui.h"
#include "menu.h"
#include "options.h"
#include "memory.h"
static int nOSListBoxLeft;
static int nOSListBoxRight;
static int nOSListBoxTop;
static int nOSListBoxBottom;
static int nOSSelected = 0; // Currently selected OS (zero based)
int RunMenu(void)
typedef struct
{
int key;
int second;
BOOL bDone = FALSE;
PUCHAR *MenuItemList;
ULONG MenuItemCount;
LONG MenuTimeRemaining;
ULONG SelectedMenuItem;
if (nTimeOut > 0)
nTimeOut++; // Increment the timeout since 0 doesn't count for a second
ULONG Left;
ULONG Top;
ULONG Right;
ULONG Bottom;
// Initialise the menu
InitMenu();
} MENU_INFO, *PMENU_INFO;
// Update the menu
DrawMenu();
VOID CalcMenuBoxSize(PMENU_INFO MenuInfo);
VOID DrawMenu(PMENU_INFO MenuInfo);
VOID DrawMenuBox(PMENU_INFO MenuInfo);
VOID DrawMenuItem(PMENU_INFO MenuInfo, ULONG MenuItemNumber);
ULONG ProcessMenuKeyboardEvent(PMENU_INFO MenuInfo);
second = getsecond();
extern ULONG nScreenWidth; // Screen Width
extern ULONG nScreenHeight; // Screen Height
// Loop
do
extern CHAR cStatusBarFgColor; // Status bar foreground color
extern CHAR cStatusBarBgColor; // Status bar background color
extern CHAR cBackdropFgColor; // Backdrop foreground color
extern CHAR cBackdropBgColor; // Backdrop background color
extern CHAR cBackdropFillStyle; // Backdrop fill style
extern CHAR cTitleBoxFgColor; // Title box foreground color
extern CHAR cTitleBoxBgColor; // Title box background color
extern CHAR cMessageBoxFgColor; // Message box foreground color
extern CHAR cMessageBoxBgColor; // Message box background color
extern CHAR cMenuFgColor; // Menu foreground color
extern CHAR cMenuBgColor; // Menu background color
extern CHAR cTextColor; // Normal text color
extern CHAR cSelectedTextColor; // Selected text color
extern CHAR cSelectedTextBgColor; // Selected text background color
BOOL DisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, PULONG SelectedMenuItem)
{
PUCHAR ScreenBuffer;
MENU_INFO MenuInformation;
ULONG CurrentClockSecond;
//
// The first thing we need to check is the timeout
// If it's zero then don't bother with anything,
// just return the default item
//
if (MenuTimeOut == 0)
{
// Check for a keypress
if (kbhit())
if (SelectedMenuItem != NULL)
{
// Cancel the timeout
if (nTimeOut != -1)
{
nTimeOut = -1;
DrawMenu();
}
// Get the key
key = getch();
// Is it extended?
if (key == 0)
key = getch(); // Yes - so get the extended key
// Process the key
switch (key)
{
case KEY_UP:
if (nOSSelected)
{
nOSSelected--;
// Update the menu
DrawMenu();
}
break;
case KEY_DOWN:
if (nOSSelected < (nNumOS-1))
{
nOSSelected++;
// Update the menu
DrawMenu();
}
break;
case KEY_ENTER:
bDone = TRUE;
break;
case KEY_F8:
DoOptionsMenu();
DrawBackdrop();
DrawMenu();
break;
}
*SelectedMenuItem = DefaultMenuItem;
}
return TRUE;
}
//
// Allocate memory to hold screen contents before menu is drawn
//
ScreenBuffer = AllocateMemory(4000);
if (ScreenBuffer == NULL)
{
return FALSE;
}
//
// Save screen contents to our buffer
//
SaveScreen(ScreenBuffer);
//
// Setup the MENU_INFO structure
//
MenuInformation.MenuItemList = MenuItemList;
MenuInformation.MenuItemCount = MenuItemCount;
MenuInformation.MenuTimeRemaining = MenuTimeOut;
MenuInformation.SelectedMenuItem = DefaultMenuItem;
//
// Calculate the size of the menu box
//
CalcMenuBoxSize(&MenuInformation);
//
// Draw the menu
//
DrawMenu(&MenuInformation);
//
// Get the current second of time
//
CurrentClockSecond = getsecond();
//
// Process keys
//
while (1)
{
//
// Process key presses
//
if (ProcessMenuKeyboardEvent(&MenuInformation) == KEY_ENTER)
{
//
// If they pressed enter then exit this loop
//
break;
}
//
// Update the date & time
//
UpdateDateTime();
if (nTimeOut > 0)
if (MenuInformation.MenuTimeRemaining > 0)
{
if (getsecond() != second)
if (getsecond() != CurrentClockSecond)
{
second = getsecond();
nTimeOut--;
//
// Update the time information
//
CurrentClockSecond = getsecond();
MenuInformation.MenuTimeRemaining--;
//
// Update the menu
DrawMenu();
//
DrawMenuBox(&MenuInformation);
}
}
if (nTimeOut == 0)
bDone = TRUE;
else if (MenuInformation.MenuTimeRemaining == 0)
{
//
// A time out occurred, exit this loop and return default OS
//
break;
}
}
while (!bDone);
return nOSSelected;
}
void InitMenu(void)
{
int i;
int height = 1; // Allow room for top & bottom borders
int width = 0;
for(i=0; i<nNumOS; i++)
//
// Update the selected menu item information
//
if (SelectedMenuItem != NULL)
{
height++;
if(strlen(OSList[i].name) > width)
width = strlen(OSList[i].name);
*SelectedMenuItem = MenuInformation.SelectedMenuItem;
}
width += 18; // Allow room for left & right borders, plus 8 spaces on each side
// Calculate the OS list box area
nOSListBoxLeft = (nScreenWidth - width) / 2;
nOSListBoxRight = nOSListBoxLeft + width;
nOSListBoxTop = (nScreenHeight - height) / 2 + 1;
nOSListBoxBottom = nOSListBoxTop + height;
nOSSelected = 0;
return TRUE;
}
void DrawMenu(void)
VOID CalcMenuBoxSize(PMENU_INFO MenuInfo)
{
int i, j;
char text[260];
char temp[260];
int space, space_left, space_right;
ULONG Idx;
ULONG Width;
ULONG Height;
ULONG Length;
//
// Height is the menu item count plus 2 (top border & bottom border)
//
Height = MenuInfo->MenuItemCount + 2;
Height -= 1; // Height is zero-based
//
// Find the length of the longest string in the menu
//
Width = 0;
for(Idx=0; Idx<MenuInfo->MenuItemCount; Idx++)
{
Length = strlen(MenuInfo->MenuItemList[Idx]);
if (Length > Width)
{
Width = Length;
}
}
//
// Allow room for left & right borders, plus 8 spaces on each side
//
Width += 18;
//
// Calculate the menu box area
//
MenuInfo->Left = (nScreenWidth - Width) / 2;
MenuInfo->Right = (MenuInfo->Left) + Width;
MenuInfo->Top = (( (nScreenHeight - TITLE_BOX_HEIGHT) - Height) / 2 + 1) + (TITLE_BOX_HEIGHT / 2);
MenuInfo->Bottom = (MenuInfo->Top) + Height;
}
VOID DrawMenu(PMENU_INFO MenuInfo)
{
ULONG Idx;
//
// Draw the menu box
//
DrawMenuBox(MenuInfo);
//
// Draw each line of the menu
//
for (Idx=0; Idx<MenuInfo->MenuItemCount; Idx++)
{
DrawMenuItem(MenuInfo, Idx);
}
}
VOID DrawMenuBox(PMENU_INFO MenuInfo)
{
UCHAR MenuLineText[80];
UCHAR TempString[80];
//
// Update the status bar
DrawStatusText(" Use \x18\x19 to select, ENTER to boot. Press F8 for advanced options.");
//
DrawStatusText(" Use \x18\x19 to select, ENTER to boot.");
DrawBox(nOSListBoxLeft, nOSListBoxTop, nOSListBoxRight, nOSListBoxBottom, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
//
// Draw the menu box
//
DrawBox(MenuInfo->Left,
MenuInfo->Top,
MenuInfo->Right,
MenuInfo->Bottom,
D_VERT,
D_HORZ,
FALSE, // Filled
TRUE, // Shadow
ATTR(cMenuFgColor, cMenuBgColor));
for(i=0; i<nNumOS; i++)
//
// If there is a timeout draw the time remaining
//
if (MenuInfo->MenuTimeRemaining >= 0)
{
space = (nOSListBoxRight - nOSListBoxLeft - 2) - strlen(OSList[i].name);
space_left = (space / 2) + 1;
space_right = (space - space_left) + 1;
strcpy(MenuLineText, "[ Time Remaining: ");
itoa(MenuInfo->MenuTimeRemaining, TempString, 10);
strcat(MenuLineText, TempString);
strcat(MenuLineText, " ]");
text[0] = '\0';
for(j=0; j<space_left; j++)
strcat(text, " ");
strcat(text, OSList[i].name);
for(j=0; j<space_right; j++)
strcat(text, " ");
DrawText(MenuInfo->Right - strlen(MenuLineText) - 1,
MenuInfo->Bottom,
MenuLineText,
ATTR(cMenuFgColor, cMenuBgColor));
}
}
if(i == nOSSelected)
VOID DrawMenuItem(PMENU_INFO MenuInfo, ULONG MenuItemNumber)
{
ULONG Idx;
UCHAR MenuLineText[80];
ULONG SpaceTotal;
ULONG SpaceLeft;
ULONG SpaceRight;
//
// We will want the string centered so calculate
// how many spaces will be to the left and right
//
SpaceTotal = (MenuInfo->Right - MenuInfo->Left - 2) - strlen(MenuInfo->MenuItemList[MenuItemNumber]);
SpaceLeft = (SpaceTotal / 2) + 1;
SpaceRight = (SpaceTotal - SpaceLeft) + 1;
//
// Insert the spaces on the left
//
for (Idx=0; Idx<SpaceLeft; Idx++)
{
MenuLineText[Idx] = ' ';
}
MenuLineText[Idx] = '\0';
//
// Now append the text string
//
strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
//
// Now append the spaces on the right
//
for (Idx=0; Idx<SpaceRight; Idx++)
{
strcat(MenuLineText, " ");
}
//
// If this is the selected menu item then draw it as selected
// otherwise just draw it using the normal colors
//
if (MenuItemNumber == MenuInfo->SelectedMenuItem)
{
DrawText(MenuInfo->Left + 1,
MenuInfo->Top + 1 + MenuItemNumber,
MenuLineText,
ATTR(cSelectedTextColor, cSelectedTextBgColor));
}
else
{
DrawText(MenuInfo->Left + 1,
MenuInfo->Top + 1 + MenuItemNumber,
MenuLineText,
ATTR(cTextColor, cMenuBgColor));
}
}
ULONG ProcessMenuKeyboardEvent(PMENU_INFO MenuInfo)
{
ULONG KeyEvent = 0;
//
// Check for a keypress
//
if (kbhit())
{
//
// Cancel the timeout
//
if (MenuInfo->MenuTimeRemaining != -1)
{
DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cSelectedTextColor, cSelectedTextBgColor));
MenuInfo->MenuTimeRemaining = -1;
DrawMenuBox(MenuInfo);
}
else
//
// Get the key
//
KeyEvent = getch();
//
// Is it extended?
//
if (KeyEvent == 0)
KeyEvent = getch(); // Yes - so get the extended key
//
// Process the key
//
switch (KeyEvent)
{
DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
case KEY_UP:
if (MenuInfo->SelectedMenuItem > 0)
{
MenuInfo->SelectedMenuItem--;
//
// Update the menu
//
DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem + 1); // Deselect previous item
DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem); // Select new item
}
break;
case KEY_DOWN:
if (MenuInfo->SelectedMenuItem < (MenuInfo->MenuItemCount - 1))
{
MenuInfo->SelectedMenuItem++;
//
// Update the menu
//
DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem - 1); // Deselect previous item
DrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem); // Select new item
}
break;
}
}
if (nTimeOut >= 0)
{
strcpy(text, "[ Time Remaining: ");
itoa(nTimeOut, temp, 10);
strcat(text, temp);
strcat(text, " ]");
DrawText(nOSListBoxRight - strlen(text) - 1, nOSListBoxBottom, text, ATTR(cMenuFgColor, cMenuBgColor));
}
}
return KeyEvent;
}

View file

@ -1,6 +1,6 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,8 +20,6 @@
#ifndef __MENU_H
#define __MENU_H
int RunMenu(void);
void InitMenu(void);
void DrawMenu(void);
BOOL DisplayMenu(PUCHAR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, PULONG SelectedMenuItem);
#endif // #defined __MENU_H

View file

@ -28,14 +28,15 @@
void LoadAndBootBootSector(int nOSToBoot)
{
FILE file;
FILE* FilePointer;
char name[260];
char value[260];
char szFileName[1024];
int i;
ULONG BytesRead;
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
/*for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if (stricmp(name, "MessageBox") == 0)
@ -69,7 +70,9 @@ void LoadAndBootBootSector(int nOSToBoot)
}
strcpy(szFileName, value);
if (!OpenFile(szFileName, &file))
FilePointer = OpenFile(szFileName);
if (FilePointer == NULL)
{
strcat(value, " not found.");
MessageBox(value);
@ -77,7 +80,7 @@ void LoadAndBootBootSector(int nOSToBoot)
}
// Read boot sector
if (ReadFile(&file, 512, (void*)0x7c00) != 512)
if (!ReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
{
MessageBox("Disk Read Error");
return;
@ -95,7 +98,7 @@ void LoadAndBootBootSector(int nOSToBoot)
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();
JumpToBootCode();*/
}
void LoadAndBootPartition(int nOSToBoot)
@ -107,7 +110,7 @@ void LoadAndBootPartition(int nOSToBoot)
int i;
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
/*for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if (stricmp(name, "MessageBox") == 0)
@ -132,14 +135,14 @@ void LoadAndBootPartition(int nOSToBoot)
BootPartition = atoi(value);
if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
if (!BiosInt13Read(BootDrive, 0, 0, 1, 1, DISKREADBUFFER))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)
if (*((WORD*)(DISKREADBUFFER + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid partition table magic (0xaa55)");
return;
@ -181,7 +184,7 @@ void LoadAndBootPartition(int nOSToBoot)
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();
JumpToBootCode();*/
}
void LoadAndBootDrive(int nOSToBoot)
@ -191,7 +194,7 @@ void LoadAndBootDrive(int nOSToBoot)
int i;
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
/*for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if (stricmp(name, "MessageBox") == 0)
@ -226,5 +229,5 @@ void LoadAndBootDrive(int nOSToBoot)
gotoxy(CursorXPos, CursorYPos);
stop_floppy();
JumpToBootCode();
JumpToBootCode();*/
}

View file

@ -36,12 +36,13 @@ BOOL MultiBootLoadKernel(FILE *KernelImage)
DWORD dwFileLoadOffset;
DWORD dwDataSize;
DWORD dwBssSize;
ULONG BytesRead;
/*
* Load the first 8192 bytes of the kernel image
* so we can search for the multiboot header
*/
ReadFile(KernelImage, 8192, ImageHeaders);
ReadFile(KernelImage, 8192, NULL, ImageHeaders);
/*
* Now find the multiboot header and copy it
@ -95,13 +96,13 @@ BOOL MultiBootLoadKernel(FILE *KernelImage)
* Get the file offset, this should be 0, and move the file pointer
*/
dwFileLoadOffset = (Idx * sizeof(DWORD)) - (mb_header.header_addr - mb_header.load_addr);
fseek(KernelImage, dwFileLoadOffset);
SetFilePointer(KernelImage, dwFileLoadOffset);
/*
* Load the file image
*/
dwDataSize = (mb_header.load_end_addr - mb_header.load_addr);
ReadFile(KernelImage, dwDataSize, (void*)mb_header.load_addr);
ReadFile(KernelImage, dwDataSize, NULL, (void*)mb_header.load_addr);
/*
* Initialize bss area
@ -142,7 +143,7 @@ BOOL MultiBootLoadModule(FILE *ModuleImage, char *ModuleName)
/*
* Load the file image
*/
ReadFile(ModuleImage, dwModuleSize, (void*)next_module_load_base);
ReadFile(ModuleImage, dwModuleSize, NULL, (void*)next_module_load_base);
next_module_load_base = ROUND_UP(pModule->mod_end, /*PAGE_SIZE*/4096);
mb_info.mods_count++;
@ -154,10 +155,14 @@ int GetBootPartition(char *OperatingSystemName)
{
int BootPartitionNumber = -1;
char value[1024];
ULONG SectionId;
if (ReadSectionSettingByName(OperatingSystemName, "BootPartition", value))
if (OpenSection(OperatingSystemName, &SectionId))
{
BootPartitionNumber = atoi(value);
if (ReadSectionSettingByName(SectionId, "BootPartition", value, 1024))
{
BootPartitionNumber = atoi(value);
}
}
return BootPartitionNumber;

View file

@ -23,7 +23,7 @@
#include "options.h"
#include "miscboot.h"
#if 0
void DoOptionsMenu(void)
{
int OptionsMenuItemCount = 1; // Count is 1 because we don't show the "Set ReactOS Boot Flags" menu item yet
@ -101,7 +101,7 @@ void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
char BootOptionsMenuItems[2][80] = { "Boot To ", "Pick A Boot Partition" };
int BootOptionsMenuItemSelected = 0;
strcat(BootOptionsMenuItems[0], BootDriveText);
/*strcat(BootOptionsMenuItems[0], BootDriveText);
while (BootOptionsMenuItemSelected != -1)
{
@ -144,7 +144,7 @@ void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
break;
}
}
}*/
}
void DoBootPartitionOptionsMenu(int BootDriveNum)
@ -164,7 +164,7 @@ void DoBootPartitionOptionsMenu(int BootDriveNum)
char temp[25];
BootDrive = BootDriveNum;
/*BootDrive = BootDriveNum;
if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
{
@ -244,7 +244,7 @@ void DoBootPartitionOptionsMenu(int BootDriveNum)
stop_floppy();
JumpToBootCode();
}
}
}*/
}
int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle)
@ -345,7 +345,7 @@ int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nO
void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount)
{
int height = OptionsMenuItemCount;
/*int height = OptionsMenuItemCount;
int width = 20;
height += 1; // Allow room for top & bottom borders
@ -355,7 +355,7 @@ void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOp
*nOptionsMenuBoxLeft = (nScreenWidth - width) / 2;
*nOptionsMenuBoxRight = *nOptionsMenuBoxLeft + width;
*nOptionsMenuBoxTop = (nScreenHeight - height) / 2 + 1;
*nOptionsMenuBoxBottom = *nOptionsMenuBoxTop + height;
*nOptionsMenuBoxBottom = *nOptionsMenuBoxTop + height;*/
}
void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom)
@ -365,7 +365,7 @@ void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int
int space, space_left, space_right;
// Update the status bar
DrawStatusText(" Use \x18\x19 to select, then press ENTER. Press ESC to go back.");
/*DrawStatusText(" Use \x18\x19 to select, then press ENTER. Press ESC to go back.");
DrawBox(nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
DrawText(nOptionsMenuBoxLeft + (((nOptionsMenuBoxRight - nOptionsMenuBoxLeft) - strlen(OptionsMenuTitle)) / 2) + 1, nOptionsMenuBoxTop, OptionsMenuTitle, ATTR(cMenuFgColor, cMenuBgColor));
@ -391,5 +391,6 @@ void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int
{
DrawText(nOptionsMenuBoxLeft+1, nOptionsMenuBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
}
}
}
}*/
}
#endif

251
freeldr/freeldr/oslist.c Normal file
View file

@ -0,0 +1,251 @@
/*
* FreeLoader
* Copyright (C) 1999, 2000, 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "freeldr.h"
#include "parseini.h"
#include "oslist.h"
BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, PULONG OperatingSystemCountPointer)
{
ULONG Idx;
ULONG CurrentOperatingSystemIndex;
UCHAR SettingName[80];
UCHAR SettingValue[80];
ULONG OperatingSystemCount;
ULONG SectionId;
ULONG OperatingSystemSectionId;
ULONG SectionSettingCount;
PUCHAR *OperatingSystemSectionNames;
PUCHAR *OperatingSystemDisplayNames;
//
// Open the [FreeLoader] section
//
if (!OpenSection("FreeLoader", &SectionId))
{
MessageBox("Section [FreeLoader] not found in freeldr.ini.");
return FALSE;
}
SectionSettingCount = GetNumSectionItems(SectionId);
OperatingSystemCount = CountOperatingSystems(SectionId);
//
// Allocate memory to hold operating system lists
//
if (!AllocateListMemory(&OperatingSystemSectionNames, &OperatingSystemDisplayNames, OperatingSystemCount))
{
return FALSE;
}
//
// Now loop through and read the operating system section names
//
CurrentOperatingSystemIndex = 0;
for (Idx=0; Idx<SectionSettingCount; Idx++)
{
ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
if (stricmp(SettingName, "OS") == 0)
{
strcpy(OperatingSystemSectionNames[CurrentOperatingSystemIndex], SettingValue);
CurrentOperatingSystemIndex++;
}
}
//
// Now loop through and read the operating system display names
//
for (Idx=0; Idx<OperatingSystemCount; Idx++)
{
if (OpenSection(OperatingSystemSectionNames[Idx], &OperatingSystemSectionId))
{
if (ReadSectionSettingByName(OperatingSystemSectionId, "Name", SettingValue, 80))
{
//
// Remove any quotes around the string
//
RemoveQuotes(SettingValue);
strcpy(OperatingSystemDisplayNames[Idx], SettingValue);
}
else
{
sprintf(SettingName, "Operating System '%s' has no Name= line in it's [section].", OperatingSystemSectionNames[Idx]);
MessageBox(SettingName);
strcpy(OperatingSystemDisplayNames[Idx], "");
}
}
}
*OperatingSystemCountPointer = OperatingSystemCount;
*SectionNamesPointer = OperatingSystemSectionNames;
*DisplayNamesPointer = OperatingSystemDisplayNames;
return TRUE;
}
ULONG CountOperatingSystems(ULONG SectionId)
{
ULONG Idx;
UCHAR SettingName[80];
UCHAR SettingValue[80];
ULONG OperatingSystemCount = 0;
ULONG SectionSettingCount;
//
// Loop through and count the operating systems
//
SectionSettingCount = GetNumSectionItems(SectionId);
for (Idx=0; Idx<SectionSettingCount; Idx++)
{
ReadSectionSettingByNumber(SectionId, Idx, SettingName, 80, SettingValue, 80);
if (stricmp(SettingName, "OS") == 0)
{
if (OpenSection(SettingValue, NULL))
{
OperatingSystemCount++;
}
else
{
sprintf(SettingName, "Operating System '%s' is listed in freeldr.ini but doesn't have a [section].", SettingValue);
MessageBox(SettingName);
}
}
}
return OperatingSystemCount;
}
BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG OperatingSystemCount)
{
ULONG Idx;
PUCHAR *OperatingSystemSectionNames = NULL;
PUCHAR *OperatingSystemDisplayNames = NULL;
//
// Allocate memory to hold operating system list arrays
//
OperatingSystemSectionNames = (PUCHAR*) AllocateMemory( sizeof(PUCHAR) * OperatingSystemCount);
OperatingSystemDisplayNames = (PUCHAR*) AllocateMemory( sizeof(PUCHAR) * OperatingSystemCount);
//
// If either allocation failed then return FALSE
//
if ( (OperatingSystemSectionNames == NULL) || (OperatingSystemDisplayNames == NULL) )
{
if (OperatingSystemSectionNames != NULL)
{
FreeMemory(OperatingSystemSectionNames);
}
if (OperatingSystemDisplayNames != NULL)
{
FreeMemory(OperatingSystemDisplayNames);
}
return FALSE;
}
//
// Clear our newly allocated memory
//
memset(OperatingSystemSectionNames, 0, sizeof(PUCHAR) * OperatingSystemCount);
memset(OperatingSystemDisplayNames, 0, sizeof(PUCHAR) * OperatingSystemCount);
//
// Loop through each array element and allocate it's string memory
//
for (Idx=0; Idx<OperatingSystemCount; Idx++)
{
OperatingSystemSectionNames[Idx] = (PUCHAR) AllocateMemory(80);
OperatingSystemDisplayNames[Idx] = (PUCHAR) AllocateMemory(80);
//
// If it failed then jump to the cleanup code
//
if ( (OperatingSystemSectionNames[Idx] == NULL) || (OperatingSystemDisplayNames[Idx] == NULL))
{
goto AllocateListMemoryFailed;
}
}
*SectionNamesPointer = OperatingSystemSectionNames;
*DisplayNamesPointer = OperatingSystemDisplayNames;
return TRUE;
AllocateListMemoryFailed:
//
// Loop through each array element and free it's string memory
//
for (Idx=0; Idx<OperatingSystemCount; Idx++)
{
if (OperatingSystemSectionNames[Idx] != NULL)
{
FreeMemory(OperatingSystemSectionNames[Idx]);
}
if (OperatingSystemDisplayNames[Idx] != NULL)
{
FreeMemory(OperatingSystemDisplayNames[Idx]);
}
}
//
// Free operating system list arrays
//
FreeMemory(OperatingSystemSectionNames);
FreeMemory(OperatingSystemDisplayNames);
return FALSE;
}
BOOL RemoveQuotes(PUCHAR QuotedString)
{
UCHAR TempString[200];
//
// If this string is not quoted then return FALSE
//
if ((QuotedString[0] != '\"') && (QuotedString[strlen(QuotedString)-1] != '\"'))
{
return FALSE;
}
if (QuotedString[0] == '\"')
{
strcpy(TempString, (QuotedString + 1));
}
else
{
strcpy(TempString, QuotedString);
}
if (TempString[strlen(TempString)-1] == '\"')
{
TempString[strlen(TempString)-1] = '\0';
}
strcpy(QuotedString, TempString);
return TRUE;
}

28
freeldr/freeldr/oslist.h Normal file
View file

@ -0,0 +1,28 @@
/*
* FreeLoader
* Copyright (C) 2001 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __OSLIST_H
#define __OSLIST_H
BOOL InitOperatingSystemList(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, PULONG OperatingSystemCountPointer);
ULONG CountOperatingSystems(ULONG SectionId);
BOOL AllocateListMemory(PUCHAR **SectionNamesPointer, PUCHAR **DisplayNamesPointer, ULONG OperatingSystemCount);
BOOL RemoveQuotes(PUCHAR QuotedString);
#endif // #defined __OSLIST_H

View file

@ -23,16 +23,17 @@
#include "fs.h"
#include "stdlib.h"
#include "memory.h"
#include "debug.h"
PUCHAR FreeLoaderIniFileData = NULL;
ULONG FreeLoaderIniFileSize = 0;
BOOL ParseIniFile(void)
BOOL ParseIniFile(VOID)
{
int i;
char name[1024];
char value[1024];
FILE Freeldr_Ini; // File handle for freeldr.ini
//int i;
//char name[1024];
//char value[1024];
PFILE Freeldr_Ini; // File handle for freeldr.ini
// Open the boot drive for file access
if (!OpenDiskDrive(BootDrive, 0))
@ -42,28 +43,31 @@ BOOL ParseIniFile(void)
}
// Try to open freeldr.ini or fail
if (!OpenFile("freeldr.ini", &Freeldr_Ini))
Freeldr_Ini = OpenFile("freeldr.ini");
if (Freeldr_Ini == NULL)
{
printf("FREELDR.INI not found.\nYou need to re-install FreeLoader.\n");
return FALSE;
}
// Get the file size & allocate enough memory for it
FreeLoaderIniFileSize = GetFileSize(&Freeldr_Ini);
FreeLoaderIniFileSize = GetFileSize(Freeldr_Ini);
FreeLoaderIniFileData = AllocateMemory(FreeLoaderIniFileSize);
// If we are out of memory then return FALSE
if (FreeLoaderIniFileData == NULL)
{
printf("Out of memory while loading FREELDR.INI.\n");
CloseFile(Freeldr_Ini);
return FALSE;
}
// Read freeldr.ini off the disk
ReadFile(&Freeldr_Ini, FreeLoaderIniFileSize, FreeLoaderIniFileData);
ReadFile(Freeldr_Ini, FreeLoaderIniFileSize, NULL, FreeLoaderIniFileData);
CloseFile(Freeldr_Ini);
// Make sure the [FREELOADER] section exists
if (!GetNumSectionItems("FREELOADER"))
/*if (OpenSection("FREELOADER", NULL))
{
printf("Section [FREELOADER] not found in FREELDR.INI.\nYou need to re-install FreeLoader.\n");
return FALSE;
@ -81,7 +85,7 @@ BOOL ParseIniFile(void)
}
else
SetSetting(name, value);
}
}*/
return TRUE;
}
@ -122,208 +126,202 @@ ULONG GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset
return CurrentOffset;
}
ULONG GetOffsetOfFirstLineOfSection(PUCHAR SectionName)
BOOL OpenSection(PUCHAR SectionName, PULONG SectionId)
{
char str[1024];
char real_section[1024];
ULONG freeldr_ini_offset;
UCHAR TempString[80];
UCHAR RealSectionName[80];
ULONG FileOffset;
BOOL SectionFound = FALSE;
//
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, SectionName);
strcat(real_section, "]");
//
strcpy(RealSectionName, "[");
strcat(RealSectionName, SectionName);
strcat(RealSectionName, "]");
//
// Get to the beginning of the file
freeldr_ini_offset = 0;
//
FileOffset = 0;
//
// Find the section
while (freeldr_ini_offset < FreeLoaderIniFileSize)
//
while (FileOffset < FreeLoaderIniFileSize)
{
//
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
// Skip comments
if (str[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
continue;
//
FileOffset = GetNextLineOfFileData(TempString, 80, FileOffset);
//
// If it isn't a section header then continue on
if (str[0] != '[')
//
if (TempString[0] != '[')
continue;
//
// Check and see if we found it
if (stricmp(str, real_section) == 0)
//
if (stricmp(TempString, RealSectionName) == 0)
{
SectionFound = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if (!SectionFound)
return 0;
if (SectionId)
{
*SectionId = FileOffset;
}
return freeldr_ini_offset;
return SectionFound;
}
ULONG GetNumSectionItems(PUCHAR SectionName)
ULONG GetNumSectionItems(ULONG SectionId)
{
UCHAR str[1024];
ULONG num_items = 0;
ULONG freeldr_ini_offset;
// Get to the beginning of the section
freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
// If the section wasn't found then exit
if (freeldr_ini_offset == 0)
{
return 0;
}
UCHAR TempString[80];
ULONG SectionItemCount = 0;
// Now count how many settings are in this section
while (freeldr_ini_offset < FreeLoaderIniFileSize)
while (SectionId < FreeLoaderIniFileSize)
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
SectionId = GetNextLineOfFileData(TempString, 80, SectionId);
// If we hit a new section then we're done
if (TempString[0] == '[')
break;
// Skip comments
if (str[0] == '#')
if (TempString[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
if (!strlen(TempString))
continue;
// If we hit a new section then we're done
if (str[0] == '[')
break;
num_items++;
SectionItemCount++;
}
return num_items;
return SectionItemCount;
}
BOOL ReadSectionSettingByNumber(PUCHAR SectionName, ULONG SettingNumber, PUCHAR SettingName, PUCHAR SettingValue)
BOOL ReadSectionSettingByNumber(ULONG SectionId, ULONG SettingNumber, PUCHAR SettingName, ULONG NameSize, PUCHAR SettingValue, ULONG ValueSize)
{
UCHAR str[1024];
ULONG num_items = 0;
ULONG i;
ULONG freeldr_ini_offset;
UCHAR TempString[1024];
ULONG SectionItemCount = 0;
ULONG Idx;
ULONG FileOffset;
//
// Get to the beginning of the section
freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
// If the section wasn't found then exit
if (freeldr_ini_offset == 0)
{
return 0;
}
//
FileOffset = SectionId;
//
// Now find the setting we are looking for
while (freeldr_ini_offset < FreeLoaderIniFileSize)
//
do
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
FileOffset = GetNextLineOfFileData(TempString, 1024, FileOffset);
// Skip comments
if (str[0] == '#')
if (TempString[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
if (!strlen(TempString))
continue;
// If we hit a new section then we're done
if (str[0] == '[')
if (TempString[0] == '[')
break;
// Increment setting number
num_items++;
// Check and see if we found the setting
if (num_items == SettingNumber)
if (SectionItemCount == SettingNumber)
{
for (i=0; i<strlen(str); i++)
for (Idx=0; Idx<strlen(TempString); Idx++)
{
// Check and see if this character is the separator
if (str[i] == '=')
if (TempString[Idx] == '=')
{
SettingName[i] = '\0';
SettingName[Idx] = '\0';
strcpy(SettingValue, str+i+1);
strncpy(SettingValue, TempString + Idx + 1, ValueSize);
return TRUE;
}
else
SettingName[i] = str[i];
else if (Idx < NameSize)
{
SettingName[Idx] = TempString[Idx];
}
}
}
// Increment setting number
SectionItemCount++;
}
while (FileOffset < FreeLoaderIniFileSize);
return FALSE;
}
BOOL ReadSectionSettingByName(PUCHAR SectionName, PUCHAR SettingName, PUCHAR SettingValue)
BOOL ReadSectionSettingByName(ULONG SectionId, PUCHAR SettingName, PUCHAR Buffer, ULONG BufferSize)
{
UCHAR str[1024];
UCHAR temp[1024];
ULONG i;
ULONG freeldr_ini_offset;
UCHAR TempString[1024];
UCHAR TempBuffer[80];
ULONG Idx;
ULONG FileOffset;
//
// Get to the beginning of the section
freeldr_ini_offset = GetOffsetOfFirstLineOfSection(SectionName);
// If the section wasn't found then exit
if (freeldr_ini_offset == 0)
{
return 0;
}
//
FileOffset = SectionId;
//
// Now find the setting we are looking for
while (freeldr_ini_offset < FreeLoaderIniFileSize)
//
while (FileOffset < FreeLoaderIniFileSize)
{
// Read a line
freeldr_ini_offset = GetNextLineOfFileData(str, 1024, freeldr_ini_offset);
FileOffset = GetNextLineOfFileData(TempString, 1024, FileOffset);
// Skip comments
if (str[0] == '#')
if (TempString[0] == '#')
continue;
// Skip blank lines
if (!strlen(str))
if (!strlen(TempString))
continue;
// If we hit a new section then we're done
if (str[0] == '[')
if (TempString[0] == '[')
break;
// Extract the setting name
for (i=0; i<strlen(str); i++)
for (Idx=0; Idx<strlen(TempString); Idx++)
{
if (str[i] != '=')
temp[i] = str[i];
if (TempString[Idx] != '=')
TempBuffer[Idx] = TempString[Idx];
else
{
temp[i] = '\0';
TempBuffer[Idx] = '\0';
break;
}
}
// Check and see if we found the setting
if (stricmp(temp, SettingName) == 0)
if (stricmp(TempBuffer, SettingName) == 0)
{
for (i=0; i<strlen(str); i++)
for (Idx=0; Idx<strlen(TempString); Idx++)
{
// Check and see if this character is the separator
if (str[i] == '=')
if (TempString[Idx] == '=')
{
strcpy(SettingValue, str+i+1);
strcpy(Buffer, TempString + Idx + 1);
return TRUE;
}
@ -434,7 +432,7 @@ BOOL IsValidSetting(char *setting, char *value)
return FALSE;
}
void SetSetting(char *setting, char *value)
/*void SetSetting(char *setting, char *value)
{
char v[260];
@ -519,4 +517,4 @@ void SetSetting(char *setting, char *value)
}
else if(stricmp(setting, "TimeOut") == 0)
nTimeOut = atoi(value);
}
}*/

View file

@ -20,13 +20,22 @@
#ifndef __PARSEINI_H
#define __PARSEINI_H
BOOL ParseIniFile(void);
/*BOOL ParseIniFile(void);
ULONG GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset); // Gets the next line of text (up to BufferSize) after CurrentOffset and returns the offset of the next line
ULONG GetOffsetOfFirstLineOfSection(PUCHAR SectionName); // Returns the offset of the first line in the section or zero if the section wasn't found
ULONG GetNumSectionItems(PUCHAR SectionName); // returns the number of items in a particular section (i.e. [FREELOADER])
BOOL ReadSectionSettingByNumber(PUCHAR SectionName, ULONG SettingNumber, PUCHAR SettingName, PUCHAR SettingValue); // Reads the num'th value from section
BOOL ReadSectionSettingByName(PUCHAR SectionName, PUCHAR SettingName, PUCHAR SettingValue); // Reads the value named name from section
BOOL IsValidSetting(char *setting, char *value);
void SetSetting(char *setting, char *value);*/
BOOL ParseIniFile(VOID);
ULONG GetNextLineOfFileData(PUCHAR Buffer, ULONG BufferSize, ULONG CurrentOffset);
BOOL OpenSection(PUCHAR SectionName, PULONG SectionId);
ULONG GetNumSectionItems(ULONG SectionId);
BOOL ReadSectionSettingByNumber(ULONG SectionId, ULONG SettingNumber, PUCHAR SettingName, ULONG NameSize, PUCHAR SettingValue, ULONG ValueSize);
BOOL ReadSectionSettingByName(ULONG SectionId, PUCHAR SettingName, PUCHAR Buffer, ULONG BufferSize);
BOOL IsValidSetting(char *setting, char *value);
void SetSetting(char *setting, char *value);

View file

@ -34,7 +34,7 @@ BOOL LoadReactOSDrivers(PUCHAR OperatingSystemName);
void LoadAndBootReactOS(PUCHAR OperatingSystemName)
{
FILE file;
PFILE FilePointer;
char name[1024];
char value[1024];
char szFileName[1024];
@ -43,6 +43,18 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
int nNumDriverFiles=0;
int nNumFilesLoaded=0;
char MsgBuffer[256];
ULONG SectionId;
//
// Open the operating system section
// specified in the .ini file
//
if (!OpenSection(OperatingSystemName, &SectionId))
{
sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
MessageBox(MsgBuffer);
return;
}
/*
* Setup multiboot information structure
@ -73,7 +85,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Make sure the system path is set in the .ini file
*/
if (!ReadSectionSettingByName(OperatingSystemName, "SystemPath", value))
if (!ReadSectionSettingByName(SectionId, "SystemPath", value, 1024))
{
MessageBox("System path not specified for selected operating system.");
return;
@ -99,7 +111,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Read the optional kernel parameters (if any)
*/
if (ReadSectionSettingByName(OperatingSystemName, "Options", value))
if (ReadSectionSettingByName(SectionId, "Options", value, 1024))
{
strcat(multiboot_kernel_cmdline, " ");
strcat(multiboot_kernel_cmdline, value);
@ -113,7 +125,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Find the kernel image name
*/
if(!ReadSectionSettingByName(OperatingSystemName, "Kernel", value))
if(!ReadSectionSettingByName(SectionId, "Kernel", value, 1024))
{
MessageBox("Kernel image file not specified for selected operating system.");
return;
@ -136,12 +148,12 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Parse the ini file and count the kernel and drivers
*/
for (i=1; i<=GetNumSectionItems(OperatingSystemName); i++)
for (i=1; i<=GetNumSectionItems(SectionId); i++)
{
/*
* Read the setting and check if it's a driver
*/
ReadSectionSettingByNumber(OperatingSystemName, i, name, value);
ReadSectionSettingByNumber(SectionId, i, name, 1024, value, 1024);
if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
nNumDriverFiles++;
}
@ -150,14 +162,17 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
* Find the kernel image name
* and try to load the kernel off the disk
*/
if(ReadSectionSettingByName(OperatingSystemName, "Kernel", value))
if(ReadSectionSettingByName(SectionId, "Kernel", value, 1024))
{
/*
* Set the name and try to open the PE image
*/
strcpy(szFileName, szBootPath);
strcat(szFileName, value);
if (!OpenFile(szFileName, &file))
//strcpy(szFileName, szBootPath);
//strcat(szFileName, value);
strcpy(szFileName, value);
FilePointer = OpenFile(szFileName);
if (FilePointer == NULL)
{
strcat(value, " not found.");
MessageBox(value);
@ -176,7 +191,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Load the kernel image
*/
MultiBootLoadKernel(&file);
MultiBootLoadKernel(FilePointer);
nNumFilesLoaded++;
DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles);
@ -186,20 +201,23 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
* Parse the ini file and load the kernel and
* load all the drivers specified
*/
for (i=1; i<=GetNumSectionItems(OperatingSystemName); i++)
for (i=1; i<=GetNumSectionItems(SectionId); i++)
{
/*
* Read the setting and check if it's a driver
*/
ReadSectionSettingByNumber(OperatingSystemName, i, name, value);
ReadSectionSettingByNumber(SectionId, i, name, 1024, value, 1024);
if (stricmp(name, "Driver") == 0)
{
/*
* Set the name and try to open the PE image
*/
strcpy(szFileName, szBootPath);
strcat(szFileName, value);
if (!OpenFile(szFileName, &file))
//strcpy(szFileName, szBootPath);
//strcat(szFileName, value);
strcpy(szFileName, value);
FilePointer = OpenFile(szFileName);
if (FilePointer == NULL)
{
strcat(value, " not found.");
MessageBox(value);
@ -218,7 +236,7 @@ void LoadAndBootReactOS(PUCHAR OperatingSystemName)
/*
* Load the driver
*/
MultiBootLoadModule(&file, szFileName);
MultiBootLoadModule(FilePointer, szFileName);
nNumFilesLoaded++;

View file

@ -253,6 +253,17 @@ char *strcpy(char *dest, char *src)
return ret;
}
char *strncpy(char *dest, char *src, size_t count)
{
char *ret = dest;
while((*src) && (count--))
*dest++ = *src++;
*dest = 0;
return ret;
}
char *strcat(char *dest, char *src)
{
char *ret = dest;
@ -324,19 +335,19 @@ int _strnicmp(const char *string1, const char *string2, size_t length)
return 0;
}
char *fgets(char *string, int n, FILE *stream)
char *fgets(char *string, int n, PFILE stream)
{
int i;
for(i=0; i<(n-1); i++)
{
if(feof(stream))
if(IsEndOfFile(stream))
{
i++;
break;
}
ReadFile(stream, 1, string+i);
ReadFile(stream, 1, NULL, string+i);
if(string[i] == '\n')
{

View file

@ -40,6 +40,7 @@ int wherey(void); // Implemented in asmcode.S
int strlen(char *str);
char *strcpy(char *dest, char *src);
char *strncpy(char *dest, char *src, size_t count);
char *strcat(char *dest, char *src);
char *strchr(const char *s, int c);
int strcmp(const char *string1, const char *string2);
@ -51,7 +52,7 @@ int tolower(int c);
int memcmp(const void *buf1, const void *buf2, size_t count);
void *memcpy(void *dest, const void *src, size_t count);
void *memset(void *dest, int c, size_t count);
char *fgets(char *string, int n, FILE *stream);
char *fgets(char *string, int n, PFILE stream);
int atoi(char *string);
#define ZeroMemory(Destination, Length) memset(Destination, 0, Length)
@ -64,18 +65,15 @@ void sprintf(char *buffer, char *format, ...);
char *convert_to_ascii(char *buf, int c, ...);
int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S
BOOL BiosInt13Read(ULONG Drive, ULONG Head, ULONG Track, ULONG Sector, ULONG SectorCount, PVOID Buffer); // Implemented in asmcode.S
BOOL BiosInt13ReadExtended(ULONG Drive, ULONG Sector, ULONG SectorCount, PVOID Buffer); // Implemented in asmcode.S
BOOL BiosInt13ExtensionsSupported(ULONG Drive);
void stop_floppy(void); // Implemented in asmcode.S
int get_heads(int drive); // Implemented in asmcode.S
int get_cylinders(int drive); // Implemented in asmcode.S
int get_sectors(int drive); // Implemented in asmcode.S
/* Values for biosdisk() */
#define _DISK_RESET 0 // Unimplemented
#define _DISK_STATUS 1 // Unimplemented
#define _DISK_READ 2 // Reads a sector into memory
#define _DISK_WRITE 3 // Unimplemented
#define _DISK_VERIFY 4 // Unimplemented
#define _DISK_FORMAT 5 // Unimplemented
#endif // defined __STDLIB_H

View file

@ -20,57 +20,193 @@
#include "freeldr.h"
#include "stdlib.h"
#include "tui.h"
#include "memory.h"
#include "debug.h"
#include "parseini.h"
int nScreenWidth = 80; // Screen Width
int nScreenHeight = 25; // Screen Height
ULONG nScreenWidth = 80; // Screen Width
ULONG nScreenHeight = 25; // Screen Height
char cStatusBarFgColor = COLOR_BLACK; // Status bar foreground color
char cStatusBarBgColor = COLOR_CYAN; // Status bar background color
char cBackdropFgColor = COLOR_WHITE; // Backdrop foreground color
char cBackdropBgColor = COLOR_BLUE; // Backdrop background color
char cBackdropFillStyle = MEDIUM_FILL; // Backdrop fill style
char cTitleBoxFgColor = COLOR_WHITE; // Title box foreground color
char cTitleBoxBgColor = COLOR_RED; // Title box background color
char cMessageBoxFgColor = COLOR_WHITE; // Message box foreground color
char cMessageBoxBgColor = COLOR_BLUE; // Message box background color
char cMenuFgColor = COLOR_WHITE; // Menu foreground color
char cMenuBgColor = COLOR_BLUE; // Menu background color
char cTextColor = COLOR_YELLOW; // Normal text color
char cSelectedTextColor = COLOR_BLACK; // Selected text color
char cSelectedTextBgColor = COLOR_GRAY; // Selected text background color
char szTitleBoxTitleText[260] = "Boot Menu"; // Title box's title text
CHAR cStatusBarFgColor = COLOR_BLACK; // Status bar foreground color
CHAR cStatusBarBgColor = COLOR_CYAN; // Status bar background color
CHAR cBackdropFgColor = COLOR_WHITE; // Backdrop foreground color
CHAR cBackdropBgColor = COLOR_BLUE; // Backdrop background color
CHAR cBackdropFillStyle = MEDIUM_FILL; // Backdrop fill style
CHAR cTitleBoxFgColor = COLOR_WHITE; // Title box foreground color
CHAR cTitleBoxBgColor = COLOR_RED; // Title box background color
CHAR cMessageBoxFgColor = COLOR_WHITE; // Message box foreground color
CHAR cMessageBoxBgColor = COLOR_BLUE; // Message box background color
CHAR cMenuFgColor = COLOR_WHITE; // Menu foreground color
CHAR cMenuBgColor = COLOR_BLUE; // Menu background color
CHAR cTextColor = COLOR_YELLOW; // Normal text color
CHAR cSelectedTextColor = COLOR_BLACK; // Selected text color
CHAR cSelectedTextBgColor = COLOR_GRAY; // Selected text background color
CHAR szTitleBoxTitleText[260] = "Boot Menu"; // Title box's title text
char szMessageBoxLineText[4000] = "";
PUCHAR szMessageBoxLineText = NULL;
BOOL UserInterfaceUp = FALSE; // Tells us if the user interface is displayed
BOOL InitUserInterface(VOID)
{
ULONG SectionId;
UCHAR SettingText[260];
DbgPrint((DPRINT_UI, "Initializing User Interface.\n"));
szMessageBoxLineText = AllocateMemory(4096);
if (szMessageBoxLineText == NULL)
{
return FALSE;
}
DbgPrint((DPRINT_UI, "Reading in UI settings from [Display] section.\n"));
if (OpenSection("Display", &SectionId))
{
if (ReadSectionSettingByName(SectionId, "TitleText", SettingText, 260))
{
strcpy(szTitleBoxTitleText, SettingText);
}
if (ReadSectionSettingByName(SectionId, "StatusBarColor", SettingText, 260))
{
cStatusBarBgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "StatusBarTextColor", SettingText, 260))
{
cStatusBarFgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "BackdropTextColor", SettingText, 260))
{
cBackdropFgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "BackdropColor", SettingText, 260))
{
cBackdropBgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "BackdropFillStyle", SettingText, 260))
{
cBackdropFillStyle = TextToFillStyle(SettingText);
}
if (ReadSectionSettingByName(SectionId, "TitleBoxTextColor", SettingText, 260))
{
cTitleBoxFgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "TitleBoxColor", SettingText, 260))
{
cTitleBoxBgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "MessageBoxTextColor", SettingText, 260))
{
cMessageBoxFgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "MessageBoxColor", SettingText, 260))
{
cMessageBoxBgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "MenuTextColor", SettingText, 260))
{
cMenuFgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "MenuColor", SettingText, 260))
{
cMenuBgColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "TextColor", SettingText, 260))
{
cTextColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "SelectedTextColor", SettingText, 260))
{
cSelectedTextColor = TextToColor(SettingText);
}
if (ReadSectionSettingByName(SectionId, "SelectedColor", SettingText, 260))
{
cSelectedTextBgColor = TextToColor(SettingText);
}
}
clrscr();
hidecursor();
// Draw the backdrop and title box
DrawBackdrop();
UserInterfaceUp = TRUE;
DbgPrint((DPRINT_UI, "InitUserInterface() returning TRUE.\n"));
return TRUE;
}
void DrawBackdrop(void)
{
// Fill in the backdrop
FillArea(0, 0, nScreenWidth-1, nScreenHeight-1, cBackdropFillStyle, ATTR(cBackdropFgColor, cBackdropBgColor));
//
// Fill in the background (excluding title box & status bar)
//
FillArea(0,
TITLE_BOX_HEIGHT,
nScreenWidth - 1,
nScreenHeight - 1,
cBackdropFillStyle,
ATTR(cBackdropFgColor, cBackdropBgColor));
//
// Draw the title box
DrawBox(1, 1, nScreenWidth, 5, D_VERT, D_HORZ, TRUE, FALSE, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
DrawBox(1,
1,
nScreenWidth,
5,
D_VERT,
D_HORZ,
TRUE,
FALSE,
ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
// Draw version
DrawText(3, 2, VERSION, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
// Draw version text
//
DrawText(3,
2,
VERSION,
ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
// Draw copyright
DrawText(3, 3, "by Brian Palmer", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
DrawText(3, 4, "<brianp@sginet.com>", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
DrawText(3,
3,
"by Brian Palmer",
ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
DrawText(3,
4,
"<brianp@sginet.com>",
ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
// Draw help text
//
//DrawText(nScreenWidth-15, 4, /*"F1 for Help"*/"F8 for Options", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
// Draw title
DrawText((nScreenWidth/2)-(strlen(szTitleBoxTitleText)/2), 3, szTitleBoxTitleText, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
// Draw date
DrawText(nScreenWidth-9, 2, "01/02/03", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
// Draw time
DrawText(nScreenWidth-9, 3, "10:12:34", ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
// Draw title text
//
DrawText( (nScreenWidth / 2) - (strlen(szTitleBoxTitleText)/2),
3,
szTitleBoxTitleText,
ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
//
// Draw status bar
//
DrawStatusText("");
//
// Update the date & time
//
UpdateDateTime();
}
@ -234,8 +370,8 @@ void DrawStatusText(char *text)
void UpdateDateTime(void)
{
char date[260];
char time[260];
char date[40];
char time[40];
char temp[20];
int hour, minute, second, bPM=FALSE;
@ -353,10 +489,19 @@ void MessageBox(char *text)
int curline = 0;
int i , j, k;
int x1, x2, y1, y2;
char savebuffer[8000];
PVOID savebuffer;
char temp[260];
char key;
if (!UserInterfaceUp)
{
printf("%s", text);
printf("Press any key.\n");
getch();
return;
}
savebuffer = AllocateMemory(8000);
SaveScreen(savebuffer);
strcat(szMessageBoxLineText, text);
@ -428,6 +573,7 @@ void MessageBox(char *text)
}
RestoreScreen(savebuffer);
FreeMemory(savebuffer);
UpdateDateTime();
strcpy(szMessageBoxLineText, "");
}

View file

@ -20,27 +20,11 @@
#ifndef __TUI_H
#define __TUI_H
#define SCREEN_MEM 0xB8000
extern int nScreenWidth; // Screen Width
extern int nScreenHeight; // Screen Height
extern char cStatusBarFgColor; // Status bar foreground color
extern char cStatusBarBgColor; // Status bar background color
extern char cBackdropFgColor; // Backdrop foreground color
extern char cBackdropBgColor; // Backdrop background color
extern char cBackdropFillStyle; // Backdrop fill style
extern char cTitleBoxFgColor; // Title box foreground color
extern char cTitleBoxBgColor; // Title box background color
extern char cMessageBoxFgColor; // Message box foreground color
extern char cMessageBoxBgColor; // Message box background color
extern char cMenuFgColor; // Menu foreground color
extern char cMenuBgColor; // Menu background color
extern char cTextColor; // Normal text color
extern char cSelectedTextColor; // Selected text color
extern char cSelectedTextBgColor; // Selected text background color
extern char szTitleBoxTitleText[260]; // Title box's title text
#define SCREEN_MEM 0xB8000
#define TITLE_BOX_HEIGHT 5
// Initialize Textual-User-Interface
BOOL InitUserInterface(VOID);
// Fills the entire screen with a backdrop
void DrawBackdrop(void);
// Fills the area specified with cFillChar and cAttr

View file

@ -4,8 +4,9 @@ To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit c
FreeLoader does not currently work with extended partitions.
Linux booting support needs to be added.
ext2 filesystem support needs to be added.
The MessageBox() function needs to not allocate memory. Because it gets called when memory allocation fails.
Current memory layout:
Old memory layout:
0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
0000:1000 - 0000:6FFF: Real mode stack area
@ -16,3 +17,27 @@ xxxx:xxxx - 6000:0000: Protected mode stack area & heap
7000:0000 - 7000:FFFF: scratch area for any function's use (ie sector buffer for biosdisk()) - can be overwritten by any function
8000:0000 - 9000:FFFF: fat table entry buffer
A000:0000 - FFFF:FFFF: reserved
New memory layout:
0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
0000:1000 - 0000:6FFF: Real mode stack area
0000:7000 - 0000:7FFF: Unused
0000:8000 - xxxx:xxxx: FreeLoader program & data area
xxxx:xxxx - 8000:FFFF: Random memory allocation heap
9000:0000 - 9000:7FFF: Disk read buffer for BIOS Int 13h
9000:8000 - 9000:8FFF: Screen save buffer passed in from boot sector
9000:9000 - 9000:FFFF: Protected mode stack area
A000:0000 - FFFF:FFFF: reserved
FreeLoader Boot Process
Boot Sector
The BIOS loads the boot sector at 0000:7C00. The FAT32 boot sector relocates itself higher in memory at 9000:0000 and loads it's extra sector at 9000:0200 and then looks for freeldr.sys on the file system. Once found it loads freeldr.sys to 0000:7E00 and then jumps to it's entry point at 0000:8000. The FAT12/16 boot sector does no relocation, it just searches for the freeldr.sys and loads the first 512 bytes to 0000:7E00. This extra code enables it to fully navigate the file allocation table. Then it loads freeldr.sys to 0000:7E00 and jumps to it's entry point at 0000:8000. Before FreeLoader gets control the boot sector saves the screen contents to a buffer at 9000:8000 and the cursor x & y position to bytes at 9000:8FA0 & 9000:8FA1 respectively.
FreeLoader Initialization
When FreeLoader gets control it saves the boot drive, passed to it in the DL register, and sets up the stack, enables protected mode, and calls BootMain().