GRUB: The Grand Unified Bootloader

Like LILO, the GRUB boot loader can load other operating systems in addition to Linux. GRUB was written by Erich Boleyn to boot operating systems on PC-based hardware, and is now developed and maintained by the GNU project. GRUB was intended to boot operating systems that conform to the Multiboot Specification, which was designed to create one booting method that would work on any conforming PC-based operating system. In addition to multiboot-conforming systems, GRUB can boot directly to Linux, FreeBSD, OpenBSD, and NetBSD. It can also boot other operating systems such as Microsoft Windows indirectly, through the use of a chainloader . The chainloader loads an intermediate file, and that file loads the operating system’s boot loader.

GRUB provides a graphical menu interface. It also provides a command interface that is accessible both while the system is booting (the native command environment) and from the command line once Linux is running.

While LILO works perfectly well, especially if you usually boot the default image, GRUB has some advantages. The graphical menu interface shows you exactly what your choices are for booting so you don’t have to remember them. It also lets you easily edit an entry on the fly, or drop down into the command interface. In addition, if you are using the menu interface and something goes wrong, GRUB automatically puts you into the command interface so you can attempt to recover and boot manually. Another advantage of GRUB is that if you install a new kernel or update the configuration file, that’s all you have to do; with LILO, you also have to remember to rerun the lilo command to reinstall the boot loader. On the other hand, if you are used to LILO, don’t need to see the prompts often, and have a stable system, LILO is quick and convenient.

A GRUB installation consists of at least two and sometimes three executables, known as stages . The stages are:

Stage 1

Stage 1 is the piece of GRUB that resides in the MBR or the boot sector of another partition or drive. Since the main portion of GRUB is too large to fit into the 512 bytes of a boot sector, Stage 1 is used to transfer control to the next stage, either Stage 1.5 or Stage 2.

Stage 1.5

Stage 1.5 is loaded by Stage 1 only if the hardware requires it. Stage 1.5 is filesystem-specific; that is, there is a different version for each filesystem that GRUB can load. The name of the filesystem is part of the filename (e2fs_stage1_5, fat_stage1_5, etc.). Stage 1.5 loads Stage 2.

Stage 2

Stage 2 runs the main body of the GRUB code. It displays the menu, lets you select the operating system to be run, and starts the system you’ve chosen.

If it was compiled with netboot support, GRUB can also be used to boot over a network. We don’t describe that process here; see the file netboot/README.netboot in the GRUB source directory for detailed information.

One of the first things to understand about GRUB is that it uses its own naming conventions. Drives are numbered starting from 0; thus, the first hard drive is hd0, the second hard drive is hd1, the first floppy drive is fd0, and so on. Partitions are also numbered from 0, and the entire name is put in parentheses. So the first partition of the first drive, /dev/hda1, is known as (hd0,0) to GRUB. The third partition of the second drive is (hd1,2). GRUB makes no distinction between IDE drives and SCSI drives, so the first drive is hd0 whether it is IDE or SCSI.

Files are specified either by the filename or by blocklist , which is used to specify files such as chainloaders that aren’t part of a filesystem. A filename looks like a standard Unix path specification with the GRUB device name prepended; for example:

(hd0,0)/grub/grub.conf

If the device name is omitted, the GRUB root device is assumed. The GRUB root device is the disk or partition where the kernel image is stored, set with the root command. See Section 4.4 for the command descriptions.

When you use blocklist notation, you tell GRUB which blocks on the disk contain the file you want. Each section of a file is specified as the offset on the partition where the block begins plus the number of blocks in the section. The offset starts at 0 for the first block on the partition. The syntax for blocklist notation is:

[device][offset]+length[,offset]+length...

In this case, too, the device name is optional for a file on the root device. With blocklist notation, you can also omit the offset if it is 0. A typical use of blocklist notation is when using a chainloader to boot Windows. If GRUB is installed in the MBR, you can chainload Windows by setting the root device to the partition that has the Windows boot loader, making it the active partition, and then using the chainloader command to read the Windows boot sector:

rootnoverify (hd0,0)
makeactive
chainloader +1

In this example, the blocklist notation (+1) does not include either the device name or the offset because we set the root device to the Windows partition, and the Windows loader begins at offset 0 of that partition.

