Initial revision

svn path=/trunk/; revision=1904
This commit is contained in:
Brian Palmer 2001-05-15 03:50:25 +00:00
parent bbf48f20aa
commit afdf923c65
40 changed files with 8541 additions and 0 deletions

339
freeldr/COPYING Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

130
freeldr/FREELDR.INI Normal file
View file

@ -0,0 +1,130 @@
# FreeLoader by Brian Palmer
# FREELDR.INI - FreeLoader Initialization file
#
# Each line must be less than 1024 characters long
# and must be either a section heading (i.e. [section_name])
# or a setting (i.e. name=value) or a blank line.
# Comments start with a '#' character.
# Background colors can be any one of the following:
# Black
# Blue
# Green
# Cyan
# Red
# Magenta
# Brown
# Gray
# Text colors can be any one of the background
# colors and any of the following:
# DarkGray
# LightBlue
# LightGreen
# LightCyan
# LightRed
# LightMagenta
# Yellow
# White
# [FREELOADER] Section Commands:
#
# MessageBox - displays the specified text in a message box upon bootup
# MessageLine - adds a new line of text to a message box (must come before MessageBox command)
# TitleText - text that is displayed in the title box
# StatusBarColor - color of status bar's background
# StatusBarTextColor - color of status bar's text
# BackdropTextColor - color of the backdrop's fill
# BackdropColor - color of the backdrop's background
# BackdropFillStyle - backdrop fill style - can be Light, Medium, or Dark
# TitleBoxTextColor - title box text color
# TitleBoxColor - title box background color
# MessageBoxTextColor - message box text color
# MessageBoxColor - message box background color
# MenuTextColor - menu text color
# MenuColor - menu color
# TextColor - normal text color
# SelectedTextColor - selected text color
# SelectedColor - selected text background color
# TimeOut - sets the timeout (in seconds) before the first OS listed gets booted automagically
# [OS-General] Section Commands:
#
# BootType - sets the boot type: ReactOS, Linux, BootSector, Partition, Drive
# BootDrive - sets the boot drive: 0 - first floppy, 1 - second floppy, 0x80 - first hard disk, 0x81 - second hard disk
# BootPartition - sets the boot partition
# [BootSector OSType] Section Commands:
#
# BootSector - sets the filename of the bootsector to be loaded
# [ReactOS OSType] Section Commands:
#
# Options - sets the command line options for the kernel being booted
# Kernel - sets the kernel filename
# Driver - sets the name of one or more drivers to be loaded (one entry per driver)
[FREELOADER]
MessageLine=Welcome to FreeLoader!
MessageLine=Copyright (c) 2000 by Brian Palmer <brianp@sginet.com>
MessageLine=
MessageBox=Edit your FREELDR.INI file to change your boot settings.
TitleText=Boot Menu
StatusBarColor=Cyan
StatusBarTextColor=Black
BackdropTextColor=White
BackdropColor=Blue
BackdropFillStyle=Medium
TitleBoxTextColor=White
TitleBoxColor=Red
MessageBoxTextColor=White
MessageBoxColor=Blue
MenuTextColor=White
MenuColor=Blue
TextColor=Yellow
SelectedTextColor=Black
SelectedColor=Gray
#OS=ReactOS
#OS=ReactOS (Debug)
#OS=Linux
OS=3« Floppy (A:)
OS=Microsoft Windows (C:)
OS=Drive D:
#TimeOut=0
#[ReactOS]
#BootType=ReactOS
#BootDrive=0
#Options=/DEBUGPORT=SCREEN
#Kernel=\NTOSKRNL.EXE
#Driver=\DRIVERS\IDE.SYS
#Driver=\DRIVERS\VFATFS.SYS
#[ReactOS (Debug)]
#BootType=ReactOS
#BootDrive=0
#Options=/DEBUG /DEBUGPORT=COM1 /BAUDRATE=19200
#Kernel=\NTOSKRNL.EXE
#Driver=\DRIVERS\IDE.SYS
#Driver=\DRIVERS\VFATFS.SYS
#[Linux]
# Linux boot type not implemented yet
#BootType=Partition
#BootDrive=0x80
#BootPartition=2
[3« Floppy (A:)]
BootType=Drive
BootDrive=0
[Microsoft Windows (C:)]
BootType=Drive
BootDrive=0x80
[Drive D:]
BootType=Partition
BootDrive=0x81
BootPartition=1

View file

@ -0,0 +1,256 @@
; BOOTSECT.ASM
; FAT12/16 Boot Sector
; Copyright (c) 1998 Brian Palmer
org 7c00h
segment .text
bits 16
start:
jmp short main
nop
OEMName db 'FreeLDR!'
BytesPerSector dw 512
SectsPerCluster db 1
ReservedSectors dw 1
NumberOfFats db 2
MaxRootEntries dw 512
TotalSectors dw 2880
MediaDescriptor db 0f0h
SectorsPerFat dw 9
SectorsPerTrack dw 18
NumberOfHeads dw 2
HiddenSectors dd 0
TotalSectorsBig dd 0
BootDrive db 0
Reserved db 0
ExtendSig db 29h
SerialNumber dd 00000000h
VolumeLabel db 'FreeLoader!'
FileSystem db 'FAT12 '
main:
cli
cld
xor ax,ax
mov ss,ax
mov sp,7c00h ; Setup a stack
mov ax,cs ; Setup segment registers
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
sti ; Enable ints now
mov [BootDrive],dl ; Save the boot drive
xor ax,ax ; Zero out AX
; Reset disk controller
int 13h
jnc Continue1
jmp BadBoot ; Reset failed...
Continue1:
; Now we must find our way to the first sector of the root directory
xor ax,ax
xor cx,cx
mov al,[NumberOfFats] ; Number of fats
mul WORD [SectorsPerFat] ; Times sectors per fat
add ax,WORD [HiddenSectors]
adc dx,WORD [HiddenSectors+2] ; Add the number of hidden sectors
add ax,[ReservedSectors] ; Add the number of reserved sectors
adc dx,cx ; Add carry bit
push ax ; Store it on the stack
push dx ; Save 32-bit logical start sector
push ax
push dx ; Save it for later use also
; DX:AX now has the number of the starting sector of the root directory
; Now calculate the size of the root directory
mov ax,0020h ; Size of dir entry
mul WORD [MaxRootEntries] ; Times the number of entries
mov bx,[BytesPerSector]
add ax,bx
dec ax
div bx ; Divided by the size of a sector
; AX now has the number of root directory sectors
xchg ax,cx ; Now CX has number of sectors
pop dx
pop ax ; Restore logical sector start
push cx ; Save for later use
mov bx,7c0h ; We will load the root directory
add bx,20h ; Right after the boot sector in memory
mov es,bx
xor bx,bx ; We will load it to [0000:7e00h]
call ReadSectors ; Read the sectors
jnc Continue2 ; BadBoot on error
jmp BadBoot
Continue2:
; Now we have to find our way through the root directory to
; The OSLOADER.SYS file
mov bx,[MaxRootEntries]; Search entire root directory
mov ax,7e0h ; We loaded at 07e0:0000
mov es,ax
xor di,di
mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx
jnz FindFile
jmp ErrBoot
FindFile:
mov ax,es ; We didn't find it in the previous dir entry
add ax,2 ; So lets move to the next one
mov es,ax ; And search again
xor di,di
mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx ; Keep searching till we run out of dir entries
jnz FindFile ; Last entry?
jmp ErrBoot
FoundFile:
xor di,di ; ES:DI has dir entry
xor dx,dx
mov ax,WORD [es:di+1ah] ; Get start cluster
dec ax
dec ax
xor ch,ch
mov cl,BYTE [SectsPerCluster] ; Times sectors per cluster
mul cx
pop cx ; Get number of sectors for root dir
add ax,cx
adc dx,0
pop cx ; Get logical start sector of
pop bx ; Root directory
add ax,bx ; Now we have DX:AX with the logical start
adc dx,cx ; Sector of OSLOADER.SYS
push ax
push dx
mov ax,WORD [es:di+1ch]
mov dx,WORD [es:di+1eh]
mov bx,[BytesPerSector]
dec bx
add ax,bx
adc dx,0
div WORD [BytesPerSector]
xchg ax,cx ; Now CX has number of sectors of OSLOADER.SYS
pop dx
pop ax
mov bx,800h
mov es,bx
xor bx,bx ; Load ROSLDR at 0000:8000h
call ReadSectors ; Load it
jc BadBoot
mov dl,[BootDrive]
xor ax,ax
push ax
mov ax,8000h
push ax ; We will do a far return to 0000:8000h
retf ; Transfer control to ROSLDR
; Reads logical sectors into [ES:BX]
; DX:AX 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,513
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
pop cx
pop dx
pop ax
jc ReadFail
inc ax ;Increment Sector to Read
jnz NoCarry
inc dx
NoCarry:
push bx
mov bx,es
add bx,20h
mov es,bx
pop bx
; Increment read buffer for next sector
loop ReadSectors ; Read next sector
ReadFail:
ret
; Displays a bad boot 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
jmp Reboot
; Displays an 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
Reboot:
xor ax,ax
int 16h ; Wait for a keypress
int 19h ; Reboot
PutChars:
lodsb
or al,al
jz short Done
mov ah,0eh
mov bx,07h
int 10h
jmp short 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'
times 510-($-$$) db 0 ; Pad to 510 bytes
dw 0aa55h ; BootSector signature

View file

