GRUB 0.5 release

This commit is contained in:
gord 1999-02-22 03:06:28 +00:00
parent ae8a5f8069
commit 6239c1ac50
28 changed files with 7484 additions and 0 deletions

14
Makefile.end Normal file
View file

@ -0,0 +1,14 @@
#
# GRUB Makefile ending stub, to be automatically added to the end of the
# part created by configure.
#
PROGS= stage1 ffs_stage1_5 stage2 stage2_debug
all:
@for X in $(PROGS) ; do (cd $$X ; $(MAKE)) ; done
clean:
@for X in $(PROGS) ; do (cd $$X ; $(MAKE) clean) ; done
rm -f config.log

69
README Normal file
View file

@ -0,0 +1,69 @@
GRUB -- GRand Unified Boot-loader
version 0.5
by Erich Boleyn <erich@uruk.org>
Introduction
This is the public release of GRUB version 0.5, a bootloader for
PC-compatible machines.
Installation
Precompiled versions are included in the "bin" directory:
bin/
stage1 This is the 512-byte stage1 which reads
in the rest of GRUB at boot-time.
ffs_stage1_5 This is an example for how to build a
"stage 1.5" to automatically load a stage2
from the filesystem.
stage2 This is the main part of GRUB.
stage2_debug Same as "stage2", but compiled with the
debug features enabled.
Instructions for installing can be found in "docs/install.html".
Building From Source
To build GRUB from source, first run the bourne-shell script "configure"
(options can be found by running "./configure --help"). It will complain
of missing or bad tools determined by it's tests. If it completes
successfully, then just type "make".
Note that the binary names correspond to subdirectories in the top level
of the distribution. See the makefiles in there for details on where
the source files are drawn from, but in general, the "stage1" only uses
the "stage1.S" file, and the others use source files from the "shared_src"
subdirectory.
IMPORTANT SIZE LIMITS:
- For the various stage2's, if they are being loaded from a block-list
in the stage1, then be sure your blocklist is big enough. The
automated install will generally do this for you, it's just when
dropping it on a raw floppy, you get the default compiled in, which
is 512 * 80 disk sectors, or 40960 bytes.
- For the FFS stage1.5, if you want to fit into the "bootloader" area
of an FFS partition, it cannot be larger than 512 * 14 disk sectors,
or 7168 bytes.
Other Documentation
Pretty much all of the documentation and other helpful information is
in the "docs" directory mostly as HTML files, the root of which is
"index.html".
The FAQ and Installation instructions really need to be updated and
improved!
The TODO and NEWS files are always up-to-date.

379
configure vendored Normal file
View file

@ -0,0 +1,379 @@
#!/bin/sh
#
# My mini-configure, used only for:
#
# (1) Setting compiler tool names
# (2) Determining assembly-level munging of C symbols
# (3) Setting defines for the makefiles in a simple manner
#
# Tried to be somewhat compatible with the autoconf configure.
# I hope this doesn't confuse people.
#
# In a subsequent release, I'll probably integrate these tests into
# autoconf and just use that.
#
#
# Starting definitions for variables
target=
silent=no
tool_vars="CC LD OBJCOPY"
tool_names="gcc ld objcopy"
tool_targeted="yes yes yes"
link_addrs="8000 2000 7C00"
path_parts=`echo ${PATH} | sed -e s/:/\ /g`
#
# This part is very much taken from autoconf-2.10
#
# Checking for options
#
ac_prev=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
ac_prev=
continue
fi
case "$ac_option" in
-*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) ac_optarg= ;;
esac
# Accept the important Cygnus configure options, so we can diagnose typos.
case "$ac_option" in
-help | --help | --hel | --he)
cat << EOF
Usage: configure [options] [target]
General Options:
--help print this message
--quiet, --silent do not print \`checking...' messages
--version print the fact that this isn't autoconf ;-)
Target Options:
--target=TARGET use \`TARGET' as a prefix to all of the tool names
EOF
exit 0 ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target="$ac_optarg" ;;
-version | --version | --versio | --versi | --vers)
echo "mini-configure written by Erich Boleyn with parts from autoconf-2.10"
exit 0 ;;
*)
echo "Warning: unrecognized configure option: \"$ac_option\"" ;;
esac
done
#
# Utility functions
#
get_substr()
{
local get_local
get_local=$(($2+2))
eval $1=\$$get_local
}
count_substrs()
{
local count_local
eval $1=-1
for count_local in $@ ; do
eval $1=\$\(\(\$$1+1\)\)
done
}
tool_failed()
{
cat << EOF >> ../config.log
Tool \`$@' either failed tests or cannot be found.
EOF
cat << EOF
FATAL ERROR in configuration !!
Tool \`$@' either failed tests or cannot be found. Please make sure
that some standard local compiler, \`grep', \`sed', GNU \`gcc', and
the complete GNU binutils version 2.8.1 or beyond are installed. The first
2 are used for automatic configuration, and the rest are required for
building GRUB. The file \`config.log' contains the debugging output of
this run, and the subdirectory \`.conf_test_dir' contains the files and
programs produced.
EOF
exit 0
}
check_exit_status()
{
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "Command failed with exit status $exit_status" >> ../config.log
tool_failed $@
fi
}
findtool()
{
local tool pathstr fail
echo -n "Looking for tool \`$1' ... " >> ../config.log
tool=
case "$1" in
/*)
if [ ! -e "$1" ]; then
tool_failed $1
fi
tool=$1
;;
*)
for pathstr in $path_parts ; do
if [ -e "$pathstr/$1" ]; then
tool="$pathstr/$1"
fi
done
if [ "$tool" = "" ]; then
tool_failed $1
fi
;;
esac
echo "found as \`$tool'" >> ../config.log
}
find_symbol_munge()
{
local munge_local i tmpvar
munge_local=`grep \.globl $2 | grep $1`
count_substrs i $munge_local
if [ $i -ne 2 ]; then
tool_failed ${CC}
fi
munge_local=`echo $munge_local | sed -e s/\\.globl// | sed -e s/$1/\ x\ /`
count_substrs i $munge_local
get_substr tmpvar 1 $munge_local
eval munge_$1=$tmpvar
if [ $i -eq 2 ]; then
get_substr tmpvar 2 $munge_local
eval munge_$1="\"\$munge_$1 \\#\\# $tmpvar\""
fi
if [ $i -eq 3 ]; then
get_substr tmpvar 3 $munge_local
eval munge_$1="\"\$munge_$1 \\#\\# $tmpvar\""
fi
}
# Cleanup from previous incomplete tests
if [ -d .conf_test_dir ]; then
rm -rf .conf_test_dir
fi
# Clear configuration log
if [ -e config.log ]; then
rm -rf config.log
fi
mkdir .conf_test_dir
cd .conf_test_dir
#
# Find tools
#
if [ "$silent" != "yes" ]; then
echo -n "checking for build tools... "
fi
# Initialize numbering
i=0
for tool_var in $tool_vars ; do
i=$(($i+1))
get_substr tool_name $i ${tool_names}
eval tmpvar=\$\{$tool_var\}
if [ "$tmpvar" = "" ]; then
get_substr tmpvar $i ${tool_targeted}
if [ "$target" != "" -a "$tmpvar" = "yes" ]; then
tool_name=$target$tool_name
fi
eval export $tool_var=$tool_name
fi
eval findtool \$\{$tool_var\}
if [ "$silent" != "yes" ]; then
echo -n "$tool_var "
fi
done
if [ "$silent" != "yes" ]; then
echo
fi
#
# Create test C source file to determine how symbols are munged
#
if [ "$silent" != "yes" ]; then
echo -n "checking C symbol munging in output of ${CC} ... "
fi
cat << EOF > test_sym.c
int
func1(int *list)
{
list[1] = 0;
return list[0];
}
double
func2(double a, int *list)
{
list[0] = ((int) a) + list[1];
return a;
}
EOF
echo "Compiling test_sym.c to assembly with ${CC}" >> ../config.log
${CC} -S test_sym.c >> ../config.log 2>&1
check_exit_status ${CC}
# Perform actual test(s) here
find_symbol_munge func1 test_sym.s
find_symbol_munge func2 test_sym.s
# if they are not equal, this simple compiling scheme will fail!
echo "C symbol amalgam macros (using \"x\" as base, and must match):" >> ../config.log
echo " \"$munge_func1\" and \"$munge_func2\"" >> ../config.log
if [ "$munge_func1" != "$munge_func2" ]; then
tool_failed ${CC}
fi
if [ "$silent" != "yes" ]; then
echo done
fi
#
# Create test C source file to determine if our version of objcopy
# is buggy
#
if [ "$silent" != "yes" ]; then
echo -n "checking to see if ${OBJCOPY} is buggy... "
fi
cat << EOF > test_objcopy.c
void
blah(void)
{
*((int *) 1000) = 2;
}
EOF
echo "Compiling test_objcopy.c with ${CC}" >> ../config.log
${CC} -nostdinc -c test_objcopy.c >> ../config.log 2>&1
check_exit_status ${CC}
# Perform actual test(s) here
for link_addr in $link_addrs ; do
echo "Linking test_objcopy.o with ${LD} at $link_addr" >> ../config.log
${LD} -N -Ttext $link_addr test_objcopy.o -o test_objcopy >> ../config.log 2>&1
check_exit_status ${LD}
${OBJCOPY} -O binary test_objcopy testout >> ../config.log 2>&1
check_exit_status ${OBJCOPY}
if [ -r testout.old ]; then
cmp testout testout.old >> ../config.log 2>&1
check_exit_status ${OBJCOPY}
fi
mv testout testout.old
done
if [ "$silent" != "yes" ]; then
echo done
fi
#
# Write out results
#
cd ..
if [ ! -d bin ]; then
mkdir bin
fi
#
# Write config file
#
if [ "$silent" != "yes" ]; then
echo -n "creating \`Makefile'... "
fi
cat << EOF > Makefile
#
# This stub \`Makefile' was created automatically by configure.
# (BEGINNING OF AUTOMATICALLY GENERATED PORTION)
EOF
for tool_var in $tool_vars ; do
eval echo \"export $tool_var = \$\{$tool_var\}\" >> Makefile
done
cat << EOF >> Makefile
export SHARED_FLAGS = -pipe -fno-builtin -nostdinc -O2 -DEXT_C\(x\)="$munge_func1"
# (END OF AUTOMATICALLY GENERATED PORTION)
#
EOF
cat Makefile.end >> Makefile
if [ "$silent" != "yes" ]; then
echo done
fi
#
# Delete test directory
#
rm -rf .conf_test_dir

31
docs/BUGS Normal file
View file

