Multibooting with GRUB, Part 1

Many Linux computers are multi-boot systems, or computers that can boot from a variety of operating systems, including multiple instances of Linux.

Many Linux computers are multi-boot systems, or computers that can boot from a variety of operating systems, including multiple instances of Linux.

However, as the number of bootable operating systems increases, managing the boot process becomes more difficulty. In fact, for anything beyond a single OS on a machine, some form of advanced boot loader is a virtual necessity. A boot loader is a program that helps manage the OS boot process. (Even DOS and Windows use boot loaders, although their default boot loaders are very simple.)

This month’s column examines boot loader theory and the basics of setting up the Grand Unified Boot Loader (GRUB), an open source boot loader for Linux. You can download GRUB from its home page at http://www.gnu.org/software/grub. Next month’s column will describe how to configure GRUB to handle a variety of non-Linux operating systems.


GRUB is a powerful boot loader, although it’s not as user-friendly as some commercial offerings (such as PowerQuest’s BootMagic and V-Com’s System Commander). It’s configured through a file that can be stored on a FAT partition, which means that you can modify the GRUB configuration in any OS that can read FAT — a great advantage when you run into boot problems. Unlike LILO, you don’t need to re-install GRUB to the disk’s boot sector whenever you make a change to its configuration. That translates into less time spent rebooting. (Many people tend to forget to re-write LILO to the boot sector after changing its configuration, a mistake that necessitates two reboots for changes to take effect.)

Multibooting isn’t just for hobbyists. Multibooting is actually quite practical: you might want to install GRUB to multiboot between your regular Linux installation and a slimmed-down version you use for emergency maintenance. You can retain multiple versions of your favorite distribution, and you can even install a minimal Linux on a Zip disk or the like and leave a GRUB entry to boot from that media in case of an emergency. Likewise, sometimes booting DOS is necessary to run a low-level hardware utility.

One thing to keep in mind: GRUB can’t be used on every computer. It works only on x86 computers.

How GRUB Works

The x86 boot process occurs in multiple steps, as shown in Figure One. The x86 CPU is hard-wired to read its first program code from a particular part of memory that corresponds to the computer’s Basic Input/Output System (BIOS). The BIOS, in turn, includes minimal instructions to read boot code from the hard disk’s Master Boot Record (MBR). (The BIOS can also boot from a floppy disk, or for modern BIOSes, from CD-ROMs and perhaps other types of disks.) The MBR’s boot code is a boot loader, and this is the first point at which you can customize the boot process, by installing a specific boot loader into the MBR.

Figure One: A stock x86 boot involves BIOS code, two boot loaders (in the MBR and the boot sector), and ordinary OS files

Upon installation, the DOS and Windows operating systems place a simple boot loader in the MBR. This primary boot loader loads a secondary boot loader from the boot partition’s boot sector. The boot sector is simply the first sector of the partition. It contains filesystem-specific information, and in many cases contains code (the secondary boot loader) that continues the boot process by loading additional OS files from the boot partition’s main data area. In the case of non-boot partitions, such as Figure One‘s data partition, the partition still contains a boot sector, but it either doesn’t contain any boot loader code or the code is unused and irrelevant.

The boot sector is the second place at which the boot process can be diverted by installing a custom boot loader, and the OS files represent the third place a boot loader can reside. Many boot loaders offer multiple options for placement, or can place files in two or all three locations. For example, GRUB can be installed in either the MBR or a partition’s boot sector, and it also relies upon ordinary OS data files.

In a multiboot scenario, one of the boot loaders or related boot files is replaced with a boot loader that lets you choose what OS to boot. For instance, Figure Two shows a system that triple-boots Windows, FreeBSD, and Linux, using a boot loader stored in the MBR. (Of course, you’re likely to have non-boot partitions, as well. Figure Two omits them for simplicity’s sake.) Figure Two‘s boot loader could be LILO, GRUB, or any other boot loader that can reside in the MBR.

Figure Two: A multiboot system involves redirections from one boot path to another