@ -0,0 +1,351 @@
; BTSECT32.ASM
; FAT32 Boot Sector
; Copyright (c) 1998, 2000 Brian Palmer
org 7c00h
segment .text
bits 16
start:
jmp short main
nop
OEMName db 'FreeLDR!'
BytesPerSector dw 512
SectsPerCluster db 1
ReservedSectors dw 1
NumberOfFats db 2
MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
MediaDescriptor db 0f8h
SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
SectorsPerTrack dw 18
NumberOfHeads dw 2
HiddenSectors dd 0
TotalSectorsBig dd 0
; FAT32 Inserted Info
SectorsPerFatBig dd 0
ExtendedFlags dw 0
FSVersion dw 0
RootDirStartCluster dd 0
FSInfoSector dw 0
BackupBootSector dw 6
Reserved1 times 12 db 0
; End FAT32 Inserted Info
BootDrive db 0
Reserved db 0
ExtendSig db 29h
SerialNumber dd 00000000h
VolumeLabel db 'FreeLoader!'
FileSystem db 'FAT32 '
main:
cli
cld
xor ax,ax
mov ss,ax
mov sp,7c00h ; Setup a stack
mov ax,cs ; Setup segment registers
mov ds,ax ; Make DS correct
mov es,ax ; Make ES correct
sti ; Enable ints now
mov [BootDrive],dl ; Save the boot drive
xor ax,ax ; Zero out AX
; Reset disk controller
int 13h
jnc Continue
jmp BadBoot ; Reset failed...
Continue:
; 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
mov cx,1
mov bx,7e0h
mov es,bx ; Read sector to [0000:7e00h]
xor bx,bx
call ReadSectors
jnc Continue1
jmp BadBoot
Continue1:
; Now we must get the first cluster of the root directory
mov eax,DWORD [RootDirStartCluster]
cmp eax,0ffffff8h ; Check to see if this is the last cluster in the chain
jb Continue2 ; If not continue, if so BadBoot
jmp ErrBoot
Continue2:
mov bx,800h
mov es,bx ; Read cluster to [0000:8000h]
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]
shl bx,4 ; BX = BX * 512 / 32
mov ax,800h ; We loaded at 0800:0000
mov es,ax
xor di,di
mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx
jnz FindFile
jmp ErrBoot
FindFile:
mov ax,es ; We didn't find it in the previous dir entry
add ax,2 ; So lets move to the next one
mov es,ax ; And search again
xor di,di
mov si,filename
mov cx,11
rep cmpsb ; Compare filenames
jz FoundFile ; If same we found it
dec bx ; Keep searching till we run out of dir entries
jnz FindFile ; Last entry?
; Get the next root dir cluster and try again until we run out of clusters
mov eax,DWORD [RootDirStartCluster]
call GetFatEntry
mov [RootDirStartCluster],eax
jmp Continue1
FoundFile:
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
mov es,bx
FoundFile2:
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
push eax
xor bx,bx ; Load ROSLDR starting at 0000:8000h
push es
call ReadCluster
pop es
xor bx,bx
mov bl,[SectsPerCluster]
shl bx,5 ; BX = BX * 512 / 16
mov ax,es ; Increment the load address by
add ax,bx ; The size of a cluster
mov es,ax
pop eax
push es
call GetFatEntry ; Get the next entry
pop es
jmp FoundFile2 ; 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
retf ; Transfer control to ROSLDR
; Reads logical sectors into [ES:BX]
; DX:AX 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,513
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
pop cx
pop dx
pop ax
jc ReadFail
inc ax ;Increment Sector to Read
jnz NoCarry
inc dx
NoCarry:
push bx
mov bx,es
add bx,20h
mov es,bx
pop bx
; Increment read buffer for next sector
loop ReadSectors ; Read next sector
ReadFail:
ret
; Displays a bad boot 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
jmp Reboot
; Displays an 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
Reboot:
xor ax,ax
int 16h ; Wait for a keypress
int 19h ; Reboot
PutChars:
lodsb
or al,al
jz short Done
mov ah,0eh
mov bx,07h
int 10h
jmp short 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'
times 510-($-$$) db 0 ; Pad to 510 bytes
dw 0aa55h ; BootSector signature
; End of bootsector
;
; Now starts the extra boot code that we will store
; at sector 14 on a FAT32 volume
;
; To remain multi-boot compatible with other operating
; systems we must not overwrite anything other than
; the bootsector which means we will have to use
; a different sector like 14 to store our extra boot code
;
; Note: Win2k uses sector 12 for this purpose
; Returns the FAT entry for a given cluster number
; On entry EAX has cluster number
; On return EAX has FAT entry for that cluster
GetFatEntry:
shl eax,2 ; EAX = EAX * 4 (since FAT32 entries are 4 bytes)
mov ecx,eax ; Save this for later in ECX
xor edx,edx
movzx ebx,WORD [BytesPerSector]
push ebx
div ebx ; FAT Sector Number = EAX / BytesPerSector
movzx ebx,WORD [ReservedSectors]
add eax,ebx ; FAT Sector Number += ReservedSectors
movzx ebx,WORD [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
push ecx
ror eax,16
mov dx,ax
ror eax,16
; DX:AX holds logical FAT sector number
mov bx,7000h
mov es,bx
xor bx,bx ; We will load it to [7000:0000h]
mov cx,1
call ReadSectors
jnc GetFatEntry1
jmp BadBoot
GetFatEntry1:
mov bx,7000h
mov es,bx
pop ecx
mov eax,DWORD [es:ecx] ; Get FAT entry
and eax,0fffffffh ; Mask off reserved bits
ret
; Reads cluster number in EAX into [ES:0000]
ReadCluster:
; StartSector = ((Cluster - 2) * SectorsPerCluster) + ReservedSectors + HiddenSectors;
dec eax
dec eax
xor edx,edx
movzx ebx,BYTE [SectsPerCluster]
mul ebx
push eax
xor edx,edx
movzx eax,BYTE [NumberOfFats]
mul DWORD [SectorsPerFatBig]
movzx ebx,WORD [ReservedSectors]
add eax,ebx
add eax,DWORD [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]
call ReadSectors
jnc ReadCluster1
jmp BadBoot
ReadCluster1:
ret
times 1022-($-$$) db 0 ; Pad to 1022 bytes
dw 0aa55h ; BootSector signature

View file

@ -0,0 +1,2 @@
nasm -o bootsect.bin -f bin bootsect.asm
nasm -o btsect32.bin -f bin btsect32.asm

View file

@ -0,0 +1,35 @@
unsigned char data[] = {
0xeb, 0x3c, 0x90, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x44, 0x52, 0x21, 0x00, 0x02, 0x01, 0x01, 0x00,
0x02, 0x00, 0x02, 0x40, 0x0b, 0xf0, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x46, 0x72, 0x65, 0x65, 0x4c,
0x6f, 0x61, 0x64, 0x65, 0x72, 0x21, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0xfa, 0xfc,
0x31, 0xc0, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0xfb, 0x88, 0x16,
0x24, 0x7c, 0x31, 0xc0, 0xcd, 0x13, 0x73, 0x03, 0xe9, 0x0b, 0x01, 0x31, 0xc0, 0x31, 0xc9, 0xa0,
0x10, 0x7c, 0xf7, 0x26, 0x16, 0x7c, 0x03, 0x06, 0x1c, 0x7c, 0x13, 0x16, 0x1e, 0x7c, 0x03, 0x06,
0x0e, 0x7c, 0x11, 0xca, 0x50, 0x52, 0x50, 0x52, 0xb8, 0x20, 0x00, 0xf7, 0x26, 0x11, 0x7c, 0x8b,
0x1e, 0x0b, 0x7c, 0x01, 0xd8, 0x48, 0xf7, 0xf3, 0x91, 0x5a, 0x58, 0x51, 0xbb, 0xc0, 0x07, 0x81,
0xc3, 0x20, 0x00, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0x8c, 0x00, 0x73, 0x03, 0xe9, 0xc7, 0x00, 0x8b,
0x1e, 0x11, 0x7c, 0xb8, 0xe0, 0x07, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xd8, 0x7d, 0xb9, 0x0b, 0x00,
0xf3, 0xa6, 0x74, 0x1f, 0x4b, 0x75, 0x03, 0xe9, 0xbb, 0x00, 0x8c, 0xc0, 0x05, 0x02, 0x00, 0x8e,
0xc0, 0x31, 0xff, 0xbe, 0xd8, 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x06, 0x4b, 0x75, 0xea,
0xe9, 0xa2, 0x00, 0x31, 0xff, 0x31, 0xd2, 0x26, 0x8b, 0x45, 0x1a, 0x48, 0x48, 0x30, 0xed, 0x8a,
0x0e, 0x0d, 0x7c, 0xf7, 0xe1, 0x59, 0x01, 0xc8, 0x81, 0xd2, 0x00, 0x00, 0x59, 0x5b, 0x01, 0xd8,
0x11, 0xca, 0x50, 0x52, 0x26, 0x8b, 0x45, 0x1c, 0x26, 0x8b, 0x55, 0x1e, 0x8b, 0x1e, 0x0b, 0x7c,
0x4b, 0x01, 0xd8, 0x81, 0xd2, 0x00, 0x00, 0xf7, 0x36, 0x0b, 0x7c, 0x91, 0x5a, 0x58, 0xbb, 0x00,
0x08, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0x0e, 0x00, 0x72, 0x4c, 0x8a, 0x16, 0x24, 0x7c, 0x31, 0xc0,
0x50, 0xb8, 0x00, 0x80, 0x50, 0xcb, 0x50, 0x52, 0x51, 0x91, 0x92, 0x31, 0xd2, 0xf7, 0x36, 0x18,
0x7c, 0x91, 0xf7, 0x36, 0x18, 0x7c, 0x42, 0x87, 0xca, 0xf7, 0x36, 0x1a, 0x7c, 0x88, 0xd6, 0x8a,
0x16, 0x24, 0x7c, 0x88, 0xc5, 0xd0, 0xcc, 0xd0, 0xcc, 0x08, 0xe1, 0xb8, 0x01, 0x02, 0xcd, 0x13,
0x59, 0x5a, 0x58, 0x72, 0x10, 0x40, 0x75, 0x01, 0x42, 0x53, 0x8c, 0xc3, 0x81, 0xc3, 0x20, 0x00,
0x8e, 0xc3, 0x5b, 0xe2, 0xc1, 0xc3, 0xbe, 0x96, 0x7d, 0xe8, 0x1b, 0x00, 0xbe, 0xbb, 0x7d, 0xe8,
0x15, 0x00, 0xe9, 0x0c, 0x00, 0xbe, 0xa3, 0x7d, 0xe8, 0x0c, 0x00, 0xbe, 0xbb, 0x7d, 0xe8, 0x06,
0x00, 0x31, 0xc0, 0xcd, 0x16, 0xcd, 0x19, 0xac, 0x08, 0xc0, 0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07,
0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x44, 0x69, 0x73, 0x6b, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 0x2e, 0x53, 0x59, 0x53, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x00, 0x50, 0x72, 0x65, 0x73, 0x73,
0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74,
0x69, 0x6e, 0x75, 0x65, 0x2e, 0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52, 0x20,
0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
};

View file

@ -0,0 +1,67 @@
unsigned char data[] = {
0xeb, 0x58, 0x90, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x44, 0x52, 0x21, 0x00, 0x02, 0x01, 0x01, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x46, 0x72, 0x65, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x65,
0x72, 0x21, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0xfa, 0xfc, 0x31, 0xc0, 0x8e, 0xd0,
0xbc, 0x00, 0x7c, 0x8c, 0xc8, 0x8e, 0xd8, 0x8e, 0xc0, 0xfb, 0x88, 0x16, 0x40, 0x7c, 0x31, 0xc0,
0xcd, 0x13, 0x73, 0x03, 0xe9, 0x05, 0x01, 0x31, 0xd2, 0xb8, 0x0e, 0x00, 0x03, 0x06, 0x1c, 0x7c,
0x13, 0x16, 0x1e, 0x7c, 0xb9, 0x01, 0x00, 0xbb, 0xe0, 0x07, 0x8e, 0xc3, 0x31, 0xdb, 0xe8, 0xab,
0x00, 0x73, 0x03, 0xe9, 0xe6, 0x00, 0x66, 0xa1, 0x2c, 0x7c, 0x66, 0x3d, 0xf8, 0xff, 0xff, 0x0f,
0x72, 0x03, 0xe9, 0xe6, 0x00, 0xbb, 0x00, 0x08, 0x8e, 0xc3, 0xe8, 0xb2, 0x01, 0x31, 0xdb, 0x8a,
0x1e, 0x0d, 0x7c, 0xc1, 0xe3, 0x04, 0xb8, 0x00, 0x08, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xee, 0x7d,
0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x2a, 0x4b, 0x75, 0x03, 0xe9, 0xbe, 0x00, 0x8c, 0xc0, 0x05,
0x02, 0x00, 0x8e, 0xc0, 0x31, 0xff, 0xbe, 0xee, 0x7d, 0xb9, 0x0b, 0x00, 0xf3, 0xa6, 0x74, 0x11,
0x4b, 0x75, 0xea, 0x66, 0xa1, 0x2c, 0x7c, 0xe8, 0x16, 0x01, 0x66, 0xa3, 0x2c, 0x7c, 0xe9, 0xa5,
0xff, 0x31, 0xff, 0x31, 0xd2, 0x26, 0x8b, 0x45, 0x14, 0x66, 0xc1, 0xe0, 0x10, 0x26, 0x8b, 0x45,
0x1a, 0xbb, 0x00, 0x08, 0x8e, 0xc3, 0x66, 0x3d, 0xf8, 0xff, 0xff, 0x0f, 0x73, 0x22, 0x66, 0x50,
0x31, 0xdb, 0x06, 0xe8, 0x49, 0x01, 0x07, 0x31, 0xdb, 0x8a, 0x1e, 0x0d, 0x7c, 0xc1, 0xe3, 0x05,
0x8c, 0xc0, 0x01, 0xd8, 0x8e, 0xc0, 0x66, 0x58, 0x06, 0xe8, 0xd4, 0x00, 0x07, 0xe9, 0xd6, 0xff,
0x8a, 0x16, 0x40, 0x7c, 0x31, 0xc0, 0x50, 0xb8, 0x00, 0x80, 0x50, 0xcb, 0x50, 0x52, 0x51, 0x91,
0x92, 0x31, 0xd2, 0xf7, 0x36, 0x18, 0x7c, 0x91, 0xf7, 0x36, 0x18, 0x7c, 0x42, 0x87, 0xca, 0xf7,
0x36, 0x1a, 0x7c, 0x88, 0xd6, 0x8a, 0x16, 0x40, 0x7c, 0x88, 0xc5, 0xd0, 0xcc, 0xd0, 0xcc, 0x08,
0xe1, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x59, 0x5a, 0x58, 0x72, 0x10, 0x40, 0x75, 0x01, 0x42, 0x53,
0x8c, 0xc3, 0x81, 0xc3, 0x20, 0x00, 0x8e, 0xc3, 0x5b, 0xe2, 0xc1, 0xc3, 0xbe, 0xac, 0x7d, 0xe8,
0x1b, 0x00, 0xbe, 0xd1, 0x7d, 0xe8, 0x15, 0x00, 0xe9, 0x0c, 0x00, 0xbe, 0xb9, 0x7d, 0xe8, 0x0c,
0x00, 0xbe, 0xd1, 0x7d, 0xe8, 0x06, 0x00, 0x31, 0xc0, 0xcd, 0x16, 0xcd, 0x19, 0xac, 0x08, 0xc0,
0x74, 0x09, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0xeb, 0xf2, 0xc3, 0x44, 0x69, 0x73, 0x6b,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x0d, 0x0a, 0x00, 0x46, 0x52, 0x45, 0x45, 0x4c, 0x44, 0x52,
0x2e, 0x53, 0x59, 0x53, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x0d, 0x0a,
0x00, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74,
0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x2e, 0x0d, 0x0a, 0x00, 0x46, 0x52,
0x45, 0x45, 0x4c, 0x44, 0x52, 0x20, 0x53, 0x59, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa,
0x66, 0xc1, 0xe0, 0x02, 0x66, 0x89, 0xc1, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb7, 0x1e, 0x0b, 0x7c,
0x66, 0x53, 0x66, 0xf7, 0xf3, 0x66, 0x0f, 0xb7, 0x1e, 0x0e, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x0f,
0xb7, 0x1e, 0x1c, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x5b, 0x66, 0x4b, 0x66, 0x21, 0xd9, 0x66, 0x51,
0x66, 0xc1, 0xc8, 0x10, 0x89, 0xc2, 0x66, 0xc1, 0xc8, 0x10, 0xbb, 0x00, 0x70, 0x8e, 0xc3, 0x31,
0xdb, 0xb9, 0x01, 0x00, 0xe8, 0xf5, 0xfe, 0x73, 0x03, 0xe9, 0x30, 0xff, 0xbb, 0x00, 0x70, 0x8e,
0xc3, 0x66, 0x59, 0x26, 0x66, 0x67, 0x8b, 0x01, 0x66, 0x25, 0xff, 0xff, 0xff, 0x0f, 0xc3, 0x66,
0x48, 0x66, 0x48, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb6, 0x1e, 0x0d, 0x7c, 0x66, 0xf7, 0xe3, 0x66,
0x50, 0x66, 0x31, 0xd2, 0x66, 0x0f, 0xb6, 0x06, 0x10, 0x7c, 0x66, 0xf7, 0x26, 0x24, 0x7c, 0x66,
0x0f, 0xb7, 0x1e, 0x0e, 0x7c, 0x66, 0x01, 0xd8, 0x66, 0x03, 0x06, 0x1c, 0x7c, 0x66, 0x5b, 0x66,
0x01, 0xd8, 0x66, 0xc1, 0xc8, 0x10, 0x89, 0xc2, 0x66, 0xc1, 0xc8, 0x10, 0x31, 0xdb, 0x0f, 0xb6,
0x0e, 0x0d, 0x7c, 0xe8, 0x96, 0xfe, 0x73, 0x03, 0xe9, 0xd1, 0xfe, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
};

49
freeldr/bootsect/c_data.c Normal file
View file

@ -0,0 +1,49 @@
#include <stdio.h>
char in_filename[260];
char out_filename[260];
FILE *in;
FILE *out;
int main(void)
{
unsigned char ch;
int cnt = 0;
printf("Enter data filename: ");
scanf("%s", in_filename);
printf("Enter output filename: ");
scanf("%s", out_filename);
if ((in = fopen(in_filename, "rb")) == NULL)
{
printf("Couldn't open data file.\n");
return 0;
}
if ((out = fopen(out_filename, "wb")) == NULL)
{
printf("Couldn't open output file.\n");
return 0;
}
fprintf(out, "unsigned char data[] = {\n");
ch = fgetc(in);
while (!feof(in))
{
if (cnt != 0)
fprintf(out, ", ");
if (!(cnt % 16))
fprintf(out, "\n");
fprintf(out, "0x%02x", (int)ch);
cnt++;
ch = fgetc(in);
}
fprintf(out, "\n};");
fclose(in);
fclose(out);
return 0;
}

View file

@ -0,0 +1 @@
debug bootsect.bin < install.src

View file

@ -0,0 +1,2 @@
w 100 0 0 1
q

View file

@ -0,0 +1,197 @@
00008000 660FB64610 movzx eax,byte [bp+NumberOfFats]
00008005 668B4E24 mov ecx,[bp+SectorsPerFatBig]
00008009 66F7E1 mul ecx
0000800C 6603461C add eax,[bp+HiddenSectors]
00008010 660FB7560E movzx edx,word [bp+ReservedSectors]
00008015 6603C2 add eax,edx
00008018 668946FC mov [bp-0x4],eax
0000801C 66C746F4FFFFFFFF mov dword [bp-0xc],0xffffffff
00008024 668B462C mov eax,[bp+RootDirStartCluster]
00008028 6683F802 cmp eax,byte +0x2
0000802C 0F82A6FC jc near 0x7cd6
00008030 663DF8FFFF0F cmp eax,0xffffff8
00008036 0F839CFC jnc near 0x7cd6
0000803A 6650 push eax
0000803C 6683E802 sub eax,byte +0x2
00008040 660FB65E0D movzx ebx,byte [bp+SectsPerCluster]
00008045 8BF3 mov si,bx
00008047 66F7E3 mul ebx
0000804A 660346FC add eax,[bp-0x4]
0000804E BB0082 mov bx,0x8200
00008051 8BFB mov di,bx
00008053 B90100 mov cx,0x1
00008056 E887FC call 0x7ce0
00008059 382D cmp [di],ch
0000805B 741E jz 0x807b
0000805D B10B mov cl,0xb
0000805F 56 push si
00008060 BE707D mov si,0x7d70
00008063 F3A6 repe cmpsb
00008065 5E pop si
00008066 741B jz 0x8083
00008068 03F9 add di,cx
0000806A 83C715 add di,byte +0x15
0000806D 3BFB cmp di,bx
0000806F 72E8 jc 0x8059
00008071 4E dec si
00008072 75DA jnz 0x804e
00008074 6658 pop eax
00008076 E86500 call 0x80de
00008079 72BF jc 0x803a
0000807B 83C404 add sp,byte +0x4
0000807E E955FC jmp 0x7cd6
00008081 0020 add [bx+si],ah
00008083 83C404 add sp,byte +0x4
00008086 8B7509 mov si,[di+0x9]
00008089 8B7D0F mov di,[di+0xf]
0000808C 8BC6 mov ax,si
0000808E 66C1E010 shl eax,0x10
00008092 8BC7 mov ax,di
00008094 6683F802 cmp eax,byte +0x2
00008098 0F823AFC jc near 0x7cd6
0000809C 663DF8FFFF0F cmp eax,0xffffff8
000080A2 0F8330FC jnc near 0x7cd6
000080A6 6650 push eax
000080A8 6683E802 sub eax,byte +0x2
000080AC 660FB64E0D movzx ecx,byte [bp+0xd]
000080B1 66F7E1 mul ecx
000080B4 660346FC add eax,[bp-0x4]
000080B8 BB0000 mov bx,0x0
000080BB 06 push es
000080BC 8E068180 mov es,[0x8081]
000080C0 E81DFC call 0x7ce0
000080C3 07 pop es
000080C4 6658 pop eax
000080C6 C1EB04 shr bx,0x4
000080C9 011E8180 add [0x8081],bx
000080CD E80E00 call 0x80de
000080D0 0F830200 jnc near 0x80d6
000080D4 72D0 jc 0x80a6
000080D6 8A5640 mov dl,[bp+0x40]
000080D9 EA00000020 jmp 0x2000:0x0
000080DE 66C1E002 shl eax,0x2
000080E2 E81100 call 0x80f6
000080E5 26668B01 mov eax,[es:bx+di]
000080E9 6625FFFFFF0F and eax,0xfffffff
000080EF 663DF8FFFF0F cmp eax,0xffffff8
000080F5 C3 ret
000080F6 BF007E mov di,0x7e00
000080F9 660FB74E0B movzx ecx,word [bp+0xb]
000080FE 6633D2 xor edx,edx
00008101 66F7F1 div ecx
00008104 663B46F4 cmp eax,[bp-0xc]
00008108 743A jz 0x8144
0000810A 668946F4 mov [bp-0xc],eax
0000810E 6603461C add eax,[bp+0x1c]
00008112 660FB74E0E movzx ecx,word [bp+0xe]
00008117 6603C1 add eax,ecx
0000811A 660FB75E28 movzx ebx,word [bp+0x28]
0000811F 83E30F and bx,byte +0xf
00008122 7416 jz 0x813a
00008124 3A5E10 cmp bl,[bp+0x10]
00008127 0F83ABFB jnc near 0x7cd6
0000812B 52 push dx
0000812C 668BC8 mov ecx,eax
0000812F 668B4624 mov eax,[bp+0x24]
00008133 66F7E3 mul ebx
00008136 6603C1 add eax,ecx
00008139 5A pop dx
0000813A 52 push dx
0000813B 8BDF mov bx,di
0000813D B90100 mov cx,0x1
00008140 E89DFB call 0x7ce0
00008143 5A pop dx
00008144 8BDA mov bx,dx
00008146 C3 ret
00008147 0000 add [bx+si],al
00008149 0000 add [bx+si],al
0000814B 0000 add [bx+si],al
0000814D 0000 add [bx+si],al
0000814F 0000 add [bx+si],al
00008151 0000 add [bx+si],al
00008153 0000 add [bx+si],al
00008155 0000 add [bx+si],al
00008157 0000 add [bx+si],al
00008159 0000 add [bx+si],al
0000815B 0000 add [bx+si],al
0000815D 0000 add [bx+si],al
0000815F 0000 add [bx+si],al
00008161 0000 add [bx+si],al
00008163 0000 add [bx+si],al
00008165 0000 add [bx+si],al
00008167 0000 add [bx+si],al
00008169 0000 add [bx+si],al
0000816B 0000 add [bx+si],al
0000816D 0000 add [bx+si],al
0000816F 0000 add [bx+si],al
00008171 0000 add [bx+si],al
00008173 0000 add [bx+si],al
00008175 0000 add [bx+si],al
00008177 0000 add [bx+si],al
00008179 0000 add [bx+si],al
0000817B 0000 add [bx+si],al
0000817D 0000 add [bx+si],al
0000817F 0000 add [bx+si],al
00008181 0000 add [bx+si],al
00008183 0000 add [bx+si],al
00008185 0000 add [bx+si],al
00008187 0000 add [bx+si],al
00008189 0000 add [bx+si],al
0000818B 0000 add [bx+si],al
0000818D 0000 add [bx+si],al
0000818F 0000 add [bx+si],al
00008191 0000 add [bx+si],al
00008193 0000 add [bx+si],al
00008195 0000 add [bx+si],al
00008197 0000 add [bx+si],al
00008199 0000 add [bx+si],al
0000819B 0000 add [bx+si],al
0000819D 0000 add [bx+si],al
0000819F 0000 add [bx+si],al
000081A1 0000 add [bx+si],al
000081A3 0000 add [bx+si],al
000081A5 0000 add [bx+si],al
000081A7 0000 add [bx+si],al
000081A9 0000 add [bx+si],al
000081AB 0000 add [bx+si],al
000081AD 0000 add [bx+si],al
000081AF 0000 add [bx+si],al
000081B1 0000 add [bx+si],al
000081B3 0000 add [bx+si],al
000081B5 0000 add [bx+si],al
000081B7 0000 add [bx+si],al
000081B9 0000 add [bx+si],al
000081BB 0000 add [bx+si],al
000081BD 0000 add [bx+si],al
000081BF 0000 add [bx+si],al
000081C1 0000 add [bx+si],al
000081C3 0000 add [bx+si],al
000081C5 0000 add [bx+si],al
000081C7 0000 add [bx+si],al
000081C9 0000 add [bx+si],al
000081CB 0000 add [bx+si],al
000081CD 0000 add [bx+si],al
000081CF 0000 add [bx+si],al
000081D1 0000 add [bx+si],al
000081D3 0000 add [bx+si],al
000081D5 0000 add [bx+si],al
000081D7 0000 add [bx+si],al
000081D9 0000 add [bx+si],al
000081DB 0000 add [bx+si],al
000081DD 0000 add [bx+si],al
000081DF 0000 add [bx+si],al
000081E1 0000 add [bx+si],al
000081E3 0000 add [bx+si],al
000081E5 0000 add [bx+si],al
000081E7 0000 add [bx+si],al
000081E9 0000 add [bx+si],al
000081EB 0000 add [bx+si],al
000081ED 0000 add [bx+si],al
000081EF 0000 add [bx+si],al
000081F1 0000 add [bx+si],al
000081F3 0000 add [bx+si],al
000081F5 0000 add [bx+si],al
000081F7 0000 add [bx+si],al
000081F9 0000 add [bx+si],al
000081FB 0000 add [bx+si],al
000081FD 0055AA add [di-0x56],dl

174
freeldr/bootsect/win2k.asm Normal file
View file

@ -0,0 +1,174 @@
segment .text
bits 16
start:
jmp short main
nop
OEMName db 'FreeLDR!'
BytesPerSector dw 512
SectsPerCluster db 1
ReservedSectors dw 1
NumberOfFats db 2
MaxRootEntries dw 0 ;512 - Always zero for FAT32 volumes
TotalSectors dw 0 ;2880 - Always zero for FAT32 volumes
MediaDescriptor db 0f8h
SectorsPerFat dw 0 ;9 - Always zero for FAT32 volumes
SectorsPerTrack dw 18
NumberOfHeads dw 2
HiddenSectors dd 0
TotalSectorsBig dd 0
; FAT32 Inserted Info
SectorsPerFatBig dd 0
ExtendedFlags dw 0
FSVersion dw 0
RootDirStartCluster dd 0
FSInfoSector dw 0
BackupBootSector dw 6
Reserved1 times 12 db 0
; End FAT32 Inserted Info
BootDrive db 0
Reserved db 0
ExtendSig db 29h
SerialNumber dd 00000000h
VolumeLabel db 'FreeLoader!'
FileSystem db 'FAT12 '
main:
00007C5A 33C9 xor cx,cx
00007C5C 8ED1 mov ss,cx
00007C5E BCF47B mov sp,0x7bf4
00007C61 8EC1 mov es,cx
00007C63 8ED9 mov ds,cx
00007C65 BD007C mov bp,0x7c00
00007C68 884E02 mov [bp+0x2],cl
00007C6B 8A5640 mov dl,[bp+BootDrive]
00007C6E B408 mov ah,0x8
00007C70 CD13 int 0x13 ; Int 13, func 8 - Get Drive Parameters
00007C72 7305 jnc 0x7c79 ; If no error jmp
00007C74 B9FFFF mov cx,0xffff
00007C77 8AF1 mov dh,cl
00007C79 660FB6C6 movzx eax,dh
00007C7D 40 inc ax
00007C7E 660FB6D1 movzx edx,cl
00007C82 80E23F and dl,0x3f
00007C85 F7E2 mul dx
00007C87 86CD xchg cl,ch
00007C89 C0ED06 shr ch,0x6
00007C8C 41 inc cx
00007C8D 660FB7C9 movzx ecx,cx
00007C91 66F7E1 mul ecx
00007C94 668946F8 mov [bp-0x8],eax
00007C98 837E1600 cmp word [bp+TotalSectors],byte +0x0
00007C9C 7538 jnz print_ntldr_error_message
00007C9E 837E2A00 cmp word [bp+FSVersion],byte +0x0
00007CA2 7732 ja print_ntldr_error_message
00007CA4 668B461C mov eax,[bp+0x1c]
00007CA8 6683C00C add eax,byte +0xc
00007CAC BB0080 mov bx,0x8000
00007CAF B90100 mov cx,0x1
00007CB2 E82B00 call read_sectors
00007CB5 E94803 jmp 0x8000
print_disk_error_message:
00007CB8 A0FA7D mov al,[DISK_ERR_offset_from_0x7d00]
putchars:
00007CBB B47D mov ah,0x7d
00007CBD 8BF0 mov si,ax
get_another_char:
00007CBF AC lodsb
00007CC0 84C0 test al,al
00007CC2 7417 jz reboot
00007CC4 3CFF cmp al,0xff
00007CC6 7409 jz print_reboot_message
00007CC8 B40E mov ah,0xe
00007CCA BB0700 mov bx,0x7
00007CCD CD10 int 0x10
00007CCF EBEE jmp short get_another_char
print_reboot_message:
00007CD1 A0FB7D mov al,[RESTART_ERR_offset_from_0x7d00]
00007CD4 EBE5 jmp short putchars
print_ntldr_error_message:
00007CD6 A0F97D mov al,[NTLDR_ERR_offset_from_0x7d00]
00007CD9 EBE0 jmp short putchars
reboot:
00007CDB 98 cbw
00007CDC CD16 int 0x16
00007CDE CD19 int 0x19
read_sectors:
00007CE0 6660 pushad
00007CE2 663B46F8 cmp eax,[bp-0x8]
00007CE6 0F824A00 jc near 0x7d34
00007CEA 666A00 o32 push byte +0x0
00007CED 6650 push eax
00007CEF 06 push es
00007CF0 53 push bx
00007CF1 666810000100 push dword 0x10010
00007CF7 807E0200 cmp byte [bp+0x2],0x0
00007CFB 0F852000 jnz near 0x7d1f
00007CFF B441 mov ah,0x41
00007D01 BBAA55 mov bx,0x55aa
00007D04 8A5640 mov dl,[bp+BootDrive]
00007D07 CD13 int 0x13
00007D09 0F821C00 jc near 0x7d29
00007D0D 81FB55AA cmp bx,0xaa55
00007D11 0F851400 jnz near 0x7d29
00007D15 F6C101 test cl,0x1
00007D18 0F840D00 jz near 0x7d29
00007D1C FE4602 inc byte [bp+0x2]
00007D1F B442 mov ah,0x42
00007D21 8A5640 mov dl,[bp+BootDrive]
00007D24 8BF4 mov si,sp
00007D26 CD13 int 0x13
00007D28 B0F9 mov al,0xf9
00007D2A 6658 pop eax
00007D2C 6658 pop eax
00007D2E 6658 pop eax
00007D30 6658 pop eax
00007D32 EB2A jmp short 0x7d5e
00007D34 6633D2 xor edx,edx
00007D37 660FB74E18 movzx ecx,word [bp+SectorsPerTrack]
00007D3C 66F7F1 div ecx
00007D3F FEC2 inc dl
00007D41 8ACA mov cl,dl
00007D43 668BD0 mov edx,eax
00007D46 66C1EA10 shr edx,0x10
00007D4A F7761A div word [bp+NumberOfHeads]
00007D4D 86D6 xchg dl,dh
00007D4F 8A5640 mov dl,[bp+BootDrive]
00007D52 8AE8 mov ch,al
00007D54 C0E406 shl ah,0x6
00007D57 0ACC or cl,ah
00007D59 B80102 mov ax,0x201
00007D5C CD13 int 0x13
00007D5E 6661 popad
00007D60 0F8254FF jc near print_disk_error_message
00007D64 81C30002 add bx,0x200
00007D68 6640 inc eax
00007D6A 49 dec cx
00007D6B 0F8571FF jnz near read_sectors
00007D6F C3 ret
NTLDR db 'NTLDR '
filler times 49 db 0
NTLDR_ERR db 0dh,0ah,'NTLDR is missing',0ffh
DISK_ERR db 0dh,0ah,'Disk error',0ffh
RESTART_ERR db 0dh,0ah,'Press any key to restart',0dh,0ah
more_filler times 16 db 0
NTLDR_offset_from_0x7d00 db 0
NTLDR_ERR_offset_from_0x7d00 db 0ach
DISK_ERR_offset_from_0x7d00 db 0bfh
RESTART_ERR_offset_from_0x7d00 db 0cch
dw 0
dw 0aa55h

7
freeldr/build.bat Normal file
View file

@ -0,0 +1,7 @@
cd bootsect
call make.bat
cd..
cd freeldr
make
copy freeldr.sys ..
cd ..

89
freeldr/freeldr/Makefile Normal file
View file

@ -0,0 +1,89 @@
#
# 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.
#
export CC = gcc
export LD = ld
export AR = ar
export RM = cmd /C del
export CP = cmd /C copy
FLAGS = -Wall -nostdinc -fno-builtin
# asmcode.o has to be first in the link line because it contains the startup code
OBJS = asmcode.a asmcode.o ros.o boot.o freeldr.o stdlib.o fs.a fs.o fs_fat.o \
rosboot.o tui.o menu.o miscboot.o options.o linux.o
ASM_OBJS = asmcode.o ros.o boot.o
C_OBJS = freeldr.o stdlib.o fs.a rosboot.o tui.o menu.o miscboot.o options.o linux.o
all: freeldr.sys
freeldr.sys: asmcode.a c_code.a
$(LD) -N -Ttext=0x8000 --oformat=binary -o freeldr.sys asmcode.a c_code.a
asmcode.a: $(ASM_OBJS)
$(LD) -r -o asmcode.a $(ASM_OBJS)
c_code.a: $(C_OBJS)
$(LD) -r -o c_code.a $(C_OBJS)
asmcode.o: asmcode.S asmcode.h Makefile
$(CC) $(FLAGS) -o asmcode.o -c asmcode.S
freeldr.o: freeldr.c freeldr.h stdlib.h fs.h rosboot.h tui.h asmcode.h menu.h miscboot.h Makefile
$(CC) $(FLAGS) -o freeldr.o -c freeldr.c
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.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
rosboot.o: rosboot.c freeldr.h rosboot.h stdlib.h fs.h tui.h Makefile
$(CC) $(FLAGS) -o rosboot.o -c rosboot.c
ros.o: ros.S asmcode.h Makefile
$(CC) $(FLAGS) -o ros.o -c ros.S
tui.o: tui.c freeldr.h stdlib.h tui.h Makefile
$(CC) $(FLAGS) -o tui.o -c tui.c
menu.o: menu.c freeldr.h stdlib.h tui.h menu.h Makefile
$(CC) $(FLAGS) -o menu.o -c menu.c
boot.o: boot.S asmcode.h Makefile
$(CC) $(FLAGS) -o boot.o -c boot.S
miscboot.o: miscboot.c freeldr.h asmcode.h stdlib.h fs.h tui.h miscboot.h Makefile
$(CC) $(FLAGS) -o miscboot.o -c miscboot.c
options.o: options.c freeldr.h stdlib.h tui.h options.h Makefile
$(CC) $(FLAGS) -o options.o -c options.c
linux.o: linux.c freeldr.h stdlib.h tui.h linux.h Makefile
$(CC) $(FLAGS) -o linux.o -c linux.c
clean:
$(RM) $(OBJS)

1177
freeldr/freeldr/asmcode.S Normal file

File diff suppressed because it is too large Load diff

57
freeldr/freeldr/asmcode.h Normal file
View file

@ -0,0 +1,57 @@
/*
* 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.
*/
/* Defines needed for switching between real and protected mode */
#define NULL_DESC 0x00 /* NULL descriptor */
#define PMODE_CS 0x08 /* PMode code selector, base 0 limit 4g */
#define PMODE_DS 0x10 /* PMode data selector, base 0 limit 4g */
#define RMODE_CS 0x18 /* RMode code selector, base 0 limit 64k */
#define RMODE_DS 0x20 /* RMode data selector, base 0 limit 64k */
#define KERNEL_BASE 0xC0000000
//#define USER_CS 0x08
//#define USER_DS 0x10
//#define KERNEL_CS 0x20
//#define KERNEL_DS 0x28
#define KERNEL_CS 0x08
#define KERNEL_DS 0x10
#define CR0_PE_SET 0x00000001 /* OR this value with CR0 to enable pmode */
#define CR0_PE_CLR 0xFFFFFFFE /* AND this value with CR0 to disable pmode */
#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 FILESYSADDR 0x80000 /* The filesystem data address will be at 8000:0000, or 0x80000 */
#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 */
/* Makes "x" a global variable or label */
#define EXTERN(x) .global x; x:

45
freeldr/freeldr/boot.S Normal file
View file

@ -0,0 +1,45 @@
/*
* 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.
*/
.text
.code16
#include "asmcode.h"
.code32
EXTERN(_JumpToBootCode)
call switch_to_real
.code16
/* Set the boot drive */
movb (_BootDrive),%dl
ljmpl $0x0000,$0x7C00
.code32
EXTERN(_JumpToLinuxBootCode)
call switch_to_real
.code16
/* Set the boot drive */
movb (_BootDrive),%dl
ljmpl $0x0200,$0x9000

734
freeldr/freeldr/freeldr.c Normal file
View file

@ -0,0 +1,734 @@
/*
* 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 "stdlib.h"
#include "fs.h"
#include "rosboot.h"
#include "tui.h"
#include "asmcode.h"
#include "menu.h"
#include "miscboot.h"
#include "linux.h"
// Variable BootDrive moved to asmcode.S
//unsigned int BootDrive = 0; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
unsigned int BootPartition = 0; // Boot Partition, 1-4
BOOL bTUILoaded = FALSE; // Tells us if the user interface is loaded
char *pFreeldrIni = (char *)(FREELDRINIADDR); // Load address for freeldr.ini
char *pScreenBuffer = (char *)(SCREENBUFFER); // Save address for screen contents
int nCursorXPos = 0; // Cursor's X Position
int nCursorYPos = 0; // Cursor's Y Position
OSTYPE OSList[16];
int nNumOS = 0;
int nTimeOut = -1; // Time to wait for the user before booting
void BootMain(void)
{
int i;
char name[1024];
char value[1024];
int nOSToBoot;
enable_a20();
SaveScreen(pScreenBuffer);
nCursorXPos = wherex();
nCursorYPos = wherey();
printf("Loading FreeLoader...\n");
if (!ParseIniFile())
{
printf("Press any key to reboot.\n");
getch();
return;
}
clrscr();
hidecursor();
// Draw the backdrop and title box
DrawBackdrop();
bTUILoaded = TRUE;
if (nNumOS == 0)
{
DrawStatusText(" Press ENTER to reboot");
MessageBox("Error: there were no operating systems listed to boot.\nPress ENTER to reboot.");
clrscr();
showcursor();
RestoreScreen(pScreenBuffer);
return;
}
DrawStatusText(" Press ENTER to continue");
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems("FREELOADER"); i++)
{
ReadSectionSettingByNumber("FREELOADER", i, name, value);
if (stricmp(name, "MessageBox") == 0)
MessageBox(value);
if (stricmp(name, "MessageLine") == 0)
MessageLine(value);
}
for (;;)
{
nOSToBoot = RunMenu();
LoadAndBootLinux(0x80, 0, "vmlinuz", "");
switch (OSList[nOSToBoot].nOSType)
{
case OSTYPE_REACTOS:
LoadAndBootReactOS(nOSToBoot);
break;
case OSTYPE_LINUX:
MessageBox("Cannot boot this OS type yet!");
break;
case OSTYPE_BOOTSECTOR:
LoadAndBootBootSector(nOSToBoot);
break;
case OSTYPE_PARTITION:
LoadAndBootPartition(nOSToBoot);
break;
case OSTYPE_DRIVE:
LoadAndBootDrive(nOSToBoot);
break;
}
}
MessageBox("Press any key to reboot.");
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
}
BOOL ParseIniFile(void)
{
int i;
char name[1024];
char value[1024];
FILE Freeldr_Ini; // File handle for freeldr.ini
// Open the boot drive for file access
if(!OpenDiskDrive(BootDrive, 0))
{
printf("Error opening boot drive for file access.\n");
return FALSE;
}
// Try to open freeldr.ini or fail
if(!OpenFile("freeldr.ini", &Freeldr_Ini))
{
printf("FREELDR.INI not found.\nYou need to re-install FreeLoader.\n");
return FALSE;
}
// Check and see if freeldr.ini is too big
// if so display a warning
if(GetFileSize(&Freeldr_Ini) > 0x4000)
{
printf("Warning: FREELDR.INI is bigger than 16k.\n");
printf("Only 16k of it will be loaded off the disk.\n");
printf("Press any key to continue.\n");
getch();
}
// Read freeldr.ini off the disk
ReadFile(&Freeldr_Ini, 0x4000, pFreeldrIni);
// Make sure the [FREELOADER] section exists
if(!GetNumSectionItems("FREELOADER"))
{
printf("Section [FREELOADER] not found in FREELDR.INI.\nYou need to re-install FreeLoader.\n");
return FALSE;
}
// Validate the settings in the [FREELOADER] section
for(i=1; i<=GetNumSectionItems("FREELOADER"); i++)
{
ReadSectionSettingByNumber("FREELOADER", i, name, value);
if(!IsValidSetting(name, value))
{
printf("Invalid setting in freeldr.ini.\nName: \"%s\", Value: \"%s\"\n", name, value);
printf("Press any key to continue.\n");
getch();
}
else
SetSetting(name, value);
}
return TRUE;
}
int GetNumSectionItems(char *section)
{
int i;
char str[1024];
char real_section[1024];
int num_items = 0;
int freeldr_ini_offset;
BOOL bFoundSection = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, section);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If it isn't a section header then continue on
if(str[0] != '[')
continue;
// Check and see if we found it
if(stricmp(str, real_section) == 0)
{
bFoundSection = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if(!bFoundSection)
return 0;
// Now count how many settings are in this section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If we hit a new section then we're done
if(str[0] == '[')
break;
num_items++;
}
return num_items;
}
BOOL ReadSectionSettingByNumber(char *section, int num, char *name, char *value)
{
char str[1024];
char real_section[1024];
int num_items = 0;
int i;
int freeldr_ini_offset;
BOOL bFoundSection = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, section);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If it isn't a section header then continue on
if(str[0] != '[')
continue;
// Check and see if we found it
if(stricmp(str, real_section) == 0)
{
bFoundSection = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if(!bFoundSection)
return FALSE;
// Now find the setting we are looking for
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If we hit a new section then we're done
if(str[0] == '[')
break;
// Increment setting number
num_items++;
// Check and see if we found the setting
if(num_items == num)
{
for(i=0; i<strlen(str); i++)
{
// Check and see if this character is the separator
if(str[i] == '=')
{
name[i] = '\0';
strcpy(value, str+i+1);
return TRUE;
}
else
name[i] = str[i];
}
}
}
return FALSE;
}
BOOL ReadSectionSettingByName(char *section, char *valuename, char *name, char *value)
{
char str[1024];
char real_section[1024];
char temp[1024];
int i;
int freeldr_ini_offset;
BOOL bFoundSection = FALSE;
// Get the real section name
strcpy(real_section, "[");
strcat(real_section, section);
strcat(real_section, "]");
// Get to the beginning of the file
freeldr_ini_offset = 0;
// Find the section
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If it isn't a section header then continue on
if(str[0] != '[')
continue;
// Check and see if we found it
if(stricmp(str, real_section) == 0)
{
bFoundSection = TRUE;
break;
}
}
// If we didn't find the section then we're outta here
if(!bFoundSection)
return FALSE;
// Now find the setting we are looking for
while(freeldr_ini_offset < 0x4000)
{
// Read a line
for(i=0; i<1024; i++,freeldr_ini_offset++)
{
if((freeldr_ini_offset < 0x4000) && (pFreeldrIni[freeldr_ini_offset] != '\n'))
str[i] = pFreeldrIni[freeldr_ini_offset];
else
{
freeldr_ini_offset++;
break;
}
}
str[i] = '\0';
//fgets(str, 1024, &Freeldr_Ini);
// Get rid of newline & linefeed characters (if any)
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
if((str[strlen(str)-1] == '\n') || (str[strlen(str)-1] == '\r'))
str[strlen(str)-1] = '\0';
// Skip comments
if(str[0] == '#')
continue;
// Skip blank lines
if(!strlen(str))
continue;
// If we hit a new section then we're done
if(str[0] == '[')
break;
// Extract the setting name
for(i=0; i<strlen(str); i++)
{
if(str[i] != '=')
temp[i] = str[i];
else
{
temp[i] = '\0';
break;
}
}
// Check and see if we found the setting
if(stricmp(temp, valuename) == 0)
{
for(i=0; i<strlen(str); i++)
{
// Check and see if this character is the separator
if(str[i] == '=')
{
name[i] = '\0';
strcpy(value, str+i+1);
return TRUE;
}
else
name[i] = str[i];
}
}
}
return FALSE;
}
BOOL IsValidSetting(char *setting, char *value)
{
if(stricmp(setting, "MessageBox") == 0)
return TRUE;
else if(stricmp(setting, "MessageLine") == 0)
return TRUE;
else if(stricmp(setting, "TitleText") == 0)
return TRUE;
else if(stricmp(setting, "StatusBarColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "StatusBarTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "BackdropFillStyle") == 0)
{
if(IsValidFillStyle(value))
return TRUE;
}
else if(stricmp(setting, "TitleBoxTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "TitleBoxColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MessageBoxTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MessageBoxColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MenuTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "MenuColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "TextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "SelectedTextColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "SelectedColor") == 0)
{
if(IsValidColor(value))
return TRUE;
}
else if(stricmp(setting, "OS") == 0)
return TRUE;
else if(stricmp(setting, "TimeOut") == 0)
return TRUE;
/*else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;
else if(stricmp(setting, "") == 0)
return TRUE;*/
return FALSE;
}
void SetSetting(char *setting, char *value)
{
char name[260];
char v[260];
if(stricmp(setting, "TitleText") == 0)
strcpy(szTitleBoxTitleText, value);
else if(stricmp(setting, "StatusBarColor") == 0)
cStatusBarBgColor = TextToColor(value);
else if(stricmp(setting, "StatusBarTextColor") == 0)
cStatusBarFgColor = TextToColor(value);
else if(stricmp(setting, "BackdropTextColor") == 0)
cBackdropFgColor = TextToColor(value);
else if(stricmp(setting, "BackdropColor") == 0)
cBackdropBgColor = TextToColor(value);
else if(stricmp(setting, "BackdropFillStyle") == 0)
cBackdropFillStyle = TextToFillStyle(value);
else if(stricmp(setting, "TitleBoxTextColor") == 0)
cTitleBoxFgColor = TextToColor(value);
else if(stricmp(setting, "TitleBoxColor") == 0)
cTitleBoxBgColor = TextToColor(value);
else if(stricmp(setting, "MessageBoxTextColor") == 0)
cMessageBoxFgColor = TextToColor(value);
else if(stricmp(setting, "MessageBoxColor") == 0)
cMessageBoxBgColor = TextToColor(value);
else if(stricmp(setting, "MenuTextColor") == 0)
cMenuFgColor = TextToColor(value);
else if(stricmp(setting, "MenuColor") == 0)
cMenuBgColor = TextToColor(value);
else if(stricmp(setting, "TextColor") == 0)
cTextColor = TextToColor(value);
else if(stricmp(setting, "SelectedTextColor") == 0)
cSelectedTextColor = TextToColor(value);
else if(stricmp(setting, "SelectedColor") == 0)
cSelectedTextBgColor = TextToColor(value);
else if(stricmp(setting, "OS") == 0)
{
if(nNumOS >= 16)
{
printf("Error: you can only boot to at most 16 different operating systems.\n");
printf("Press any key to continue\n");
getch();
return;
}
if(!GetNumSectionItems(value))
{
printf("Error: OS \"%s\" listed.\n", value);
printf("It does not have it's own [section], or it is empty.\n");
printf("Press any key to continue\n");
getch();
return;
}
strcpy(OSList[nNumOS].name, value);
if (!ReadSectionSettingByName(value, "BootType", name, v))
{
printf("Unknown BootType for OS \"%s\"\n", value);
printf("Press any key to continue\n");
getch();
return;
}
if (stricmp(v, "ReactOS") == 0)
OSList[nNumOS].nOSType = OSTYPE_REACTOS;
else if (stricmp(v, "Linux") == 0)
OSList[nNumOS].nOSType = OSTYPE_LINUX;
else if (stricmp(v, "BootSector") == 0)
OSList[nNumOS].nOSType = OSTYPE_BOOTSECTOR;
else if (stricmp(v, "Partition") == 0)
OSList[nNumOS].nOSType = OSTYPE_PARTITION;
else if (stricmp(v, "Drive") == 0)
OSList[nNumOS].nOSType = OSTYPE_DRIVE;
else
{
printf("Unknown BootType for OS \"%s\"\n", value);
printf("Press any key to continue\n");
getch();
return;
}
nNumOS++;
}
else if(stricmp(setting, "TimeOut") == 0)
nTimeOut = atoi(value);
}