@ -0,0 +1,31 @@
Known problems/bugs:
- FreeBSD boot command-line options are slightly problematic, and
OpenBSD options are probably quite wrong. This is because they
use options that are bits in a data word passed at boot time, and
the developers change the encoding sometimes. Will re-sync in a later
release.
- Password feature in the config file is a bit primitive, and needs
fleshing out/design work to make more intuitive.
- If an "uppermem=" command was used to tell GRUB it had a different
amount of upper memory available, then the user escapes to the menu
interface, the upper memory displayed there still says the amount
set by the user instead of being reset to the default by the escape.
It actually resets when the next command-line is entered or config
file entry is executed.
- There is at least one problem when using an "install_partition" that is
a BSD sub-partition where the PC partition isn't explicit (i.e.
the default 0xFF00FF is a problem)... this is when using "makeactive"
without explicitly setting the root partition. If this is done, a
"no such partition" error will be generated.
- Cannot boot FreeBSD "kzip"ed image. Use a normal kernel (using GRUB's
automatic "gzip" decompression works fine).
- Hitting Ctrl-Alt-Delete when in GRUB locks some machines. Use Reset
for now. (This apparently hasn't been observed for a while)

339
docs/COPYING Normal file
View file

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

213
docs/NEWS Normal file
View file

@ -0,0 +1,213 @@
Version 0.5:
- Improved error messages in the stage1 to be strings (easier
to read than the previous case of single characters), and
removed any display in the case of no error (less confusing).
- New document describing error conditions and messages.
- Improved configure/build process.
- Made the early bootup interrupt-safe. Wasn't doing cli/sti when
necessary sometimes.
- It now shuts off the floppy before transferring control to any other
programs/modules/loaders. (chain-loading doesn't matter here,
just loading 32-bit modules/kernels)
- Fixed a few stupid bugs, including a several in the ext2fs code.
- Linux boot format support extended from just "zImage" to include
"bzImage" and initial ramdisk (also called "initrd") support for
both. "initrd" support is untested, but the critical parts were
taken from a supplied patch and seem OK.
- Several new command features. See the command-listing for details.
Version 0.4:
- GRUB now correctly points ES:SI at a partition descriptor when
chain-loading.
- Many minor bugs fixed (some in the build scripts).
- Intel MPS 1.4 config/check code is totally new, and the "syscmd="
command is completely removed. Check command-listing for details.
Version 0.4-pre -- (pre-release for public testing):
- Reorganized docs, moved most "NOTE" items to a FAQ (with new
entries as well).
- Now supports automatic decompression of any files loaded via the
GRUB stage2 filesystem code. Simply compress the file using GNU
gzip normally, then when loading, the GRUB internals will see the
contents in the decompressed state... i.e. all GRUB functions operate
normally as if it is the uncompressed file. An extra version of the
"module" loading function has been added which disables this
functionality if desired (in all the other cases, not decompressing
doesn't make sense).
- Changed device strings used in filesystem code to more logical
format. Added "relative" disk and partition capability, see
command-listing and filesystem syntax description for details.
- "install=" command vastly improved. Also moved to non-debug area.
Check command-listing and install documentation for details.
- Added several new commands: "rootnoverify=", "uppermem=", and a
new debug command "displaymem". Check command-listing for details.
- Added versioning numbers (and subsequently broke compatibility with
some of the previous code, so GRUB should be re-installed!).
- Added unattended booting support via new "fallback=" command.
- During debug probe of SMP configuration table compatible with Intel
MPS 1.4 standard, GRUB now checks for a pointer in the EBDA.
- Using a "default=" entry greater than 11 caused the UI to do funny
things (it didn't pre-scroll the list to the appropriate place).
- Reading files on FAT floppies had yet more problems related by many
users of version 0.3 6/17/96. Again, all known problems fixed.
- "Extended" partitions now work (still cannot make an extended partition
active with "makeactive" command).
- The build environment is greatly simplified, now using an autoconf-like
"configure" script.
Version 0.3 dated 6/17/96 -- public "beta" release:
- Yet more documentation improvements.
- Known bugs in floppy operation fixed (12-bit FAT didn't work for most
cases, and inserting other floppies didn't flush the filesystem cache).
- NASTY uninitialized pointer bug causing "raw" floppy operation to crash
on several PCs is now fixed. This seems to have been the root cause of
all of the compatibility problems that have currently been observed.
- debug-mode command added to automate most difficult step of installation
for common cases (new install method #4).
- Testing "mini-debugger" now merged with command-line when "DEBUG"
defined in compile (no SYSDEBUG option anymore). See description of
commands in the command-line for details.
Version 0.3 dated 6/2/96 -- first public "alpha" release:
- Completed initial licenses.
- Initial filesystem documentation written.
- Block-list and FAT filesystems now work as documented (in particular,
for the blocklist filesystem, shortcuts like "+1" for "0+1,512" now
work correctly).
- Fixed several problems (old and new) in the various filesystems
(for example, the ext2fs filesystem code is now much faster, as it
caches some mapping blocks where it didn't at all before). Filesystem
semantics are much more uniform as well (symbolic links and reading
a directory as a file now return errors where it would silently fail
before).
- "makeactive" now works for standard PC partitions on hard disks (not
extended partitions... so any PC partition number above 3 will give
a "no such partition" error). If a BSD sub-partition is is used, it
will ignore it, and only use the primary PC partition number.
Version 0.3 dated 5/20/96:
- Updated instructions (though still very sparse).
- New floppy probe (works much like the Linux floppy boot probe) attempts
to find the size of a floppy in a drive. Might still need work! Please
try on various floppy drives with various media!
- New floppy handler will claim a non-existent drive if the floppy disk
isn't present in the drive. (for example, it won't be on the list of
installed drives unless a floppy is present)
- Stage1 now compatible with both a hard disk MBR and the DOS BIOS
parameter block (see "install/README" for more details on how this can
be used).
- Block-list filesystem partially works, as described in the file "NOTES".
Loading an a.out or elf kernel won't work with it, but all other filetypes
pretty much should. (certainly chain-loading works OK) NOTE:
you must use the full format "0+1,512" for just he first block... no
parameters can be implicit in this version.. THis is being fixed too.
- Linux ext2 filesystem works. (it's very slow for big files, but this
is being fixed)
- Linux boot type now supported. Use a standard piggybacked image as
with LILO. Put in hack to support >64MB via GRUB placing the RAM size
as the first item on the command-line automatically. Must pass root
partition on command-line using normal Linux syntax... if not, it uses
it's builtin root partition.
- Supports chain-loading. For details, see "COMMANDS" and the examples
directory. (was able to boot DOS and Windows NT on my test box). NOTE
that the "root partition" must be set to work right. "makeactive"
is currently a no-op.
- Several weird bugs fixed. One important note: If you recompile,
it will warn about a clash with builtin "strcmp". This is normal...
do NOT remove the strcmp definition, as then GCC will possibly put
inline code from it's own builtin function in some places. (my strcmp
has slightly different functionality, hence the problem)
- Mini-debugger is currently broken.
Version 0.2 dated 4/12/96:
- Completely new menu-based UI. See "COMMANDS" and the examples
directory for details. NOTE that the argument to a command must
be preceded by a space between it and the '=', in both the config
file and the command-line. This will be fixed.
Version 0.1 dated 3/31/96 (lots of changes):
- Newer version of Multiboot Standard (version 0.6) supported.
- Autodetects kernel types. Supports Multiboot, FreeBSD, NetBSD (Linux
isn't finished).
- Stage 1.5 works now. Default setup is now for working with a BSD FFS
floppy loading "/grub/stage2" as the main bootloader.
- Filesystem support improved. It didn't work on many floppies
before (problem with the partition-detection code).
- Memory probe now supports arbitrary amounts of RAM (some technical
limitations exist, see Multiboot standard version 0.6 for details).
- A mini-debugger is included by default, activated by hitting '~'
on the command-line (it might interfere with things, but it
seems OK for my alpha-testing). The commands are in the function
"enter_sysdebug" defined in "common.c". If you have an Intel MPS-
compatible machine, there are extra commands enabled for SMP cpu
testing. 'q' exits and goes back to what you were doing before.
Version 0.0 dated 2/6/96:
- Newer version of Multiboot Standard (version 0.4) supported.
Version 0.0 dated 12/10/95:
- You can now perform TAB-based completion listing of any valid
partially completed disk/partition/file-name combination. Try it
out to see what you like, examples are in the NOTES file under
"Device completion".
- Fixed a bug causing the memory size routine to sometimes report
rediculous values.
- Fixed some documentation (what little there is :-/ and a few assembly
bugs in the BIOS access routines that nobody reported yet, so I won't
detail it here.

2417
docs/PC_partitioning.txt Normal file

File diff suppressed because it is too large Load diff

21
docs/TODO Normal file
View file

@ -0,0 +1,21 @@
Check for other patches sent in e-mail!!! There are several...
Add support/delays so that a floppy can be installed from
another floppy.
Add bootable CDROM support (this probably means I have to support
ISO-9660 plus maybe even the Rock Ridge extensions... ugh).
Add/Finish LBA and/or Int13 extensions support.
Fix keyboard/gateA20 bug (???? at least look at the code).
The keyboard status bits may be checked wrong.
Add indirect block support to the BSD FFS filesystem code, so files
larger than 16MB can be read.
??? Make symbolic links work for BSD FFS and Linux ext2fs filesystems.
??? Add command for modifying partition types.
Fix-up FreeBSD, NetBSD (and OpenBSD ?) command-line boot parameters

68
docs/bios_mapping.txt Normal file
View file

@ -0,0 +1,68 @@
BIOS Device Mapping Techniques
NOTE: This is only necessary to do for hard disks. Floppies are
already easy to determine. (IDE are in the order of "Master from
controller on INT 14, Slave from controller on INT 14, Master from
controller on INT 15, and Slave from controller on INT 15, and
always come before SCSI)
Both of these techniques should be usable from any PC OS, and neither
require any special support in the drivers themselves. This document
will be flushed out into detailed explanations, particularly for #2
below.
The general rule is that technique #1 is the quick and dirty solution.
It works most of the time, but doesn't cover all the bases, and is
relatively simple.
Technique #2 is much more complex, but it has potential to solve the
problem under all conditions, plus allow access of the remaining
BIOS devices when not all of them have OS drivers.
-- BIOS device mapping technique #1 --
Before activating ANY of the device drivers, gather enough data
from similar sectors on each of the disks such that each one can be
uniquely identified.
After activating the device drivers, compare data from the drives
using the OS drivers. This should hopefully be sufficient to provide
such a mapping.
Problems: (1) The data on some BIOS devices might be identical (so
the part reading the drives from the BIOS should have some mechanism
to give up), and (2) There might be extra drives not accessible from
the BIOS which are identical to some drive used by the BIOS (so it
should be capable of giving up there as well).
-- BIOS device mapping technique #2 --
This first step may be unnecessary, but first create copy-on-write
mappings for the device drivers writing into PC RAM. Keep the original
copies for the "clean BIOS virtual machine" to be created later.
For each device driver brought online, determine which BIOS devices
become inaccessible by:
-- Creating a "clean BIOS virtual machine".
-- Set the I/O permission map for the I/O area claimed by the device driver
to no permissions (neither read nor write).
-- Access each device.
-- Record which devices succed, and those which try to access the
"restricted" I/O areas (hopefully, this will be an "xor" situation).
For each device driver, given how many of the BIOS devices were subsumed
by it (there should be no gaps in this list), it should be easy to
determine which devices on the controller these are.
In general, you have at most 2 disks from each controller given BIOS numbers,
but they pretty much always count from the lowest logically numbered devices
on the controller.

664
docs/boot-proposal.html Normal file
View file

@ -0,0 +1,664 @@
<HTML>
<HEAD>
<TITLE>Multiboot Standard</TITLE>
</HEAD>
<BODY>
<CENTER><H1>Multiboot Standard</H1></CENTER>
<CENTER><H3>Version 0.6</H3></CENTER>
<HR>
<H2>Contents</H2>
<UL>
<LI> <A HREF="#motivation">Motivation</A>
<LI> <A HREF="#terminology">Terminology</A>
<LI> <A HREF="#scope">Scope and Requirements</A>
<LI> <A HREF="#details">Details</A>
<LI> <A HREF="#author">Authors</A>
<LI> <B>NOTE: The following items are not part of the standards document,
but are included for prospective OS and bootloader writers.</B>
<LI> <A HREF="#notes">Notes on PCs</A>
<LI> <A HREF="#example_os">Example OS Code</A>
<LI> <A HREF="#example_boot">Example Bootloader Code</A>
</UL>
<HR>
<H2><A NAME="motivation">Motivation</A></H2>
Every OS ever created tends to have its own boot loader. Installing a new
OS on a machine generally involves installing a whole new set of boot
mechanisms, each with completely different install-time and boot-time user
interfaces. Getting multiple operating systems to coexist reliably on one
machine through typical "chaining" mechanisms can be a nightmare. There is
little or no choice of boot loaders for a particular operating system - if
the one that comes with the OS doesn't do exactly what you want, or doesn't
work on your machine, you're screwed.<P>
While we may not be able to fix this problem in existing commercial
operating systems, it shouldn't be too difficult for a few people in the
free OS communities to put their heads together and solve this problem for
the popular free operating systems. That's what this standard aims for.
Basically, it specifies an interface between a boot loader and a operating
system, such that any complying boot loader should be able to load any
complying operating system. This standard does NOT specify how boot
loaders should work - only how they must interface with the OS being
loaded.<P>
<HR>
<H2><A NAME="terminology">Terminology</A></H2>
Throughout this document, the term "boot loader" means whatever program or
set of programs loads the image of the final operating system to be run on
the machine. The boot loader may itself consist of several stages, but
that is an implementation detail not relevant to this standard. Only the
"final" stage of the boot loader - the stage that eventually transfers
control to the OS - needs to follow the rules specified in this document
in order to be "MultiBoot compliant"; earlier boot loader stages can be
designed in whatever way is most convenient.<P>
The term "OS image" is used to refer to the initial binary image that the
boot loader loads into memory and transfers control to to start the OS.
The OS image is typically an executable containing the OS kernel.<P>
The term "boot module" refers to other auxiliary files that the boot loader
loads into memory along with the OS image, but does not interpret in any
way other than passing their locations to the OS when it is invoked.<P>
<HR>
<H2><A NAME="scope">Scope and Requirements</A></H2>
<H3>Architectures</H3>
This standard is primarily targetted at PC's, since they are the most
common and have the largest variety of OS's and boot loaders. However, to
the extent that certain other architectures may need a boot standard and do
not have one already, a variation of this standard, stripped of the
x86-specific details, could be adopted for them as well.<P>
<H3>Operating systems</H3>
This standard is targetted toward free 32-bit operating systems that can be
fairly easily modified to support the standard without going through lots of
bureaucratic rigmarole. The particular free OS's that this standard is
being primarily designed for are Linux, FreeBSD, NetBSD, Mach, and VSTa.
It is hoped that other emerging free OS's will adopt it from the start, and
thus immediately be able to take advantage of existing boot loaders. It
would be nice if commercial operating system vendors eventually adopted
this standard as well, but that's probably a pipe dream.<P>
<H3>Boot sources</H3>
It should be possible to write compliant boot loaders that
load the OS image from a variety of sources, including floppy disk, hard
disk, and across a network.<P>
Disk-based boot loaders may use a variety of techniques to find the
relevant OS image and boot module data on disk, such as by interpretation
of specific file systems (e.g. the BSD/Mach boot loader), using
precalculated "block lists" (e.g. LILO), loading from a special "boot
partition" (e.g. OS/2), or even loading from within another operating
system (e.g. the VSTa boot code, which loads from DOS). Similarly,
network-based boot loaders could use a variety of network hardware and
protocols.<P>
It is hoped that boot loaders will be created that support multiple loading
mechanisms, increasing their portability, robustness, and
user-friendliness.<P>
<H3>Boot-time configuration</H3>
It is often necessary for one reason or another for the user to be able to
provide some configuration information to the OS dynamically at boot time.
While this standard should not dictate how this configuration information
is obtained by the boot loader, it should provide a standard means for the
boot loader to pass such information to the OS.<P>
<H3>Convenience to the OS</H3>
OS images should be easy to generate. Ideally, an OS image should simply
be an ordinary 32-bit executable file in whatever file format the OS
normally uses. It should be possible to 'nm' or disassemble OS images just
like normal executables. Specialized tools should not be needed to create
OS images in a "special" file format. If this means shifting some work
from the OS to the boot loader, that is probably appropriate, because all
the memory consumed by the boot loader will typically be made available
again after the boot process is created, whereas every bit of code in the
OS image typically has to remain in memory forever. The OS should not have
to worry about getting into 32-bit mode initially, because mode switching
code generally needs to be in the boot loader anyway in order to load OS
data above the 1MB boundary, and forcing the OS to do this makes creation
of OS images much more difficult.<P>
Unfortunately, there is a horrendous variety of executable file formats
even among free Unix-like PC-based OS's - generally a different format for
each OS. Most of the relevant free OS's use some variant of a.out format,
but some are moving to ELF. It is highly desirable for boot loaders not to
have to be able to interpret all the different types of executable file
formats in existence in order to load the OS image - otherwise the boot
loader effectively becomes OS-specific again.<P>
This standard adopts a compromise solution to this problem.
MultiBoot compliant boot images always either (a) are in ELF format, or (b)
contain a "magic MultiBoot header", described below, which allows the boot
loader to load the image without having to understand numerous a.out
variants or other executable formats. This magic header does not need
to be at the very beginning of the executable file, so kernel images can
still conform to the local a.out format variant in addition to being
MultiBoot compliant.<P>
<H3>Boot modules</H3>
Many modern operating system kernels, such as those of VSTa and Mach, do
not by themselves contain enough mechanism to get the system fully
operational: they require the presence of additional software modules at
boot time in order to access devices, mount file systems, etc. While these
additional modules could be embedded in the main OS image along with the
kernel itself, and the resulting image be split apart manually by the OS
when it receives control, it is often more flexible, more space-efficient,
and more convenient to the OS and user if the boot loader can load these
additional modules independently in the first place.<P>
Thus, this standard should provide a standard method for a boot loader to
indicate to the OS what auxiliary boot modules were loaded, and where they
can be found. Boot loaders don't have to support multiple boot modules,
but they are strongly encouraged to, because some OS's will be unable to
boot without them.<P>
<HR>
<H2><A NAME="details">Details</H2>
There are three main aspects of the boot-loader/OS image interface this
standard must specify:<P>
<UL>
<LI>The format of the OS image as seen by the boot loader.
<LI>The state of the machine when the boot loader starts the OS.
<LI>The format of the information passed by the boot loader to the OS.
</UL>
<H3>OS Image Format</H3>
An OS image is generally just an ordinary 32-bit executable file in the
standard format for that particular OS, except that it may be linked at a
non-default load address to avoid loading on top of the PC's I/O region
or other reserved areas, and of course it can't use shared libraries or
other fancy features. Initially, only images in a.out format are
supported; ELF support will probably later be specified in the standard.<P>
Unfortunately, the exact meaning of the text, data, bss, and entry fields
of a.out headers tends to vary widely between different executable flavors,
and it is sometimes very difficult to distinguish one flavor from another
(e.g. Linux ZMAGIC executables and Mach ZMAGIC executables). Furthermore,
there is no simple, reliable way of determining at what address in memory
the text segment is supposed to start. Therefore, this standard requires
that an additional header, known as a 'multiboot_header', appear somewhere
near the beginning of the executable file. In general it should come "as
early as possible", and is typically embedded in the beginning of the text
segment after the "real" executable header. It _must_ be contained
completely within the first 8192 bytes of the executable file, and must be
longword (32-bit) aligned. These rules allow the boot loader to find and
synchronize with the text segment in the a.out file without knowing
beforehand the details of the a.out variant. The layout of the header is
as follows:<P>
<pre>
+-------------------+
0 | magic: 0x1BADB002 | (required)
4 | flags | (required)
8 | checksum | (required)
+-------------------+
8 | header_addr | (present if flags[16] is set)
12 | load_addr | (present if flags[16] is set)
16 | load_end_addr | (present if flags[16] is set)
20 | bss_end_addr | (present if flags[16] is set)
24 | entry_addr | (present if flags[16] is set)
+-------------------+
</pre>
All fields are in little-endian byte order, of course. The first field is
the magic number identifying the header, which must be the hex value
0x1BADB002.<P>
The flags field specifies features that the OS image requests or requires
of the boot loader. Bits 0-15 indicate requirements; if the boot loader
sees any of these bits set but doesn't understand the flag or can't fulfill
the requirements it indicates for some reason, it must notify the user and
fail to load the OS image. Bits 16-31 indicate optional features; if any
bits in this range are set but the boot loader doesn't understand them, it
can simply ignore them and proceed as usual. Naturally, all
as-yet-undefined bits in the flags word must be set to zero in OS
images. This way, the flags fields serves for version control as well as
simple feature selection.<P>
If bit 0 in the flags word is set, then all boot modules loaded along with
the OS must be aligned on page (4KB) boundaries. Some OS's expect to be
able to map the pages containing boot modules directly into a paged address
space during startup, and thus need the boot modules to be page-aligned.<P>
If bit 1 in the flags word is set, then information on available memory
via at least the 'mem_*' fields of the multiboot_info structure defined
below must be included. If the bootloader is capable of passing a memory
map (the 'mmap_*' fields) and one exists, then it must be included as
well.<P>
If bit 16 in the flags word is set, then the fields at offsets 8-24 in the
multiboot_header are valid, and the boot loader should use them instead of
the fields in the actual executable header to calculate where to load the
OS image. This information does not need to be provided if the kernel
image is in ELF format, but it should be provided if the images is in a.out
format or in some other format. Compliant boot loaders must be able to
load images that either are in ELF format or contain the load address
information embedded in the multiboot_header; they may also directly
support other executable formats, such as particular a.out variants, but
are not required to.<P>
All of the address fields enabled by flag bit 16 are physical addresses.
The meaning of each is as follows:<P>
<UL>
<LI><B>header_addr</B> -- Contains the address corresponding to the
beginning of the multiboot_header - the physical memory location at which
the magic value is supposed to be loaded. This field serves to "synchronize"
the mapping between OS image offsets and physical memory addresses.
<LI><B>load_addr</B> -- Contains the physical address of the beginning
of the text segment. The offset in the OS image file at which to start
loading is defined by the offset at which the header was found, minus
(header_addr - load_addr). load_addr must be less than or equal to
header_addr.
<LI><B>load_end_addr</B> -- Contains the physical address of the end of the
data segment. (load_end_addr - load_addr) specifies how much data to load.
This implies that the text and data segments must be consecutive in the
OS image; this is true for existing a.out executable formats.
<LI><B>bss_end_addr</B> -- Contains the physical address of the end of
the bss segment. The boot loader initializes this area to zero, and
reserves the memory it occupies to avoid placing boot modules and other
data relevant to the OS in that area.
<LI><B>entry</B> -- The physical address to which the boot loader should
jump in order to start running the OS.
</UL>
The checksum is a 32-bit unsigned value which, when added to
the other required fields, must have a 32-bit unsigned sum of zero.<P>
<H3>Machine State</H3>
When the boot loader invokes the 32-bit operating system,
the machine must have the following state:<P>
<UL>
<LI>CS must be a 32-bit read/execute code segment with an offset of 0
and a limit of 0xffffffff.
<LI>DS, ES, FS, GS, and SS must be a 32-bit read/write data segment with
an offset of 0 and a limit of 0xffffffff.
<LI>The address 20 line must be usable for standard linear 32-bit
addressing of memory (in standard PC hardware, it is wired to
0 at bootup, forcing addresses in the 1-2 MB range to be mapped to the
0-1 MB range, 3-4 is mapped to 2-3, etc.).
<LI>Paging must be turned off.
<LI>The processor interrupt flag must be turned off.
<LI>EAX must contain the magic value 0x2BADB002; the presence of this value
indicates to the OS that it was loaded by a MultiBoot-compliant boot
loader (e.g. as opposed to another type of boot loader that the OS can
also be loaded from).
<LI>EBX must contain the 32-bit physical address of the multiboot_info
structure provided by the boot loader (see below).
</UL>
All other processor registers and flag bits are undefined. This includes,
in particular:<P>
<UL>
<LI>ESP: the 32-bit OS must create its own stack as soon as it needs one.
<LI>GDTR: Even though the segment registers are set up as described above,
the GDTR may be invalid, so the OS must not load any segment registers
(even just reloading the same values!) until it sets up its own GDT.
<LI>IDTR: The OS must leave interrupts disabled until it sets up its own IDT.
</UL>
However, other machine state should be left by the boot loader in "normal
working order", i.e. as initialized by the BIOS (or DOS, if that's what
the boot loader runs from). In other words, the OS should be able to make
BIOS calls and such after being loaded, as long as it does not overwrite
the BIOS data structures before doing so. Also, the boot loader must leave
the PIC programmed with the normal BIOS/DOS values, even if it changed them
during the switch to 32-bit mode.<P>
<H3>Boot Information Format</H3>
Upon entry to the OS, the EBX register contains the physical address of
a 'multiboot_info' data structure, through which the boot loader
communicates vital information to the OS. The OS can use or ignore any
parts of the structure as it chooses; all information passed by the boot
loader is advisory only.<P>
The multiboot_info structure and its related substructures may be placed
anywhere in memory by the boot loader (with the exception of the memory
reserved for the kernel and boot modules, of course). It is the OS's
responsibility to avoid overwriting this memory until it is done using it.<P>
The format of the multiboot_info structure (as defined so far) follows:<P>
<pre>
+-------------------+
0 | flags | (required)
+-------------------+
4 | mem_lower | (present if flags[0] is set)
8 | mem_upper | (present if flags[0] is set)
+-------------------+
12 | boot_device | (present if flags[1] is set)
+-------------------+
16 | cmdline | (present if flags[2] is set)
+-------------------+
20 | mods_count | (present if flags[3] is set)
24 | mods_addr | (present if flags[3] is set)
+-------------------+
28 - 40 | syms | (present if flags[4] or flags[5] is set)
+-------------------+
44 | mmap_length | (present if flags[6] is set)
48 | mmap_addr | (present if flags[6] is set)
+-------------------+
</pre>
The first longword indicates the presence and validity of other fields in
the multiboot_info structure. All as-yet-undefined bits must be set to
zero by the boot loader. Any set bits that the OS does not understand
should be ignored. Thus, the flags field also functions as a version
indicator, allowing the multiboot_info structure to be expanded in the
future without breaking anything.<P>
If bit 0 in the multiboot_info.flags word is set, then the 'mem_*' fields
are valid. 'mem_lower' and 'mem_upper' indicate the amount of lower and upper
memory, respectively, in kilobytes. Lower memory starts at address 0, and
upper memory starts at address 1 megabyte. The maximum possible
value for lower memory is 640 kilobytes. The value returned for upper
memory is maximally the address of the first upper memory hole minus
1 megabyte. It is not guaranteed to be this value.<P>
If bit 1 in the multiboot_info.flags word is set, then the 'boot_device'
field is valid, and indicates which BIOS disk device the boot loader loaded
the OS from. If the OS was not loaded from a BIOS disk, then this field
must not be present (bit 3 must be clear). The OS may use this field as a
hint for determining its own "root" device, but is not required to. The
boot_device field is layed out in four one-byte subfields as follows:<P>
<pre>
+-------+-------+-------+-------+
| drive | part1 | part2 | part3 |
+-------+-------+-------+-------+
</pre>
The first byte contains the BIOS drive number as understood by the BIOS
INT 0x13 low-level disk interface: e.g. 0x00 for the first floppy disk or
0x80 for the first hard disk.<P>
The three remaining bytes specify the boot partition. 'part1' specifies
the "top-level" partition number, 'part2' specifies a "sub-partition" in
the top-level partition, etc. Partition numbers always start from zero.
Unused partition bytes must be set to 0xFF. For example, if the disk is
partitioned using a simple one-level DOS partitioning scheme, then 'part1'
contains the DOS partition number, and 'part2' and 'part3' are both zero.
As another example, if a disk is partitioned first into DOS partitions, and
then one of those DOS partitions is subdivided into several BSD partitions
using BSD's "disklabel" strategy, then 'part1' contains the DOS partition
number, 'part2' contains the BSD sub-partition within that DOS partition,
and 'part3' is 0xFF.<P>
DOS extended partitions are indicated as partition numbers starting from 4
and increasing, rather than as nested sub-partitions, even though the
underlying disk layout of extended partitions is hierarchical in nature.
For example, if the boot loader boots from the second extended partition
on a disk partitioned in conventional DOS style, then 'part1' will be 5,
and 'part2' and 'part3' will both be 0xFF.<P>
If bit 2 of the flags longword is set, the 'cmdline' field is valid, and
contains the physical address of the the command line to be passed to the
kernel. The command line is a normal C-style null-terminated string.<P>
If bit 3 of the flags is set, then the 'mods' fields indicate to the kernel
what boot modules were loaded along with the kernel image, and where they
can be found. 'mods_count' contains the number of modules loaded;
'mods_addr' contains the physical address of the first module structure.
'mods_count' may be zero, indicating no boot modules were loaded, even if
bit 1 of 'flags' is set. Each module structure is formatted as follows:<P>
<pre>
+-------------------+
0 | mod_start |
4 | mod_end |
+-------------------+
8 | string |
+-------------------+
12 | reserved (0) |
+-------------------+
</pre>
The first two fields contain the start and end addresses of the boot module
itself. The 'string' field provides an arbitrary string to be associated
with that particular boot module; it is a null-terminated ASCII string,
just like the kernel command line. The 'string' field may be 0 if there is
no string associated with the module. Typically the string might be a
command line (e.g. if the OS treats boot modules as executable programs),
or a pathname (e.g. if the OS treats boot modules as files in a file
system), but its exact use is specific to the OS. The 'reserved' field
must be set to 0 by the boot loader and ignored by the OS.<P>
NOTE: Bits 4 & 5 are mutually exclusive.<P>
If bit 4 in the multiboot_info.flags word is set, then the following
fields in the multiboot_info structure starting at byte 28 are valid:<P>
<pre>
+-------------------+
28 | tabsize |
32 | strsize |
36 | addr |
40 | reserved (0) |
+-------------------+
</pre>
These indicate where the symbol table from an a.out kernel image can be
found. 'addr' is the physical address of the size (4-byte unsigned
long) of an array of a.out-format 'nlist' structures, followed immediately
by the array itself, then the size (4-byte unsigned long) of a set of
null-terminated ASCII strings (plus sizeof(unsigned long) in this case),
and finally the set of strings itself. 'tabsize' is equal to it's size
parameter (found at the beginning of the symbol section), and 'strsize'
is equal to it's size parameter (found at the beginning of the string section)
of the following string table to which the symbol table refers. Note that
'tabsize' may be 0, indicating no symbols, even if bit 4 in the flags
word is set.<P>
If bit 5 in the multiboot_info.flags word is set, then the following
fields in the multiboot_info structure starting at byte 28 are valid:<P>
<pre>
+-------------------+
28 | num |
32 | size |
36 | addr |
40 | shndx |
+-------------------+
</pre>
These indicate where the section header table from an ELF kernel is, the
size of each entry, number of entries, and the string table used as the
index of names. They correspond to the 'shdr_*' entries ('shdr_num', etc.)
in the Executable and Linkable Format (ELF) specification in the program
header. All sections are loaded, and the physical address fields
of the elf section header then refer to where the sections are in memory
(refer to the i386 ELF documentation for details as to how to read the
section header(s)). Note that 'shdr_num' may be 0, indicating no symbols,
even if bit 5 in the flags word is set.<P>
If bit 6 in the multiboot_info.flags word is set, then the 'mmap_*' fields
are valid, and indicate the address and length of a buffer containing a
memory map of the machine provided by the BIOS. 'mmap_addr' is the address,
and 'mmap_length' is the total size of the buffer. The buffer consists of
one or more of the following size/structure pairs ('size' is really used
for skipping to the next pair):<P>
<pre>
+-------------------+
-4 | size |
+-------------------+
0 | BaseAddrLow |
4 | BaseAddrHigh |
8 | LengthLow |
12 | LengthHigh |
16 | Type |
+-------------------+
</pre>
where 'size' is the size of the associated structure in bytes, which can
be greater than the minimum of 20 bytes. 'BaseAddrLow' is the lower 32
bits of the starting address, and 'BaseAddrHigh' is the upper 32 bits,
for a total of a 64-bit starting address. 'LengthLow' is the lower 32 bits
of the size of the memory region in bytes, and 'LengthHigh' is the upper 32
bits, for a total of a 64-bit length. 'Type' is the variety of address
range represented, where a value of 1 indicates available RAM, and all
other values currently indicated a reserved area.<P>
The map provided is guaranteed to list all standard RAM that should
be available for normal use.<P>
<HR>
<H2><A NAME="author">Authors</A></H2>
<pre>
Bryan Ford
Computer Systems Laboratory
University of Utah
Salt Lake City, UT 84112
(801) 581-4280
baford@cs.utah.edu
Erich Stefan Boleyn
924 S.W. 16th Ave, #202
Portland, OR, USA 97205
(503) 226-0741
erich@uruk.org
</pre>
We would also like to thank the many other people have provided comments,
ideas, information, and other forms of support for our work.<P>
<H3>Revision History</H3>
<pre>
Version 0.6 3/29/96 (a few wording changes, header checksum, and
clarification of machine state passed to the OS)
Version 0.5 2/23/96 (name change)
Version 0.4 2/1/96 (major changes plus HTMLification)
Version 0.3 12/23/95
Version 0.2 10/22/95
Version 0.1 6/26/95
</pre>
<HR>
<H2><A NAME="notes">Notes on PCs</A></H2>
In reference to bit 0 of the multiboot_info.flags parameter,
if the bootloader
in question uses older BIOS interfaces, or the newest ones are not
available (see description about bit 6), then a maximum of either
15 or 63 megabytes of memory may be reported. It is HIGHLY recommended
that bootloaders perform a thorough memory probe.<P>
In reference to bit 1 of the multiboot_info.flags parameter, it is
recognized that determination of which BIOS drive maps to which
OS-level device-driver is non-trivial, at best. Many kludges have
been made to various OSes instead of solving this problem, most of
them breaking under many conditions. To encourage the use of
general-purpose solutions to this problem, here are 2
<A HREF=bios_mapping.txt>BIOS Device Mapping Techniques</A>.<P>
In reference to bit 6 of the multiboot_info.flags parameter, it is
important to note that the data structure used there
(starting with 'BaseAddrLow') is the data returned by the
<A HREF=mem64mb.html>INT 15h, AX=E820h
- Query System Address Map</A> call. More information
on reserved memory regions is defined on that web page.
The interface here is meant to allow a bootloader to
work unmodified with any reasonable extensions of the BIOS interface,
passing along any extra data to be interpreted by the OS as desired.<P>
<HR>
<H2><A NAME="example_os">Example OS Code</A> (from Bryan Ford)</H2>
EDITOR'S NOTE: These examples are relevant to the Proposal version 0.5,
which is basically identical except for the multiboot OS header, which was
missing the checksum. A patch to bring Mach4 UK22 up to version 0.6 is
available in the GRUB FTP area mentioned in the
<A HREF="#example_boot">Example Bootloader Code</A> section below.<P>
The Mach 4 distribution, available by anonymous FTP from
flux.cs.utah.edu:/flux, contains a C header file that defines the
MultiBoot data structures described above; anyone is welcome to rip it
out and use it for other boot loaders and OS's:<P>
<pre>
mach4-i386/include/mach/machine/multiboot.h
</pre>
This distribution also contains code implementing a "Linux boot adaptor",
which collects a MultiBoot-compliant OS image and an optional set of boot
modules, compresses them, and packages them into a single traditional Linux
boot image that can be loaded from LILO or other Linux boot loaders. There
is also a corresponding "BSD boot adaptor" which can be used to wrap a
MultiBoot kernel and set of modules and produce an image that can be loaded
from the FreeBSD and NetBSD boot loaders. All of this code can be used as-is
or as a basis for other boot loaders. These are the directories of primary
relevance:<P>
<pre>
mach4-i386/boot
mach4-i386/boot/bsd
mach4-i386/boot/linux
</pre>
The Mach kernel itself in this distribution contains code that demonstrates
how to create a compliant OS. The following files are of primary
relevance:<P>
<pre>
mach4-i386/kernel/i386at/boothdr.S
mach4-i386/kernel/i386at/model_dep.c
</pre>
Finally, I have created patches against the Linux 1.2.2 and FreeBSD 2.0
kernels, in order to make them compliant with this proposed standard.
These patches are available in kahlua.cs.utah.edu:/private/boot.<P>
<HR>
<H2><A NAME"example_boot">Example Bootloader Code</A> (from Erich Boleyn)</H2>
The <A HREF=http://www.uruk.org/grub/>GRUB</A> bootloader project
will be fully
Multiboot-compliant, supporting all required and optional
features present in this standard.<P>
A final release has not been made, but both the GRUB beta release
(which is quite stable) and a patch for Multiboot version 0.6 for
Mach4 UK22 are available in the GRUB
<A HREF=ftp://ftp.uruk.org/public/grub/>public release</A>
area.<P>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

228
docs/commands.txt Normal file
View file

@ -0,0 +1,228 @@
Listing of commands available in the configuration files, a subset of
which is usable on the command-line.
The interpretation of the config file represents a simple state-machine,
where:
(1) Config-file specific commands have to be used before any others.
(2) A multiboot kernel must be loaded before modules can be.
(3) A kernel must be loaded before either the config-file entry ends,
or any "boot" command is issued in any case.
Semantics are as follows:
-- The files *must* be in plain-text format!!
-- "#" at the beginning of a line means it is a comment line in a config
file only.
-- Options are separated by spaces.
-- All numbers can be either decimal or hexidecimal. A hexidecimal number
must be preceeded by "0x", and is case insensitive.
-- Extra options/text at the end of the line is ignored unless otherwise
specified.
-- Bad commands generally get included in the current entry being added
to, except before entries start, where they are ignored.
Notes for interpreting commands described in double-quotes below:
-- "literal_string" : means use the string "literal_string".
-- "<name>" : means the whole name "<name>" represents some variable
quantity that is interpreted at runtime (like a number
or device/file name).
-- "[option]" : means "option" is may be omitted.
-- "..." : means extra text included at the end of the line is used for
some purpose.
Commands usable in config files only.
-- "timeout= <sec>"
Sets a timeout, in <sec> seconds, before automatically booting the
default entry (normally the first entry defined).
-- "default= <num>"
Sets the default entry to entry number <num> (otherwise it is 0,
the first entry).
-- "fallback= <num>"
Goes into unattended boot mode: if the default boot entry has any
errors, instead of waiting for the user to do anything, it
immediately starts over using the <num> entry (same numbering
as the "default=" command). This obviously doesn't help if the
machine was in the middle of the boot process (after leaving GRUBs
code) and rebooted.
-- "password= <passwd> <new_config_file>"
Disables all interactive editing control (menu entry editor
and command-line). If the password <passwd> is entered, it
loads the <new_config_file> as a new config file and restarts
the GRUB Stage 2.
-- "title= ..."
Starts a new menu entry, and sets it's name to the contents of the
rest of the line, starting with the first non-space character.
Commands usable in config files and interactively.
-- "pause= ..."
Prints the entirety of "pause= ..." to the end of it's line, then
waits until a key is pressed.
NOTE that placing a ^G in it will cause the speaker to emit the
standard beep sound, which is useful when asking the user to change
floppies, etc.
-- "uppermem= <kbytes>"
Forces GRUB to ignore what it found during the autoprobe of the
memory available to the system, and to use <kbytes> as the number
of kilobytes of upper memory installed. Any address range maps
of the system are discarded.
NOTE: This should be used with great caution, and should only
be necessary on some old machines. GRUB's BIOS probe can pick up
all RAM on all new machines the author has ever heard of. It can
also be used for debugging purposes to lie to an OS.
-- "root= <device> [<hdbias>]"
Sets the current "root partition" to the device <device>, then
attempts to mount it to get the partition size (for passing the
partition descriptor in ES:ESI, used by some chainloaded
bootloaders), the BSD drive-type (for booting BSD kernels using
their native boot format), and fixup automatic determination of
the PC partition where a BSD sub-partition is located. The optional
<hdbias> parameter is a number to tell a kernel which is using
one of the BSD boot methodologies how many BIOS drive numbers
are on controllers before the current one. An example is if there
is an IDE disk and a SCSI disk, then set the root partition
normally, except for a kernel using a BSD boot methodology
(FreeBSD or NetBSD), then use a "1" for <hdbias>.
-- "rootnoverify= <device> [<hdbias>]"
Similar to "root=", but doesn't attempt to mount the partition.
This is useful for when an OS is outside of the area of the disk
that GRUB can read, but setting the correct root partition is still
desired.
NOTE: the items mentioned in "root=" above which are derived from
attempting the mount will NOT work correctly.
-- "chainloader= <file>"
Loads <file> as a chainloader.
NOTE: like any other file loaded by the filesystem code, it can
use the blocklist notation to grab the first sector of the current
partition with "+1".
-- "kernel= <file> ..."
Attempts to load the primary boot image (Multiboot a.out or ELF,
Linux zImage or bzImage, FreeBSD-a.out, or NetBSD-a.out) from
<file>. This command ignores the rest of the contents of the line,
except that the entire line starting with the kernel filename is
passed verbatim as the "kernel command-line". The module state is
reset by this (i.e. reload any modules).
-- "module= <file> ..."
Loads a boot module for a Multiboot format boot image (no
interpretation of the file contents are made, so the user of this
command/writer of the config file must know what the kernel in
question works with). The rest of the line is passed as the "module
command-line" much like with the "kernel=" command.
-- "modulenounzip= <file> ..."
Exactly like "module", except that automatic decompression is
disabled.
-- "initrd= <file> ..."
Loads an initial ramdisk for a Linux format boot image and sets
the appropriate parameters in the Linux setup area in memory.
-- "install= <stage1_file> [d] <dest_dev> <file> <addr> [p] [<config_file>]"
This command is fairly complex, and for detailed examples one
should look at the install documentation. In short, it will
perform a full install presuming the stage1.5 or stage2 (they're
loaded the same way, I'll just refer to it as a stage2 from now on)
is in it's final install location (pretty much all other edits are
performed by the "install=" command).
In slightly more detail, it will load <stage1_file>, validate
that it is a GRUB stage1 of the right version number, install
blocklists for loading <file> (if the option "d" is present,
the stage1 will always look for the actual disk <file> was
installed on, rather than using the booting drive) as a stage2
into memory at address <addr> (for a stage1.5, an address of
0x2000 should be used, and for a stage2, an address of 0x8000
should be used), then write the completed stage1 to the first
block of the device <dest_dev>. If the options "p" or <config_file>
are present, then it reads the first block of stage2, modifies it
with the values of the partition <file> was found on (for "p") or
places the string <config_file> into the area telling the stage2
where to look for a configuration file at boot time. Finally, it
preserves the DOS BPB (and for hard disks, the partition table) of
the sector the stage1 is to be installed into.
-- "makeactive"
Sets the active partition on the root disk to GRUB's root partition
(on a floppy this is a NO-OP). This is limited to working with
"primary" PC partitions.
-- "boot"
This boots the OS/chainloader which has been loaded. Only necessary
if running the fully interactive command-line (it is implicit at the
end of a config-file entry).
Commands usable in config files and interactively which are only available
in the debug version of the GRUB Stage 2.
-- "testload= <file>"
Reads the entire contents of <file> in several different ways and
compares them, to test the filesystem code. The output is somewhat
cryptic (see the "T" subcommand of "syscmd=" below), but if no
errors are reported and the part right at the end which reads
"i=<X>, filepos=<Y>" has <X> and <Y> equal, then it is definitely
consistent, and very likely works correctly subject to a consistent
offset error. A good idea if this works is then to try loading a
kernel with your code.
-- "read= <addr>"
Reads a 32-bit unsigned value at address <addr> and displays it
in hex format.
-- "displaymem"
Displays what GRUB thinks the system address space map of the
machine is, including all regions of physical RAM installed.
The "upper/lower memory" thing GRUB has uses the standard BIOS
interface for the available memory in the first megabyte, or
"lower memory", and a synthesized number from various BIOS
interfaces of the memory starting at 1MB and going up to the first
chipset hole for "upper memory" (the standard PC "upper memory"
interface is limited to reporting a maximum of 64MB).
-- "impsprobe"
Probes Intel MPS spec 1.1 or 1.4 configuration table and boots
the various other CPUs which are found into a tight loop.
-- "fstest"
Toggles filesystem test mode.
Filesytem test mode, when turned on, prints out data corresponding
to all the device reads and what values are being sent to the
low-level routines. The format is:
"<sector, byte_offset, byte_len>" for high-level reads
inside a partition (so "sector" is an offset from
the start of the partition).
"[sector]" for low-level sector requests from the disk
(so "sector" is offset from the start of the disk).
Filesystem test mode is turned off by any uses of the "install=" or
"testload=" commands.

118
docs/embedded_data.txt Normal file
View file

@ -0,0 +1,118 @@
NOTE that GRUB's own install functions can alter all of the significant
variables here... look in the install.html file for details.
This file describes embedded variables in GRUB's stage1 and stage2 and
how they are meant to be used and manipulated.
The primary reason for them being in well-defined locations is to allow
changes/installation/etc. without needing to recompile the modules, just
patch the binary directly.
"stage1" :
NOTE: these are all defined in "stage1/stage1.S".
-- at offset 0x1BC : "major version"
This is the major version byte (should be a 1).
-- at offset 0x1BD : "minor version"
This is the minor version byte (should be a 0).
-- at offset 0x1B8 : "stage2 start address"
This is the data for the "ljmp" command to the starting address
of the component loaded by the stage1. The format is two 2-byte
words: the first is the IP, and the second is the CS segment
register (remember, we're in x86 real-mode... 16-bit instruction
pointer and segment registers shifted left by 4 bits).
A "stage1.5" should be loaded at address 0x2000, and a "stage2"
should be loaded at address 0x8000. Both use a CS of 0.
-- at offset 0x1B0 : "firstlist"
This is the ending address of the blocklist data area.
The trick here is that it is actually read backward, and the first
8-byte blocklist is not read here, but after the pointer is
decremented 8 bytes, then after reading it, it decrements again,
reads, decrements, reads, etc. until it is finished. The
terminating condition is when the number of sectors to be read
in the next blocklist is 0.
The format of a blocklist can be seen from the example in the
code just before the "firstlist" label. (note that it is
always from the beginning of the disk, and *NOT* relative to
the partition boundaries)
-- at offset 0x1B0 : "loading drive"
This is the BIOS drive number to load the blocklists from.
If the number is 0xFF, then load from the booting drive.
"stage1.5" and "stage2" (same structure) :
NOTE: these are all defined at the beginning of "shared_src/asm.S".
-- at offset 0x6 : "major version"
This is the major version byte (should be a 1).
-- at offset 0x7 : "minor version"
This is the minor version byte (should be a 0).
-- at offset 0x8 : "install_partition"
This is an unsigned long representing the partition on the currently
booted disk which GRUB should expect to find it's data files and
treat as the default root partition.
The format of is exactly the same as the "partition" part (the "disk"
part is ignored) of the data passed to an OS by a Multiboot-compliant
bootloader in the "boot_device" data element, with one exception.
The exception is that if the first level of disk partitioning is
left as 0xFF (decimal 255, which is marked as no partitioning being
used), but the second level does have a partition number, it looks
for the first BSD-style PC partition, and finds the numbered BSD
sub-partition in it. The default "install_partition" 0xFF00FF,
would then find the first BSD-style PC partition, and use the "a"
partition in it, and 0xFF01FF would use the "b" partition, etc.
If an explicit first-level partition is given, then no search is
performed, and it will expect that the BSD-style PC partition is
in the appropriate location, else a "no such partition" error will
be returned.
IMPORTANT NOTE: If a "stage1.5" is being used, it will pass it's own
"install_partition" to any "stage2" it loads, therefore overwriting
the one present in the "stage2".
-- at offset 0xC : "version_string"
This is the "stage1.5" or "stage2" version string. It isn't
meant to be changed, simply easy to find.
-- after the terminating zero of "version_string" : "config_file"
This is the location, using the GRUB filesystem syntax, of the
config file. It will, by default, look in the "install_partition"
of the disk GRUB was loaded from, though one can use any valid
GRUB filesystem string, up to and including making it look on
other disks.
IMPORTANT NOTE: The bootloader itself doesn't search for the end of
"version_string", it simply knows where "config_file" is, so the
beginning of the string cannot be moved after compile-time. This
should be OK, since the "version_string" is meant to be static.
IMPORTANT NOTE #2: The code of stage2 starts again at offset 0x70,
so "config_file" string obviously can't go past there. Also,
remember to terminate the string with a 0.

198
docs/errors.html Normal file
View file

@ -0,0 +1,198 @@
<HTML>
<HEAD>
<TITLE>GRUB Error Messages</TITLE>
</HEAD>
<BODY>
<CENTER><H1>GRUB Error Messages</H1></CENTER>
<CENTER><H3>by
<A HREF=http://www.uruk.org/~erich/>Erich Boleyn</A></H3></CENTER>
<HR>
<H2>Contents</H2>
<UL>
<LI><A HREF="#stage1">Errors Reported by the Stage 1</A>
<LI><A HREF="#stage1_5">Errors Reported by the Stage 1.5</A>
<LI><A HREF="#stage2">Errors Reported by the Stage 2</A>
</UL>
<HR>
<H2><A NAME="stage1">Errors Reported by the Stage 1</A></H2>
The general way that the Stage 1 handles errors is to print an
error string and then halt. Pressing Ctrl-Alt-Del will reboot.<P>
The following is a comprehensive list of error messages for the
Stage 1:<P>
<UL>
<LI><B>"Hard Disk Error"</B><P>
This error message will occur if the Stage 2 or Stage 1.5 is being read
from a hard disk, and the attempt to determine the size and
geometry of the hard disk fails.<P>
<LI><B>"Floppy Error"</B><P>
This error message will occur if the Stage 2 or Stage 1.5 is being read
from a floppy disk, and the attempt to determine the size and
geometry of the floppy disk fails. It's listed as a different error
since the probe sequence is different than for hard disks.<P>
<LI><B>"Read Error"</B><P>
This error message will occur if a disk read error happens while trying
to read the Stage 2 or Stage 1.5.<P>
<LI><B>"Geom Error"</B><P>
This error message will occur if the location of the Stage 2 or Stage 1.5
is not in the area supported by reading the disk with the BIOS directly.
This could occur because the BIOS translated geometry has been changed
by the user or the disk is moved to another machine or controller after
installation, or GRUB was not installed using itself (if it was, the
Stage 2 version of this error would have been seen during that process
and it would not have completed the install).<P>
</UL>
<HR>
<H2><A NAME="stage1_5">Errors Reported by the Stage 1.5</A></H2>
The general way that the Stage 1.5 handles errors is to print an
error number in the form "Error: <num>" and then halt. Pressing
Ctrl-Alt-Del will reboot.<P>
The error numbers correspond to the
<A HREF="#stage2">Errors Reported by the Stage 2</A> in the
listed sequence.<P>
<HR>
<H2><A NAME="stage2">Errors Reported by the Stage 2</A></H2>
The general way that the Stage 2 handles errors is to abort the
operation in question, print an error string, then (if possible)
either continue based on the fact that an error occurred or wait
for the user to deal with the error.<P>
The following is a comprehensive list of error messages for the
Stage 2 (error numbers for the Stage 1.5 are listed before the
colon in each description):<P>
<UL>
<LI><B>1</B> : <B>"Selected item won't fit into memory"</B><P>
This error is returned if a kernel, module, or raw file load
command is either trying to load it's data such that it won't fit into
memory or it is simply too big.<P>
<LI><B>2</B> : <B>"Selected disk doesn't exist"</B><P>
This error is returned if the device part of a device- or full filename
refers to a disk or BIOS device that is not present or not recognized
by the BIOS in the system.<P>
<LI><B>3</B> : <B>"Disk read error"</B><P>
This error is returned if there is a disk read error when trying to probe or
read data from a particular disk.<P>
<LI><B>4</B> : <B>"Disk write error"</B><P>
This error is returned if there is a disk write error when trying to write
to a particular disk. This would generally only occur during an
install of set active partition command.<P>
<LI><B>5</B> : <B>"Disk geometry error"</B><P>
This error is returned when a read is attempted at a linear block address
beyond the end of the BIOS translated area. This generally happens
if your disk is larger than the BIOS can handle (512MB for (E)IDE disks on
older machines or larger than 8GB in general).<P>
<LI><B>6</B> : <B>"Attempt to access block outside partition"</B><P>
This error is returned if a linear block address
is outside of the disk partition. This generally happens
because of a corrupt filesystem on the disk or a bug in the code handling
it in GRUB (it's a great debugging tool).<P>
<LI><B>7</B> : <B>"Partition table invalid or corrupt"</B><P>
This error is returned if the sanity checks on the integrity of the partition
table fail. This is a bad sign.<P>
<LI><B>8</B> : <B>"No such partition"</B><P>
This error is returned if a partition is requested in the device part of a
device- or full filename which isn't on the selected disk.<P>
<LI><B>9</B> : <B>"Bad filename (must be absolute pathname or blocklist)"</B><P>
This error is returned if a filename is requested which doesn't fit the
syntax/rules listed in the <A HREF=filesystem.txt>Filesystem
Description</A>.<P>
<LI><B>10</B> : <B>"Bad file or directory type"</B><P>
This error is returned if a file requested is not a regular file, but
something like a symbolic link, directory, or FIFO.<P>
<LI><B>11</B> : <B>"File not found"</B><P>
This error is returned if the specified filename cannot be found, but
everything else (like the disk/partition info) is OK.<P>
<LI><B>12</B> : <B>"Cannot mount selected partition"</B><P>
This error is returned if the partition requested exists, but the filesystem
type cannot be recognized by GRUB.<P>
<LI><B>13</B> : <B>"Inconsistent filesystem structure"</B><P>
This error is returned by the filesystem code to denote an internal
error caused by the sanity checks of the filesystem structure on disk
not matching what it expects. This is usually caused by a corrupt
filesystem or bugs in the code handling it in GRUB.<P>
<LI><B>14</B> : <B>"Filesystem compatibility error, can\'t read whole file"</B><P>
Some of the filesystem reading code in GRUB has limits on the length of
the files it can read. This error is returned when the user runs into
such a limit.<P>
<LI><B>15</B> : <B>"Error while parsing number"</B><P>
This error is returned if GRUB was expecting to read a numbur and encountered
bad data.<P>
<LI><B>16</B> : <B>"Device string unrecognizable"</B><P>
This error is returned if a device string was expected, and the string
encountered didn't fit the
syntax/rules listed in the <A HREF=filesystem.txt>Filesystem
Description</A>.<P>
<LI><B>17</B> : <B>"Invalid device requested"</B><P>
This error is returned if a device string is recognizable but does not
fall under the other device errors.<P>
<LI><B>18</B> : <B>"Invalid or unsupported executable format"</B><P>
This error is returned if the kernel image boing loaded is not recognized
as Multiboot or one of the supported native formats (Linux zImage or
bzImage, FreeBSD, or NetBSD).<P>
<LI><B>19</B> : <B>"Loading below 1MB is not supported"</B><P>
This error is returned if the lowest address in a kernel is below the
1MB boundary. The Linux zImage format is a special case and can be
handled since it has a fixed loading address and maximum size.<P>
<LI><B>20</B> : <B>"Unsupported Multiboot features requested"</B><P>
This error is returned when the Multiboot features word in the Multiboot
header requires a feature that is not recognized. The point of this is
that the kernel requires special handling which GRUB is likely unable
to provide.<P>
<LI><B>21</B> : <B>"Unknown boot failure"</B><P>
This error is returned if the boot attempt did not succeed for reasons
which are unknown.<P>
<LI><B>22</B> : <B>"Must load Multiboot kernel before modules"</B><P>
This error is returned if the module load command is used before loading
a Multiboot kernel. It only makes sense in this case anyway, as GRUB
has no idea how to communicate the presence of location of such modules
to a non-Multiboot-aware kernel.<P>
<LI><B>23</B> : <B>"Must load Linux kernel before initrd"</B><P>
This error is returned if the initrd command is used before loading
a Linux kernel. Similar to the above error, it only makes sense in that
case anyway.<P>
<LI><B>24</B> : <B>"Cannot boot without kernel loaded"</B><P>
This error is returned if GRUB is told to execute the boot sequence without
having a kernel to start.<P>
<LI><B>25</B> : <B>"Unrecognized command"</B><P>
This error is returned if an unrecognized command is entered into the
command-line or in a boot sequence section of a config file and that
entry is selected.<P>
<LI><B>26</B> : <B>"Bad or incompatible header on compressed file"</B><P>
This error is returned if the file header for a supposedly compressed file
is bad.<P>
<LI><B>27</B> : <B>"Bad or corrupt data while decompressing file"</B><P>
This error is returned the run-length decompression code gets an
internal error. This is usually from a corrupt file.<P>
<LI><B>28</B> : <B>"Bad or corrupt version of stage1/stage2"</B><P>
This error is returned if the install command is pointed to incompatible
or corrupt versions of the stage1 or stage2. It can't detect corruption
in general, but this is a sanity check on the version numbers, which
should be correct.<P>
</UL>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

213
docs/faq.html Normal file
View file

@ -0,0 +1,213 @@
<HTML>
<HEAD>
<TITLE>GRUB FAQ -- Frequently Asked Questions</TITLE>
</HEAD>
<BODY>
<CENTER><H1>GRUB FAQ -- Frequently Asked Questions</H1></CENTER>
<CENTER><H3>for version 0.4</H3></CENTER>
<HR>
<H2>Contents</H2>
<UL>
<LI> <A HREF="#general">General</A>
<LI> <A HREF="#commands">Commands</A>
<LI> <A HREF="#filesys">Filesystems</A>
<LI> <A HREF="#install">Installation</A>
</UL>
<HR>
<H2><A NAME="general">General</A></H2>
<UL>
<LI><B>I thought there was no way to autodetect all of the RAM
on a PC, can GRUB really do it reliably?</B><P>
For any fairly modern machine, yes. GRUB can also generally detect
more than 64MB, as described in the
<A HREF=technical.html>GRUB Technical Info</A>. It has been tried in
many machines with memory sizes ranging from 72MB up to 2 GB in one case.
There are some machines still in use which don't report most of their RAM
using any of the well-known BIOS memory interfaces. For those, there
really is no recourse but to use the "uppermem=" command to set it
manually, which is described in the
<A HREF=commands.txt>list of commands</A>.<P>
Note that passing this value correctly to Linux involved patching
a "mem=" statement onto the beginning of the command-line, and for FreeBSD
required a fix to some earlier versions (as it figured any value over
64MB was a bug and it would panic on this). A Multiboot compliant kernel
has no problem.<P>
<LI><B>Is there any way to abort operations?</B><P>
Whenever GRUB is waiting for input, if the user presses the ESC key,
then as much of the internal state changes as possible is cancelled
and GRUB goes up one
interface level (if at the top level, it just redraws the screen).<P>
<LI><B>What does GRUB do if there is an error during booting a config
file entry (such as a disk read error) ?</B><P>
Unless otherwise told to (via the "fallback=" command), GRUB will drop
into the interactive command-line after displaying the error message
to the user. If the user presses enter (perhaps after some editing), then
it will attempt to execute this line and if successful continue from where
it left off in the config file entry.<P>
</UL>
<HR>
<H2><A NAME="commands">Commands</A></H2>
Here is the generic
<A HREF=commands.txt>list of commands</A>.<P>
<UL>
<LI><B>When editing the config file for GRUB in DOS/Windows/NT, do I
have to worry about CR/LF translation?</B><P>
No. GRUB will work with CR/LF or LF only line endings in it's
configuration file perfectly fine. I have created and managed a config
file from Windows 95 using the NOTEPAD program with no problems after
installing GRUB on the hard disk using a floppy created from Windows 95
as well.<P>
<LI><B>I noticed that there are some command examples in hexidecimal and
some in decimal, what formats are supported and where?</B><P>
Whenever there is a number entered by the user from either a command-line
or the config file, it can be entered in decimal or hexidecimal as desired
(the letters used for hex numbers are case-insensitive).
The way GRUB uses to distinguish them is that hex numbers
start with "0x", so one could type "128" or "0x80" alternately.<P>
<LI><B>Some commands corrupt some memory state</B><P>
Performing an "install=" or "testload=" command will corrupt any
chainloaders/kernels currently loaded into memory. I.e. simply redo
the loads or always make sure that installs or testloads are done first.<P>
<LI><B>When running interactively, can an a different chainloader/kernel
be loaded after one has already been, or do I have to reset all the
internal state with the ESC key?</B><P>
Any "chainloader=" or "kernel=" command used overrides any previous ones,
and in the case of Multiboot-compatible kernels, requires that modules
be reloaded.<P>
</UL>
<HR>
<H2><A NAME="filesys">Filesystems</A></H2>
Here is the listing of
<A HREF=filesystem.txt>GRUB Filesystems and Interfaces</A>.<P>
<UL>
<LI><B>What is the "root partition" ?</B><P>
This is both the default partition for searching for/loading files and
the source of the "root partition" information used for chainloaders
and data passed to kernels in various formats. This defaults to the
"install_partition" variable in the
<A HREF=http://www.uruk.org/embedded_data.txt>embedded data</A> of the
stage1.5/stage2, and can be changed via the "root=" or "rootnoverify="
commands.<P>
<LI><B>What filesystems are supported, and how do I tell it which one
to use?</B><P>
GRUB comes with support for <B>DOS FAT</B>, <B>BSD FFS</B>, and <B>Linux
ext2fs</B> filesystems, plus a blocklisting notation for accessing blocks
directly. When using the normal file syntax, GRUB will autodetect the
filesystem type.<P>
<LI><B>When booting an OS, how do I tell the OS what the root
partition is?</B><P>
The root partition setting in GRUB is mostly for it's own use (where
it looks for data by default if no device is specified), and is passed
to a fully Multiboot-compliant OS. When possible, the information is
passed along to the OS being booted. Here is a listing of where each
of the major OSes GRUB is being used for gets it's root partition from:<P>
<UL>
<LI><B>FreeBSD</B>: GRUB passes it in the same manner as it's original
bootloader, as of the version 2.1.0 release.<P>
<LI><B>NetBSD</B>: GRUB passes it in the same manner as it's original
bootloader, as of the version 1.1 release.<P>
<LI><B>Linux</B>: GRUB doesn't pass any special root partition info,
so unless the root partition is set on the command-line, the default
one complied into the image will be used.<P>
<LI><B>Mach4</B>: Mach4 currently ignores the root partition info
passed in the Multiboot info structure. You have to explicitly
put it on the command-line via a "root=hd0a" or "root=hd0s1" type
of command; see the release notes on Mach4 for details.<P>
<B>NOTE:</B> The default version of the UK22 release is compliant with an
earlier and incompatible multiboot version. A patch to bring it up
to Multiboot 0.6 is available in the GRUB FTP area.
The version distributed with
the GNU HURD already has this patch.<P>
<LI><B>Chainloaded OS's such as DOS or NT</B>: The only way they
have of knowing anything about a root or boot partition is via
preset offsets in their boot sectors (such as the "hidden sectors"
parameter of the DOS BIOS parameter block) or
the "active partition" marker (see "makeactive" in the list of
commands).<P>
</UL>
</UL>
<HR>
<H2><A NAME="install">Installation</A></H2>
Here is the
<A HREF=install.html>GRUB Installation Guide</A>.<P>
<UL>
<LI><B>What partition does GRUB look for the config file on?</B><P>
GRUB looks for the config file in the default root partition, unless
a partition name was included at the beginning of the config file name
when it was installed (in that case it ignores the default).<P>
To keep matters simple, it is recommended that when installing, ALWAYS
use the "p" option in the "install=" command when the stage2 file is
in a partition type readable by GRUB,
which will force default root partition to be the
same as where the stage2 is (i.e. that's where it looks for the config
file).<P>
<LI><B>How do I install taking a stage1 from a floppy and
placing it on another floppy in the same drive</B><P>
You don't. There is currently no provision to pause an install
operation so you can switch floppies in the middle. Placing the stage1
as a file on the destination floppy, or on a hard disk somewhere, is
what has to be done here.<P>
<LI><B>When trying to install using the stage1 from my hard disk,
it complained about a "bad or corrupt version"</B><P>
When installing to a floppy, you must use a stage1 which has NOT been used
to boot off of a hard disk, as an essential piece of code for floppy
booting is deleted when installing the stage1 to a hard disk. A
"bad or corrupt version" error will be returned if the code is
not present.<P>
<LI><B>When using a stage1.5 AND stage2, does the "install_partition"
need to be set in the stage2?</B><P>
After the Stage 2 is loaded, the Stage 1.5 will patch the
"install_partition" in the
<A HREF=embedded_data.txt>embedded data</A> with it's own value. This
behavior is to make it easier to install new versions of the Stage 2
without having to patch special values into it each time, since the
whole point of the Stage 1.5 is to allow the convenience of reading
the largest component as a normal file.<P>
<LI><B>Is there anywhere on a hard disk I can put GRUB's stage2 which is
separate from the rest of the filesystems?</B><P>
Sometimes. This is something of an advanced operation to set up, and is
not recommended for general use.<P>
On all PC-partitioned hard disks, there is an area after the
partition table (starting at the second sector) but before the first
partition. This can be used for more-or-less any purpose that is
desired, as it is usually dead space. On most modern hard disks,
it is 31.5K in size (63 disk sectors), which is large enough for the
non-debug version of GRUB. If a some other special "multi-OS" bootloader
is installed, then this might already be in use by that program.<P>
On Linux or FreeBSD, one would use a "dd" command to place the stage2 on
the disk (here's a Linux example using the first SCSI disk):
<pre>
dd if=stage2 of=/dev/sda bs=512 seek=1
</pre>
...then run the install command mostly normally, but for the stage2 file
use the blocklist string "1+63", which will point to this area.<P>
</UL>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

299
docs/filesystem.txt Normal file
View file

@ -0,0 +1,299 @@
The top of this file is the filesystem syntax and semantics.
The rest of the file describes the interface used by the filesystem
code.
General FS semantics rules:
-- When listing completions, directories are not labeled any differently
from files (symbolic links, FIFOs, etc. are listed as well).
-- Only regular directories and files are interpreted (i.e. a symbolic
link or FIFO would generate a "Bad file type" error if an attempt
is made to read one... an attempt to read a directory as a file
or vice-versa will also generate a "Bad file type" error).
-- All numbers can be either decimal or hexidecimal. A hexidecimal number
must be preceeded by "0x", and is case insensitive.
VERY IMPORTANT NOTE about devices: The only disk devices accessible from a
bootloader are BIOS-controlled devices. All any PC bootloader knows is
the "device number" (floppies are numbered consecutively starting with 0,
and hard drives are numbered consecutively starting with 0x80). There
is no way to tell if a hard drive is IDE, ESDI, SCSI, etc. GRUB punts
and simply uses the BIOS device number in all circumstances. It is
presumed the OS has some mechanism to translate to the physical
controllers (examples are provided in the Multiboot document). Some
OSes kludge it by requiring disklabels like the *BSDs use (which, might
it be noted, breaks under some circumstances, and may not always be
possible to use).
Device syntax like this ("[]" means optional), but note, no spaces
are allowed!!!
disk/partition -> "(<bios_device>[,<part_num>[,<bsd_subpart_letter>]])"
A shortcut for bios devices are:
fd0 -> 0 (first floppy disk)
fd1 -> 1 (second floppy disk)
...
hd0 -> 0x80 (first hard disk)
hd1 -> 0x81 (second hard disk)
whole disks: "(fd0)" -- first floppy, "(hd0)" -- first hard disk.
PC partitions: "(hd0,0)" -- first hard disk PC partition 0,
"(hd1,3)" or "(0x81,3)" -- second hard disk PC partition 3.
BSD sub-partitions: "(hd0,1,a)" -- first hard disk, first PC
partition contains BSD sub-partitions, BSD sub-partition "a".
"(0)" -- BIOS device 0 (first floppy disk) whole disk.
"(0x80,0)" -- first PC partition on BIOS device 0x80 (first hard disk).
A shortcut for specifying BSD sub-partitions is:
"(<bios_device>,<bsd_subpart_letter>)"
"(hd0,a)" -- first hard disk, searches for first PC partition
containing BSD sub-partitions, then finds the "a" subpartition.
"(fd0,a)" -- first floppy disk, searches for BSD partition "a".
Inheriting from the defaults can be done by the following variations:
-- omitting the drive number completely will use the current
device taken from the current root partition.
"(,0)" looks for the first PC partition on the current disk.
-- omitting the partition information (but using at least one comma
after the bios device number) changes the bios device but
leaves the partition the same.
"(hd1,)" looks for the same partition as the current root but
on hard disk 1.
Interactive device completion (usable on the command-line after the "="
in a command, like "kernel="):
(nothing) -> lists all possible disks (hard and floppy)
"(" -> same
"(h" -> error (doesn't know what "h" means).
"(hd" -> error (doesn't know what "hd" means).
"(hd0" -> lists the first hard disk
"(hd0," -> lists all partitions on the first hard disk
"(hd0,a" -> finds and mounts BSD partition 'a', then reports FS type.
"(hd0,a)" -> same
"(hd0,a)/" -> lists all files in root directory... (becomes file-completion
listing at this point).
NOTE: for any of the completion stuff, it searches back to the beginning
of the line or the most recent space, then uses that string for the
completion listing operation (file, device, partition). It uses the
*cursor* position as the determiner, so, in the above example, one could
have "(hd0,a)/kernel" on the command-line, then move the cursor to the
beginning (with C-a or lots of C-b's), then hit TAB, move it one character
forward (with C-f), hit TAB again, etc. with the same results as the
above example!!!
Block-list syntax like this:
Primitive-block-list -> "<p-b-l>" = "{,<start-num>}+<length>"
example: "1+20" or "+5"
The interpretation of a primitive-block-list is that the first number
is the first block, then a "+", and a block-length (must be greater than
zero). These are all relative to the partition, and must be contained
within the partition boundaries (a whole disk would be "(hd0)"). If
the starting number is omitted, it is presumed to be zero (the first
block).
construction -> "<block-list>" =
"<p-b-l-1>,<p-b-l-2>,...,<p-b-l-N>{\,<length_in_bytes>}"
example: "1+100,200+1,300+300,<length_in_bytes>"
This represents a conglomerate of blocks, all to be loaded as part of
one block-list. If the exact length is omitted, then it is calculated as
the size of all of the blocks.
Absolute-pathname syntax like this:
Directory notation is via a forward slash, always in absolute form (like
a UNIX absolute pathname), like: "/kernel" or "/test/kernel".
Overall filename syntax is:
[<device>][<block-list>][<absolute-pathname>]
<device> is optional (will use the root partition then), but never ignored.
Either <block-list> or <absolute-pathname> must be used when providing
the name for a generic file. If <block-list> is used, all past it in the
filename is ignored (i.e. if you use both, the blocklist takes precedence).
Legal characters as parts of a directory/filename are any normally
printable ascii character (not control-characters of any kind) except
a space (since it is the delimiter of the end of the whole file/device
name string) and "/" (since it is used as a directory delimiter).
So, legal examples are:
"(hd0,a)/kernel"
"/kernel"
"1+20,25+10,15000"
"(hd0,a)1+20"
"(hd0,a)1+20,400+50,500+100"
"1+20,25+10,15000/kernel"
"(hd0,a)1+20,400+500/kernel"
INTERFACE DESCRIPTION
---------------------
This file also describes the generic interface used by the filesystem code.
The "BLK_NOTES" heading below is for the blocklist filesystem.
The "FAT_NOTES" heading below is for the FAT filesystem.
The "FFS_NOTES" heading below is for the FFS filesystem.
General function description:
For any particular partition, it is presumed that only one of the "normal"
filesystems such as FAT, FFS, or ext2fs can be used, so there is
a switch table managed by the functions in "disk_io.c". The notation is
that you can only "mount" one at a time.
The blocklist filesystem has a special place in the system. In addition
to the "normal" filesystem (or even without one mounted), you can access
disk blocks directly (in the indicated partition) via the blocklist
notation. Using the blocklist filesystem doesn't effect any other
filesystem mounts.
Interface description (this was done somewhat hastily, so important
parts might be missing):
Errors generated:
-- look at "fsys_ffs.c" for examples... (yeah, this is a cop-out for
now, I know).
The variables which can be read by the filesystem backend are:
-- "current_drive", a global which contains the current BIOS drive
number (numbered from 0, if a floppy, and numbered from 0x80,
if a hard disk).
-- "current_slice", a global which contains the current partition
type, if a hard disk.
-- "part_length", a global which contains the current partition
length, in sectors.
-- "print_possibilities", a global which is true when the "dir"
function should print the possible completions of a file, and
false when it should try to actually open a file of that name.
-- the "#define FSYS_BUF", which points to a filesystem buffer which
is 32K in size, to use in any way which the filesystem backend
desires.
The variables which need to be written by a filesystem backend are:
-- "filepos", a global which should be the current position in
the file.
NOTE: the value of "filepos" can be changed out from under the
filesystem code in the current implementation. Don't depend on
it being the same for later calls into the back-end code!!!
-- "filemax", a global which should be the length of the file.
-- "debug_fs_func", a global which should be set to the value of
"debug_fs" ONLY during reading of data for the file, not any
other FS data, inodes, FAT tables, whatever, then set to NULL
at all other times (it will be NULL by default). If this isn't
done correctly, then the "testload=" and "install=" commands
won't work correctly!!! (look at "fsys_ffs.c" for details).
The functions expected to be used by the filesystem backend are:
-- "devread", which only reads sectors from within a partition. Sector
0 is the first sector in the partition.
-- If the backend uses the blocklist code (like the FAT filesystem
backend does), then "read" can be used, after setting "blocklist"
to 1.
The functions expected to be defined by the filesystem backend are described
at least moderately in the file "filesys.h". Their usage is fairly evident
from their use in the functions in "disk_io.c", look for the use of the
"fsys_table" array.
NOTE: The semantics are such that then "mount"ing the filesystem, presume
the filesystem buffer "FSYS_BUF" is corrupted, and (re-)load all important
contents. When opening and reading a file, presume that the data from
the "mount" is available, and doesn't get corrupted by the open/read (i.e.
multiple opens and/or reads will be done with only one mount if in the
same filesystem).
BLK_NOTES:
block filesystem info goes like this:
NOTE: a "block-list" is two 4-byte values, representing the start and length
of a set of 512 byte sectors.
<buffer start>
[ cur_filepos, cur_block_list, cur_block_num,
block-list, block-list, block-list, etc.... ]
<buffer end>
The buffer is 32Kbytes long, so the maximum length of such a list is
32Kbytes - 12 bytes.
FAT_NOTES:
The filenames are all mapped to lower-case.
The FAT filesystem actually uses the "blocklist" filesystem as it's read
routine, reading the appropriate FAT entries and placing them into the
blocklist area. (in this case, a portion of the end of the blocklist
buffer area is used for FAT filesystem information)
It concatenates adjacent blocks in the FAT table together when possible
to consolodate the number of blocklists.
NOTE: The above is important, since there is a maximum number of
approx 1800 blocklists. This is generally more than adequate, but
if it runs off the end and a read is attempted in this area, an
"ERR_FILELENGTH" error will be generated.
FFS_NOTES:
Notes on the FFS filesystem implementation and limitations.
Limitations:
-- Only 1 level of indirect blocks is supported. This implies a
limitation in file-length to approx 16MB. If a read past this point
is attempted, an "ERR_FILELENGTH" error is generated.
-- If the "blocksize" is greater than 8Kbytes, various buffers will
overwrite themselves and the whole thing will come apart at the
seams.

120
docs/grub.html Normal file
View file

@ -0,0 +1,120 @@
<HTML>
<HEAD>
<TITLE>GRUB -- GRand Unified Bootloader</TITLE>
</HEAD>
<BODY>
<CENTER><H1>GRUB -- GRand Unified Bootloader</H1></CENTER>
<CENTER><H3>version 0.5</H3></CENTER>
<CENTER><H3>by
<A HREF=http://www.uruk.org/~erich/>Erich Boleyn</A></H3></CENTER>
<HR>
<H2>Master Contents</H2>
Some of these contents are included in other pages.<P>
<UL>
<LI> <A HREF="#intro">Introduction</A>
<LI> <A HREF="#thanks">Thanks To</A>
<LI> <A HREF="#status">Distribution and Status</A>
<LI> <A HREF=using.html>Using GRUB</A>
<LI> <A HREF=install.html>Installation</A>
<LI> <A HREF=errors.html>GRUB Error Messages</A>
<LI> <A HREF=technical.html>Technical Info</A>
<LI> <A HREF=faq.html>GRUB FAQ</A>
</UL>
<B>NOTE</B>: Up-to-date versions of this documentation directory can
be found at
<A HREF=http://www.uruk.org/grub/>http://www.uruk.org/grub/</A>. The
specifics might be for a newer version of the program, so check the
<A HREF=http://www.uruk.org/grub/NEWS>online NEWS file</A> for details
about the differences.<P>
<HR>
<H2><A NAME="intro">Introduction</A></H2>
GRUB is an attempt to produce a bootloader for IBM PC-compatible machines
that has both the capability to be friendly to beginning or
otherwise non-technically
interested users and the flexibility to help experts in diverse
environments. It is currently most useful for users of at least
one of the various free UNIX-like operating systems, though it can
be used with most any PC operating system.<P>
This project actually started because we wanted to boot the
<A HREF=http://www.cs.pdx.edu/~trent/gnu/hurd/>GNU HURD</A>
operating system on top of
<A HREF=http://www.cs.utah.edu/projects/flux/mach4/html/Mach4-proj.html>
Mach4</A> on an IBM PC-compatible system in a manner compliant
with the <A HREF=boot-proposal.html>Multiboot Standard</A>, which
was put together as a general solution to the problem of the different
boot formats and the functionality they need.
I then tried to add support for the extra functionality to the
standard bootloader used for FreeBSD. The number of things I had to do
to get it all to work multiplied until it was obviously necessary to
start from scratch with something different.<P>
GRUB has evolved a long way from it's beginnings as a multi-module
bootloader. Several
of the techniques used have no analogue in the rest of the free
software world, and a few are apparently superior to most proprietary OSes
as well.
The documentation here and in the multiboot proposal should be very
useful to prospective OS and bootloader writers for PCs.<P>
The name comes from the acronym, but also from the realization that although
a grub is one of the smaller (and less interesting) critters - barely worthy
of notice - it is nearly ubiquitous and vital to the order of things.<P>
<HR>
<H2><A NAME="thanks">Thanks To</A></H2>
<UL>
<LI><B>Members of the Multiboot e-mail list and Bryan Ford
(baford@cs.utah.edu)</B> -- for all the multiboot discussion
and OS code to test with.<P>
<LI><B>VaX#n8 (vax@linkdead.paranoia.com)</B> -- for testing feedback plus the
initial implementation for the ext2fs filesystem.<P>
<LI><B>Miles Bader (miles@gnu.ai.mit.edu)</B> -- for testing feedback.<P>
<LI><B>Eric Hanchrow (erich@microsoft.com)</B> -- for interstate remote
debugging by hand.<P>
<LI><B>Gord Matzigkeit (gord@enci.ucalgary.ca)</B> -- for lots of
testing feedback.<P>
<LI><B>Heiko Schroeder (heiko@pool.informatik.rwth-aachen.de)</B> -- for
a re-writing stage1 to be much more readable, plus several patches.<P>
</UL>
<HR>
<H2><A NAME="status">Distribution and Status</A></H2>
GRUB is currently available under the
<A HREF=COPYING>GNU General Public License</A>.
This should not be an issue for OS developers or users who dislike
the terms of the GPL, as it is a separate package, and will not
have any licensing impact upon their own work or installation.
If it is still an issue,
<A HREF=mailto:erich@uruk.org>send me e-mail</A> and maybe we can
work something out.<P>
The publically available releases are available on my
<A HREF=ftp://ftp.uruk.org/public/grub/>FTP site</A>, and I
believe they will get included in the GNU FTP sites as well.<P>
Here are links to the <A HREF=NEWS>NEWS file</A>,
<A HREF=TODO>TODO list</A>, and list of <A HREF=BUGS>known BUGS</A>.<P>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

160
docs/install.html Normal file
View file

@ -0,0 +1,160 @@
<HTML>
<HEAD>
<TITLE>GRUB Installation Guide</TITLE>
</HEAD>
<BODY>
<CENTER><H1>GRUB Installation Guide</H1></CENTER>
<CENTER><H3>by
<A HREF=http://www.uruk.org/~erich/>Erich Boleyn</A></H3></CENTER>
<HR>
<H2>Contents</H2>
<UL>
<LI><A HREF="#raw">Install using "rawrite" or "dd" to floppy disk</A>
<LI><A HREF="#automated">Automated Install using GRUB</A>
</UL>
<H3>Getting Started Quickly</H3>
If you just want to use GRUB, or simply try it out quickly, try the
<A HREF="#raw">Install using "rawrite" or "dd" to floppy disk</A> in the
following section to create a "raw" GRUB floppy.<P>
<HR>
<H2><A NAME="raw">Install using "rawrite" or "dd" to floppy disk</A></H2>
This installation method can generally only access the command-line
part of the interface (since there is no filesystem in which to
find a config-file). It is also by far the simplest installation
method to get going.<P>
<B>NOTE:</B> This will destroy any data currently on the floppy.<P>
Execute your OS's equivalent of (this should work for recent FreeBSD
versions and Linux just fine):<P>
<pre>
dd if=bin/stage1 of=/dev/fd0 bs=512 count=1
dd if=bin/stage2 of=/dev/fd0 bs=512 seek=1
</pre>
Under <B>DOS/Windows/NT</B>, courtesy of Eric
Hanchrow (erich@microsoft.com):
<UL>
<LI>Use the <B>copy /b</B> command to binary concatenate the stage1
and stage2 files together via:
<pre>
copy /b stage1 + stage2 grub.raw
</pre>
<LI>Use rawrite.exe (which is available in many places on the net and in
some Linux distributions) to write grub.raw to a floppy.
</UL>
<HR>
<H2><A NAME="automated">Automated Install using GRUB</A></H2>
<B>IMPORTANT NOTE:</B> If the stage1 is installed on a specific
partition, this can erase the normal boot-sector used by an OS.
GRUB can boot Linux, FreeBSD, NetBSD, Mach, and the GNU HURD directly,
so this may be desired. Generally, it is a good idea to back up the
first sector of a partition if installing GRUB's stage1 there.
For the first sector of a hard disk, this is OK, since it's easy
to reinitialize it via "FDISK /MBR" in DOS, or other methods in other
OSes.<P>
GRUB has a command called "install=" which is described in
the <A HREF=commands.txt>list of commands</A>. The purpose
of this section is to give examples and describe how to use the command
in different situations.<P>
<B>NOTE:</B> Given that "install=" can be used in config-file entries,
this could very easily be used as part of a completely automated set of
install scripts for an OS.<P>
First, you make a "raw" GRUB floppy created via <A HREF="#raw">Install
using "rawrite" or "dd" to floppy disk</A> above. Actually, any booting
copy of GRUB of the right version number will work fine, this is simply
a way to get the process started easily.<P>
On the partition that is the desired area for GRUB to be installed in
(call it the "install partition"), make a "/boot/grub" directory and
place the stage2 and menu.lst (config file) there. (If desired, place
a stage1.5 there as well)<P>
Now use the "install=" command appropriately, and you're done!<P>
Examples of how to use the "install=" command:<P>
<UL>
<LI><B>Making a Hard Disk bootable with GRUB's stage2 on PC partition
number 2:</B> Make a directory in the partition called "/boot/grub",
place the stage2 (and if desired, your config file called "menu.lst"),
then run the following command after getting GRUB's command-line from
booting the floppy:
<pre>
install= (fd0)+1 (hd0) (hd0,2)/boot/grub/stage2 0x8000 p
</pre>
This tells GRUB to grab the first sector of the floppy and use it as
the stage1, create a blocklist using the file "/boot/grub/stage2" on
the first hard disk, partition number 2, merge them together, set the
load address to 0x8000 (correct for a stage2), write the "install
partition" number into the first sector of the stage2 (the "p" at the
end), then write the result to the first sector of the hard disk.<P>
<LI><B>Same as above, but placing the stage1 on the floppy, then having
it start the stage2 on the hard disk:</B> The difference here is you're
telling GRUB's stage1 to read from the first hard disk no matter where
stage1 is being run from:
<pre>
install= (fd0)+1 d (fd0) (hd0,2)/boot/grub/stage2 0x8000 p
</pre>
The "d" option near the beginning is what sets the "forced" loading
from the disk where the stage2 was installed from. The rest of the
options are the same except for the "destination device" to place the
finished stage1 on is changed to the floppy disk.<P>
<LI><B>Installing from an "install directory" to the second hard disk:</B>
Here we're loading the stage1 from a file on the first hard disk,
installing stage2 from the first BSD "a" partition on the second hard disk,
and setting the "config file" of the stage2 to a different value than
usual:
<pre>
install= (hd0,2)/boot/grub/stage1 (hd1) (hd1,a)/boot/grub/stage2 0x8000 p /grubdir/configfile
</pre>
</UL>
An easily imaginable way of using this as part of an automated
installation process would be to note that the commands listed above
can be part of any sequence of commands in an entry in a GRUB config
file, so this could be automated even more by using a GRUB floppy with
a filesystem and config file, with an entry such as:<P>
<pre>
# Start of entries
title= Linux HD install
# install command
install= (fd0)+1 (hd0) (hd0,1)/boot/grub/stage2 0x8000 p
# actually boot here
root= (hd0,1)
kernel= /zImage root=/dev/hda2
</pre>
...then have the install script continue from there after boot of the OS.<P>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

329
docs/mem64mb.html Normal file
View file

@ -0,0 +1,329 @@
<HTML>
<HEAD>
<TITLE>INT 15h, AX=E820h - Query System Address Map</TITLE>
</HEAD>
<BODY>
<H1>INT 15h, AX=E820h - Query System Address Map</H1>
<HR>
Real mode only.<P>
This call returns a memory map of all the installed RAM, and of physical
memory ranges reserved by the BIOS. The address map is returned by making
successive calls to this API, each returning one "run" of physical address
information. Each run has a type which dictates how this run of physical
address range should be treated by the operating system.<P>
If the information returned from INT 15h, AX=E820h in some way differs from
<A HREF="#int15e801">INT 15h, AX=E801h</A> or
<A HREF="#int1588">INT 15h AH=88h</A>,
then the information returned from E820h
supersedes what is returned from these older interfaces.
This allows the BIOS
to return whatever information it wishes to for compatibility reasons.<P>
<HR>
Input:<P>
<pre>
EAX Function Code E820h
EBX Continuation Contains the "continuation value" to get the
next run of physical memory. This is the
value returned by a previous call to this
routine. If this is the first call, EBX
must contain zero.
ES:DI Buffer Pointer Pointer to an Address Range Descriptor
structure which the BIOS is to fill in.
ECX Buffer Size The length in bytes of the structure passed
to the BIOS. The BIOS will fill in at most
ECX bytes of the structure or however much
of the structure the BIOS implements. The
minimum size which must be supported by both
the BIOS and the caller is 20 bytes. Future
implementations may extend this structure.
EDX Signature 'SMAP' - Used by the BIOS to verify the
caller is requesting the system map
information to be returned in ES:DI.
</pre>
Output:<P>
<pre>
CF Carry Flag Non-Carry - indicates no error
EAX Signature 'SMAP' - Signature to verify correct BIOS
revision.
ES:DI Buffer Pointer Returned Address Range Descriptor pointer.
Same value as on input.
ECX Buffer Size Number of bytes returned by the BIOS in the
address range descriptor. The minimum size
structure returned by the BIOS is 20 bytes.
EBX Continuation Contains the continuation value to get the
next address descriptor. The actual
significance of the continuation value is up
to the discretion of the BIOS. The caller
must pass the continuation value unchanged
as input to the next iteration of the E820
call in order to get the next Address Range
Descriptor. A return value of zero means that
this is the last descriptor. Note that the
BIOS indicate that the last valid descriptor
has been returned by either returning a zero
as the continuation value, or by returning
carry.
</pre>
<HR>
<H3>Address Range Descriptor Structure</H3>
<pre>
Offset in Bytes Name Description
0 BaseAddrLow Low 32 Bits of Base Address
4 BaseAddrHigh High 32 Bits of Base Address
8 LengthLow Low 32 Bits of Length in Bytes
12 LengthHigh High 32 Bits of Length in Bytes
16 Type Address type of this range.
</pre>
The <I>BaseAddrLow</I> and <I>BaseAddrHigh</I> together are the 64 bit
<I>BaseAddress</I> of this range. The <I>BaseAddress</I>
is the physical address of the
start of the range being specified.<P>
The <I>LengthLow</I> and <I>LengthHigh</I> together are the 64 bit
<I>Length</I> of this range.
The <I>Length</I> is the physical contiguous length in bytes of a range being
specified.<P>
The <I>Type</I> field describes the usage of the described address range as
defined in the table below.<P>
<pre>
Value Pneumonic Description
1 AddressRangeMemory This run is available RAM usable by the
operating system.
2 AddressRangeReserved This run of addresses is in use or reserved
by the system, and must not be used by the
operating system.
Other Undefined Undefined - Reserved for future use. Any
range of this type must be treated by the
OS as if the type returned was
AddressRangeReserved.
</pre>
The BIOS can use the AddressRangeReserved address range type to block out
various addresses as "not suitable" for use by a programmable device.<P>
Some of the reasons a BIOS would do this are:<P>
<UL>
<LI>The address range contains system ROM.
<LI>The address range contains RAM in use by the ROM.
<LI>The address range is in use by a memory mapped system device.
<LI>The address range is for whatever reason are unsuitable for a
standard device to use as a device memory space.
</UL>
<HR>
<H3>Assumptions and Limitations</H3>
<UL>
<LI><B>1.</B> The BIOS will return address ranges describing base board
memory and ISA or PCI memory that is contiguous with that baseboard memory.
<LI><B>2.</B> The BIOS WILL NOT return a range description for the memory
mapping of PCI devices, ISA Option ROM's, and ISA plug & play cards. This
is because the OS has mechanisms available to detect them.
<LI><B>3.</B> The BIOS will return chipset defined address holes that are not
being used by devices as reserved.
<LI><B>4.</B> Address ranges defined for base board memory mapped I/O devices
(for example APICs) will be returned as reserved.
<LI><B>5.</B> All occurrences of the system BIOS will be mapped as reserved.
This includes the area below 1 MB, at 16 MB (if present) and at
end of the address space (4 gig).
<LI><B>6.</B> Standard PC address ranges will not be reported. Example video
memory at A0000 to BFFFF physical will not be described by this
function. The range from E0000 to EFFFF is base board specific
and will be reported as suits the bas board.
<LI><B>7.</B> All of lower memory is reported as normal memory. It is OS's
responsibility to handle standard RAM locations reserved for
specific uses, for example: the interrupt vector table(0:0) and
the BIOS data area(40:0).
</UL>
<HR>
<H3>Example address map</H3>
This sample address map describes a machine which has 128 MB RAM, 640K
of base memory and 127 MB extended. The base memory has 639K
available for the user and 1K for an extended BIOS data area. There
is a 4 MB Linear Frame Buffer (LFB) based at 12 MB. The memory hole
created by the chipset is from 8 M to 16 M. There are memory mapped
APIC devices in the system. The IO Unit is at FEC00000 and the Local
Unit is at FEE00000. The system BIOS is remapped to 4G - 64K.<P>
Note that the 639K endpoint of the first memory range is also the base
memory size reported in the BIOS data segment at 40:13.<P>
Key to types: "ARM" is AddressRangeMemory, "ARR" is AddressRangeReserved.<P>
<pre>
Base (Hex) Length Type Description
0000 0000 639K ARM Available Base memory - typically the same
value as is returned via the INT 12 function.
0009 FC00 1K ARR Memory reserved for use by the BIOS(s).
This area typically includes the Extended
BIOS data area.
000F 0000 64K ARR System BIOS
0010 0000 7M ARM Extended memory, this is not limited to
the 64 MB address range.
0080 0000 8M ARR Chipset memory hole required to support the
LFB mapping at 12 MB.
0100 0000 120M ARM Base board RAM relocated above a chipset
memory hole.
FEC0 0000 4K ARR IO APIC memory mapped I/O at FEC00000. Note
the range of addresses required for an APIC
device may vary from base OEM to OEM.
FEE0 0000 4K ARR Local APIC memory mapped I/O at FEE00000.
FFFF 0000 64K ARR Remapped System BIOS at end of address space.
</pre>
<HR>
<H3>Sample operating system usage</H3>
The following code segment is intended to describe the algorithm needed when
calling the Query System Address Map function. It is an implementation
example and uses non standard mechanisms.<P>
<pre>
E820Present = FALSE;
Regs.ebx = 0;
do {
Regs.eax = 0xE820;
Regs.es = SEGMENT (&Descriptor);
Regs.di = OFFSET (&Descriptor);
Regs.ecx = sizeof (Descriptor);
Regs.edx = 'SMAP';
_int( 0x15, Regs );
if ((Regs.eflags & EFLAG_CARRY) || Regs.eax != 'SMAP') {
break;
}
if (Regs.ecx < 20 || Regs.ecx > sizeof (Descriptor) ) {
// bug in bios - all returned descriptors must be
// at least 20 bytes long, and can not be larger then
// the input buffer.
break;
}
E820Present = TRUE;
.
.
.
Add address range Descriptor.BaseAddress through
Descriptor.BaseAddress + Descriptor.Length
as type Descriptor.Type
.
.
.
} while (Regs.ebx != 0);
if (!E820Present) {
.
.
.
call INT 15h, AX=E801h and/or INT 15h, AH=88h to obtain old style
memory information
.
.
.
}
</pre>
<HR>
<A NAME="int15e801"><H1>INT 15h, AX=E801h - Get Memory Size for
Large Configurations</H1></A>
<HR>
Real mode only (as far as I know).<P>
Originally defined for EISA servers, this interface is capable of
reporting up to 4 GB of RAM. While not nearly as flexible as E820h, it
is present in many more systems.<P>
Input:<P>
<pre>
AX Function Code E801h
</pre>
Output:<P>
<pre>
CF Carry Flag Non-Carry - indicates no error
AX Extended 1 Number of contiguous KB between 1 and 16 MB,
maximum 0x3C00 = 15 MB.
BX Extended 2 Number of contiguous 64 KB blocks between
16 MB and 4 GB.
CX Configured 1 Number of contiguous KB between 1 and 16 MB,
maximum 0x3C00 = 15 MB.
DX Configured 2 Number of contiguous 64 KB blocks between
16 MB and 4 GB.
</pre>
Not sure what this difference between the "Extended" and "Configured"
numbers are, but they appear to be identical, as reported from the BIOS.<P>
NOTE: It is possible for a machine using this interface to report a memory
hole just under 16 MB (Count 1 is less than 15 MB, but Count 2 is
non-zero).<P>
<HR>
<A NAME="int1588"><H1>INT 15h, AH=88h - Get Extended Memory Size</H1></A>
<HR>
Real mode only.<P>
This interface is quite primitive. It returns a single value for
contiguous memory above 1 MB. The biggest
limitation is that the value returned is a 16-bit value, in KB,
so it has a maximum saturation of just under 64 MB even presuming
it returns as much as it can. On some systems, it won't return
anything above the 16 MB boundary.<P>
The one useful point is that it works on every PC available.<P>
Input:<P>
<pre>
AH Function Code 88h
</pre>
Output:<P>
<pre>
CF Carry Flag Non-Carry - indicates no error
AX Memory Count Number of contiguous KB above 1 MB.
</pre>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

44
docs/menu.lst Normal file
View file

@ -0,0 +1,44 @@
#
# Sample boot menu configuration file
#
# Timeout here...
timeout = 30
# For booting Mach (getting kernel from floppy)
title= Utah Mach4 multiboot
root= (hd0,2)
pause=My test!!
kernel= (fd0)/boot/kernel root=hd0s3
module= (fd0)/boot/bootstrap
# For booting FreeBSD (getting kernel from floppy)
title= FreeBSD 2.2-SNAP
root= (hd0,2)
kernel= (fd0)/kernel
# For booting the GNU HURD (getting kernel from floppy)
title= GNU HURD
root= (hd0,a)
kernel= /boot/kernel root=hd0a
module= /boot/serverboot
# For booting OS/2 (test, I have no OS/2 to test for!)
title= OS/2
root= (hd0,1)
makeactive
chainloader= /boot/chain.os2
# This is similar to "chainload", but loads a specific file
# For booting Windows NT 3.5 or DOS
title= Windows NT 3.5/DOS boot menu
root= (0x80,0)
makeactive
chainloader= +1
# For booting DOS from a Windows NT/DOS installation
title= DOS
root= (0x80,0)
makeactive
chainloader= /bootsect.dos

390
docs/technical.html Normal file
View file

@ -0,0 +1,390 @@
<HTML>
<HEAD>
<TITLE>GRUB Technical Info</TITLE>
</HEAD>
<BODY>
<CENTER><H1>GRUB Technical Info</H1></CENTER>
<CENTER><H3>by
<A HREF=http://www.uruk.org/~erich/>Erich Boleyn</A></H3></CENTER>
<HR>
<H2>Contents</H2>
<UL>
<LI> <A HREF="#challenges">Challenges/Issues</A>
<LI> <A HREF="#specs">Specifications and other Goals</A>
<LI> <A HREF="#features">Features</A>
<LI> <A HREF="#other">Other Implementation Details</A>
</UL>
<HR>
<H2><A NAME="challenges">Challenges/Issues</A></H2>
Several major issues have plagued bootloaders for IBM PC compatibles for
a long time, mostly related to compatibility.<P>
For more detail about the operation of standard floppy and hard disk
bootloaders, I have a 100K text document version of
<A HREF="PC_partitioning.txt">Hale Landis' How It Works Series</A>,
which is about the BIOS, booting, etc., and is very informative, though
mildly outdated, and with what seem to be a few errors. I'm looking into
getting updated information for flushing it out myself into a real
HTML document.<P>
The worst problems and the general way they are solved in GRUB are
listed here (some of these have to be cooperatively solved with the OS):<P>
<H3>Bootloader Size Limits</H3>
Bootloaders have to be very small, typically limited to one or more very
small areas on the media in question.<P>
At the start of the process, the BIOS loads the first block off of the
boot disk (floppy or hard drive), 512 bytes in size. This one block
must be capable of performing all the functions necessary to start up
the system, or handing off to another program. On a hard disk, at
least 64 bytes are reserved for a partition table, therefore unusable.<P>
Traditionally, if the first block is not enough, at the start of the
partition with the OS being booted (or, for a floppy, just at the
beginning) is a fixed area, the size (generally from 512 bytes to
8 Kbytes) of which is dependent on the filesystem variety in question.<P>
Most bootloaders are written to fit within this limitation, giving them
only room for a very sparse functionality.<P>
GRUB is very large compared to other bootloaders (typically
20 to 30 K). A mechanism is
in place which can load all of it's components for different
<A HREF=install.html>installal methods</A>.
The feeling from
the author is that this will not be a problem since most of the features pay
for themselves both in terms of space (certainly the generic decompression
code, for example) and flexibilty
to both end-users and experts.<P>
<H3>Partitioning Issues</H3>
The traditional layout of a floppy on a PC is with the first block
being the boot-controller, and the rest of the disk being formatted
to some filesystem type.<P>
The traditional layout of a hard disk on a PC is with the first block
being the boot-controller, referred to as the MBR (Master Boot Record),
with the rest of the disk subdivided into 4 sections (called
"partitions"), each of which look either like a logical floppy
(boot block + filsystem), or a full hard disk (sort of a recursive
definition here, though only one of the partitions can be one of
these). Inside one of the recursive hard disk definitions, only one
of the 4 partitions can have a filesystem. The pratical result is that
an arbitrary number of partitions can be represented. The biggest
problem here is that generally only one of the 4 partitions listed
directly in the main MBR can be the "active" one, which is the one
where any subsidary boot blocks are pulled from.<P>
Most bootloaders don't deal with the "active partition" marker in
a very intelligent manner.<P>
GRUB can both PC style partitions (normal and extended DOS-style) and
386BSD/Mach style BSD sub-partitions in a consistent manner, plus it
can set the "active partition" marker as desired (he "active partition"
marker is currently irrelevant to GRUBs actual behavior, this still
needs some work related to default device notations).<P>
<H3>Geometry Translation</H3>
There are several methods of using the BIOS to access a disk before
any kind of driver is active. The only consistent one is the INT 13h
interface, which uses an addressing scheme based on the Cylinder, Head,
and Sector positions of a block, packed into a value consisting of 10 bits,
8 bits, and 6 bits, respectively.<P>
To attempt to get around this issue, and in the case of SCSI disks, to allow
a differential number of sectors in different physical cylinders without
confusing the heck out of the software, the concept of Geometry Translation
was introduced. Geometry Translation produces a transparent virtual
mapping from some phantom number of Cylinders, Sectors and Heads onto
the real hardware of the disk, generally trying to increase the space of
the disk accessible via the INT 13h interface.<P>
Another problem created from the above is that different controller/BIOS
combinations (and possibly even different particular installations of
software) can use different geometry translations, and since the bootloaders
on the disk depend on the particular numbers, they either have to be
carefully updated, or, in some cases, the whole OS must be re-installed when
moving the disk to another controller/BIOS combination.<P>
The essential issue is that pretty much all bootloaders prior to GRUB use
Cylinder/Head/Sector numbers for the first stage of booting, so if
that mapping should change, your OS can't boot, even though the linear
mapping is the same, and if you could get it booted somehow, everything
work would fine.<P>
GRUB solves this by translating from/to a linear block-number
<B>AT ALL TIMES</B>. This turns out to be OK, as the major OS used
to test a BIOS translation mechanism, DOS, uses exactly the same
mappings.<P>
<H3>512MB - 8GB BIOS Translation Size Limits</H3>
Related to the Gemetry Translation problem is the problem that in standard
INT 13h BIOS interface has a maximum of 24 bits to access the disk with.<P>
The problem is that even
presuming a perfectly spanned space, 24 bits is only 16 M blocks,
and at 512 bytes each,
this is a maximum disk size of 8 GB. Most real systems have limitations
of either 512 MB (this is where the IDE limit of 508 MB comes from, I'm
pretty sure, as the top 4 bits of the "head" number can't be used
in most BIOS IDE interfaces), or 1 GB, though this is changing, moving
toward the 8 GB maximum size.<P>
GRUB can't universally solve this problem, as there is no new interface
which is used in all machines. At least one newer interface which
is present on some machines ("LBA", which is in more and more new
ones, supposedly) may
be able to be used transparently in place of INT 13h when available.
This is still being investigated.<P>
<H3>Memory size determination</H3>
Various OS's do this differently. Some rely on their bootloader, and
some perform the probe themselves. Most are limited to detecting a
maximum of 64MB on a PC, in any case. Kludges where a hard-coded
portion telling the machine how much RAM is installed, or even compiling
it in, have been made for many OSes.<P>
Since this is both once-only
code and only involves the BIOS, the solution which Multiboot and
GRUB uses is to perform the probe in the bootloader.
Look at the bulleted item "Detects all Installed RAM" in the section
<A HREF="#features">Features</A> below.<P>
<HR>
<H2><A NAME="specs">Specifications and other Goals</A></H2>
The primary requirement for GRUB is that it be compliant with the
<A HREF="boot-proposal.html">Multiboot Standard</A>.<P>
The other goals, listed in approximate order of importance, are:<P>
<UL>
<LI>Basic functions must be easy for an end-user to use.<P>
<LI>Rich functionality for OS experts/designers.<P>
<LI>Compatibility for booting FreeBSD, NetBSD, and Linux.
Proprietary OS's such as DOS, Windows NT, and OS/2 are
supported via a chain-loading function.<P>
</UL>
Except for specific compatibility modes (chain-loading and the
Linux 'piggyback' format),
all kernels will be started in much the same state as in the Multiboot
Standard listed above. Only kernels being loaded at 1 megabyte or above
are presently supported. Any attempt to load below that boundary will
simply result in immediate failure and an error message reporting the
problem.<P>
<HR>
<H2><A NAME="features">Features</A></H2>
In addition to the requirements in the previous section, GRUB has the
following features (note that the Multiboot Standard doesn't explicitly
require everything listed in it, but GRUB will support all options):<P>
<UL>
<LI><B>Multiple Executable Formats</B>: Supports many of the <B>a.out</B>
variants plus <B>ELF</B>. Any symbol table present is also loaded.<P>
<LI><B>Supports Non-Multiboot OS's</B>: Supports many of the various
free 32-bit OS's prior to any Multiboot compliance. Chiefly FreeBSD,
NetBSD, and Linux. Chain-loading is also supported.<P>
<LI><B>Loads Multiple Modules</B>: Multiboot feature of loading multiple
modules is fully supported.<P>
<LI><B>Configuration File</B>:
Supports a human-readable text configuration file with preset boot commands.
The <A HREF=commands.txt>list of commands</A> are a superset
of those supported on the command-line.
An <A HREF=menu.lst>example command-file</A> is provided.<P>
<LI><B>Menu Interface</B>: A menu-interface listing
the preset boot commands, with a programmable timeout, is available.
There is no fixed limit on the number of boot command-set entries, and
should have space for several hundred.<P>
<LI><B>Flexible Command-Line Interface</B>: A fairly flexible
command-line interface, accessible from the
menu, is available to edit any preset commands, or simply start a new
command-set from scratch.
The <A HREF=commands.txt>list of commands</A> are a subset of those
supported for command-files. Editing commands closely resemble the
BASH shell command-line, with TAB-completion-listing (it doesn't
perform the completion, just lists the possibilities) of commands,
devices, partitions, and files in a directory depending on context.
If no config file is present, it goes into the command-line.<P>
<LI><B>Multiple Filesystem Types</B>: Supports multiple filesystem
types transparently, plus an explicitly usable block-list notation.
The currently supported filesystem types are <B>BSD FFS</B>, <B>DOS FAT</B>,
and <B>Linux ext2fs</B>. There is also a page describing the
<A HREF=filesystem.txt>GRUB filesystems and interfaces</A>.<P>
<LI><B>Decompression Support</B>: Can decompress files which were
compressed with using "gzip". This function is both automatic and
transparent to the user (i.e. all functions operate normally upon
the uncompressed contents of the files in question). This is a win
on 2 fronts, as it both greatly reduces file size and loading time (there
are a few pathological cases where loading a very badly organized ELF
kernel might make it take longer, but IMO you'll never see this in
practice), a particularly major win for floppies. It is conceivable
that some kernel modules should be loaded in a compressed state, so a
variant of the module loading command which doesn't uncompress them
can be used.<P>
<LI><B>Access Data on Any Installed Device</B>: Supports reading data
from any or all floppy or hard disk(s) recognized by the BIOS, independent
of the setting for the root partition.<P>
<LI><B>Geometry Translation-Idependent</B>: Subject to the constraint
that it cannot go past the end of the geometry-translated area of a drive,
the particular translation used is generally irrelevant. This implies a
drive installed and running on a controller with one translation in use
may in general be moved to another controller with a different translation
(or the translation settings on the first controller, if configurable,
may be changed) with no adverse effects and no other changes necessary.<P>
<LI><B>Detects All Installed RAM</B>: GRUB can generally find all the
installed RAM on a PC-compatible machine. It uses the
BIOS query technique described on the
<A HREF="mem64mb.html">
INT 15h, AX=E820h - Query System Address Map</A> web page. As described on
the Multiboot Standard web page listed above, OS's which only use the
lower and upper memory values (whose presence is determined by bit 0 of
the flags word passed to the OS) may not be capable of receiving information
on all of installed memory. On most machines, upper memory is contiguous,
so the problem does not arise.<P>
</UL>
Future directions might include an internal programming language for
supporting richer sets of boot options with control statements
(it becomes a boot-script at that point),
and possibly support for non-IBM PC-compatible machines.<P>
One definite path for future work is how to fairly transparently get
around the 8 GB geometry translation limitation.<P>
<HR>
<H2><A NAME="other">Other Implementation Details</A></H2>
GRUB can completely replace the primary bootloader on a hard disk or
floppy disk. On a hard disk, it can also be run after some other
bootloader capable of chain-loading.<P>
GRUB is broken into 2 distinct components, or stages, which are loaded at
different times in the boot process. The Stage 1 has to know where to
find Stage 2, and the Stage 2 has to know where to find it's configuration
file (if Stage 2 doesn't have a config file, it drops into the command-line
interface and waits for a user command).<P>
Here is a memory map of the various components:<P>
<pre>
0 to 4K-1 : Interrupt & BIOS area.
down from 8K-1 : 16-bit stack area.
8K to (ebss1.5) : Stage-1.5 (optionally) loaded here by Stage-1.
0x7c00 to 0x7dff : Stage-1 loaded here by the BIOS.
0x7e00 to 0x7e08 : scratch space used by Stage-1.
32K to (ebss2) : Stage-2 loaded here by Stage-1.5 or Stage-1.
(middle area) : heap used for random memory allocation.
down from 416K-1 : 32-bit stack area.
416K to 448K-1 : Filesystem info buffer (when reading a filesys).
448K to 479.5K-1 : BIOS track read buffer.
479.5K to 480K-1 : 512 byte fixed SCRATCH area.
480K to 511K-1 : general storage heap.
</pre>
Description of GRUB's major components (and some of the boot sequence):<P>
<H3>Stage 1</H3>
Stage 1 is only used to load Stage 2. If Stage 2 can be loaded in
some other manner in a compatible fashion, then Stage 1 is unnecessary,
and doesn't need to be used.<P>
<UL>
<LI>On a floppy, there is generally only one possible boot area, the first
boot sector. The Stage 1 portion would go there.<P>
<LI>On a hard disk, Stage 1 can be part of the MBR block or part of the
first block of some partition.<P>
</UL>
Stage 1 "knows" where Stage 2 is by entries in a block-list loading table
embedded in it. It loads the lists of blocks off of the booting drive,
then jumps to a specified CS:IP in 16-bit real mode. These are described
in the page on <A HREF=embedded_data.txt>embedded data</A>. It queries the
BIOS for the disk geometry, and maps the linear block numbers there to
C:H:S addresses used by the INT 13h BIOS interface.<P>
See the <A HREF=install.html>Installation
Guide</A> for details on how to set up loading Stage 2 from Stage 1.<P>
<H3>OPTIONAL Stage 1.5</H3>
Since the Stage 2 is so large (typically 30K or larger in size),
a special stripped down version of the
Stage 2 code, sort of a Stage 1.5, can be used because it might fit into
one of the fixed areas of the disk. The idea is to have the Stage 1.5
look for a certain file and attempt to execute it as a Stage 2 (this
allows changing Stage 2 easily, while leaving it a normal file in
the filesystem).<P>
This is actually the case for the BSD FFS filesystem. There is a fixed
area 7K in size at the beginning of the partition which is reserved for
the bootloader. The Stage 1.5 with BSD FFS filesystem support is
about 6.5 K in size when compiled in a.out format, and fits nicely,
allowing the Stage 2 to be a normal file in the "/boot/grub" directory
of the install partition.<P>
This same technique can in principle be applied to other filesystems,
but the problem here is that the fixed area available to bootloaders is
generally quite small (0.5 to 3 K), and a Stage 1.5 wouldn't fit.<P>
It contains
<A HREF=embedded_data.txt>embedded data</A>
on where to look for the install partition
and the Stage 2 (it uses what would be the "configuration file"
entry in the Stage 2 for this purpose).<P>
<H3>Stage 2</H3>
This component is the GRUB proper.<P>
It gets most of the information about the machine and the boot state
from the BIOS and information passed into it at starting time, except
that it contains
<A HREF=embedded_data.txt>embedded data</A>
on where to look for the install partition and the configuration file.<P>
The first action of the Stage 2 is to look for it's configuration file.
If one is not found, then
it drops into the command-line interface.
If one is found, the full menu interface is activated containing
whatever entries were found in the file (the command-line is still
available via a command from the menu interface).<P>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

99
docs/using.html Normal file
View file

@ -0,0 +1,99 @@
<HTML>
<HEAD>
<TITLE>Using GRUB</TITLE>
</HEAD>
<BODY>
<CENTER><H1>Using GRUB</H1></CENTER>
<CENTER><H3>by
<A HREF=http://www.uruk.org/~erich/>Erich Boleyn</A></H3></CENTER>
<HR>
<H2>Contents</H2>
<UL>
<LI> <A HREF="#cmdline">Command-Line Interface</A>
<LI> <A HREF="#menu">Menu Interface</A>
<LI> <A HREF="#editor">Menu Entry Editor</A>
</UL>
GRUB has both a simple menu interface for preset options from a
configuration file, and a highly flexible command-line for performing
any desired combination of boot commands.<P>
The first action GRUB takes after it is loaded is
to look for it's configuration file.
If one is not found, then
it drops into the command-line interface (and stays there).
If one is found, the full menu interface is activated containing
whatever entries were found in the file (the command-line is still
available via a command from the menu interface).<P>
<HR>
<H2><A NAME="cmdline">Command-Line Interface</A></H2>
The command-line interface provides a prompt and after it an editable
text area much like a command-line in DOS or UNIX. Each command is
immediately executed after it is entered. The
<A HREF=commands.txt>list of commands</A> are a subset of those available
in the configuration file, used with exactly the same syntax.<P>
Cursor movement and editing of the text on the line can be done
via a subset of the functions
available in the BASH shell (C-f forward, C-b backward, C-a beginning
of line, C-e end of line, C-k delete to end, C-u delete to beginning;
the PC left and right arrow keys, HOME, DELETE, and END work as well).<P>
When typing commands interactively, if the cursor is before the "="
character in a command being typed, pressing the TAB key will display
a listing of the available commands, and if the cursor is after the
"=" character, the TAB will provide
a completion listing of disks, partitions, and filenames depending on
the context.<P>
<HR>
<H2><A NAME="menu">Menu Interface</A></H2>
The menu interface is quite easy to use. It's commands are both
reasonably intuitive and described onscreen.<P>
Basically, the menu interface provides a list of "boot configurations"
to the user to choose from. Use the arrow keys to select the entry
of choice, then press ENTER to run it. An optional timeout is available
to boot the default entry (the first one if not set),
which is aborted by pressing any key.<P>
Commands are available to enter a bare command-line (operating
exactly like the non-config-file version of GRUB, but allowing one to
return to the menu if desired) or to edit any of the "boot
configurations".
<HR>
<H2><A NAME="editor">Menu Entry Editor</A></H2>
This looks much like the main menu interface, but with the lines in the
menu being individual commands of the selected configuration instead of
configuration names.<P>
If an ESC is pressed in the editor, it aborts all the changes made to
the configuration entry and goes back to the main menu interface.<P>
When a particular line is selected, then it
places the user in a special version of the command-line for editing
that line. When the user is finished, GRUB replaces the line in question
in the "boot configuration" with the changes (unless it was aborted via
ESC, and in that case the changes are thrown away).<P>
<HR>
<A HREF=mailto:erich@uruk.org><I>erich@uruk.org</I></A><P>
</BODY>
</HTML>

50
ffs_stage1_5/Makefile Normal file
View file

@ -0,0 +1,50 @@
#
# GRUB ffs_stage1_5 makefile
#
CFLAGS= $(SHARED_FLAGS) -DFSYS_FFS -DNO_DECOMPRESSION -DNO_FANCY_STUFF \
-DNO_BLOCK_FILES -DCONFIG_FILE_ASM=".string \"/boot/grub/stage2\"" \
-I../shared_src
# "asm.o" absolutely has to come first in the link line!
SHARED_OBJS= asm.o char_io.o common.o disk_io.o stage1_5.o fsys_ffs.o
all: ../bin/ffs_stage1_5
asm.o: ../shared_src/asm.S ../shared_src/shared.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/asm.S
char_io.o: ../shared_src/char_io.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/char_io.c
common.o: ../shared_src/common.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/common.c
disk_io.o: ../shared_src/disk_io.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/disk_io.c
stage1_5.o: ../shared_src/stage1_5.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/stage1_5.c
fsys_ffs.o: ../shared_src/fsys_ffs.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h \
../shared_src/defs.h ../shared_src/disk_inode.h \
../shared_src/disk_inode_ffs.h ../shared_src/dir.h \
../shared_src/fs.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_ffs.c
# "asm.o" absolutely has to come first in the link line!
ffs_stage1_5.exec: $(SHARED_OBJS) Makefile ../Makefile
$(LD) -N -Ttext 2000 -o ffs_stage1_5.exec $(SHARED_OBJS)
../bin/ffs_stage1_5: ffs_stage1_5.exec Makefile ../Makefile
$(OBJCOPY) -O binary ffs_stage1_5.exec ../bin/ffs_stage1_5
clean:
rm -f $(SHARED_OBJS) ffs_stage1_5.exec

73
shared_src/apic.h Normal file
View file

@ -0,0 +1,73 @@
/*
* <Insert copyright here : it must be BSD-like so everyone can use it>
*
* Author: Erich Boleyn <erich@uruk.org> http://www.uruk.org/~erich/
*
* Header file for Intel Architecture local and I/O APIC definitions.
*
* This file was created from information in the Intel Pentium Pro
* Family Developer's Manual, Volume 3: Operating System Writer's
* Manual, order number 242692-001, which can be ordered from the
* Intel literature center.
*/
#ifndef _APIC_H
#define _APIC_H
/*
* APIC Defines.
*/
#define APIC_BROADCAST_ID 0xFF
/*
* APIC register definitions
*/
/*
* Shared defines for I/O and local APIC definitions
*/
/* APIC version register */
#define APIC_VERSION(x) ((x) & 0xFF)
/* if the APIC version is equal or greater than APIC_VER_NEW, it
is a "new" APIC */
#define APIC_VER_NEW 0x10
/* this next one is used in all cases but an old local APIC, which has
2 entries in it's LVT */
#define APIC_MAXREDIR(x) (((x) >> 16) & 0xFF)
/* APIC id register */
#define APIC_OLD_ID(x) ((x) >> 24)
#define APIC_NEW_ID(x) (((x) >> 24) & 0xF)
#define IOAPIC_REGSEL 0
#define IOAPIC_RW 0x10
#define IOAPIC_ID 0
#define IOAPIC_VER 1
#define IOAPIC_REDIR 0x10
#define LAPIC_ID 0x20
#define LAPIC_VER 0x30
#define LAPIC_TPR 0x80
#define LAPIC_APR 0x90
#define LAPIC_PPR 0xA0
#define LAPIC_EOI 0xB0
#define LAPIC_LDR 0xD0
#define LAPIC_DFR 0xE0
#define LAPIC_SPIV 0xF0
#define LAPIC_SPIV_ENABLE_APIC 0x100
#define LAPIC_ISR 0x100
#define LAPIC_TMR 0x180
#define LAPIC_IRR 0x200
#define LAPIC_ESR 0x280
#define LAPIC_ICR 0x300
#define LAPIC_DEST_MASK 0xFFFFFF
#define LAPIC_LVTT 0x320
#define LAPIC_LVTPC 0x340
#define LAPIC_LVT0 0x350
#define LAPIC_LVT1 0x360
#define LAPIC_LVTE 0x370
#define LAPIC_TICR 0x380
#define LAPIC_TCCR 0x390
#define LAPIC_TDCR 0x3E0
#endif /* _APIC_H */

549
shared_src/smp-imps.c Normal file
View file

@ -0,0 +1,549 @@
/*
* <Insert copyright here : it must be BSD-like so anyone can use it>
*
* Author: Erich Boleyn <erich@uruk.org> http://www.uruk.org/~erich/
*
* Source file implementing Intel MultiProcessor Specification (MPS)
* version 1.1 and 1.4 SMP hardware control for Intel Architecture CPUs,
* with hooks for running correctly on a standard PC without the hardware.
*
* This file was created from information in the Intel MPS version 1.4
* document, order number 242016-004, which can be ordered from the
* Intel literature center.
*
* General limitations of this code:
*
* (1) : This code has never been tested on an MPS-compatible system with
* 486 CPUs, but is expected to work.
* (2) : Presumes "int", "long", and "unsigned" are 32 bits in size, and
* that 32-bit pointers and memory addressing is used uniformly.
*/
#define _SMP_IMPS_C
/*
* XXXXX The following absolutely must be defined!!!
*
* The "KERNEL_PRINT" could be made a null macro with no danger, of
* course, but pretty much nothing would work without the other
* ones defined.
*/
#if 0
#define KERNEL_PRINT(x) /* some kind of print function */
#define CMOS_WRITE_BYTE(x,y) /* write unsigned char "y" at CMOS loc "x" */
#define CMOS_READ_BYTE(x) /* read unsigned char at CMOS loc "x" */
#define PHYS_TO_VIRTUAL(x) /* convert physical address "x" to virtual */
#define VIRTUAL_TO_PHYS(x) /* convert virtual address "x" to physical */
#endif
/*
* Includes here
*/
#include "apic.h"
#include "smp-imps.h"
/*
* Defines that are here so as not to be in the global header file.
*/
#define EBDA_SEG_ADDR 0x40E
#define BIOS_RESET_VECTOR 0x467
#define LAPIC_ADDR_DEFAULT 0xFEE00000uL
#define IOAPIC_ADDR_DEFAULT 0xFEC00000uL
#define CMOS_RESET_CODE 0xF
#define CMOS_RESET_JUMP 0xa
#define CMOS_BASE_MEMORY 0x15
/*
* Static defines here for SMP use.
*/
#define DEF_ENTRIES 23
static int lapic_dummy = 0;
static struct {
imps_processor proc[2];
imps_bus bus[2];
imps_ioapic ioapic;
imps_interrupt intin[16];
imps_interrupt lintin[2];
} defconfig = {
{ { IMPS_BCT_PROCESSOR, 0, 0, 0, 0, 0},
{ IMPS_BCT_PROCESSOR, 1, 0, 0, 0, 0} },
{ { IMPS_BCT_BUS, 0, {'E', 'I', 'S', 'A', ' ', ' '}},
{ 255, 1, {'P', 'C', 'I', ' ', ' ', ' '}} },
{ IMPS_BCT_IOAPIC, 0, 0, IMPS_FLAG_ENABLED, IOAPIC_ADDR_DEFAULT },
{ { IMPS_BCT_IO_INTERRUPT, IMPS_INT_EXTINT, 0, 0, 0, 0xFF, 0},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 1, 0xFF, 1},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 0, 0xFF, 2},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 3, 0xFF, 3},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 4, 0xFF, 4},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 5, 0xFF, 5},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 6, 0xFF, 6},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 7, 0xFF, 7},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 8, 0xFF, 8},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 9, 0xFF, 9},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 10, 0xFF, 10},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 11, 0xFF, 11},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 12, 0xFF, 12},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 13, 0xFF, 13},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 14, 0xFF, 14},
{ IMPS_BCT_IO_INTERRUPT, IMPS_INT_INT, 0, 0, 15, 0xFF, 15} },
{ { IMPS_BCT_LOCAL_INTERRUPT, IMPS_INT_EXTINT, 0, 0, 15, 0xFF, 0},
{ IMPS_BCT_LOCAL_INTERRUPT, IMPS_INT_NMI, 0, 0, 15, 0xFF, 1} }
};
/*
* Exported globals here.
*/
int imps_any_new_apics = 0;
volatile int imps_release_cpus = 0;
int imps_enabled = 0;
int imps_num_cpus = 1;
unsigned imps_lapic_addr = ((unsigned)(&lapic_dummy)) - LAPIC_ID;
unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
/*
* MPS checksum function
*
* Function finished.
*/
static int
get_checksum(unsigned start, int length)
{
unsigned sum = 0;
while (length-- > 0) {
sum += *((unsigned char *) (start++));
}
return (sum&0xFF);
}
/*
* Primary function for booting individual CPUs.
*
* This must be modified to perform whatever OS-specific initialization
* that is required.
*/
static int
boot_cpu(imps_processor *proc)
{
int apicid = proc->apic_id;
unsigned bootaddr, send_status, accept_status, cfg;
unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
/* %%%%% ESB */
extern char patch_code[];
bootaddr = 256*1024;
bcopy(patch_code, (char *)bootaddr, 32);
/*
* Generic CPU startup sequence starts here.
*/
/* set BIOS reset vector */
CMOS_WRITE_BYTE(CMOS_RESET_CODE, CMOS_RESET_JUMP);
*((volatile unsigned *) bios_reset_vector) = bootaddr << 12;
/* clear the error register */
if (proc->apic_ver & 0x10) {
IMPS_LAPIC_WRITE(LAPIC_ESR, 0);
accept_status = IMPS_LAPIC_READ(LAPIC_ESR);
}
#if 0
/* assert INIT IPI */
cfg = IMPS_LAPIC_READ(LAPIC_ICR+1);
cfg &= LAPIC_DEST_MASK;
IMPS_LAPIC_WRITE(LAPIC_ICR+1, cfg);
cfg = IMPS_LAPIC_READ(LAPIC_ACR);
cfg &= ;
/* %%%%% ESB finish adding startup sequence */
#endif
/* clean up BIOS reset vector */
CMOS_WRITE_BYTE(CMOS_RESET_CODE, 0);
*((volatile unsigned *) bios_reset_vector) = 0;
/*
* Generic CPU startup sequence ends here.
*/
KERNEL_PRINT(("\n"));
return 1;
/* XXXXX add OS-specific initialization here! */
}
/*
* read bios stuff and fill tables
*/
static void
add_processor(imps_processor *proc)
{
int apicid = proc->apic_id;
KERNEL_PRINT((" Processor [APIC id %d ver %d]: ",
apicid, proc->apic_ver));
if (!(proc->flags & IMPS_FLAG_ENABLED)) {
KERNEL_PRINT(("DISABLED\n"));
return;
}
if (proc->apic_ver > 0xF) {
imps_any_new_apics = 1;
}
if (proc->flags & (IMPS_CPUFLAG_BOOT)) {
KERNEL_PRINT(("#0 Bootstrap Processor (BSP)\n"));
return;
}
imps_cpu_apic_map[imps_num_cpus] = apicid;
imps_apic_cpu_map[apicid] = imps_num_cpus;
if (boot_cpu(proc)) {
/* XXXXX add OS-specific setup for secondary CPUs here */
imps_num_cpus++;
}
}
static void
add_bus(imps_bus *bus)
{
char str[8];
bcopy(bus->bus_type, str, 6);
str[6] = 0;
KERNEL_PRINT((" Bus id %d is %s\n", bus->id, str));
/* XXXXX add OS-specific code here */
}
static void
add_ioapic(imps_ioapic *ioapic)
{
KERNEL_PRINT((" I/O APIC id %d ver %d, address: 0x%x ",
ioapic->id, ioapic->ver, ioapic->addr));
if (!(ioapic->flags & IMPS_FLAG_ENABLED)) {
KERNEL_PRINT(("DISABLED\n"));
return;
}
KERNEL_PRINT(("\n"));
/* XXXXX add OS-specific code here */
}
static void
imps_read_config_table(unsigned start, int count)
{
while (count-- > 0) {
switch (*((unsigned char *)start)) {
case IMPS_BCT_PROCESSOR:
add_processor((imps_processor *)start);
start += 12; /* 20 total */
break;
case IMPS_BCT_BUS:
add_bus((imps_bus *)start);
break;
case IMPS_BCT_IOAPIC:
add_ioapic((imps_ioapic *)start);
break;
#if 0 /* XXXXX uncomment this if "add_io_interrupt" is implemented */
case IMPS_BCT_IO_INTERRUPT:
add_io_interrupt((imps_interrupt *)start);
break;
#endif
#if 0 /* XXXXX uncomment this if "add_local_interrupt" is implemented */
case IMPS_BCT_LOCAL_INTERRUPT:
add_local_interupt((imps_interrupt *)start);
break;
#endif
default:
}
start += 8;
}
}
static int
imps_bad_bios(imps_fps *fps_ptr)
{
int sum;
imps_cth *local_cth_ptr
= (imps_cth *) PHYS_TO_VIRTUAL(fps_ptr->cth_ptr);
if (fps_ptr->feature_info[0] > IMPS_FPS_DEFAULT_MAX) {
KERNEL_PRINT((" Invalid MP System Configuration type %d\n",
fps_ptr->feature_info[0]));
return 1;
}
if (fps_ptr->cth_ptr) {
sum = get_checksum((unsigned)local_cth_ptr,
local_cth_ptr->base_length);
if (local_cth_ptr->sig != IMPS_CTH_SIGNATURE || sum) {
KERNEL_PRINT((" Bad MP Config Table sig 0x%x and/or checksum 0x%x\n", (unsigned)(fps_ptr->cth_ptr), sum));
return 1;
}
if (local_cth_ptr->spec_rev != fps_ptr->spec_rev) {
KERNEL_PRINT((" Bad MP Config Table sub-revision # %d\n", local_cth_ptr->spec_rev));
return 1;
}
if (local_cth_ptr->extended_length) {
sum = (get_checksum(((unsigned)local_cth_ptr)
+ local_cth_ptr->base_length,
local_cth_ptr->extended_length)
+ local_cth_ptr->extended_checksum) & 0xFF;
if (sum) {
KERNEL_PRINT((" Bad Extended MP Config Table checksum 0x%x\n", sum));
return 1;
}
}
} else if (!fps_ptr->feature_info[0]) {
KERNEL_PRINT((" Missing configuration information\n"));
return 1;
}
return 0;
}
static void
imps_read_bios(imps_fps *fps_ptr)
{
int apicid;
unsigned cth_start, cth_count;
imps_cth *local_cth_ptr
= (imps_cth *)PHYS_TO_VIRTUAL(fps_ptr->cth_ptr);
char *str_ptr;
KERNEL_PRINT(("Intel MultiProcessor Spec 1.%d BIOS support detected\n",
fps_ptr->spec_rev));
/*
* Do all checking of errors which would definitely
* lead to failure of the SMP boot here.
*/
if (imps_bad_bios(fps_ptr)) {
KERNEL_PRINT((" Disabling MPS support\n"));
return;
}
if (fps_ptr->feature_info[1] & IMPS_FPS_IMCRP_BIT) {
str_ptr = "IMCR and PIC";
} else {
str_ptr = "Virtual Wire";
}
if (fps_ptr->cth_ptr) {
imps_lapic_addr = local_cth_ptr->lapic_addr;
} else {
imps_lapic_addr = LAPIC_ADDR_DEFAULT;
}
KERNEL_PRINT((" APIC config: \"%s mode\" Local APIC address: 0x%x\n",
str_ptr, imps_lapic_addr));
imps_lapic_addr = PHYS_TO_VIRTUAL(imps_lapic_addr);
/*
* Setup primary CPU.
*/
apicid = IMPS_LAPIC_READ(LAPIC_SPIV);
IMPS_LAPIC_WRITE(LAPIC_SPIV, apicid|LAPIC_SPIV_ENABLE_APIC);
imps_any_new_apics = IMPS_LAPIC_READ(LAPIC_VER) & 0xF0;
apicid = IMPS_APIC_ID(IMPS_LAPIC_READ(LAPIC_ID));
imps_cpu_apic_map[0] = apicid;
imps_apic_cpu_map[apicid] = 0;
if (fps_ptr->cth_ptr) {
char str1[16], str2[16];
bcopy(local_cth_ptr->oem_id, str1, 8);
str1[8] = 0;
bcopy(local_cth_ptr->prod_id, str2, 12);
str2[12] = 0;
KERNEL_PRINT((" OEM id: %s Product id: %s\n", str1, str2));
cth_start = ((unsigned) local_cth_ptr) + sizeof(imps_cth);
cth_count = local_cth_ptr->entry_count;
} else {
*((volatile unsigned *) IOAPIC_ADDR_DEFAULT) = IOAPIC_ID;
defconfig.ioapic.id
= IMPS_APIC_ID(*((volatile unsigned *)
(IOAPIC_ADDR_DEFAULT+IOAPIC_RW)));
*((volatile unsigned *) IOAPIC_ADDR_DEFAULT) = IOAPIC_VER;
defconfig.ioapic.ver
= APIC_VERSION(*((volatile unsigned *)
(IOAPIC_ADDR_DEFAULT+IOAPIC_RW)));
defconfig.proc[apicid].flags
= IMPS_FLAG_ENABLED|IMPS_CPUFLAG_BOOT;
defconfig.proc[!apicid].flags = IMPS_FLAG_ENABLED;
imps_num_cpus = 2;
if (fps_ptr->feature_info[0] == 1
|| fps_ptr->feature_info[0] == 5) {
bcopy("ISA ", defconfig.bus[0].bus_type, 6);
}
if (fps_ptr->feature_info[0] == 4
|| fps_ptr->feature_info[0] == 7) {
bcopy("MCA ", defconfig.bus[0].bus_type, 6);
}
if (fps_ptr->feature_info[0] > 4) {
defconfig.proc[0].apic_ver = 0x10;
defconfig.proc[1].apic_ver = 0x10;
defconfig.bus[1].type = IMPS_BCT_BUS;
}
if (fps_ptr->feature_info[0] == 2) {
defconfig.intin[2].type = 255;
defconfig.intin[13].type = 255;
}
if (fps_ptr->feature_info[0] == 7) {
defconfig.intin[0].type = 255;
}
cth_start = (unsigned) &defconfig;
cth_count = DEF_ENTRIES;
}
imps_read_config_table(cth_start, cth_count);
/* %%%%% ESB read extended entries here */
imps_enabled = 1;
}
/*
* Given a region to check, this actually looks for the "MP Floating
* Pointer Structure". The return value indicates if the correct
* signature and checksum for a floating pointer structure of the
* appropriate spec revision was found. If so, then do not search
* further.
*
* NOTE: The memory scan will always be in the bottom 1 MB.
*
* This function presumes that "start" will always be aligned to a 16-bit
* boundary.
*
* Function finished.
*/
static int
imps_scan(unsigned start, unsigned length)
{
IMPS_DEBUG_PRINT(("Scanning from 0x%x for %d bytes\n",
start, length));
while (length > 0) {
imps_fps *fps_ptr = (imps_fps *) PHYS_TO_VIRTUAL(start);
if (fps_ptr->sig == IMPS_FPS_SIGNATURE
&& fps_ptr->length == 1
&& (fps_ptr->spec_rev == 1 || fps_ptr->spec_rev == 4)
&& !get_checksum(start, 16)) {
IMPS_DEBUG_PRINT(("Found MP Floating Structure Pointer at %x\n", start));
imps_read_bios(fps_ptr);
return 1;
}
length -= 16;
start += 16;
}
return 0;
}
/*
* This is the primary function for probing for MPS compatible hardware
* and BIOS information. Call this during the early stages of OS startup,
* before memory can be messed up.
*
* The probe looks for the "MP Floating Pointer Structure" at locations
* listed at the top of page 4-2 of the spec.
*
* Environment requirements from the OS to run:
*
* (1) : A non-linear virtual to physical memory mapping is probably OK,
* as (I think) the structures all fall within page boundaries,
* but a linear mapping is recommended. Currently assumes that
* the mapping will remain identical over time (which should be
* OK since it only accesses memory which shouldn't be munged
* by the OS anyway).
* (2) : The OS only consumes memory which the BIOS says is OK to use,
* and not any of the BIOS standard areas (the areas 0x400 to
* 0x600, the EBDA, 0xE0000 to 0xFFFFF, and unreported physical
* RAM). Sometimes a small amount of physical RAM is not
* reported by the BIOS, to be used to store MPS and other
* information.
* (3) : It must be possible to read the CMOS.
* (4) : There must be between 512K and 640K of lower memory (this is a
* sanity check).
*
* Function finished.
*/
int
imps_probe(void)
{
/*
* Determine possible address of the EBDA
*/
unsigned ebda_addr = *((unsigned short *)
PHYS_TO_VIRTUAL(EBDA_SEG_ADDR)) << 4;
/*
* Determine amount of installed lower memory (not *available*
* lower memory).
*
* NOTE: This should work reliably as long as we verify the
* machine is at least a system that could possibly have
* MPS compatibility to begin with.
*/
unsigned mem_lower = ((CMOS_READ_BYTE(CMOS_BASE_MEMORY+1) << 8)
| CMOS_READ_BYTE(CMOS_BASE_MEMORY)) << 10;
#ifdef IMPS_DEBUG
imps_enabled = 0;
imps_num_cpus = 1;
#endif
/*
* Sanity check : if this isn't reasonable, it is almost impossibly
* unlikely to be an MPS compatible machine, so return failure.
*/
if (mem_lower < 512*1024 || mem_lower > 640*1024) {
return 0;
}
if (ebda_addr > mem_lower - 1024
|| ebda_addr + *((unsigned char *) PHYS_TO_VIRTUAL(ebda_addr))
* 1024 > mem_lower) {
ebda_addr = 0;
}
if (((ebda_addr && imps_scan(ebda_addr, 1024))
|| (!ebda_addr && imps_scan(mem_lower - 1024, 1024))
|| imps_scan(0xF0000, 0x10000)) && imps_enabled) {
return 1;
}
/*
* If no BIOS info on MPS hardware is found, then return failure.
*/
return 0;
}

