mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
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:
parent
709cd514ab
commit
3662f1f720
34 changed files with 3659 additions and 1730 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1163
freeldr/freeldr/fat.c
Normal file
File diff suppressed because it is too large
Load diff
179
freeldr/freeldr/fat.h
Normal file
179
freeldr/freeldr/fat.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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();*/
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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();*/
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
251
freeldr/freeldr/oslist.c
Normal 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
28
freeldr/freeldr/oslist.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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')
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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, "");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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().
|
Loading…
Reference in a new issue