82
freeldr/freeldr/freeldr.h Normal file
View file

@ -0,0 +1,82 @@
/*
* 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.
*/
#ifndef __FREELDR_H
#define __FREELDR_H
/* just some stuff */
#define VERSION "FreeLoader v0.8"
#define COPYRIGHT "Copyright (C) 1999, 2000 Brian Palmer <brianp@sginet.com>"
#define ROSLDR_MAJOR_VERSION 0
#define ROSLDR_MINOR_VERSION 8
#define ROSLDR_PATCH_VERSION 0
#define size_t unsigned int
#define BOOL int
#define NULL 0
#define TRUE 1
#define FALSE 0
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
#define CHAR char
#define WCHAR unsigned short
#define LONG long
#define ULONG unsigned long
#define PULONG unsigned long *
#define PDWORD DWORD *
#define PWORD WORD *
#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;
extern unsigned int BootDrive; // BIOS boot drive, 0-A:, 1-B:, 0x80-C:, 0x81-D:, etc.
extern unsigned int BootPartition; // Boot Partition, 1-4
extern BOOL bTUILoaded; // Tells us if the user interface is loaded
extern char *pFreeldrIni; // Load address for freeldr.ini
extern char *pScreenBuffer; // Save address for screen contents
extern int nCursorXPos; // Cursor's X Position
extern int nCursorYPos; // 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
void BootMain(void);
BOOL ParseIniFile(void);
int GetNumSectionItems(char *section); // returns the number of items in a particular section (i.e. [FREELOADER])
BOOL ReadSectionSettingByNumber(char *section, int num, char *name, char *value); // Reads the num'th value from section
BOOL ReadSectionSettingByName(char *section, char *valuename, char *name, char *value); // Reads the value named name from section
BOOL IsValidSetting(char *setting, char *value);
void SetSetting(char *setting, char *value);
#endif // defined __FREELDR_H

