The disk space can be used in a boot loader is very restricted because
a MBR (see MBR) is only 512 bytes but it also contains a partition
table (see Partition table) and a BPB. So the question is how to
make a boot loader code enough small to be fit in a MBR.
However, GRUB is a very large program, so we break GRUB into 2 (or 3)
distinct components, Stage 1 and Stage 2 (and optionally
Stage 1.5). See Memory map, for more information.
We embed Stage 1 in a MBR or in the boot sector of a partition, and
place Stage 2 in a filesystem. The optional Stage 1.5 can be installed
in a filesystem, in the boot loader area in a FFS or a ReiserFS,
and in the sectors right after a MBR, because Stage 1.5 is enough small
and the sectors right after a MBR is normally an unused region. The size
of this region is the number of sectors per head minus 1.
Thus, all Stage1 must do is just load Stage2 or Stage1.5. But even if
Stage 1 needs not to support the user interface or the filesystem
interface, it is impossible to make Stage 1 less than 400 bytes, because
GRUB should support both the CHS mode and the LBA mode (see Low-level disk I/O).
The solution used by GRUB is that Stage 1 loads only the first sector of
Stage 2 (or Stage 1.5) and Stage 2 itself loads the rest. The flow of
Stage 1 is:
Initialize the system briefly.
Detect the geometry and the accessing mode of the loading drive.
Load the first sector of Stage 2.
Jump to the starting address of the Stage 2.
The flow of Stage 2 (and Stage 1.5) is:
Load the rest of itself to the real starting address, that is, the
starting address plus 512 bytes. The block lists are stored in the last
part of the first sector.
Long jump to the real starting address.
Note that Stage 2 (or Stage 1.5) does not probe the geometry
or the accessing mode of the loading drive, since Stage 1 has
already probed them.
Published under the terms of the GNU General Public License