blob: c2adff4dba9410214797f5fe8226947a5d81b941 [file] [log] [blame] [raw]
<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>