426
freeldr/freeldr/fs.c Normal file
View file

@ -0,0 +1,426 @@
/*
* 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"
#define FS_DO_ERROR(s) \
{ \
if (bTUILoaded) \
MessageBox(s); \
else \
{ \
printf(s); \
printf("\nPress any key\n"); \
getch(); \
} \
}
int nSectorBuffered = -1; // Tells us which sector was read into SectorBuffer[]
BYTE SectorBuffer[512]; // 512 byte buffer space for read operations, ReadOneSector reads to here
int FSType = NULL; // Type of filesystem on boot device, set by OpenDiskDrive()
char *pFileSysData = (char *)(FILESYSADDR); // Load address for filesystem data
char *pFat32FATCacheIndex = (char *)(FILESYSADDR); // Load address for filesystem data
BOOL OpenDiskDrive(int nDrive, int nPartition)
{
int num_bootable_partitions = 0;
int boot_partition = 0;
int partition_type = 0;
int head, sector, cylinder;
int offset;
// Check and see if it is a floppy drive
if (nDrive < 0x80)
{
// 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;
}
}
else
{
// Read master boot record
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 partition table magic (0xaa55)");
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;
}
}
// 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)
{
/* 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;
}
}
FSType = FS_FAT;
// Buffer the FAT table if it is small enough
if ((FSType == FS_FAT) && (nFATType == FAT12))
{
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;
}
return TRUE;
}
BOOL ReadMultipleSectors(int nSect, int nNumberOfSectors, void *pBuffer)
{
BOOL bRetVal;
int PhysicalSector;
int PhysicalHead;
int PhysicalTrack;
int nNum;
nSect += nHiddenSectors;
while (nNumberOfSectors)
{
PhysicalSector = 1 + (nSect % nSectorsPerTrack);
PhysicalHead = (nSect / nSectorsPerTrack) % nNumberOfHeads;
PhysicalTrack = nSect / (nSectorsPerTrack * nNumberOfHeads);
if (PhysicalSector > 1)
{
if (nNumberOfSectors >= (nSectorsPerTrack - (PhysicalSector - 1)))
nNum = (nSectorsPerTrack - (PhysicalSector - 1));
else
nNum = nNumberOfSectors;
}
else
{
if (nNumberOfSectors >= nSectorsPerTrack)
nNum = nSectorsPerTrack;
else
nNum = nNumberOfSectors;
}
bRetVal = biosdisk(_DISK_READ, BootDrive, PhysicalHead, PhysicalTrack, PhysicalSector, nNum, pBuffer);
if (!bRetVal)
{
FS_DO_ERROR("Disk Error");
return FALSE;
}
pBuffer += (nNum * 512);
nNumberOfSectors -= nNum;
nSect += nNum;
}
return TRUE;
}
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)
{
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)))
return FALSE;
pFile->filesize = pFile->fat.dwSize;
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
return FALSE;
break;
}
return TRUE;
}
/*
* ReadFile()
* returns number of bytes read or EOF
*/
int ReadFile(FILE *pFile, int count, void *buffer)
{
switch(FSType)
{
case FS_FAT:
return FATRead(&(pFile->fat), count, buffer);
default:
FS_DO_ERROR("Error: Unknown filesystem.");
return EOF;
}
return 0;
}
DWORD GetFileSize(FILE *pFile)
{
return pFile->filesize;
}
DWORD Rewind(FILE *pFile)
{
switch (FSType)
{
case FS_FAT:
pFile->fat.dwCurrentCluster = pFile->fat.dwStartCluster;
pFile->fat.dwCurrentReadOffset = 0;
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
break;
}
return pFile->filesize;
}
int feof(FILE *pFile)
{
switch (FSType)
{
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)
{
case FS_FAT:
return FATfseek(&(pFile->fat), offset);
break;
default:
FS_DO_ERROR("Error: Unknown filesystem.");
break;
}
return -1;
}

182
freeldr/freeldr/fs.h Normal file
View file

