Skip to content

102.2 Install a boot manager

Boot overview

Most systems use BIOS or UEFI. When on BIOS, the system performs a self-test called POST (Power-On Self-Test). Then it hands over the boot process to the first sector of the Master Boot Record (MBR), which is track (Cylinder) 0, side (Head) 0 and Sector 1 of the first disk.

MBR is only 512 bytes and contains both a partition table and bootstrap code (the bootloader). Because of the size limit, a smart bootloader is needed to handle larger boot managers and even multiple systems. Some of these bootloaders are LILO, GRUB and GRUB2.

On an MBR-partitioned disk, the boot code for GRUB is installed to the MBR. This loads and passes control to a "core" image installed in the 32 KB space between the MBR and the first partition. From this point, GRUB can load the rest of its resources (menu definitions, configuration files and extra modules) from disk.

If the system is using UEFI, the hardware follows the UEFI stages. They start with a security phase and continue until the end phase where the UEFI looks for an EFI System Partition, which is a FAT-based partition (usually the first one, but that is implementation-defined) containing PE executables, and runs them. On UEFI systems, GRUB is loaded from files like grubia32.efi (32-bit) or grubx64.efi (64-bit) from the ESP.

In both cases, the binary starts the boot loader. It might be a complete bootloader on /boot/efi/ of your computer, a small loader for the main GRUB on the MBR, a Windows loader, or even a chainloader.

Chain Loading is when a boot loader loads another boot loader. This is done when a Linux bootloader needs to start a Windows system.

BIOS path:
  Power on --> POST --> MBR (512 bytes) --> GRUB core image (32 KB gap) --> /boot/grub/ --> kernel
                        [sector 0]         [between MBR & 1st partition]

UEFI path:
  Power on --> Security phase --> ESP (FAT partition) --> grubx64.efi --> /boot/grub/ --> kernel
                                 [/boot/efi/]

Chainloading (dual boot):
  GRUB --> chainloader +1 --> Windows bootloader --> Windows

GRUB

GRUB (GRand Unified Bootloader) started to replace the older LILO. The first version (1) is called GRUB Legacy and started in 1999. The 2nd version started in 2005 and is a complete rewrite of version 1. GRUB Legacy is no longer under active development (the last release was 0.97, in 2005), and today most major Linux distributions install GRUB 2 as the default boot loader.

It is a menu-based system where you can choose which kernel or chainloader to boot. It is also possible to edit the menus on the fly or give direct commands from a command line.