239
shared_src/smp-imps.h Normal file
View file

@ -0,0 +1,239 @@
/*
* <Insert copyright here : it must be BSD-like so everyone can use it>
*
* Author: Erich Boleyn <erich@uruk.org> http://www.uruk.org/~erich/
*
* Header file implementing Intel MultiProcessor Specification (MPS)
* version 1.1 and 1.4 SMP hardware control for Intel Architecture CPUs,
* with hooks for running correctly on a standard PC without the hardware.
*
* This file was created from information in the Intel MPS version 1.4
* document, order number 242016-004, which can be ordered from the
* Intel literature center.
*/
#ifndef _SMP_IMPS_H
#define _SMP_IMPS_H
/* make sure "apic.h" is included */
#ifndef _APIC_H
#error Must include "apic.h" before "smp-imps.h"
#endif /* !_APIC_H */
/*
* Defines used.
*/
#ifdef IMPS_DEBUG
#define IMPS_DEBUG_PRINT(x) KERNEL_PRINT(x)
#else /* !IMPS_DEBUG */
#define IMPS_DEBUG_PRINT(x)
#endif /* !IMPS_DEBUG */
#define IMPS_MAX_CPUS APIC_BROADCAST_ID
/*
* Defines representing limitations on values usable in different
* situations. This mostly depends on whether the APICs are old
* (82489DX) or new (SIO or Pentium/Pentium Pro integrated APICs).
*
* NOTE: It appears that the APICs must either be all old or all new,
* or broadcasts won't work right.
* NOTE #2: Given that, the maximum ID which can be sent to predictably
* is 14 for new APICs and 254 for old APICs. So, this all implies that
* a maximum of 15 processors is supported with the new APICs, and a
* maximum of 255 processors with the old APICs.
*/
#define IMPS_APIC_ID(x) \
( imps_any_new_apics ? APIC_NEW_ID(x) : APIC_OLD_ID(x) )
/*
* This is the value that must be in the "sig" member of the MP
* Floating Pointer Structure.
*/
#define IMPS_FPS_SIGNATURE ('_' | ('M'<<8) | ('P'<<16) | ('_'<<24))
#define IMPS_FPS_IMCRP_BIT 0x80
#define IMPS_FPS_DEFAULT_MAX 7
/*
* This is the value that must be in the "sig" member of the MP
* Configuration Table Header.
*/
#define IMPS_CTH_SIGNATURE ('P' | ('C'<<8) | ('M'<<16) | ('P'<<24))
/*
* These are the "type" values for Base MP Configuration Table entries.
*/
#define IMPS_FLAG_ENABLED 1
#define IMPS_BCT_PROCESSOR 0
#define IMPS_CPUFLAG_BOOT 2
#define IMPS_BCT_BUS 1
#define IMPS_BCT_IOAPIC 2
#define IMPS_BCT_IO_INTERRUPT 3
#define IMPS_BCT_LOCAL_INTERRUPT 4
#define IMPS_INT_INT 0
#define IMPS_INT_NMI 1
#define IMPS_INT_SMI 2
#define IMPS_INT_EXTINT 3
/*
* Typedefs and data item definitions done here.
*/
typedef struct imps_fps imps_fps; /* MP floating pointer structure */
typedef struct imps_cth imps_cth; /* MP configuration table header */
typedef struct imps_processor imps_processor;
typedef struct imps_bus imps_bus;
typedef struct imps_ioapic imps_ioapic;
typedef struct imps_interrupt imps_interrupt;
/*
* Data structures defined here
*/
/*
* MP Floating Pointer Structure (fps)
*
* Look at page 4-3 of the MP spec for the starting definitions of
* this structure.
*/
struct imps_fps
{
unsigned sig;
imps_cth *cth_ptr;
unsigned char length;
unsigned char spec_rev;
unsigned char checksum;
unsigned char feature_info[5];
};
/*
* MP Configuration Table Header (cth)
*
* Look at page 4-5 of the MP spec for the starting definitions of
* this structure.
*/
struct imps_cth
{
unsigned sig;
unsigned short base_length;
unsigned char spec_rev;
unsigned char checksum;
char oem_id[8];
char prod_id[12];
unsigned oem_table_ptr;
unsigned short oem_table_size;
unsigned short entry_count;
unsigned lapic_addr;
unsigned short extended_length;
unsigned char extended_checksum;
char reserved[1];
};
/*
* Base MP Configuration Table Types. They are sorted according to
* type (i.e. all of type 0 come first, etc.). Look on page 4-6 for
* the start of the descriptions.
*/
struct imps_processor
{
unsigned char type; /* must be 0 */
unsigned char apic_id;
unsigned char apic_ver;
unsigned char flags;
unsigned signature;
unsigned features;
char reserved[8];
};
struct imps_bus
{
unsigned char type; /* must be 1 */
unsigned char id;
char bus_type[6];
};
struct imps_ioapic
{
unsigned char type; /* must be 2 */
unsigned char id;
unsigned char ver;
unsigned char flags;
unsigned addr;
};
struct imps_interrupt
{
unsigned char type; /* must be 3 or 4 */
unsigned char int_type;
unsigned short flags;
unsigned char source_bus_id;
unsigned char source_bus_irq;
unsigned char dest_apic_id;
unsigned char dest_apic_intin;
};
/*
* Exported globals here.
*/
/*
* "imps_any_new_apics" is non-zero if any of the APICS (local or I/O)
* are *not* an 82489DX. This is useful to determine if more than 15
* CPUs can be supported (true if zero).
*/
extern int imps_any_new_apics;
/*
* "imps_enabled" is non-zero if the probe sequence found IMPS
* information and was successful.
*/
extern int imps_enabled;
/*
* This contains the local APIC hardware address.
*/
extern unsigned imps_lapic_addr;
/*
* This represents the number of CPUs found.
*/
extern int imps_num_cpus;
/*
* These map from virtual cpu numbers to APIC id's and back.
*/
extern unsigned char imps_cpu_apic_map[IMPS_MAX_CPUS];
extern unsigned char imps_apic_cpu_map[IMPS_MAX_CPUS];
/*
* This is the primary function for probing for Intel MPS 1.1/1.4
* compatible hardware and BIOS information. While probing the CPUs
* information returned from the BIOS, this also starts up each CPU
* and gets it ready for use.
*
* Call this during the early stages of OS startup, before memory can
* be messed up.
*
* Returns 1 if IMPS information was found and is valid, else 0.
*/
int imps_probe(void);
/*
* Defines that use variables
*/
#define IMPS_LAPIC_READ(x) (*((volatile unsigned *) (imps_lapic_addr+(x))))
#define IMPS_LAPIC_WRITE(x, y) \
(*((volatile unsigned *) (imps_lapic_addr+(x))) = (y))
#endif /* !_SMP_IMPS_H */