@ -0,0 +1,182 @@
/*
* 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.
*/
#ifndef __FS_FAT_H
#define __FS_FAT_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
{
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;
/*
* Structure of internal file control block
*/
typedef struct //_FCB
{
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;
typedef struct //_FAT_STRUCT
{
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;
typedef struct //_FILE
{
//DIRENTRY de;
//FCB fcb;
FAT_STRUCT fat;
unsigned long filesize;
} FILE;
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
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);
#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 FS_FAT 1
#define FS_NTFS 2
#define FS_EXT2 3
#define FAT12 1
#define FAT16 2
#define FAT32 3
#endif // #defined __FS_FAT_H

541
freeldr/freeldr/fs_fat.c Normal file
View file

@ -0,0 +1,541 @@
/*
* 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;
}

101
freeldr/freeldr/linux.c Normal file
View file

@ -0,0 +1,101 @@
/*
* 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 "asmcode.h"
#include "miscboot.h"
#include "stdlib.h"
#include "fs.h"
#include "tui.h"
#include "linux.h"
void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line)
{
FILE file;
char temp[260];
char bootsector[512];
char setup[2048];
int len;
BootDrive = DriveNum;
BootPartition = Partition;
if (!OpenDiskDrive(BootDrive, BootPartition))
{
MessageBox("Failed to open boot drive.");
return;
}
if (!OpenFile(vmlinuz, &file))
{
strcpy(temp, vmlinuz);
strcat(temp, " not found.");
MessageBox(temp);
return;
}
// Read boot sector
if (ReadFile(&file, 512, bootsector) != 512)
{
MessageBox("Disk Read Error");
return;
}
MessageBox("bootsector loaded");
// Read setup code
if (ReadFile(&file, 2048, setup) != 2048)
{
MessageBox("Disk Read Error");
return;
}
MessageBox("setup loaded");
// Read kernel code
len = GetFileSize(&file) - (2048 + 512);
//len = 0x200;
if (ReadFile(&file, len, (void*)0x100000) != len)
{
MessageBox("Disk Read Error");
return;
}
MessageBox("kernel loaded");
// Check for validity
if (*((WORD*)(bootsector + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return;
}
if (*((DWORD*)(setup + 2)) != 0x53726448)
{
MessageBox("Invalid setup magic (\"HdrS\")");
return;
}
memcpy((void*)0x90000, bootsector, 512);
memcpy((void*)0x90200, setup, 2048);
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
stop_floppy();
JumpToLinuxBootCode();
}

27
freeldr/freeldr/linux.h Normal file
View file

@ -0,0 +1,27 @@
/*
* 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.
*/
#ifndef __LINUX_H
#define __LINUX_H
void JumpToLinuxBootCode(void); // Implemented in boot.S
void LoadAndBootLinux(int DriveNum, int Partition, char *vmlinuz, char *cmd_line);
#endif // defined __LINUX_H

190
freeldr/freeldr/menu.c Normal file
View file

@ -0,0 +1,190 @@
/*
* 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 "stdlib.h"
#include "tui.h"
#include "menu.h"
#include "options.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)
{
int key;
int second;
BOOL bDone = FALSE;
if (nTimeOut > 0)
nTimeOut++; // Increment the timeout since 0 doesn't count for a second
// Initialise the menu
InitMenu();
// Update the menu
DrawMenu();
second = getsecond();
// Loop
do
{
// Check for a keypress
if (kbhit())
{
// 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;
}
}
// Update the date & time
UpdateDateTime();
if (nTimeOut > 0)
{
if (getsecond() != second)
{
second = getsecond();
nTimeOut--;
// Update the menu
DrawMenu();
}
}
if (nTimeOut == 0)
bDone = TRUE;
}
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++)
{
height++;
if(strlen(OSList[i].name) > width)
width = strlen(OSList[i].name);
}
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;
}
void DrawMenu(void)
{
int i, j;
char text[260];
char temp[260];
int space, space_left, space_right;
// Update the status bar
DrawStatusText(" Use \x18\x19 to select, ENTER to boot. Press F8 for advanced options.");
DrawBox(nOSListBoxLeft, nOSListBoxTop, nOSListBoxRight, nOSListBoxBottom, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
for(i=0; i<nNumOS; i++)
{
space = (nOSListBoxRight - nOSListBoxLeft - 2) - strlen(OSList[i].name);
space_left = (space / 2) + 1;
space_right = (space - space_left) + 1;
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, " ");
if(i == nOSSelected)
{
DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cSelectedTextColor, cSelectedTextBgColor));
}
else
{
DrawText(nOSListBoxLeft+1, nOSListBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
}
}
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));
}
}

27
freeldr/freeldr/menu.h Normal file
View file

@ -0,0 +1,27 @@
/*
* 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.
*/
#ifndef __MENU_H
#define __MENU_H
int RunMenu(void);
void InitMenu(void);
void DrawMenu(void);
#endif // #defined __MENU_H

229
freeldr/freeldr/miscboot.c Normal file
View file

@ -0,0 +1,229 @@
/*
* 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 "asmcode.h"
#include "miscboot.h"
#include "stdlib.h"
#include "fs.h"
#include "tui.h"
void LoadAndBootBootSector(int nOSToBoot)
{
FILE file;
char name[260];
char value[260];
char szFileName[1024];
int i;
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if (stricmp(name, "MessageBox") == 0)
MessageBox(value);
if (stricmp(name, "MessageLine") == 0)
MessageLine(value);
}
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
{
MessageBox("Boot drive not specified for selected OS!");
return;
}
BootDrive = atoi(value);
BootPartition = 0;
if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
BootPartition = atoi(value);
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootSector", name, value))
{
MessageBox("Boot sector file not specified for selected OS!");
return;
}
if (!OpenDiskDrive(BootDrive, BootPartition))
{
MessageBox("Failed to open boot drive.");
return;
}
strcpy(szFileName, value);
if (!OpenFile(szFileName, &file))
{
strcat(value, " not found.");
MessageBox(value);
return;
}
// Read boot sector
if (ReadFile(&file, 512, (void*)0x7c00) != 512)
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return;
}
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
stop_floppy();
JumpToBootCode();
}
void LoadAndBootPartition(int nOSToBoot)
{
char name[260];
char value[260];
int head, sector, cylinder;
int offset;
int i;
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if (stricmp(name, "MessageBox") == 0)
MessageBox(value);
if (stricmp(name, "MessageLine") == 0)
MessageLine(value);
}
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
{
MessageBox("Boot drive not specified for selected OS!");
return;
}
BootDrive = atoi(value);
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
{
MessageBox("Boot partition not specified for selected OS!");
return;
}
BootPartition = atoi(value);
if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid partition table magic (0xaa55)");
return;
}
offset = 0x1BE + ((BootPartition-1) * 0x10);
// Check for valid partition
if (SectorBuffer[offset + 4] == 0)
{
MessageBox("Invalid boot partition");
return;
}
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, BootDrive, head, cylinder, sector, 1, (void*)0x7c00))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return;
}
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
stop_floppy();
JumpToBootCode();
}
void LoadAndBootDrive(int nOSToBoot)
{
char name[260];
char value[260];
int i;
// Find all the message box settings and run them
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if (stricmp(name, "MessageBox") == 0)
MessageBox(value);
if (stricmp(name, "MessageLine") == 0)
MessageLine(value);
}
if (!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
{
MessageBox("Boot drive not specified for selected OS!");
return;
}
BootDrive = atoi(value);
if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, (void*)0x7c00))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return;
}
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
stop_floppy();
JumpToBootCode();
}

View file

@ -0,0 +1,29 @@
/*
* 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.
*/
#ifndef __BOOT_H
#define __BOOT_H
void JumpToBootCode(void); // Implemented in boot.S
void LoadAndBootBootSector(int nOSToBoot);
void LoadAndBootPartition(int nOSToBoot);
void LoadAndBootDrive(int nOSToBoot);
#endif // defined __BOOT_H

395
freeldr/freeldr/options.c Normal file
View file

@ -0,0 +1,395 @@
/*
* 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 "stdlib.h"
#include "tui.h"
#include "options.h"
#include "miscboot.h"
void DoOptionsMenu(void)
{
int OptionsMenuItemCount = 1; // Count is 1 because we don't show the "Set ReactOS Boot Flags" menu item yet
char OptionsMenuItems[2][80] = { "Boot Wizard", "Set ReactOS Boot Flags" /* i.e. Safe Mode, Last Known Good Configuration */ };
int OptionsMenuItemSelected = 0;
while (OptionsMenuItemSelected != -1)
{
OptionsMenuItemSelected = RunOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, OptionsMenuItemSelected, "[Advanced Options]");
switch (OptionsMenuItemSelected)
{
case 0:
DoDiskOptionsMenu();
break;
}
}
}
void DoDiskOptionsMenu(void)
{
char DiskMenuItems[25][80];
int DiskMenuItemCount = 0;
int FloppyDiskMenuItemCount = 0;
int HardDiskMenuItemCount = 0;
int DiskMenuItemSelected = 0;
char temp[255];
int i;
FloppyDiskMenuItemCount = (int)*((char *)((0x40 * 16) + 0x10)); // Get number of floppy disks from bios data area 40:10
if (FloppyDiskMenuItemCount & 1)
FloppyDiskMenuItemCount = (FloppyDiskMenuItemCount >> 6) + 1;
else
FloppyDiskMenuItemCount = 0;
HardDiskMenuItemCount = (int)*((char *)((0x40 * 16) + 0x75)); // Get number of hard disks from bios data area 40:75
DiskMenuItemCount = FloppyDiskMenuItemCount + HardDiskMenuItemCount;
for (i=0; i<FloppyDiskMenuItemCount; i++)
{
strcpy(DiskMenuItems[i], "Floppy Disk ");
itoa(i + 1, temp, 10);
strcat(DiskMenuItems[i], temp);
}
for (i=0; i<HardDiskMenuItemCount; i++)
{
strcpy(DiskMenuItems[i + FloppyDiskMenuItemCount], "Hard Disk ");
itoa(i + 1, temp, 10);
strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], temp);
strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], " (");
itoa((get_heads(i+0x80) * get_cylinders(i+0x80) * get_sectors(i+0x80)) / 2048, temp, 10);
strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], temp);
strcat(DiskMenuItems[i + FloppyDiskMenuItemCount], " MB)");
}
DiskMenuItemSelected = 0;
while (DiskMenuItemSelected != -1)
{
DiskMenuItemSelected = RunOptionsMenu(DiskMenuItems, DiskMenuItemCount, DiskMenuItemSelected, "[Boot Wizard]");
if (DiskMenuItemSelected != -1)
{
if (DiskMenuItemSelected < FloppyDiskMenuItemCount)
DoBootOptionsMenu(DiskMenuItemSelected, DiskMenuItems[DiskMenuItemSelected]);
else
DoBootOptionsMenu((DiskMenuItemSelected - FloppyDiskMenuItemCount) + 0x80, DiskMenuItems[DiskMenuItemSelected]);
}
}
}
void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText)
{
int BootOptionsMenuItemCount = 2;
char BootOptionsMenuItems[2][80] = { "Boot To ", "Pick A Boot Partition" };
int BootOptionsMenuItemSelected = 0;
strcat(BootOptionsMenuItems[0], BootDriveText);
while (BootOptionsMenuItemSelected != -1)
{
BootOptionsMenuItemSelected = RunOptionsMenu(BootOptionsMenuItems, BootOptionsMenuItemCount, BootOptionsMenuItemSelected, "[Boot Options]");
switch (BootOptionsMenuItemSelected)
{
case 0:
BootDrive = BootDriveNum;
if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, (void*)0x7c00))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return;
}
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
stop_floppy();
JumpToBootCode();
break;
case 1:
if (BootDriveNum < 0x80)
{
MessageBox("This option is not available for a floppy disk.");
continue;
}
else
DoBootPartitionOptionsMenu(BootDriveNum);
break;
}
}
}
void DoBootPartitionOptionsMenu(int BootDriveNum)
{
struct
{
int partition_num;
int partition_type;
int head, sector, cylinder;
} BootPartitions[8];
int BootOptionsMenuItemCount = 0;
char BootOptionsMenuItems[8][80];
int BootOptionsMenuItemSelected = 0;
int head, sector, cylinder;
int offset;
int i;
char temp[25];
BootDrive = BootDriveNum;
if (!biosdisk(_DISK_READ, BootDrive, 0, 0, 1, 1, SectorBuffer))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(SectorBuffer + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid partition table magic (0xaa55)");
return;
}
offset = 0x1BE;
for (i=0; i<4; i++)
{
// Check for valid partition
if (SectorBuffer[offset + 4] != 0)
{
BootPartitions[BootOptionsMenuItemCount].partition_num = i;
BootPartitions[BootOptionsMenuItemCount].partition_type = SectorBuffer[offset + 4];
BootPartitions[BootOptionsMenuItemCount].head = SectorBuffer[offset + 1];
BootPartitions[BootOptionsMenuItemCount].sector = (SectorBuffer[offset + 2] & 0x3F);
BootPartitions[BootOptionsMenuItemCount].cylinder = SectorBuffer[offset + 3];
if (SectorBuffer[offset + 2] & 0x80)
BootPartitions[BootOptionsMenuItemCount].cylinder += 0x200;
if (SectorBuffer[offset + 2] & 0x40)
BootPartitions[BootOptionsMenuItemCount].cylinder += 0x100;
strcpy(BootOptionsMenuItems[BootOptionsMenuItemCount], "Boot To Partition ");
itoa(i+1, temp, 10);
strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], temp);
strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], " (Type: 0x");
itoa(BootPartitions[BootOptionsMenuItemCount].partition_type, temp, 16);
if (strlen(temp) < 2)
strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], "0");
strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], temp);
strcat(BootOptionsMenuItems[BootOptionsMenuItemCount], ")");
BootOptionsMenuItemCount++;
}
offset += 0x10;
}
while (BootOptionsMenuItemSelected != -1)
{
BootOptionsMenuItemSelected = RunOptionsMenu(BootOptionsMenuItems, BootOptionsMenuItemCount, BootOptionsMenuItemSelected, "[Boot Partition Options]");
if (BootOptionsMenuItemSelected != -1)
{
head = BootPartitions[BootOptionsMenuItemCount].head;
sector = BootPartitions[BootOptionsMenuItemCount].sector;
cylinder = BootPartitions[BootOptionsMenuItemCount].cylinder;
// Read partition boot sector
if (!biosdisk(_DISK_READ, BootDrive, head, cylinder, sector, 1, (void*)0x7c00))
{
MessageBox("Disk Read Error");
return;
}
// Check for validity
if (*((WORD*)(0x7c00 + 0x1fe)) != 0xaa55)
{
MessageBox("Invalid boot sector magic (0xaa55)");
return;
}
RestoreScreen(pScreenBuffer);
showcursor();
gotoxy(nCursorXPos, nCursorYPos);
stop_floppy();
JumpToBootCode();
}
}
}
int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle)
{
int key;
int second;
BOOL bDone = FALSE;
int nOptionsMenuBoxLeft;
int nOptionsMenuBoxRight;
int nOptionsMenuBoxTop;
int nOptionsMenuBoxBottom;
// Initialise the menu
InitOptionsMenu(&nOptionsMenuBoxLeft, &nOptionsMenuBoxTop, &nOptionsMenuBoxRight, &nOptionsMenuBoxBottom, OptionsMenuItemCount);
DrawBackdrop();
// Update the menu
DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
second = getsecond();
// Loop
do
{
// Check for a keypress
if (kbhit())
{
// Cancel the timeout
if (nTimeOut != -1)
{
nTimeOut = -1;
DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
}
// 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 (nOptionSelected)
{
nOptionSelected--;
// Update the menu
DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
}
break;
case KEY_DOWN:
if (nOptionSelected < (OptionsMenuItemCount - 1))
{
nOptionSelected++;
// Update the menu
DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
}
break;
case KEY_ENTER:
//MessageBox("The Advanced Options are still being implemented.");
bDone = TRUE;
break;
case KEY_ESC:
nOptionSelected = -1;
bDone = TRUE;
break;
}
}
// Update the date & time
UpdateDateTime();
if (nTimeOut > 0)
{
if (getsecond() != second)
{
second = getsecond();
nTimeOut--;
// Update the menu
DrawOptionsMenu(OptionsMenuItems, OptionsMenuItemCount, nOptionSelected, OptionsMenuTitle, nOptionsMenuBoxLeft, nOptionsMenuBoxTop, nOptionsMenuBoxRight, nOptionsMenuBoxBottom);
}
}
if (nTimeOut == 0)
bDone = TRUE;
}
while (!bDone);
return nOptionSelected;
}
void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount)
{
int height = OptionsMenuItemCount;
int width = 20;
height += 1; // Allow room for top & bottom borders
width += 18; // Allow room for left & right borders, plus 8 spaces on each side
// Calculate the OS list box area
*nOptionsMenuBoxLeft = (nScreenWidth - width) / 2;
*nOptionsMenuBoxRight = *nOptionsMenuBoxLeft + width;
*nOptionsMenuBoxTop = (nScreenHeight - height) / 2 + 1;
*nOptionsMenuBoxBottom = *nOptionsMenuBoxTop + height;
}
void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom)
{
int i, j;
char text[260];
int space, space_left, space_right;
// Update the status bar
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));
for(i=0; i<OptionsMenuItemCount; i++)
{
space = (nOptionsMenuBoxRight - nOptionsMenuBoxLeft - 2) - strlen(OptionsMenuItems[i]);
space_left = (space / 2) + 1;
space_right = (space - space_left) + 1;
text[0] = '\0';
for(j=0; j<space_left; j++)
strcat(text, " ");
strcat(text, OptionsMenuItems[i]);
for(j=0; j<space_right; j++)
strcat(text, " ");
if(i == nOptionSelected)
{
DrawText(nOptionsMenuBoxLeft+1, nOptionsMenuBoxTop+1+i, text, ATTR(cSelectedTextColor, cSelectedTextBgColor));
}
else
{
DrawText(nOptionsMenuBoxLeft+1, nOptionsMenuBoxTop+1+i, text, ATTR(cTextColor, cMenuBgColor));
}
}
}

31
freeldr/freeldr/options.h Normal file
View file

@ -0,0 +1,31 @@
/*
* 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.
*/
#ifndef __OPTIONS_H
#define __OPTIONS_H
void DoOptionsMenu(void);
void DoDiskOptionsMenu(void);
void DoBootOptionsMenu(int BootDriveNum, char *BootDriveText);
void DoBootPartitionOptionsMenu(int BootDriveNum);
int RunOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle);
void InitOptionsMenu(int *nOptionsMenuBoxLeft, int *nOptionsMenuBoxTop, int *nOptionsMenuBoxRight, int *nOptionsMenuBoxBottom, int OptionsMenuItemCount);
void DrawOptionsMenu(char OptionsMenuItems[][80], int OptionsMenuItemCount, int nOptionSelected, char *OptionsMenuTitle, int nOptionsMenuBoxLeft, int nOptionsMenuBoxTop, int nOptionsMenuBoxRight, int nOptionsMenuBoxBottom);
#endif // #defined __OPTIONS_H

593
freeldr/freeldr/pe.h Normal file
View file