GRUB Legacy vs GRUB2 at a glance:

  GRUB Legacy (v1, 0.9x)                    GRUB2 (v2)
  --------------------------                 --------------------------
  Config:  /boot/grub/menu.lst               Config:  /boot/grub/grub.cfg
           (or grub.conf on Red Hat)                  (auto-generated, don't edit)
  Edit:    directly by hand                  Edit:    /etc/default/grub
                                                      + /etc/grub.d/ scripts
                                                      then run grub-mkconfig
  Numbering: (hd0,0) = 1st disk, 1st part   Numbering: (hd0,1) = 1st disk, 1st part
  Install: grub-install /dev/sda             Install:   grub-install /dev/sda
  Shell:   press 'c', boot with 'boot'       Shell:     press 'c', boot with 'boot'
  Edit:    press 'e', boot with 'b'          Edit:      press 'e', boot with Ctrl+X

GRUB Legacy

GRUB v1 (actually version 0.9x) is installed in /boot/grub. Its main configuration file is /boot/grub/menu.lst, but some distros (including Red Hat based ones) symlink this to /boot/grub/grub.conf.

A sample menu.lst / grub.conf file has two sections. The first section contains global configs, the second defines kernel/initramfs or chainloader boot entries.

Global configuration options:

Config Description
# Comment
color Foreground and background colors for normal and active items
default Which boot menu item is the default, numbered from zero. E.g. default=1 boots the second entry
fallback If the default entry fails to boot, try this one instead
hiddenmenu Don't show the menu at all, just boot the default silently. Press a key during timeout to reveal it
splashimage Background image behind the menu
timeout Seconds to wait before auto-booting the default. 0 boots immediately, no chance to choose
password Require this password before anyone can edit menu entries. Prevents unauthorized kernel parameter changes (like adding init=/bin/bash to bypass login)
savedefault Remember whichever entry was booted last, use it as default next time

Boot entry options:

Config Description
title Defines the section name (what you see on the menu)
root Disk and partition where /boot is, in the form (hd0,0). This tells GRUB where to find files, NOT where Linux will mount /
kernel Kernel image file name in /boot
initrd Initramfs file in /boot
rootnoverify Same as root, but skips checking the filesystem. Used for non-Linux partitions (like Windows) where GRUB can't read the filesystem anyway
chainloader Load the first sector of another partition's bootloader. +1 means "first sector." Used for dual-boot: GRUB hands off to Windows' own bootloader instead of trying to boot Windows directly

Sample GRUB Legacy config:

# grub.conf generated by anaconda
default=1
timeout=10
splashimage=(hd0,5)/boot/grub/splash.xpm.gz
#hiddenmenu
password --md5 $1$RW1VW/$4XGAklxB7/GJk0uO47Srx1
title Upgrade to Fedora 11 (Leonidas)
    kernel /boot/upgrade/vmlinuz preupgrade \
      repo=hd::/var/cache/yum/preupgrade stage2=\
      hd:UUID=8b4c62e7-2022-4288-8995-5eda92cd149b:/boot/upgrade/install.img \
      ks=hd:UUID=8b4c62e7-2022-4288-8995-5eda92cd149b:/boot/upgrade/ks.cfg
    initrd /boot/upgrade/initrd.img
title Fedora (2.6.26.8-57.fc8)
    root (hd0,5)
    kernel /boot/vmlinuz-2.6.26.8-57.fc8 ro root=LABEL=FEDORA8 rhgb quiet
    initrd /boot/initrd-2.6.26.8-57.fc8.img
title GRUB Menu
    rootnoverify (hd0,1)
    chainloader +1
title Windows
    rootnoverify (hd0,0)
    chainloader +1

Important: in GRUB Legacy, both disks AND partitions are numbered from zero. So (hd0,0) means the first partition on the first disk.

GRUB Legacy commands

After creating the configuration, install GRUB on a disk MBR:

grub-install /dev/fd0
grub-install '(fd0)'

GRUB can be installed on a CD, floppy, MBR (/dev/sda, /dev/sdb, etc.) or a partition (/dev/sdb2, /dev/sda6, etc.). If you install it on anything other than the MBR, use a chainloader to point your boot sequence toward it.

To install from the GRUB shell itself (if the system can't boot normally):

grub> root (hd0,0)
grub> setup (hd0)

Use find /boot/grub/stage1 to locate which partition contains the boot files.

Interacting with GRUB Legacy

If you press c on the GRUB menu, you enter the GRUB Command Line (GRUB shell). There you can type commands like root, kernel, initrd and boot the system with boot, or press Esc to return to the menu.

If you need to edit an entry on the fly, press e on that item to get an interactive editing environment. Press Enter when done and b to boot.

GRUB2

This is the most common boot loader today. On BIOS systems it is installed in /boot/grub/ or /boot/grub2/. Under UEFI it goes in /boot/efi/EFI/distro-name/ (e.g. /boot/efi/EFI/fedora/). GRUB2's configuration file is called grub.cfg.

The default configuration file is /boot/grub/grub.cfg. This file is automatically generated and manual editing is not recommended. To make changes, edit /etc/default/grub and then run update-grub (or grub-mkconfig) to regenerate a compliant grub.cfg.

Simplified grub.cfg:

set default="0"
menuentry "Fedora" {
  set root=(hd0,1)
  linux /boot/vmlinuz-5.10.0-9-arm64 ro quiet
  initrd /boot/initrd.img-5.10.0-9-arm64
}
menuentry "Windows" {
  chainloader (hd1,msdos2)+1
}

Important: in GRUB2, disks are still numbered from zero, but partitions are numbered from one. So the first partition on the first disk is (hd0,1) or (hd0,msdos1) for MBR partitions or (hd0,gpt1) for GPT drives. This is different from GRUB Legacy where it would be (hd0,0).

GRUB2 menu entry options:

Option Description
menuentry Defines a new menu entry
set root Defines the root where /boot is located
linux, linux16 Defines the location of the Linux kernel on BIOS systems
linuxefi Defines the Linux kernel on UEFI systems
initrd Defines the initramfs image for BIOS systems
initrdefi Defines the initramfs image for UEFI systems

Key settings in /etc/default/grub:

Setting Description
GRUB_DEFAULT= Default menu entry. 0 = first entry, saved = whatever was booted last (needs GRUB_SAVEDEFAULT=true). Can also be a name like "Fedora"
GRUB_SAVEDEFAULT= If true with GRUB_DEFAULT=saved, remembers last selection across reboots
GRUB_TIMEOUT= Seconds before auto-booting default. 0 boots instantly (press Shift to catch the menu), -1 waits forever
GRUB_CMDLINE_LINUX= Kernel parameters added to ALL entries (including recovery). E.g. "net.ifnames=0" to use old-style network names on every boot
GRUB_CMDLINE_LINUX_DEFAULT= Extra parameters for the default entry only, NOT recovery. E.g. "quiet splash" hides boot messages on normal boot, but recovery mode still shows them
GRUB_ENABLE_CRYPTODISK= If y, allows booting from an encrypted disk. GRUB will ask for the encryption passphrase before loading the kernel

Menu entries can also be added manually by editing scripts inside /etc/grub.d/. These files are processed in numerical order (05_debian_theme before 10_linux, etc.). Custom entries go in 40_custom.

Instead of specifying a device and partition directly with set root, you can also have GRUB2 search for a filesystem by UUID or label:

search --set=root --fs-uuid ae71b214-0aec-48e8-80b2-090b6986b625
search --set=root --label MY_PARTITION

Add --no-floppy so GRUB does not waste time searching floppy drives.

GRUB2 commands

Installation is done with:

grub-install /dev/sda

If installing from a rescue environment to a mounted boot partition:

grub-install --boot-directory=/mnt/tmp /dev/sda

After changing config files, regenerate grub.cfg:

grub-mkconfig -o /boot/grub/grub.cfg
grub2-mkconfig -o /boot/grub2/grub.cfg     # on some distros

There is also update-grub, which is a frontend that runs grub-mkconfig -o /boot/grub/grub.cfg.

On some modern distros, both grub and grub2 prefixed commands exist for compatibility reasons, and one links to the other.

GRUB2 configuration workflow:

  /etc/default/grub          (settings: timeout, default, kernel params)
        |
        +--- /etc/grub.d/    (scripts processed in order)
        |      00_header
        |      05_debian_theme
        |      10_linux       (auto-detects installed kernels)
        |      30_os-prober   (auto-detects other OSes)
        |      40_custom      (your manual entries go here)
        |
        v
  grub-mkconfig / update-grub   (reads all the above)
        |
        v
  /boot/grub/grub.cfg           (generated output - NEVER edit directly)
Interacting with GRUB2

Press c on the GRUB menu (or Ctrl+C from the editing window) to enter the GRUB shell (grub>). Type help to see available commands, or Esc to return to the menu.

To edit an entry, select it and press e. After editing, type Ctrl+X or F10 to boot, or Esc to return.

If you see just a countdown but not a menu, press Shift to bring it up. The menu will not appear at all if GRUB_TIMEOUT is set to 0 in /etc/default/grub.

Booting from the GRUB2 shell (when a menu entry is broken):

grub> ls                                    # list disks and partitions
grub> ls (hd0,msdos1)/                      # browse a partition's contents
grub> set root=(hd0,msdos1)                 # set the boot partition
grub> linux /vmlinuz root=/dev/sda1         # load the kernel
grub> initrd /initrd.img                    # load the initramfs
grub> boot                                  # boot the system

Booting from the rescue shell (grub rescue>): same process, but you must first load modules manually:

grub rescue> set prefix=(hd0,msdos1)/boot/grub
grub rescue> insmod normal
grub rescue> insmod linux

Then proceed with set root, linux, initrd, and boot as above.

GRUB2 interactive recovery:

  GRUB menu appears
    |
    +-- press 'e' --> edit entry --> Ctrl+X to boot (quick fix)
    |
    +-- press 'c' --> grub> shell
    |     ls --> set root --> linux /vmlinuz --> initrd --> boot
    |
    +-- boot fails badly --> grub rescue> shell
          set prefix --> insmod normal --> insmod linux
          --> then same as grub> shell above

  GRUB Legacy (for comparison):
    press 'e' --> edit --> Enter --> 'b' to boot
    press 'c' --> grub> shell --> root, kernel, initrd, boot
Partition numbering - the key exam trap:

  GRUB Legacy:  (hd0,0) = first disk, first partition    (both from zero)
  GRUB2:        (hd0,1) = first disk, first partition    (disk from zero, partition from one)
                (hd0,msdos1) = same, MBR explicit
                (hd0,gpt1)   = same, GPT explicit

Kernel boot parameters

Parameters can be passed to the kernel on the linux line:

linux /boot/vmlinuz-5.10.0-9-arm64 root=/dev/sda1 ro quiet
Option Description
console= Redirect boot output to a specific device. E.g. console=ttyS0,115200 sends output to the serial port at 115200 baud - used on headless servers where you connect via serial cable instead of a monitor
debug Show detailed kernel messages during boot - useful when a driver fails silently and you need to see where it stopped
init= Run something else instead of the normal init. E.g. init=/bin/bash drops you directly into a root shell with no login prompt - used to recover a system when even init is broken or you forgot the root password
initrd= Specify a different initramfs file than the default
ro Mount root read-only at first. This is the normal default - the system runs fsck (filesystem check) while it's read-only, then remounts it read-write once the check passes
rw Mount root read-write immediately, skipping the read-only check phase
root= Tell the kernel which partition is /. E.g. root=/dev/sda2 or root=LABEL=FEDORA8 or root=UUID=...
selinux=0 Disable SELinux entirely on boot. Used when SELinux is blocking something and you need to get in to fix the policy
single, S, 1, Single Boot into single-user mode (SysV) - root shell, no network, no other users. Used for emergency maintenance like fixing /etc/fstab or resetting a password
systemd.unit= Boot into a specific systemd target instead of the default. E.g. systemd.unit=rescue.target is the systemd equivalent of single-user mode

Summary

I have a Linux system that needs a boot manager to load the kernel after the firmware (BIOS or UEFI) finishes its initial hardware checks. On BIOS systems, the bootloader code lives in the 512-byte MBR of the first disk and loads a larger "core" image from the gap between the MBR and the first partition. On UEFI systems, the firmware loads a .efi file directly from the EFI System Partition. If one bootloader needs to start a different OS (like Windows), it uses chainloading to hand off to that OS's own bootloader.

The exam covers two versions of GRUB. GRUB Legacy stores its configuration directly in /boot/grub/menu.lst (or grub.conf on Red Hat), which you edit by hand. It numbers both disks and partitions from zero, so the first partition on the first disk is (hd0,0). GRUB2, the current standard, stores its generated config in /boot/grub/grub.cfg, but you never edit that file directly. Instead, you change settings in /etc/default/grub and add custom entries in /etc/grub.d/40_custom, then regenerate with grub-mkconfig or update-grub. GRUB2 numbers disks from zero but partitions from one, so the same first partition becomes (hd0,1).

Both versions provide an interactive shell (press c at the menu) where I can manually specify a root device, load a kernel and initramfs, and boot the system. This is the key recovery tool when a menu entry is broken or a kernel upgrade fails. In GRUB2, pressing e to edit an entry and Ctrl+X to boot is the most common live-troubleshooting workflow. The GRUB2 rescue shell (grub rescue>) requires manually loading the normal and linux modules with insmod before any of the usual commands work.