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