@ -0,0 +1,593 @@
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define IMAGE_SECTION_CHAR_CODE 0x00000020
#define IMAGE_SECTION_CHAR_DATA 0x00000040
#define IMAGE_SECTION_CHAR_BSS 0x00000080
#define IMAGE_SECTION_CHAR_NON_CACHABLE 0x04000000
#define IMAGE_SECTION_CHAR_NON_PAGEABLE 0x08000000
#define IMAGE_SECTION_CHAR_SHARED 0x10000000
#define IMAGE_SECTION_CHAR_EXECUTABLE 0x20000000
#define IMAGE_SECTION_CHAR_READABLE 0x40000000
#define IMAGE_SECTION_CHAR_WRITABLE 0x80000000
#define IMAGE_DOS_MAGIC 0x5a4d
#define IMAGE_PE_MAGIC 0x00004550
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
WORD e_cblp; // Bytes on last page of file
WORD e_cp; // Pages in file
WORD e_crlc; // Relocations
WORD e_cparhdr; // Size of header in paragraphs
WORD e_minalloc; // Minimum extra paragraphs needed
WORD e_maxalloc; // Maximum extra paragraphs needed
WORD e_ss; // Initial (relative) SS value
WORD e_sp; // Initial SP value
WORD e_csum; // Checksum
WORD e_ip; // Initial IP value
WORD e_cs; // Initial (relative) CS value
WORD e_lfarlc; // File address of relocation table
WORD e_ovno; // Overlay number
WORD e_res[4]; // Reserved words
WORD e_oemid; // OEM identifier (for e_oeminfo)
WORD e_oeminfo; // OEM information; e_oemid specific
WORD e_res2[10]; // Reserved words
LONG e_lfanew; // File address of new exe header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
#define IMAGE_SIZEOF_FILE_HEADER 20
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file.
#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file.
#define IMAGE_FILE_SYSTEM 0x1000 // System File.
#define IMAGE_FILE_DLL 0x2000 // File is a DLL.
#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
#define IMAGE_FILE_MACHINE_UNKNOWN 0
#define IMAGE_FILE_MACHINE_I386 0x14c // Intel 386.
#define IMAGE_FILE_MACHINE_R3000 0x162 // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000 0x166 // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000 0x168 // MIPS little-endian
#define IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP
#define IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM PowerPC Little-Endian
//
// Directory format.
//
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
//
// Optional header format.
//
typedef struct _IMAGE_OPTIONAL_HEADER {
//
// Standard fields.
//
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
//
// NT additional fields.
//
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
#define IMAGE_SUBSYSTEM_UNKNOWN 0
#define IMAGE_SUBSYSTEM_NATIVE 1
#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
#define IMAGE_SUBSYSTEM_OS2_GUI 4
#define IMAGE_SUBSYSTEM_OS2_CUI 5
#define IMAGE_SUBSYSTEM_POSIX_GUI 6
#define IMAGE_SUBSYSTEM_POSIX_CUI 7
#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
// Directory Entries
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Description String
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // Machine Value (MIPS GP)
#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address
//
// Section header format.
//
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
#define IMAGE_SIZEOF_SECTION_HEADER 40
#define IMAGE_SECTION_CODE (0x20)
#define IMAGE_SECTION_INITIALIZED_DATA (0x40)
#define IMAGE_SECTION_UNINITIALIZED_DATA (0x80)
//
// Export Format
//
typedef struct _IMAGE_EXPORT_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Name;
DWORD Base;
DWORD NumberOfFunctions;
DWORD NumberOfNames;
PDWORD *AddressOfFunctions;
PDWORD *AddressOfNames;
PWORD *AddressOfNameOrdinals;
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;
//
// Import Format
//
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
#define IMAGE_ORDINAL_FLAG 0x80000000
#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
// Predefined resource types ... there may be some more, but I don't have
// the information yet. .....sang cho.....
#define RT_NEWRESOURCE 0x2000
#define RT_ERROR 0x7fff
#define NEWBITMAP (RT_BITMAP|RT_NEWRESOURCE)
#define NEWMENU (RT_MENU|RT_NEWRESOURCE)
#define NEWDIALOG (RT_DIALOG|RT_NEWRESOURCE)
//
// Resource Format.
//
//
// Resource directory consists of two counts, following by a variable length
// array of directory entries. The first count is the number of entries at
// beginning of the array that have actual names associated with each entry.
// The entries are in ascending order, case insensitive strings. The second
// count is the number of entries that immediately follow the named entries.
// This second count identifies the number of entries that have 16-bit integer
// Ids as their name. These entries are also sorted in ascending order.
//
// This structure allows fast lookup by either name or number, but for any
// given resource entry only one form of lookup is supported, not both.
// This is consistant with the syntax of the .RC file and the .RES file.
//
//
// Each directory contains the 32-bit Name of the entry and an offset,
// relative to the beginning of the resource directory of the data associated
// with this directory entry. If the name of the entry is an actual text
// string instead of an integer Id, then the high order bit of the name field
// is set to one and the low order 31-bits are an offset, relative to the
// beginning of the resource directory of the string, which is of type
// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the
// low-order 16-bits are the integer Id that identify this resource directory
// entry. If the directory entry is yet another resource directory (i.e. a
// subdirectory), then the high order bit of the offset field will be
// set to indicate this. Otherwise the high bit is clear and the offset
// field points to a resource data entry.
//
typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY {
DWORD Name;
DWORD OffsetToData;
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
WORD NumberOfNamedEntries;
WORD NumberOfIdEntries;
IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[0];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY;
#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
//
// For resource directory entries that have actual string names, the Name
// field of the directory entry points to an object of the following type.
// All of these string objects are stored together after the last resource
// directory entry and before the first resource data object. This minimizes
// the impact of these variable length objects on the alignment of the fixed
// size directory entry objects.
//
typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING {
WORD Length;
CHAR NameString[ 1 ];
} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING;
typedef struct _IMAGE_RESOURCE_DIR_STRING_U {
WORD Length;
WCHAR NameString[ 1 ];
} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U;
//
// Each resource data entry describes a leaf node in the resource directory
// tree. It contains an offset, relative to the beginning of the resource
// directory of the data for the resource, a size field that gives the number
// of bytes of data at that offset, a CodePage that should be used when
// decoding code point values within the resource data. Typically for new
// applications the code page would be the unicode code page.
//
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData;
DWORD Size;
DWORD CodePage;
DWORD Reserved;
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
// Menu Resources ... added by .....sang cho....
// Menu resources are composed of a menu header followed by a sequential list
// of menu items. There are two types of menu items: pop-ups and normal menu
// itmes. The MENUITEM SEPARATOR is a special case of a normal menu item with
// an empty name, zero ID, and zero flags.
typedef struct _IMAGE_MENU_HEADER{
WORD wVersion; // Currently zero
WORD cbHeaderSize; // Also zero
} IMAGE_MENU_HEADER, *PIMAGE_MENU_HEADER;
typedef struct _IMAGE_POPUP_MENU_ITEM{
WORD fItemFlags;
WCHAR szItemText[1];
} IMAGE_POPUP_MENU_ITEM, *PIMAGE_POPUP_MENU_ITEM;
typedef struct _IMAGE_NORMAL_MENU_ITEM{
WORD fItemFlags;
WORD wMenuID;
WCHAR szItemText[1];
} IMAGE_NORMAL_MENU_ITEM, *PIMAGE_NORMAL_MENU_ITEM;
#define MI_GRAYED 0x0001 // GRAYED keyword
#define MI_INACTIVE 0x0002 // INACTIVE keyword
#define MI_BITMAP 0x0004 // BITMAP keyword
#define MI_OWNERDRAW 0x0100 // OWNERDRAW keyword
#define MI_CHECKED 0x0008 // CHECKED keyword
#define MI_POPUP 0x0010 // used internally
#define MI_MENUBARBREAK 0x0020 // MENUBARBREAK keyword
#define MI_MENUBREAK 0x0040 // MENUBREAK keyword
#define MI_ENDMENU 0x0080 // used internally
// Dialog Box Resources .................. added by sang cho.
// A dialog box is contained in a single resource and has a header and
// a portion repeated for each control in the dialog box.
// The item DWORD IStyle is a standard window style composed of flags found
// in WINDOWS.H.
// The default style for a dialog box is:
// WS_POPUP | WS_BORDER | WS_SYSMENU
//
// The itme marked "Name or Ordinal" are :
// If the first word is an 0xffff, the next two bytes contain an ordinal ID.
// Otherwise, the first one or more WORDS contain a double-null-terminated string.
// An empty string is represented by a single WORD zero in the first location.
//
// The WORD wPointSize and WCHAR szFontName entries are present if the FONT
// statement was included for the dialog box. This can be detected by checking
// the entry IStyle. If IStyle & DS_SETFONT ( which is 0x40), then these
// entries will be present.
typedef struct _IMAGE_DIALOG_BOX_HEADER1{
DWORD IStyle;
DWORD IExtendedStyle; // New for Windows NT
WORD nControls; // Number of Controls
WORD x;
WORD y;
WORD cx;
WORD cy;
// N_OR_O MenuName; // Name or Ordinal ID
// N_OR_O ClassName; // Name or Ordinal ID
// WCHAR szCaption[];
// WORD wPointSize; // Only here if FONT set for dialog
// WCHAR szFontName[]; // This too
} IMAGE_DIALOG_HEADER, *PIMAGE_DIALOG_HEADER;
typedef union _NAME_OR_ORDINAL{ // Name or Ordinal ID
struct _ORD_ID{
WORD flgId;
WORD Id;
} ORD_ID;
WCHAR szName[1];
} NAME_OR_ORDINAL, *PNAME_OR_ORDINAL;
// The data for each control starts on a DWORD boundary (which may require
// some padding from the previous control), and its format is as follows:
typedef struct _IMAGE_CONTROL_DATA{
DWORD IStyle;
DWORD IExtendedStyle;
WORD x;
WORD y;
WORD cx;
WORD cy;
WORD wId;
// N_OR_O ClassId;
// N_OR_O Text;
// WORD nExtraStuff;
} IMAGE_CONTROL_DATA, *PIMAGE_CONTROL_DATA;
#define BUTTON 0x80
#define EDIT 0x81
#define STATIC 0x82
#define LISTBOX 0x83
#define SCROLLBAR 0x84
#define COMBOBOX 0x85
// The various statements used in a dialog script are all mapped to these
// classes along with certain modifying styles. The values for these styles
// can be found in WINDOWS.H. All dialog controls have the default styles
// of WS_CHILD and WS_VISIBLE. A list of the default styles used follows:
//
// Statement Default Class Default Styles
// CONTROL None WS_CHILD|WS_VISIBLE
// LTEXT STATIC ES_LEFT
// RTEXT STATIC ES_RIGHT
// CTEXT STATIC ES_CENTER
// LISTBOX LISTBOX WS_BORDER|LBS_NOTIFY
// CHECKBOX BUTTON BS_CHECKBOX|WS_TABSTOP
// PUSHBUTTON BUTTON BS_PUSHBUTTON|WS_TABSTOP
// GROUPBOX BUTTON BS_GROUPBOX
// DEFPUSHBUTTON BUTTON BS_DFPUSHBUTTON|WS_TABSTOP
// RADIOBUTTON BUTTON BS_RADIOBUTTON
// AUTOCHECKBOX BUTTON BS_AUTOCHECKBOX
// AUTO3STATE BUTTON BS_AUTO3STATE
// AUTORADIOBUTTON BUTTON BS_AUTORADIOBUTTON
// PUSHBOX BUTTON BS_PUSHBOX
// STATE3 BUTTON BS_3STATE
// EDITTEXT EDIT ES_LEFT|WS_BORDER|WS_TABSTOP
// COMBOBOX COMBOBOX None
// ICON STATIC SS_ICON
// SCROLLBAR SCROLLBAR None
///
//
// Debug Format
//
typedef struct _IMAGE_DEBUG_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Type;
DWORD SizeOfData;
DWORD AddressOfRawData;
DWORD PointerToRawData;
} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
#define IMAGE_DEBUG_TYPE_UNKNOWN 0
#define IMAGE_DEBUG_TYPE_COFF 1
#define IMAGE_DEBUG_TYPE_CODEVIEW 2
#define IMAGE_DEBUG_TYPE_FPO 3
#define IMAGE_DEBUG_TYPE_MISC 4
#define IMAGE_DEBUG_TYPE_EXCEPTION 5
#define IMAGE_DEBUG_TYPE_FIXUP 6
#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7
#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8
typedef struct _IMAGE_DEBUG_MISC {
DWORD DataType; // type of misc data, see defines
DWORD Length; // total length of record, rounded to four
// byte multiple.
BOOL Unicode; // TRUE if data is unicode string
BYTE Reserved[ 3 ];
BYTE Data[ 1 ]; // Actual data
} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC;
//
// Debugging information can be stripped from an image file and placed
// in a separate .DBG file, whose file name part is the same as the
// image file name part (e.g. symbols for CMD.EXE could be stripped
// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED
// flag in the Characteristics field of the file header. The beginning of
// the .DBG file contains the following structure which captures certain
// information from the image file. This allows a debug to proceed even if
// the original image file is not accessable. This header is followed by
// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more
// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in
// the image file contain file offsets relative to the beginning of the
// .DBG file.
//
// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure
// is left in the image file, but not mapped. This allows a debugger to
// compute the name of the .DBG file, from the name of the image in the
// IMAGE_DEBUG_MISC structure.
//
typedef struct _IMAGE_SEPARATE_DEBUG_HEADER {
WORD Signature;
WORD Flags;
WORD Machine;
WORD Characteristics;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD ImageBase;
DWORD SizeOfImage;
DWORD NumberOfSections;
DWORD ExportedNamesSize;
DWORD DebugDirectorySize;
DWORD SectionAlignment;
DWORD Reserved[2];
} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER;
#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944
#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000
#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the
// old checksum didn't match.
//
// End Image Format
//
#define SIZE_OF_NT_SIGNATURE sizeof (DWORD)
#define MAXRESOURCENAME 13
/* global macros to define header offsets into file */
/* offset to PE file signature */
#define NTSIGNATURE(a) ((LPVOID)((BYTE *)a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew))
/* DOS header identifies the NT PEFile signature dword
the PEFILE header exists just after that dword */
#define PEFHDROFFSET(a) ((LPVOID)((BYTE *)a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew + \
SIZE_OF_NT_SIGNATURE))
/* PE optional header is immediately after PEFile header */
#define OPTHDROFFSET(a) ((LPVOID)((BYTE *)a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew + \
SIZE_OF_NT_SIGNATURE + \
sizeof (IMAGE_FILE_HEADER)))
/* section headers are immediately after PE optional header */
#define SECHDROFFSET(a) ((LPVOID)((BYTE *)a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew + \
SIZE_OF_NT_SIGNATURE + \
sizeof (IMAGE_FILE_HEADER) + \
sizeof (IMAGE_OPTIONAL_HEADER)))
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY
{
DWORD dwRVAFunctionNameList;
DWORD dwUseless1;
DWORD dwUseless2;
DWORD dwRVAModuleName;
DWORD dwRVAFunctionAddressList;
} IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY;
typedef struct _RELOCATION_DIRECTORY
{
DWORD VirtualAddress; /* adresse virtuelle du bloc ou se font les relocations */
DWORD SizeOfBlock; // taille de cette structure + des structures
// relocation_entry qui suivent (ces dernieres sont
// donc au nombre de (SizeOfBlock-8)/2
} RELOCATION_DIRECTORY, *PRELOCATION_DIRECTORY;
typedef struct _RELOCATION_ENTRY
{
WORD TypeOffset;
// (TypeOffset >> 12) est le type
// (TypeOffset&0xfff) est l'offset dans le bloc
} RELOCATION_ENTRY, *PRELOCATION_ENTRY;
#define TYPE_RELOC_ABSOLUTE 0
#define TYPE_RELOC_HIGH 1
#define TYPE_RELOC_LOW 2
#define TYPE_RELOC_HIGHLOW 3
#define TYPE_RELOC_HIGHADJ 4
#define TYPE_RELOC_MIPS_JMPADDR 5

374
freeldr/freeldr/ros.S Normal file
View file

@ -0,0 +1,374 @@
/*
* 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.
*/
.text
.code16
#include "asmcode.h"
/*
* Needed for enabling the a20 address line
*/
empty_8042:
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
inb $0x64,%al
testb $0x02,%al
jnz empty_8042
ret
/*
* Enable the A20 address line (to allow access to over 1mb)
*/
.code32
EXTERN(_enable_a20)
call switch_to_real
.code16
call empty_8042
movb $0xD1,%al // command write
outb %al,$0x64
call empty_8042
mov $0xDF,%al // A20 on
out %al,$0x60
call empty_8042
call switch_to_prot
.code32
ret
.code16
/*
* Reprogram the PIC because they overlap the Intel defined
* exceptions
*/
reprogram_pic:
movb $0x11,%al // initialization sequence
outb %al,$0x20 // send it to 8259A-1
.word 0x00eb,0x00eb // jmp $+2, jmp $+2
outb %al,$0xA0 // and to 8259A-2
.word 0x00eb,0x00eb
movb $0x40,%al // start of hardware int's (0x20)
outb %al,$0x21
.word 0x00eb,0x00eb
movb $0x48,%al // start of hardware int's 2 (0x28)
outb %al,$0xA1
.word 0x00eb,0x00eb
movb $0x04,%al // 8259-1 is master
outb %al,$0x21
.word 0x00eb,0x00eb
movb $0x02,%al // 8259-2 is slave
outb %al,$0xA1
.word 0x00eb,0x00eb
movb $0x01,%al // 8086 mode for both
outb %al,$0x21
.word 0x00eb,0x00eb
outb %al,$0xA1
.word 0x00eb,0x00eb
movb $0xFF,%al // mask off all interrupts for now
outb %al,$0x21
.word 0x00eb,0x00eb
outb %al,$0xA1
ret
/*
* In: EDI = address
* Out: FS = segment
* DI = base
*/
convert_to_seg:
pushl %eax
movl %edi,%eax
//shrl $16,%eax
//shll $12,%eax
//movw %ax,%fs
shrl $4,%eax
movw %ax,%fs
andl $0xf,%edi
//andl $0xFFFF,%edi
popl %eax
ret
/*
* Here we assume the kernel is loaded at 1mb
* This boots the kernel
*/
.code32
EXTERN(_boot_ros)
call switch_to_real
.code16
/* Save cursor position */
movw $3,%ax //! Reset video mode
int $0x10
movb $10,%bl
movb $12,%ah
int $0x10
movw $0x1112,%ax //! Use 8x8 font
xorb %bl,%bl
int $0x10
movw $0x1200,%ax //! Use alternate print screen
movb $0x20,%bl
int $0x10
movb $1,%ah //! Define cursor (scan lines 6 to 7)
movw $0x0607,%cx
int $0x10
movb $1,%ah
movw $0x600,%cx
int $0x10
MOVb $6,%AH //SCROLL ACTIVE PAGE UP
MOVb $0x32,%AL //CLEAR 25 LINES
MOVw $0,%CX //UPPER LEFT OF SCROLL
MOVw $0x314F,%dx //LOWER RIGHT OF SCROLL
MOVb $(1*0x10+1),%bh //USE NORMAL ATTRIBUTE ON BLANKED LINE
INT $0x10 //VIDEO-IO
movw $0,%dx
movb $0,%dh
movb $2,%ah
movb $0,%bh
int $0x10
movw $0,%dx
movb $0,%dh
movb $2,%ah
movb $0,%bh
int $0x10
cli
// The page tables are setup elsewhere
/*
// Map in the lowmem page table (and reuse it for the identity map)
movl _kernel_page_directory_base,%edi
call convert_to_seg
movl _lowmem_page_table_base,%eax
addl $0x07,%eax
movl %eax,%fs:(%edi)
movl %eax,%fs:0xd00(%edi)//(0xd0000000/(1024*1024))(%edi)
// Map the page tables from the page directory
movl _kernel_page_directory_base,%eax
addl $0x07,%eax
movl %eax,%fs:0xf00(%edi)//(0xf0000000/(1024*1024))(%edi)
// Map in the kernel page table
movl _system_page_table_base,%eax
addl $0x07,%eax
movl %eax,%fs:0xc00(%edi)//(0xc0000000/(1024*1024))(%edi)
// Setup the lowmem page table
movl _lowmem_page_table_base,%edi
call convert_to_seg
movl $0,%ebx
l9:
movl %ebx,%eax
shll $12,%eax // ebx = ebx * 4096
addl $07,%eax // user, rw, present
movl %eax,%fs:(%edi,%ebx,4)
incl %ebx
cmpl $1024,%ebx
jl l9
// Setup the system page table
movl _system_page_table_base,%edi
call convert_to_seg
movl $07,%eax
l8:
movl %eax,%edx
addl _start_kernel,%edx
movl %edx,%fs:(%edi)
addl $4,%edi
addl $0x1000,%eax
cmpl $0x100007,%eax
jl l8
*/
/*
* Load the page directory into cr3
*/
movl _kernel_page_directory_base,%eax
movl %eax,%cr3
/*
* Setup various variables
*/
movw %ds,%bx
movzwl %bx,%eax
shll $4,%eax
addl %eax,kernel_gdtbase
//call enable_a20 // enabled elsewhere
call reprogram_pic
/*
* Load stack
*/
movw %ds,%bx
movzwl %bx,%eax
shll $4,%eax
addl $real_stack_end,%eax
movl %eax,real_stack_base
movl real_stack_base,%esp
movl _boot_param_struct_base,%edx
/*
* load gdt
*/
lgdt kernel_gdtptr
/*
* Enter pmode and clear prefetch queue
*/
movl %cr0,%eax
orl $0x80010001,%eax
/*orl $0x80000001,%eax*/
movl %eax,%cr0
jmp next
next:
/*
* NOTE: This must be position independant (no references to
* non absolute variables)
*/
/*
* Initalize segment registers
*/
movw $KERNEL_DS,%ax
movw %ax,%ds
movw %ax,%ss
movw %ax,%es
movw %ax,%fs
movw %ax,%gs
/*
* Initalize eflags
*/
pushl $0
popfl
/*
* Jump to start of 32 bit code at 0xc0000000 + 0x1000
*/
pushl %edx
pushl $0
ljmpl $KERNEL_CS,$(KERNEL_BASE+0x1000)
.p2align 2 /* force 4-byte alignment */
kernel_gdt:
.word 0 // Zero descriptor
.word 0
.word 0
.word 0
//.word 0x0000 // User code descriptor
//.word 0x0000 // base: 0h limit: 3gb
//.word 0xfa00
//.word 0x00cc
//.word 0x0000 // User data descriptor
//.word 0x0000 // base: 0h limit: 3gb
//.word 0xf200
//.word 0x00cc
//.word 0x0000
//.word 0x0000
//.word 0x0000
//.word 0x0000
.word 0xffff // Kernel code descriptor
.word 0x0000 //
.word 0x9a00 // base 0h limit 4gb
.word 0x00cf
.word 0xffff // Kernel data descriptor
.word 0x0000 //
.word 0x9200 // base 0h limit 4gb
.word 0x00cf
/* TSS space */
//.rept NR_TASKS
//.word 0
//.word 0
//.word 0
//.word 0
//.endr
kernel_gdtptr:
.word (((6+NR_TASKS)*8)-1) /* Limit */
kernel_gdtbase:
.long kernel_gdt /* Base Address */
EXTERN(_boot_param_struct_base)
.long 0
EXTERN(_start_mem)
.long 0
EXTERN(_kernel_page_directory_base)
.long 0
EXTERN(_system_page_table_base)
.long 0
EXTERN(_lowmem_page_table_base)
.long 0
EXTERN(_start_kernel)
.long 0
EXTERN(_load_base)
.long 0
/* boot_param structure */
EXTERN(_boot_parameters)
.long 0 // Magic
.long 0 // Cursor X
.long 0 // Cursor Y
.long 0 // nr_files
.long 0 // start_mem
.long 0 // end_mem
.rept 64
.long 0 // List of module lengths (terminated by a 0)
.endr
.rept 256
.byte 0 // Kernel parameter string
.endr
/* Our initial stack */
real_stack:
.rept 1024
.byte 0
.endr
real_stack_end:
real_stack_base:
.long 0