GRUB also includes a device map. The device map is an ASCII file, usually /boot/grub/device.map. Since the operating system isn’t loaded yet when you use GRUB to boot Linux (or any other operating system), GRUB knows only the BIOS drive names. The purpose of the device map is to map the BIOS drives to Linux devices. For example:

(fd0)   /dev/fd0
(hd0)   /dev/hda

Installing GRUB

Installing GRUB involves two stages. First, you install the GRUB files on your system, either by compiling and installing the source tarball or from a package. That puts the GRUB files in the correct locations on your system. The second step is to install the GRUB software as your boot manager. This is the step we describe in this section.

If you installed GRUB as part of your Linux installation, the distribution’s installation program took care of both stages of installing GRUB, and you’ll most likely see the GRUB menu when you boot Linux. If you didn’t install GRUB as part of your Linux installation, you have two choices. The easiest way to install GRUB is with the grub-install shell script that comes with GRUB. If grub-install doesn’t work, or if you want to do the installation manually, you can run the grub command and issue the installation commands yourself.

The following sections describe how to create a GRUB boot floppy and how to install GRUB.

Creating a GRUB boot floppy

You can create a GRUB boot floppy for everyday use or to have for an emergency. The following instructions make a floppy that boots to the GRUB command line:

  1. From the directory where GRUB was installed (e.g., /usr/share/grub/i386-pc), use the dd command to write the file stage1 to the floppy:

    % dd if=stage1 of=/dev/fd0 bs=512 count=1

    This command writes one block, with a blocksize of 512, from the input file stage1 to the floppy device /dev/fd0.

  2. Now write the file stage2 to the floppy, skipping over the first block (seek=1) so you don’t overwrite stage1:

    % dd if=stage2 of=/dev/fd0 bs=512 seek=1

Put together, the process looks like this:

% dd if=stage1 of=/dev/fd0 bs=512 count=1
1+0 records in
1+0 records out
% dd if=stage2 of=/dev/fd0 bs=512 seek=1
254+1 records in
254+1 records out

The boot floppy is now ready to boot to the GRUB command line.

You can also make a boot floppy that boots to the GRUB menu:

  1. Create a GRUB configuration file (/boot/grub/grub.conf) if you don’t already have one. The configuration file is described later in Section 4.3.2.

  2. Create a filesystem on your floppy disk. For example:

    $ mke2fs /dev/fd0
  3. Mount the floppy drive and create the directory /boot/grub:

    % mount /mnt
    % mkdir /mnt/boot
    % mkdir /mnt/boot/grub
  4. Copy the stage1, stage2, and grub.conf GRUB images from /boot/grub on your Linux partition to /mnt/boot/grub.

  5. Run the grub command. This example assumes the command is in /sbin/grub, but it might be in /usr/sbin/grub on your system:

    $ /sbin/grub --batch <<EOT
    root (fd0)
    setup (fd0)
    quit
    EOT

You should now be able to boot to the GRUB menu from the floppy disk you just created.

Using grub-install

GRUB comes with a shell script, grub-install, which uses the GRUB shell to automate the installation. The command syntax is:

grub-install options 
                  install-device

where install-device is the name of the device on which you want to install GRUB, specified as either the GRUB device name (e.g., (hd0)) or the system device (e.g., /dev/hda). For example, you might issue following the command (as root):

# grub-install /dev/hda

This command installs GRUB into the MBR of the first hard drive. The grub-install options are:

--force-lba

Force GRUB to use LBA mode, to allow booting from partitions beyond cylinder 1024.

--grub-shell= file

Specify that file is to be used as the GRUB shell. You might want to use this option to append options to grub. For example:

% grub-install --grub-shell="grub --read-only" /dev/fd0
-h, --help

Print a help message on standard output and exit.

--recheck

Force probing of a device map. You should run grub-install with this option if you add or remove a disk from your system. The device map is found at /boot/grub/device.map.

--root-directory= dir

Install GRUB images in the directory dir instead of the GRUB root directory.

-v, --version

Print the GRUB version number to standard output and exit.

Installing from the GRUB command line

To install GRUB from the native command environment, make a GRUB boot floppy as described previously. You will use that floppy to boot to the GRUB command line to do the installation. If you know which partition holds the GRUB files, you’re all set. Otherwise, you can find the partition with the find command:

grub> find /boot/grub/stage1
(hd0,0)

Here, the files are on (hd0,0). Use that information to set the GRUB root device:

grub> root (hd0,0)

