How Does GRUB Load the Kernel and Initial Ramdisk?
A multi-stage bootloader like GRUB bridges the gap between system firmware and the operating system kernel during the boot process. Because early boot environments have strict size and hardware limitations, a single small program cannot understand complex filesystems or load large operating system images on its own. By splitting the boot process into sequential stages, GRUB initializes the necessary hardware interfaces, reads the filesystem, loads the kernel image and initial ramdisk into memory, and transfers execution control to the kernel.
Why a Multi-Stage Design Is Necessary
In classical computing architectures, system firmware such as BIOS or UEFI hands control to a tiny initial boot program. Under legacy BIOS, the Master Boot Record (MBR) only provides 512 bytes of space, and only 446 bytes of that are available for executable boot code. This is far too small to contain drivers for filesystems like ext4, XFS, or Btrfs, let alone a user interface or configuration parser.
A multi-stage bootloader solves this constraint by using each stage to load a larger, more capable stage:
- Stage 1: Stored in the MBR (or the EFI System Partition under UEFI), this minimal code locates and loads the next stage from disk.
- Stage 1.5 (GRUB Legacy) /
core.img(GRUB 2): Embedded in the post-MBR gap or a dedicated BIOS Boot Partition, this intermediate stage contains basic filesystem drivers needed to read/boot/grub. - Stage 2: Residing on the filesystem itself, this
full-featured stage loads configuration files (
grub.cfg), displays the boot menu, and provides a command-line interface.
Locating and Reading the Kernel Image
Once Stage 2 is running, GRUB uses its built-in filesystem modules to
navigate the storage device and locate the operating system files. In
Linux systems, this typically includes the compressed kernel image (such
as vmlinuz) and the initial ramdisk (such as
initrd.img or initramfs).
GRUB reads the grub.cfg file to determine which kernel
parameters, root device identifiers, and boot options to use. It then
reads the kernel image from disk and places it into system RAM at a
designated memory address, often decompressing or preparing it according
to the boot protocol (such as the Linux x86 Boot Protocol or Multiboot
specification).
Loading the Initial Ramdisk into Memory
Modern operating system kernels are modular and do not include every possible storage or filesystem driver compiled directly into the main binary. To mount the real root filesystem, the kernel often needs drivers that are stored on that very filesystem.
GRUB resolves this circular dependency by loading the initial ramdisk
(initrd or initramfs) into a separate region
of memory alongside the kernel image. The initial ramdisk is a
compressed archive containing a minimal root filesystem with essential
kernel modules, device-mapper tools, and initialization scripts.
Handing Over Control to the Kernel
After both the kernel image and the initial ramdisk are safely in memory, GRUB performs final preparations before transferring execution:
- Passing Boot Parameters: GRUB populates a boot
parameter structure in memory, including the kernel command line (for
example,
root=UUID=... ro quiet) and the exact memory address and size of the loaded initial ramdisk. - Setting Up CPU State: Depending on the architecture and firmware mode, GRUB ensures the CPU is in the expected operating mode (such as 32-bit protected mode or 64-bit long mode) with interrupts and memory mappings configured as required by the kernel's entry point.
- Jumping to the Kernel Entry Point: GRUB executes a jump instruction to the kernel's entry address, relinquishing control permanently.
From that moment on, the kernel initializes hardware, unpacks the initial ramdisk from memory, loads the required storage drivers, and mounts the actual root filesystem to continue starting the operating system.