mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
Initial revision
svn path=/trunk/; revision=1904
This commit is contained in:
parent
bbf48f20aa
commit
afdf923c65
339
freeldr/COPYING
Normal file
339
freeldr/COPYING
Normal 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
130
freeldr/FREELDR.INI
Normal 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
|
256
freeldr/bootsect/BOOTSECT.ASM
Normal file
256
freeldr/bootsect/BOOTSECT.ASM
Normal 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
|
||||||
|
|
351
freeldr/bootsect/BTSECT32.ASM
Normal file
351
freeldr/bootsect/BTSECT32.ASM
Normal 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
|
2
freeldr/bootsect/MAKE.BAT
Normal file
2
freeldr/bootsect/MAKE.BAT
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
nasm -o bootsect.bin -f bin bootsect.asm
|
||||||
|
nasm -o btsect32.bin -f bin btsect32.asm
|
35
freeldr/bootsect/bootsect.h
Normal file
35
freeldr/bootsect/bootsect.h
Normal 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
|
||||||
|
};
|
67
freeldr/bootsect/btsect32.h
Normal file
67
freeldr/bootsect/btsect32.h
Normal 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
49
freeldr/bootsect/c_data.c
Normal 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;
|
||||||
|
}
|
1
freeldr/bootsect/install.bat
Normal file
1
freeldr/bootsect/install.bat
Normal file
|
@ -0,0 +1 @@
|
||||||
|
debug bootsect.bin < install.src
|
2
freeldr/bootsect/install.src
Normal file
2
freeldr/bootsect/install.src
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
w 100 0 0 1
|
||||||
|
q
|
197
freeldr/bootsect/win2k-12.asm
Normal file
197
freeldr/bootsect/win2k-12.asm
Normal 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
174
freeldr/bootsect/win2k.asm
Normal 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
7
freeldr/build.bat
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
cd bootsect
|
||||||
|
call make.bat
|
||||||
|
cd..
|
||||||
|
cd freeldr
|
||||||
|
make
|
||||||
|
copy freeldr.sys ..
|
||||||
|
cd ..
|
89
freeldr/freeldr/Makefile
Normal file
89
freeldr/freeldr/Makefile
Normal 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
1177
freeldr/freeldr/asmcode.S
Normal file
File diff suppressed because it is too large
Load diff
57
freeldr/freeldr/asmcode.h
Normal file
57
freeldr/freeldr/asmcode.h
Normal 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
45
freeldr/freeldr/boot.S
Normal 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
734
freeldr/freeldr/freeldr.c
Normal 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
82
freeldr/freeldr/freeldr.h
Normal 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
426
freeldr/freeldr/fs.c
Normal 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
182
freeldr/freeldr/fs.h
Normal 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
541
freeldr/freeldr/fs_fat.c
Normal 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
101
freeldr/freeldr/linux.c
Normal 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
27
freeldr/freeldr/linux.h
Normal 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
190
freeldr/freeldr/menu.c
Normal 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
27
freeldr/freeldr/menu.h
Normal 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
229
freeldr/freeldr/miscboot.c
Normal 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();
|
||||||
|
}
|
29
freeldr/freeldr/miscboot.h
Normal file
29
freeldr/freeldr/miscboot.h
Normal 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
395
freeldr/freeldr/options.c
Normal 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
31
freeldr/freeldr/options.h
Normal 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
593
freeldr/freeldr/pe.h
Normal 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
374
freeldr/freeldr/ros.S
Normal 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
390
freeldr/freeldr/rosboot.c
Normal 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
75
freeldr/freeldr/rosboot.h
Normal 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
306
freeldr/freeldr/stdlib.c
Normal 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
74
freeldr/freeldr/stdlib.h
Normal 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
572
freeldr/freeldr/tui.c
Normal 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
162
freeldr/freeldr/tui.h
Normal 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
5
freeldr/install.bat
Normal 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
18
freeldr/notes.txt
Normal 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
|
Loading…
Reference in a new issue