Run the setup command to install GRUB. To install GRUB on the MBR, run setup as follows:

grub> setup (hd0)

If you are going to chainload Linux and want to install GRUB on the boot sector of the Linux partition, run setup like this:

grub> setup (hd0,0)

The GRUB Configuration File

GRUB uses a configuration file that sets up the menu interface. The configuration file is called grub.conf and is found with the other GRUB files in the /boot/grub directory. grub.conf is also known as menu.lst, and at least on some distributions (e.g., Red Hat 8), menu.lst is a symbolic link to grub.conf.

The configuration file begins with a section containing global commands that apply to all boot entries, followed by an entry for each Linux image or other operating system that you want to be able to boot. Here is an example of a global section (a hash sign, #, begins a comment):

default=0                                  # default to the first entry
timeout=20                                 # set the timeout to 20 seconds
splashimage=(hd0,0)/grub/splash.xpm.gz     # the splash image displayed with
                                           # the menu

Certain GRUB commands are available only in the global section of the configuration file, for use with the GRUB menu. These commands are described in the following list. All other commands can be used either in the configuration file or on the command line and are described later in Section 4.4.

default num

Set the default menu entry to num. The default entry is started if the user does not make a selection before the timeout time. Menu entries are numbered from 0. If no default is specified, the first entry (0) is used as the default.

fallback num

Specify the entry to be used if for any reason the default entry has errors. If this command is specified and the default doesn’t work, GRUB boots the fallback entry automatically instead of waiting for user input.

hiddenmenu

Specify that the menu is not to be displayed. The user can press Esc before the end of the timeout period to have the menu displayed; otherwise the default entry is booted at the end of the timeout.

timeout time

Specify the timeout period, in seconds. The timeout is the amount of time GRUB waits for user input before booting the default entry.

title name

Start a new boot entry with specified name.

Following the global section, the configuration file includes an entry for each boot image. An entry begins with a title command that specifies the text that will appear on the menu for that entry when the system boots. A typical boot entry might look like this one from a Red Hat 8.0 system:

title Red Hat Linux (2.4.18-14)
root (hd0,1)
kernel /vmlinuz-2.4.18-14 ro root=LABEL=/ hdc=ide-scsi
initrd /initrd-2.4.18-14.img

This entry provides the information GRUB needs to boot to Linux. When the menu is displayed, it will include an entry that says:

Red Hat Linux (2.4.18-14)

The GRUB root is on the second partition of the first hard drive (hd0,1). The kernel command specifies which Linux kernel to run and passes some parameters to the kernel, and the initrd command sets up an initial RAM disk.

The configuration file also provides some security features, such as the ability to set passwords and to lock certain entries so only the root user can boot them. The configuration file can be set up so that a password is required to run interactively (i.e., for editing menu entries or using the command interface) or simply to protect certain menu entries while leaving other entries available to all users. See the explanation of the password and lock commands in Section 4.4.

In addition to providing a password feature, GRUB provides the command md5crypt to encrypt passwords in MD5 format, and a corresponding Linux command, grub-md5-crypt. grub-md5-crypt is a shell script that acts as a frontend to the grub shell, calling md5crypt. Passwords encrypted either directly with md5crypt or with grub-md5-crypt can be used with the password command to set up a GRUB password. grub-md5-crypt has three possible options:

--help

Print help message and exit.

--grub-shell= file

Specify that file is to be used as the GRUB shell.

--version

Print version information and exit.

Using the Menu Interface

The most common way to use GRUB is with the menu interface. The Stage 2 loader reads the configuration file grub.conf and displays the menu. If a timeout is set in the configuration file, GRUB displays a countdown at the bottom of the window showing how much time is left before it boots to the default entry. Move the cursor to an entry and press Enter to boot; or, press e to edit the command line for that entry, a to modify the kernel arguments, or c to go to the command-line interface to issue commands manually.

If you go to the command line, you can return to the menu at any time by pressing Esc.

Selecting a and e are similar, except that a displays only the kernel command line and lets you append options to it, while e displays the entire boot entry for you to edit. In either case, the available editing commands are similar to those available on the shell command line. When you are through editing, press Esc to return to the main menu. Your changes take effect for this session only; the configuration file is not permanently changed.

One common use for editing a kernel command is to boot to single-user mode. To do that, select a from the menu and append the word “single” to the end of the kernel command. Then press Esc to return to the menu and select the entry.

The GRUB Shell

In addition to using the command line from within the GRUB menu interface (or booting directly to the command line), you can run a GRUB shell directly from the Linux command line with the grub command. For the most part, using the grub shell is the same as running in the native command-line environment. The major difference is that the shell uses operating system calls to emulate the BIOS calls that the native environment uses. That can lead to some differences in behavior.

The syntax of the grub command is:

grub [options]

For example:

% grub --no-floppy

The grub command-line options are:

--batch

Turn on batch mode for noninteractive use. Equivalent to grub --no-config-file --no-curses --no-pager.

--boot-drive= drive

Use drive as the Stage 2 boot drive, specified as a decimal, hexadecimal, or octal integer. The default is hexadecimal 0x0.

--config-file= file

Use file as the GRUB configuration file. The default is /boot/grub/grub.conf.

--device-map= file

Use file for the device map. The value of file is usually /boot/grub/device.map.

--help

Display a help message to standard output and exit.

--hold

Wait for a debugger to attach before starting grub.

--install-partition= partition

Use partition as the Stage 2 installation partition, specified as a decimal, hexadecimal, or octal number. The default is hexadecimal 0x20000.

--no-config-file

Run without reading the configuration file.

--no-curses

Don’t use the curses interface for managing the cursor on the screen.

--no-floppy

Don’t probe for a floppy drive. This option is ignored if --device-map is also specified.

--no-pager

Don’t use the internal pager.

--preset-menu

Use a preset menu, for example if your system has no console and you need to get a serial terminal set up to see messages. To use this option, compile GRUB with the --enable-preset-menu= file option and create a menu file. See the GRUB documentation for more information.

--probe-second-floppy

Probe the second floppy drive (which is not probed by default). This option is ignored if --device-map is also specified.

--read-only

Do not write to any disk drives.

--verbose

Print verbose messages.

--version

Print version information and exit.

When you run grub, you will see something like this:

    GRUB  version 0.92  (640K lower / 3072K upper memory)

 [ Minimal BASH-like line editing is supported.  For the first word, TAB
   lists possible command completions.  Anywhere else TAB lists the possible
   completions of a device/filename. ]

grub>

You can now enter commands at the “grub>” prompt. Press Tab to get a brief help message, listing all the commands:

grub> 
Possible commands are: blocklist boot cat chainloader cmp color configfile 
debug device displayapm displaymem dump embed find fstest geometry halt help 
hide impsprobe initrd install ioprobe kernel lock makeactive map md5crypt 
module modulenounzip pager partnew parttype password pause quit read reboot 
root rootnoverify savedefault serial setkey setup terminal testload testvbe 
unhide uppermem vbeprobe

Using Tab is a quick way to remind yourself of the commands, but it can be confusing to see them all run together and wrapping across lines. You can also run the help command, which lists the most frequently used commands and their syntax:

grub> help
blocklist FILE                         boot
cat FILE                               chainloader [--force] FILE
color NORMAL [HIGHLIGHT]               configfile FILE
device DRIVE DEVICE                    displayapm
displaymem                             find FILENAME
geometry DRIVE [CYLINDER HEAD SECTOR [ halt [--no-apm]
help [--all] [PATTERN ...]             hide PARTITION
initrd FILE [ARG ...]                  kernel [--no-mem-option] [--type=TYPE]
makeactive                             map TO_DRIVE FROM_DRIVE
md5crypt                               module FILE [ARG ...]
modulenounzip FILE [ARG ...]           pager [FLAG]
partnew PART TYPE START LEN            parttype PART TYPE
quit                                   reboot
root [DEVICE [HDBIAS]]                 rootnoverify [DEVICE [HDBIAS]]
serial [--unit=UNIT] [--port=PORT] [-- setkey [TO_KEY FROM_KEY]
setup [--prefix=DIR] [--stage2=STAGE2_ terminal [--dumb] [--timeout=SECS] [--
testvbe MODE                           unhide PARTITION
uppermem KBYTES                        vbeprobe [MODE]

You can add the --all option to see all the commands.

To get help for a specific command, add the command name (e.g., help read). help treats the text you enter as a pattern; therefore, if you enter help find, you’ll get help for the find command, but if you enter help module, you’ll get help for both module and modulenounzip.

Get Linux in a Nutshell, Fourth Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.