390
freeldr/freeldr/rosboot.c Normal file
View file

@ -0,0 +1,390 @@
/*
* 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 "asmcode.h"
#include "rosboot.h"
#include "stdlib.h"
#include "fs.h"
#include "tui.h"
extern boot_param boot_parameters; // Boot parameter structure passed to the kernel
extern int boot_param_struct_base; // Physical address of the boot parameters structure
extern int start_mem; // Start of the continuous range of physical kernel memory
extern int kernel_page_directory_base; // Physical address of the kernel page directory
extern int system_page_table_base; // Physical address of the system page table
extern int lowmem_page_table_base; // Physical address of the low mem page table
extern int start_kernel; // Physical address of the start of kernel code
extern int load_base; // Physical address of the loaded kernel modules
static int next_load_base;
void LoadAndBootReactOS(int nOSToBoot)
{
FILE file;
char name[1024];
char value[1024];
char szFileName[1024];
int i;
int nNumDriverFiles=0;
int nNumFilesLoaded=0;
/*
* Enable a20 so we can load at 1mb and initialize the page tables
*/
//enable_a20(); // enabled in freeldr.c
ReactOSMemInit();
// Setup kernel parameters
boot_param_struct_base = (int)&boot_parameters;
boot_parameters.magic = 0xdeadbeef;
boot_parameters.cursorx = 0;
boot_parameters.cursory = 0;
boot_parameters.nr_files = 0;
boot_parameters.start_mem = start_mem;
boot_parameters.end_mem = load_base;
boot_parameters.kernel_parameters[0] = 0;
next_load_base = load_base;
/*
* Read the optional kernel parameters
*/
if(ReadSectionSettingByName(OSList[nOSToBoot].name, "Options", name, value))
{
strcpy(boot_parameters.kernel_parameters,value);
}
/*
* Find the kernel image name
*/
if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "Kernel", name, value))
{
MessageBox("Kernel image file not specified for selected operating system.");
return;
}
/*
* Get the boot partition
*/
BootPartition = 0;
if (ReadSectionSettingByName(OSList[nOSToBoot].name, "BootPartition", name, value))
BootPartition = atoi(value);
/*
* Make sure the boot drive is set in the .ini file
*/
if(!ReadSectionSettingByName(OSList[nOSToBoot].name, "BootDrive", name, value))
{
MessageBox("Boot drive not specified for selected operating system.");
return;
}
DrawBackdrop();
DrawStatusText(" Loading...");
DrawProgressBar(0);
/*
* Set the boot drive and try to open it
*/
BootDrive = atoi(value);
if (!OpenDiskDrive(BootDrive, BootPartition))
{
MessageBox("Failed to open boot drive.");
return;
}
/*
* Parse the ini file and count the kernel and drivers
*/
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
/*
* Read the setting and check if it's a driver
*/
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
nNumDriverFiles++;
}
/*
* Parse the ini file and load the kernel and
* load all the drivers specified
*/
for (i=1; i<=GetNumSectionItems(OSList[nOSToBoot].name); i++)
{
/*
* Read the setting and check if it's a driver
*/
ReadSectionSettingByNumber(OSList[nOSToBoot].name, i, name, value);
if ((stricmp(name, "Kernel") == 0) || (stricmp(name, "Driver") == 0))
{
/*
* Set the name and try to open the PE image
*/
strcpy(szFileName, value);
if (!OpenFile(szFileName, &file))
{
strcat(value, " not found.");
MessageBox(value);
return;
}
/*
* Update the status bar with the current file
*/
strcpy(name, " Reading ");
strcat(name, value);
while (strlen(name) < 80)
strcat(name, " ");
DrawStatusText(name);
/*
* Load the driver
*/
ReactOSLoadPEImage(&file);
nNumFilesLoaded++;
DrawProgressBar((nNumFilesLoaded * 100) / nNumDriverFiles);
// Increment the number of files we loaded
boot_parameters.nr_files++;
}
else if (stricmp(name, "MessageBox") == 0)
{
DrawStatusText(" Press ENTER to continue");
MessageBox(value);
}
else if (stricmp(name, "MessageLine") == 0)
MessageLine(value);
else if (stricmp(name, "ReOpenBootDrive") == 0)
{
if (!OpenDiskDrive(BootDrive, BootPartition))
{
MessageBox("Failed to open boot drive.");
return;
}
}
}
/*
* End the list of modules we load with a zero length entry
* and update the end of kernel mem
*/
boot_parameters.module_lengths[boot_parameters.nr_files] = 0;
boot_parameters.end_mem = next_load_base;
/*
* Clear the screen and redraw the backdrop and status bar
*/
DrawBackdrop();
DrawStatusText(" Press any key to boot");
/*
* Wait for user
*/
strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
strcat(name, OSList[nOSToBoot].name);
strcat(name, ".");
//MessageBox(name);
RestoreScreen(pScreenBuffer);
/*
* Now boot the kernel
*/
stop_floppy();
ReactOSBootKernel();
}
void ReactOSMemInit(void)
{
int base;
/* Calculate the start of extended memory */
base = 0x100000;
/* Set the start of the page directory */
kernel_page_directory_base = base;
/*
* Set the start of the continuous range of physical memory
* occupied by the kernel
*/
start_mem = base;
base += 0x1000;
/* Calculate the start of the system page table (0xc0000000 upwards) */
system_page_table_base = base;
base += 0x1000;
/* Calculate the start of the page table to map the first 4mb */
lowmem_page_table_base = base;
base += 0x1000;
/* Set the position for the first module to be loaded */
load_base = base;
/* Set the address of the start of kernel code */
start_kernel = base;
}
void ReactOSBootKernel(void)
{
int i;
int *pPageDirectory = (int *)kernel_page_directory_base;
int *pLowMemPageTable = (int *)lowmem_page_table_base;
int *pSystemPageTable = (int *)system_page_table_base;
/* Zero out the kernel page directory */
for(i=0; i<1024; i++)
pPageDirectory[i] = 0;
/* Map in the lowmem page table */
pPageDirectory[(0x00/4)] = lowmem_page_table_base + 0x07;
/* Map in the lowmem page table (and reuse it for the identity map) */
pPageDirectory[(0xd00/4)] = lowmem_page_table_base + 0x07;
/* Map the page tables from the page directory */
pPageDirectory[(0xf00/4)] = kernel_page_directory_base + 0x07;
/* Map in the kernel page table */
pPageDirectory[(0xc00/4)] = system_page_table_base + 0x07;
/* Setup the lowmem page table */
for(i=0; i<1024; i++)
pLowMemPageTable[i] = (i * 4096) + 0x07;
/* Setup the system page table */
for(i=0; i<1024; i++)
pSystemPageTable[i] = ((i * 4096) + start_kernel) + 0x07;
boot_ros();
}
BOOL ReactOSLoadPEImage(FILE *pImage)
{
unsigned int Idx, ImageBase;
PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_FILE_HEADER PEFileHeader;
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
PIMAGE_SECTION_HEADER PESectionHeaders;
ImageBase = next_load_base;
boot_parameters.module_lengths[boot_parameters.nr_files] = 0;
/*
* Load the headers
*/
ReadFile(pImage, 0x1000, (void *)next_load_base);
/*
* Get header pointers
*/
PEDosHeader = (PIMAGE_DOS_HEADER) next_load_base;
PEMagic = (PULONG) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew);
PEFileHeader = (PIMAGE_FILE_HEADER) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew + sizeof(ULONG));
PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
PESectionHeaders = (PIMAGE_SECTION_HEADER) ((unsigned int) next_load_base +
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) +
sizeof(IMAGE_OPTIONAL_HEADER));
/*
* Check file magic numbers
*/
if(PEDosHeader->e_magic != IMAGE_DOS_MAGIC)
{
MessageBox("Incorrect MZ magic");
return FALSE;
}
if(PEDosHeader->e_lfanew == 0)
{
MessageBox("Invalid lfanew offset");
return 0;
}
if(*PEMagic != IMAGE_PE_MAGIC)
{
MessageBox("Incorrect PE magic");
return 0;
}
if(PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
{
MessageBox("Incorrect Architecture");
return 0;
}
/*
* Get header size and bump next_load_base
*/
next_load_base += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
boot_parameters.end_mem += ROUND_UP(PEOptionalHeader->SizeOfHeaders, PEOptionalHeader->SectionAlignment);
/*
* Copy image sections into virtual section
*/
// memcpy(DriverBase, ModuleLoadBase, PESectionHeaders[0].PointerToRawData);
// CurrentBase = (PVOID) ((DWORD)DriverBase + PESectionHeaders[0].PointerToRawData);
// CurrentSize = 0;
for (Idx = 0; Idx < PEFileHeader->NumberOfSections; Idx++)
{
/*
* Copy current section into current offset of virtual section
*/
if (PESectionHeaders[Idx].Characteristics &
(IMAGE_SECTION_CHAR_CODE | IMAGE_SECTION_CHAR_DATA))
{
//memcpy(PESectionHeaders[Idx].VirtualAddress + DriverBase,
// (PVOID)(ModuleLoadBase + PESectionHeaders[Idx].PointerToRawData),
// PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
//MessageBox("loading a section");
fseek(pImage, PESectionHeaders[Idx].PointerToRawData);
ReadFile(pImage, PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/, (void *)next_load_base);
//printf("PointerToRawData: %x\n", PESectionHeaders[Idx].PointerToRawData);
//printf("bytes at next_load_base: %x\n", *((unsigned long *)next_load_base));
//getch();
}
else
{
//memset(PESectionHeaders[Idx].VirtualAddress + DriverBase,
// '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
//MessageBox("zeroing a section");
memset((void *)next_load_base, '\0', PESectionHeaders[Idx].Misc.VirtualSize /*SizeOfRawData*/);
}
PESectionHeaders[Idx].PointerToRawData = next_load_base - ImageBase;
next_load_base += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment);
boot_parameters.module_lengths[boot_parameters.nr_files] += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment);
boot_parameters.end_mem += ROUND_UP(PESectionHeaders[Idx].Misc.VirtualSize, PEOptionalHeader->SectionAlignment);
//DrawProgressBar((Idx * 100) / PEFileHeader->NumberOfSections);
}
return TRUE;
}

75
freeldr/freeldr/rosboot.h Normal file
View file

@ -0,0 +1,75 @@
/*
* 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.
*/
#ifndef __ROSBOOT_H
#define __ROSBOOT_H
#include "freeldr.h"
#include "stdlib.h"
#include "pe.h"
#define PACKED __attribute__((packed))
void LoadAndBootReactOS(int nOSToBoot);
void ReactOSMemInit(void);
void ReactOSBootKernel(void);
BOOL ReactOSLoadPEImage(FILE *pImage);
void enable_a20(void);
void boot_ros(void);
// WARNING:
// This structure is prototyped here but allocated in ros.S
// if you change this prototype make sure to update ros.S
typedef struct
{
/*
* Magic value (useless really)
*/
unsigned int magic;
/*
* Cursor position
*/
unsigned int cursorx;
unsigned int cursory;
/*
* Number of files (including the kernel) loaded
*/
unsigned int nr_files;
/*
* Range of physical memory being used by the system
*/
unsigned int start_mem;
unsigned int end_mem;
/*
* List of module lengths (terminated by a 0)
*/
unsigned int module_lengths[64];
/*
* Kernel parameter string
*/
char kernel_parameters[256];
} boot_param PACKED;
#endif // defined __ROSBOOT_H

306
freeldr/freeldr/stdlib.c Normal file
View file

@ -0,0 +1,306 @@
/*
* 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 "stdlib.h"
/*
* print() - prints unformatted text to stdout
*/
void print(char *str)
{
int i;
for(i=0; i<strlen(str); i++)
putchar(str[i]);
}
/*
* convert_to_ascii() - converts a number to it's ascii equivalent
* from:
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1996 Erich Boleyn <erich@uruk.org>
*/
char *convert_to_ascii(char *buf, int c, ...)
{
unsigned long num = *((&c) + 1), mult = 10;
char *ptr = buf;
if (c == 'x')
mult = 16;
if ((num & 0x80000000uL) && c == 'd')
{
num = (~num)+1;
*(ptr++) = '-';
buf++;
}
do
{
int dig = num % mult;
*(ptr++) = ( (dig > 9) ? dig + 'a' - 10 : '0' + dig );
}
while (num /= mult);
/* reorder to correct direction!! */
{
char *ptr1 = ptr-1;
char *ptr2 = buf;
while (ptr1 > ptr2)
{
int c = *ptr1;
*ptr1 = *ptr2;
*ptr2 = c;
ptr1--;
ptr2++;
}
}
return ptr;
}
/*
* printf() - prints formatted text to stdout
* from:
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1996 Erich Boleyn <erich@uruk.org>
*/
void printf(char *format, ... )
{
int *dataptr = (int *) &format;
char c, *ptr, str[16];
dataptr++;
while ((c = *(format++)))
{
if (c != '%')
putchar(c);
else
switch (c = *(format++))
{
case 'd': case 'u': case 'x':
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
ptr = str;
while (*ptr)
putchar(*(ptr++));
break;
case 'c': putchar((*(dataptr++))&0xff); break;
case 's':
ptr = (char *)(*(dataptr++));
while ((c = *(ptr++)))
putchar(c);
break;
}
}
}
int strlen(char *str)
{
int len;
for(len=0; str[len] != '\0'; len++);
return len;
}
char *itoa(int value, char *string, int radix)
{
if(radix == 16)
*convert_to_ascii(string, 'x', value) = 0;
else
*convert_to_ascii(string, 'd', value) = 0;
return string;
}
int toupper(int c)
{
if((c >= 'a') && (c <= 'z'))
c -= 32;
return c;
}
int tolower(int c)
{
if((c >= 'A') && (c <= 'Z'))
c += 32;
return c;
}
int memcmp(const void *buf1, const void *buf2, size_t count)
{
size_t i;
const char *buffer1 = buf1;
const char *buffer2 = buf2;
for(i=0; i<count; i++)
{
if(buffer1[i] == buffer2[i])
continue;
else
return (buffer1[i] - buffer2[i]);
}
return 0;
}
void *memcpy(void *dest, const void *src, size_t count)
{
size_t i;
char *buf1 = dest;
const char *buf2 = src;
for(i=0; i<count; i++)
buf1[i] = buf2[i];
return dest;
}
void *memset(void *dest, int c, size_t count)
{
size_t i;
char *buf1 = dest;
for(i=0; i<count; i++)
buf1[i] = c;
return dest;
}
char *strcpy(char *dest, char *src)
{
char *ret = dest;
while(*src)
*dest++ = *src++;
*dest = 0;
return ret;
}
char *strcat(char *dest, char *src)
{
char *ret = dest;
while(*dest)
dest++;
while(*src)
*dest++ = *src++;
*dest = 0;
return ret;
}
int strcmp(const char *string1, const char *string2)
{
while(*string1 == *string2)
{
if(*string1 == 0)
return 0;
string1++;
string2++;
}
return *(unsigned const char *)string1 - *(unsigned const char *)(string2);
}
int stricmp(const char *string1, const char *string2)
{
while(tolower(*string1) == tolower(*string2))
{
if(*string1 == 0)
return 0;
string1++;
string2++;
}
return (int)tolower(*string1) - (int)tolower(*string2);
}
char *fgets(char *string, int n, FILE *stream)
{
int i;
for(i=0; i<(n-1); i++)
{
if(feof(stream))
{
i++;
break;
}
ReadFile(stream, 1, string+i);
if(string[i] == '\n')
{
i++;
break;
}
}
string[i] = '\0';
return string;
}
int atoi(char *string)
{
int i, j;
int base;
int result = 0;
char *str;
if((string[0] == '0') && (string[1] == 'x'))
{
base = 16;
str = string + 2;
}
else
{
base = 10;
str = string;
}
for(i=strlen(str)-1,j=1; i>=0; i--)
{
if((str[i] < '0') || (str[i] > '9'))
break;
if(i == (strlen(str)-1))
result += (str[i] - '0');
else
{
result += (str[i] - '0') * (j * base);
j *= base;
}
}
return result;
}

74
freeldr/freeldr/stdlib.h Normal file
View file

@ -0,0 +1,74 @@
/*
* 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.
*/
#ifndef __STDLIB_H
#define __STDLIB_H
#include "fs.h"
void putchar(int ch); // Implemented in asmcode.S
void clrscr(void); // Implemented in asmcode.S
int kbhit(void); // Implemented in asmcode.S
int getch(void); // Implemented in asmcode.S
void gotoxy(int x, int y); // Implemented in asmcode.S
int getyear(void); // Implemented in asmcode.S
int getday(void); // Implemented in asmcode.S
int getmonth(void); // Implemented in asmcode.S
int gethour(void); // Implemented in asmcode.S
int getminute(void); // Implemented in asmcode.S
int getsecond(void); // Implemented in asmcode.S
void hidecursor(void); // Implemented in asmcode.S
void showcursor(void); // Implemented in asmcode.S
int wherex(void); // Implemented in asmcode.S
int wherey(void); // Implemented in asmcode.S
int strlen(char *str);
char *strcpy(char *dest, char *src);
char *strcat(char *dest, char *src);
int strcmp(const char *string1, const char *string2);
int stricmp(const char *string1, const char *string2);
char *itoa(int value, char *string, int radix);
int toupper(int c);
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);
int atoi(char *string);
void print(char *str);
void printf(char *fmt, ...);
int biosdisk(int cmd, int drive, int head, int track, int sector, int nsects, void *buffer); // Implemented in asmcode.S
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

572
freeldr/freeldr/tui.c Normal file
View file