LILO, GRUB, and some other boot loaders can also be stored in one OS’s boot sector, which changes the precise order of operations, but works the same in principle. LILO and GRUB can also both be stored on a floppy disk. When the BIOS is configured to boot from a floppy disk and the floppy contains an advanced boot loader, the process closely resembles Figure Two, except that the floppy disk’s boot sector would be used instead of the MBR.

Remember that the boot loader need not be concerned with the details of how the boot sector eventually leads to the boot of the operating system — it only needs to direct the boot process to the appropriate partition. The boot loader may need to take care of some OS-specific details to do so, though. In the case of Linux (and, depending upon your configuration, FreeBSD), GRUB can bypass the partition’s boot sector to boot the kernel directly.

GRUB is an extremely flexible boot loader, in part because it reads certain critical data files from a location that you can specify. These files are ordinary OS files, so you can modify them using text editors without re-installing GRUB into the MBR or boot sector. GRUB can read files from many different filesystems, including ext2fs, ext3fs, ReiserFS, FAT, and FFS (used by the BSD operating systems). A patch to support JFS and XFS is available, and some distributions include support for those file systems with their versions of GRUB.

GRUB also has the ability to modify the partition table (which is stored in the MBR along with the primary boot loader) and change the order in which the BIOS views the disks. These capabilities enable GRUB to hide specific partitions from view and allow operating systems that insist on booting from the first disk to boot from the second or subsequent disks.

Safely Testing GRUB

Experimenting with a boot loader configuration can be a tricky proposition. If you misconfigure a boot loader, chances are you won’t be able to boot your computer. For this reason, test GRUB by installing the boot loader code on a floppy disk and leaving your hard disk boot process unmodified. Once you’ve achieved the desired results using the floppy disk, you can install GRUB on your hard disk’s MBR, or possibly on the boot partition’s boot sector.

To test GRUB, install the GRUB package. (Installing the GRUB package using an RPM, Debian package, or tarball does not by itself install GRUB in the MBR, boot sector, or floppy disk.) Most Linux distributions ship with GRUB, and many use it by default, so check to see if it’s already installed.

After you install the GRUB package, install the GRUB boot loader to the MBR or boot sector of the disk from which you want to boot. To do this, though, you must first know where the GRUB configuration files reside. Most GRUB packages for Linux place these files in the /boot/grub directory. If your system already boots with GRUB, you may want to copy these files to another partition or to the floppy disk you use for testing.

For instance, use mkdosfs or mformat to create a FAT floppy disk, then mount it and copy the /boot/grub directory tree to the floppy disk. (If your existing installation uses symbolic links, these may not copy correctly. Be sure to copy the linked-to files, if necessary.) You can then use the grub utility itself to put the boot loader on the floppy disk’s boot sector. At root, run grub, and at the prompt, type root (fd0), then setup (fd0), then quit.

The root (fd0) command tells GRUB to look on the fd0 device (the floppy disk) for its configuration files. After typing this command, GRUB should report that it’s found a FAT filesystem and is using the whole disk. The setup (fd0) command tells GRUB to install the boot loader code on the floppy disk’s boot sector. After a brief delay, GRUB should display several lines of summary information about the specific steps it’s taken. The final installation step should succeed, although the embed commands may not. Don’t be concerned about this. GRUB searches for its configuration files in /grub/ and /boot/grub/ on the disk you specify with the root command, so be sure they’re located in the correct place.

Although the (fd0) identifier for the floppy drive may seem somewhat familiar, GRUB doesn’t use the regular Linux hard disk device identifiers. Instead, GRUB identifies disks via a string of the form (hdx,y), where x is the physical disk number and y is the partition number. Both of these identifiers begin numbering with 0. For example, on an EIDE system, Linux’s /dev/hda4 is (hd0,3); and on an all-SCSI system, Linux’s /dev/sdb7 is GRUB’s (hd1,6). (GRUB doesn’t distinguish between EIDE and SCSI disks.)

Setting GRUB Global Options

The GRUB configuration file (menu.lst or grub.conf) begins with a few default options, such as default=0, fallback=1, and timeout=10.

The default and fallback lines tell GRUB which OS to boot by default, and which to boot as a fallback in case the first OS can’t be booted.