20
stage1/Makefile Normal file
View file

@ -0,0 +1,20 @@
#
# GRUB stage1 makefile
#
CFLAGS= $(SHARED_FLAGS)
all: ../bin/stage1
stage1.o: stage1.S Makefile ../Makefile
$(CC) $(CFLAGS) -c -o stage1.o stage1.S
stage1.exec: stage1.o Makefile ../Makefile
$(LD) -N -Ttext 7C00 -o stage1.exec stage1.o
../bin/stage1: stage1.exec Makefile ../Makefile
$(OBJCOPY) -O binary stage1.exec ../bin/stage1
clean:
rm -f stage1.o stage1.exec

70
stage2/Makefile Normal file
View file

@ -0,0 +1,70 @@
#
# GRUB stage2 makefile
#
CFLAGS= $(SHARED_FLAGS) -I../shared_src
# "asm.o" absolutely must come first!!!
SHARED_OBJS= asm.o common.o char_io.o boot.o cmdline.o gunzip.o \
disk_io.o stage2.o fsys_ffs.o fsys_ext2fs.o fsys_fat.o
all: ../bin/stage2
asm.o: ../shared_src/asm.S ../shared_src/shared.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/asm.S
boot.o: ../shared_src/boot.c ../shared_src/shared.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/boot.c
char_io.o: ../shared_src/char_io.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/char_io.c
cmdline.o: ../shared_src/cmdline.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/cmdline.c
common.o: ../shared_src/common.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/common.c
gunzip.o: ../shared_src/gunzip.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/gunzip.c
disk_io.o: ../shared_src/disk_io.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/disk_io.c
stage2.o: ../shared_src/stage2.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/stage2.c
fsys_ffs.o: ../shared_src/fsys_ffs.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h \
../shared_src/defs.h ../shared_src/disk_inode.h \
../shared_src/disk_inode_ffs.h ../shared_src/dir.h \
../shared_src/fs.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_ffs.c
fsys_ext2fs.o: ../shared_src/fsys_ext2fs.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_ext2fs.c
fsys_fat.o: ../shared_src/fsys_fat.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h \
../shared_src/fat.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_fat.c
# "asm.o" absolutely has to come first in the link line!
stage2.exec: $(SHARED_OBJS) Makefile ../Makefile
$(LD) -N -Ttext 8000 -o stage2.exec $(SHARED_OBJS)
../bin/stage2: stage2.exec Makefile ../Makefile
$(OBJCOPY) -O binary stage2.exec ../bin/stage2
clean:
rm -f $(SHARED_OBJS) stage2.exec