@ -0,0 +1,572 @@
/*
* 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 "stdlib.h"
#include "tui.h"
int nScreenWidth = 80; // Screen Width
int 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 szMessageBoxLineText[4000] = "";
void DrawBackdrop(void)
{
// Fill in the backdrop
FillArea(0, 0, 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));
// Draw version
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));
// 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 status bar
DrawStatusText("");
// Update the date & time
UpdateDateTime();
}
/*
* FillArea()
* This function assumes coordinates are zero-based
*/
void FillArea(int nLeft, int nTop, int nRight, int nBottom, char cFillChar, char cAttr /* Color Attributes */)
{
char *screen = (char *)SCREEN_MEM;
int i, j;
for(i=nTop; i<=nBottom; i++)
{
for(j=nLeft; j<=nRight; j++)
{
screen[((i*2)*nScreenWidth)+(j*2)] = cFillChar;
screen[((i*2)*nScreenWidth)+(j*2)+1] = cAttr;
}
}
}
/*
* DrawShadow()
* This function assumes coordinates are zero-based
*/
void DrawShadow(int nLeft, int nTop, int nRight, int nBottom)
{
char *screen = (char *)SCREEN_MEM;
int i;
// Shade the bottom of the area
if(nBottom < (nScreenHeight-1))
{
for(i=nLeft+2; i<=nRight; i++)
screen[(((nBottom+1)*2)*nScreenWidth)+(i*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
}
// Shade the right of the area
if(nRight < (nScreenWidth-1))
{
for(i=nTop+1; i<=nBottom; i++)
screen[((i*2)*nScreenWidth)+((nRight+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
}
if(nRight+1 < (nScreenWidth-1))
{
for(i=nTop+1; i<=nBottom; i++)
screen[((i*2)*nScreenWidth)+((nRight+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
}
// Shade the bottom right corner
if((nRight < (nScreenWidth-1)) && (nBottom < (nScreenHeight-1)))
screen[(((nBottom+1)*2)*nScreenWidth)+((nRight+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
if((nRight+1 < (nScreenWidth-1)) && (nBottom < (nScreenHeight-1)))
screen[(((nBottom+1)*2)*nScreenWidth)+((nRight+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
}
/*
* DrawBox()
* This function assumes coordinates are one-based
*/
void DrawBox(int nLeft, int nTop, int nRight, int nBottom, int nVertStyle, int nHorzStyle, int bFill, int bShadow, char cAttr)
{
char cULCorner, cURCorner, cLLCorner, cLRCorner;
char cHorz, cVert;
nLeft--;
nTop--;
nRight--;
nBottom--;
cHorz = nHorzStyle;
cVert = nVertStyle;
if(nHorzStyle == HORZ)
{
if(nVertStyle == VERT)
{
cULCorner = UL;
cURCorner = UR;
cLLCorner = LL;
cLRCorner = LR;
}
else // nVertStyle == D_VERT
{
cULCorner = VD_UL;
cURCorner = VD_UR;
cLLCorner = VD_LL;
cLRCorner = VD_LR;
}
}
else // nHorzStyle == D_HORZ
{
if(nVertStyle == VERT)
{
cULCorner = HD_UL;
cURCorner = HD_UR;
cLLCorner = HD_LL;
cLRCorner = HD_LR;
}
else // nVertStyle == D_VERT
{
cULCorner = D_UL;
cURCorner = D_UR;
cLLCorner = D_LL;
cLRCorner = D_LR;
}
}
// Fill in box background
if(bFill)
FillArea(nLeft, nTop, nRight, nBottom, ' ', cAttr);
// Fill in corners
FillArea(nLeft, nTop, nLeft, nTop, cULCorner, cAttr);
FillArea(nRight, nTop, nRight, nTop, cURCorner, cAttr);
FillArea(nLeft, nBottom, nLeft, nBottom, cLLCorner, cAttr);
FillArea(nRight, nBottom, nRight, nBottom, cLRCorner, cAttr);
// Fill in left line
FillArea(nLeft, nTop+1, nLeft, nBottom-1, cVert, cAttr);
// Fill in top line
FillArea(nLeft+1, nTop, nRight-1, nTop, cHorz, cAttr);
// Fill in right line
FillArea(nRight, nTop+1, nRight, nBottom-1, cVert, cAttr);
// Fill in bottom line
FillArea(nLeft+1, nBottom, nRight-1, nBottom, cHorz, cAttr);
if(bShadow)
DrawShadow(nLeft, nTop, nRight, nBottom);
}
/*
* DrawText()
* This function assumes coordinates are one-based
*/
void DrawText(int nX, int nY, char *text, char cAttr)
{
char *screen = (char *)SCREEN_MEM;
int i, j;
nX--;
nY--;
// Draw the text
for(i=nX, j=0; text[j]; i++,j++)
{
screen[((nY*2)*nScreenWidth)+(i*2)] = text[j];
screen[((nY*2)*nScreenWidth)+(i*2)+1] = cAttr;
}
}
void DrawStatusText(char *text)
{
int i;
DrawText(1, nScreenHeight, text, ATTR(cStatusBarFgColor, cStatusBarBgColor));
for(i=strlen(text)+1; i<=nScreenWidth; i++)
DrawText(i, nScreenHeight, " ", ATTR(cStatusBarFgColor, cStatusBarBgColor));
}
void UpdateDateTime(void)
{
char date[260];
char time[260];
char temp[20];
int hour, minute, second, bPM=FALSE;
switch(getmonth())
{
case 1:
strcpy(date, "January ");
break;
case 2:
strcpy(date, "February ");
break;
case 3:
strcpy(date, "March ");
break;
case 4:
strcpy(date, "April ");
break;
case 5:
strcpy(date, "May ");
break;
case 6:
strcpy(date, "June ");
break;
case 7:
strcpy(date, "July ");
break;
case 8:
strcpy(date, "August ");
break;
case 9:
strcpy(date, "September ");
break;
case 10:
strcpy(date, "October ");
break;
case 11:
strcpy(date, "November ");
break;
case 12:
strcpy(date, "December ");
break;
}
itoa(getday(), temp, 10);
if((getday() == 1) || (getday() == 21) || (getday() == 31))
strcat(temp, "st");
else if((getday() == 2) || (getday() == 22))
strcat(temp, "nd");
else if((getday() == 3) || (getday() == 23))
strcat(temp, "rd");
else
strcat(temp, "th");
strcat(date, temp);
strcat(date, " ");
itoa(getyear(), temp, 10);
strcat(date, temp);
// Draw the date
DrawText(nScreenWidth-strlen(date)-1, 2, date, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
hour = gethour();
if(hour > 12)
{
hour -= 12;
bPM = TRUE;
}
if (hour == 0)
hour = 12;
minute = getminute();
second = getsecond();
itoa(hour, temp, 10);
strcpy(time, " ");
strcat(time, temp);
strcat(time, ":");
itoa(minute, temp, 10);
if(minute < 10)
strcat(time, "0");
strcat(time, temp);
strcat(time, ":");
itoa(second, temp, 10);
if(second < 10)
strcat(time, "0");
strcat(time, temp);
if(bPM)
strcat(time, " PM");
else
strcat(time, " AM");
// Draw the time
DrawText(nScreenWidth-strlen(time)-1, 3, time, ATTR(cTitleBoxFgColor, cTitleBoxBgColor));
}
void SaveScreen(char *buffer)
{
char *screen = (char *)SCREEN_MEM;
int i;
for(i=0; i < (nScreenWidth * nScreenHeight * 2); i++)
buffer[i] = screen[i];
}
void RestoreScreen(char *buffer)
{
char *screen = (char *)SCREEN_MEM;
int i;
for(i=0; i < (nScreenWidth * nScreenHeight * 2); i++)
screen[i] = buffer[i];
}
void MessageBox(char *text)
{
int width = 8;
int height = 1;
int curline = 0;
int i , j, k;
int x1, x2, y1, y2;
char savebuffer[8000];
char temp[260];
char key;
SaveScreen(savebuffer);
strcat(szMessageBoxLineText, text);
// Find the height
for(i=0; i<strlen(szMessageBoxLineText); i++)
{
if(szMessageBoxLineText[i] == '\n')
height++;
}
// Find the width
for(i=0,j=0,k=0; i<height; i++)
{
while((szMessageBoxLineText[j] != '\n') && (szMessageBoxLineText[j] != 0))
{
j++;
k++;
}
if(k > width)
width = k;
k = 0;
j++;
}
// Calculate box area
x1 = (nScreenWidth - (width+2))/2;
x2 = x1 + width + 3;
y1 = ((nScreenHeight - height - 2)/2) + 1;
y2 = y1 + height + 4;
// Draw the box
DrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(cMessageBoxFgColor, cMessageBoxBgColor));
// Draw the text
for(i=0,j=0; i<strlen(szMessageBoxLineText)+1; i++)
{
if((szMessageBoxLineText[i] == '\n') || (szMessageBoxLineText[i] == 0))
{
temp[j] = 0;
j = 0;
DrawText(x1+2, y1+1+curline, temp, ATTR(cMessageBoxFgColor, cMessageBoxBgColor));
curline++;
}
else
temp[j++] = szMessageBoxLineText[i];
}
// Draw OK button
strcpy(temp, " OK ");
DrawText(x1+((x2-x1)/2)-3, y2-2, temp, ATTR(COLOR_BLACK, COLOR_GRAY));
for(;;)
{
if(kbhit())
{
key = getch();
if(key == KEY_EXTENDED)
key = getch();
if(key == KEY_ENTER)
break;
else if(key == KEY_SPACE)
break;
}
UpdateDateTime();
}
RestoreScreen(savebuffer);
UpdateDateTime();
strcpy(szMessageBoxLineText, "");
}
void MessageLine(char *text)
{
strcat(szMessageBoxLineText, text);
strcat(szMessageBoxLineText, "\n");
}
BOOL IsValidColor(char *color)
{
if(stricmp(color, "Black") == 0)
return TRUE;
else if(stricmp(color, "Blue") == 0)
return TRUE;
else if(stricmp(color, "Green") == 0)
return TRUE;
else if(stricmp(color, "Cyan") == 0)
return TRUE;
else if(stricmp(color, "Red") == 0)
return TRUE;
else if(stricmp(color, "Magenta") == 0)
return TRUE;
else if(stricmp(color, "Brown") == 0)
return TRUE;
else if(stricmp(color, "Gray") == 0)
return TRUE;
else if(stricmp(color, "DarkGray") == 0)
return TRUE;
else if(stricmp(color, "LightBlue") == 0)
return TRUE;
else if(stricmp(color, "LightGreen") == 0)
return TRUE;
else if(stricmp(color, "LightCyan") == 0)
return TRUE;
else if(stricmp(color, "LightRed") == 0)
return TRUE;
else if(stricmp(color, "LightMagenta") == 0)
return TRUE;
else if(stricmp(color, "Yellow") == 0)
return TRUE;
else if(stricmp(color, "White") == 0)
return TRUE;
return FALSE;
}
char TextToColor(char *color)
{
if(stricmp(color, "Black") == 0)
return COLOR_BLACK;
else if(stricmp(color, "Blue") == 0)
return COLOR_BLUE;
else if(stricmp(color, "Green") == 0)
return COLOR_GREEN;
else if(stricmp(color, "Cyan") == 0)
return COLOR_CYAN;
else if(stricmp(color, "Red") == 0)
return COLOR_RED;
else if(stricmp(color, "Magenta") == 0)
return COLOR_MAGENTA;
else if(stricmp(color, "Brown") == 0)
return COLOR_BROWN;
else if(stricmp(color, "Gray") == 0)
return COLOR_GRAY;
else if(stricmp(color, "DarkGray") == 0)
return COLOR_DARKGRAY;
else if(stricmp(color, "LightBlue") == 0)
return COLOR_LIGHTBLUE;
else if(stricmp(color, "LightGreen") == 0)
return COLOR_LIGHTGREEN;
else if(stricmp(color, "LightCyan") == 0)
return COLOR_LIGHTCYAN;
else if(stricmp(color, "LightRed") == 0)
return COLOR_LIGHTRED;
else if(stricmp(color, "LightMagenta") == 0)
return COLOR_LIGHTMAGENTA;
else if(stricmp(color, "Yellow") == 0)
return COLOR_YELLOW;
else if(stricmp(color, "White") == 0)
return COLOR_WHITE;
return COLOR_BLACK;
}
BOOL IsValidFillStyle(char *fill)
{
if(stricmp(fill, "Light") == 0)
return TRUE;
else if(stricmp(fill, "Medium") == 0)
return TRUE;
else if(stricmp(fill, "Dark") == 0)
return TRUE;
return FALSE;
}
char TextToFillStyle(char *fill)
{
if(stricmp(fill, "Light") == 0)
return LIGHT_FILL;
else if(stricmp(fill, "Medium") == 0)
return MEDIUM_FILL;
else if(stricmp(fill, "Dark") == 0)
return DARK_FILL;
return LIGHT_FILL;
}
void DrawProgressBar(int nPos)
{
int left, top, right, bottom;
int width = 50; // Allow for 50 "bars"
int height = 2;
int i;
if(nPos > 100)
nPos = 100;
left = (nScreenWidth - width - 4) / 2;
right = left + width + 3;
top = (nScreenHeight - height - 2) / 2;
top += 4;
bottom = top + height + 1;
// Draw the box
DrawBox(left, top, right, bottom, VERT, HORZ, TRUE, TRUE, ATTR(cMenuFgColor, cMenuBgColor));
// Draw the "Loading..." text
DrawText(70/2, top+1, "Loading...", ATTR(cTextColor, cMenuBgColor));
// Draw the percent complete
for(i=0; i<(nPos/2); i++)
DrawText(left+2+i, top+2, "\xDB", ATTR(cTextColor, cMenuBgColor));
// Draw the rest
for(; i<50; i++)
DrawText(left+2+i, top+2, "\xB2", ATTR(cTextColor, cMenuBgColor));
UpdateDateTime();
}

162
freeldr/freeldr/tui.h Normal file
View file

@ -0,0 +1,162 @@
/*
* 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.
*/
#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
// Fills the entire screen with a backdrop
void DrawBackdrop(void);
// Fills the area specified with cFillChar and cAttr
void FillArea(int nLeft, int nTop, int nRight, int nBottom, char cFillChar, char cAttr /* Color Attributes */);
// Draws a shadow on the bottom and right sides of the area specified
void DrawShadow(int nLeft, int nTop, int nRight, int nBottom);
// Draws a box around the area specified
void DrawBox(int nLeft, int nTop, int nRight, int nBottom, int nVertStyle, int nHorzStyle, int bFill, int bShadow, char cAttr);
// Draws text at coordinates specified
void DrawText(int nX, int nY, char *text, char cAttr);
// Draws text at the very bottom line on the screen
void DrawStatusText(char *text);
// Updates the date and time
void UpdateDateTime(void);
// Saves the screen so that it can be restored later
void SaveScreen(char *buffer);
// Restores the screen from a previous save
void RestoreScreen(char *buffer);
// Displays a message box on the screen with an ok button
void MessageBox(char *text);
// Adds a line of text to the message box buffer
void MessageLine(char *text);
// Returns true if color is valid
BOOL IsValidColor(char *color);
// Converts the text color into it's equivalent color value
char TextToColor(char *color);
// Returns true if fill is valid
BOOL IsValidFillStyle(char *fill);
// Converts the text fill into it's equivalent fill value
char TextToFillStyle(char *fill);
// Draws the progress bar showing nPos percent filled
void DrawProgressBar(int nPos);
/*
* Combines the foreground and background colors into a single attribute byte
*/
#define ATTR(cFore, cBack) ((cBack << 4)|cFore)
/*
* Fill styles for DrawBackdrop()
*/
#define LIGHT_FILL 0xB0
#define MEDIUM_FILL 0xB1
#define DARK_FILL 0xB2
/*
* Screen colors
*/
#define COLOR_BLACK 0
#define COLOR_BLUE 1
#define COLOR_GREEN 2
#define COLOR_CYAN 3
#define COLOR_RED 4
#define COLOR_MAGENTA 5
#define COLOR_BROWN 6
#define COLOR_GRAY 7
#define COLOR_DARKGRAY 8
#define COLOR_LIGHTBLUE 9
#define COLOR_LIGHTGREEN 10
#define COLOR_LIGHTCYAN 11
#define COLOR_LIGHTRED 12
#define COLOR_LIGHTMAGENTA 13
#define COLOR_YELLOW 14
#define COLOR_WHITE 15
/* Add COLOR_BLINK to a background to cause blinking */
#define COLOR_BLINK 8
/*
* Defines for IBM box drawing characters
*/
#define HORZ (0xc4) /* Single horizontal line */
#define D_HORZ (0xcd) /* Double horizontal line.*/
#define VERT (0xb3) /* Single vertical line */
#define D_VERT (0xba) /* Double vertical line. */
/* Definitions for corners, depending on HORIZ and VERT */
#define UL (0xda)
#define UR (0xbf) /* HORZ and VERT */
#define LL (0xc0)
#define LR (0xd9)
#define D_UL (0xc9)
#define D_UR (0xbb) /* D_HORZ and D_VERT */
#define D_LL (0xc8)
#define D_LR (0xbc)
#define HD_UL (0xd5)
#define HD_UR (0xb8) /* D_HORZ and VERT */
#define HD_LL (0xd4)
#define HD_LR (0xbe)
#define VD_UL (0xd6)
#define VD_UR (0xb7) /* HORZ and D_VERT */
#define VD_LL (0xd3)
#define VD_LR (0xbd)
// Key codes
#define KEY_EXTENDED 0x00
#define KEY_ENTER 0x0D
#define KEY_SPACE 0x20
#define KEY_UP 0x48
#define KEY_DOWN 0x50
#define KEY_LEFT 0x4B
#define KEY_RIGHT 0x4D
#define KEY_ESC 0x1B
#define KEY_F1 0x3B
#define KEY_F2 0x3C
#define KEY_F3 0x3D
#define KEY_F4 0x3E
#define KEY_F5 0x3F
#define KEY_F6 0x40
#define KEY_F7 0x41
#define KEY_F8 0x42
#define KEY_F9 0x43
#define KEY_F10 0x44
#endif // #defined __TUI_H

5
freeldr/install.bat Normal file
View file

@ -0,0 +1,5 @@
cd bootsect
call install.bat
cd..
copy freeldr.sys a:\
copy freeldr.ini a:\

18
freeldr/notes.txt Normal file
View file

@ -0,0 +1,18 @@
FreeLoader notes
To build FreeLoader you will need DJGPP because Mingw32 doesn't support 16-bit code
FreeLoader does not currently work with extended partitions.
Linux booting support needs to be added.
ext2 filesystem support needs to be added.
Current memory layout:
0000:0000 - 0000:0FFF: Interrupt vector table & BIOS data
0000:1000 - 0000:6FFF: Real mode stack area
0000:7000 - xxxx:xxxx: FreeLoader program & data area
xxxx:xxxx - 6000:0000: Protected mode stack area & heap
6000:0000 - 6000:C000: Filesystem data buffer
6000:C000 - 7000:0000: FREELDR.INI loaded here
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