The numbers refer to the sections (later in the file) for each specific OS. Each of those sections begins with the keyword title, and GRUB numbers them starting with 0. Thus, default=0 tells GRUB to boot the first OS in its configuration file by default. This default boot occurs after a delay specified by the timeout line, measured in seconds. Other options are available, as well, and you’re likely to encounter some of these in any GRUB configuration file installed by a Linux distribution. For the most part, you can ignore these options, although you may want to change drive identifiers for any file references if you move the files to a different partition or disk device.

Booting Linux

GRUB’s main configuration file is normally called menu.lst, although Red Hat’s version of GRUB calls this file grub.conf. This file should be in the /grub/ or /boot/grub/ directory on the root partition you specified. Before proceeding further, you may want to examine this file for references to non-boot files. For instance, your file might contain lines like these:

i18n (hd0,4)/grub/messages
keytable (hd0,4)/us.klt

These lines all refer to files on (hd0,4) — that is, /dev/hda5 on an EIDE system. Referring to such files shouldn’t cause problems if GRUB is already working on your system, but if GRUB isn’t currently working or if you’re booting GRUB from a floppy for test purposes, you may want to change these lines to point to files in an appropriate location, or comment them out with hash marks (#). Note that these lines use GRUB-style drive identifiers, and paths after those identifiers are relative to the partition, not to your Linux root filesystem. This difference can be important if you use a separate /boot partition, since you won’t include the /boot directory in the paths.

Once you’ve checked for and, if necessary, modified references to disk files, you can create a set of lines that refer to a Linux kernel you want to boot. Those lines look like this:

title Linux Test Boot
root (hd0,4)
kernel /vmlinuz-2.4.20 ro root=/dev/hda6
initrd /initrd-2.4.20-8.img

These four lines tell GRUB how to present the boot options on-screen, what files to load as the Linux kernel, and what options to use when booting Linux. Specifically, the title line tells GRUB what to call the option when it presents a list of options at boot time; root tells GRUB on what partition it can find the kernel — in this case, (hd0,4), or /dev/hda5 in Linux parlance; and the kernel line tells GRUB what file to load as the kernel and what options to pass to that kernel. In the Linux Test Boot example, GRUB is to load vmlinuz-2.4.20 as the kernel and pass it the ro root=/dev/hda6 option. In most cases, something very similar to this will work.

While the previous line (root) specifies (hd0,4) (aka /dev/hda5), it’s entirely unrelated to the root option passed to the kernel (/dev/hda6). The former is the partition on which the kernel is found, whereas the latter is the Linux root filesystem. And if your kernel is in a separate /boot partition, do not include the /boot directory in the reference to the kernel; GRUB reads all files relative to the partition you specify with the root line. If you don’t use a separate boot partition, though, you should include that directory name in the reference to the kernel file.

* initrd — This line is is common on many Linux distributions. It tells GRUB to use the specified file as a RAM disk image, which Linux can access to load drivers compiled as modules. It’s often required to boot a Linux kernel as delivered with a distribution, but if you recompile your own kernel, you may be able to do away with this line.

* boot — In theory, this line is required to boot an OS. In practice, it can often be omitted without causing problems.

After you modify these lines, you can reboot your system. Be sure your BIOS is configured to boot from the floppy disk before trying the hard disk. Your floppy disk should come to life and you should see the entry you created for booting Linux. Select it, press the ENTER key, and Linux should boot from the hard disk — or from the floppy disk, if you specified a root of fd0 and copied your kernel to the floppy.

If you have problems, try examining the menu.lst or grub. conf file again, and review everything to be sure all the files are where they should be.

If the problem is in the GRUB configuration file and it’s stored on a FAT partition, you can modify the file from DOS, Windows, or any other OS that can handle FAT partitions.

You can create multiple title sections for different Linux configurations. For example, you might create one entry to handle booting the kernel delivered with your distribution and another entry to boot a kernel you’ve compiled yourself.

Roderick W. Smith is the author or co-author of eleven books, including Advanced Linux Networking and Linux Power Tools. He can be reached at rodsmith@rodsbooks.com.

Comments are closed.