70
stage2_debug/Makefile Normal file
View file

@ -0,0 +1,70 @@
#
# GRUB stage2 DEBUG makefile
#
CFLAGS= $(SHARED_FLAGS) -DDEBUG -I../shared_src
# "asm.o" absolutely must come first!!!
SHARED_OBJS= asm.o common.o char_io.o boot.o cmdline.o gunzip.o \
disk_io.o stage2.o fsys_ffs.o fsys_ext2fs.o fsys_fat.o
all: ../bin/stage2_debug
asm.o: ../shared_src/asm.S ../shared_src/shared.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/asm.S
boot.o: ../shared_src/boot.c ../shared_src/shared.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/boot.c
char_io.o: ../shared_src/char_io.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/char_io.c
cmdline.o: ../shared_src/cmdline.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/cmdline.c
common.o: ../shared_src/common.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/common.c
gunzip.o: ../shared_src/gunzip.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/gunzip.c
disk_io.o: ../shared_src/disk_io.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/disk_io.c
stage2.o: ../shared_src/stage2.c ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/stage2.c
fsys_ffs.o: ../shared_src/fsys_ffs.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h \
../shared_src/defs.h ../shared_src/disk_inode.h \
../shared_src/disk_inode_ffs.h ../shared_src/dir.h \
../shared_src/fs.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_ffs.c
fsys_ext2fs.o: ../shared_src/fsys_ext2fs.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h Makefile \
../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_ext2fs.c
fsys_fat.o: ../shared_src/fsys_fat.c ../shared_src/filesys.h \
../shared_src/pc_slice.h ../shared_src/shared.h \
../shared_src/fat.h Makefile ../Makefile
$(CC) $(CFLAGS) -c ../shared_src/fsys_fat.c
# "asm.o" absolutely has to come first in the link line!
stage2.exec: $(SHARED_OBJS) Makefile ../Makefile
$(LD) -N -Ttext 8000 -o stage2.exec $(SHARED_OBJS)
../bin/stage2_debug: stage2.exec Makefile ../Makefile
$(OBJCOPY) -O binary stage2.exec ../bin/stage2_debug
clean:
rm -f $(SHARED_OBJS) stage2.exec