How OS Kernel Locates Root Filesystem via UEFI Variables
When a modern computer boots, the operating system kernel relies on a chain of execution initiated by the Unified Extensible Firmware Interface (UEFI). The firmware uses non-volatile RAM (NVRAM) variables—specifically boot options defined in the UEFI specification—to determine which binary to execute and which parameters to pass. By reading these variables, either directly through the Linux EFI Boot Stub or indirectly via a bootloader, the kernel receives the precise identifier of the storage device and partition hosting the root filesystem, allowing the initial RAM disk to locate and mount it.
1. UEFI Boot Variables and NVRAM Storage
UEFI systems store boot configuration in non-volatile storage known as NVRAM. The firmware utilizes specific standardized variables to orchestrate startup:
BootOrder: An array of 16-bit integers defining the sequence in which boot options are attempted.BootNext: An optional variable specifying a one-time boot override.BootCurrent: A variable set by the firmware indicating which boot entry was successfully loaded.Boot####: Individual entries (e.g.,Boot0001,Boot0002) structured asEFI_LOAD_OPTIONdescriptors.
Each EFI_LOAD_OPTION contains several critical fields:
attributes, a human-readable description, a UEFI device path pointing to
the executable file (typically on the EFI System Partition, or ESP), and
an OptionalData binary buffer.
2. Passing Boot
Parameters via OptionalData
The OptionalData field in a Boot####
variable acts as a command-line carrier. System utilities like
efibootmgr can populate this field with kernel parameters
such as:
root=UUID=4f9c8b72-1234-4a5b-8c9d-0123456789ab rw
Alternatively, partition identifiers can be used:
root=PARTUUID=a1b2c3d4-e5f6-7890-abcd-ef0123456789
When the UEFI Boot Manager executes the binary specified in the
device path, it encapsulates these parameters inside an
EFI_LOADED_IMAGE_PROTOCOL structure. The executable
receives access to this structure, specifically reading the
LoadOptions and LoadOptionsSize fields, which
contain the exact string stored in the NVRAM
OptionalData.
3. Handoff to the Kernel: Direct Boot vs. Bootloader
There are two primary ways the kernel acquires these parameters:
- Direct Boot (EFI Boot Stub): When compiled with
CONFIG_EFI_STUB, the Linux kernel binary functions as a native PE/COFF UEFI executable. The firmware loads the kernel directly. The kernel's stub code queries theEFI_LOADED_IMAGE_PROTOCOLforLoadOptions, extracts the command-line string containing theroot=parameter, and integrates it into the kernel's internal command buffer before exiting UEFI Boot Services. - Bootloader Handoff (GRUB, systemd-boot): The
firmware loads the bootloader first. The bootloader inspects the boot
variables, determines the boot entry, merges any user configuration with
the variables, loads the kernel and initramfs into memory, and passes
the synthesized command line to the kernel via the boot protocol.
Bootloaders like
systemd-bootalso set additional UEFI variables (e.g.,LoaderDevicePartUUID) to inform the OS where it booted from.
4. Reading UEFI Variables from Userspace and Initramfs
Once the kernel takes control and terminates UEFI Boot Services, direct calls to the UEFI firmware interface are largely replaced by UEFI Runtime Services.
The kernel exposes these services to user space via the
efivarfs pseudo-filesystem, typically mounted at
/sys/firmware/efi/efivars. This allows early boot
components in the initial RAM disk (initramfs) to inspect NVRAM
variables dynamically if required by the boot scheme (for example,
discovering system-token variables or partition identifiers generated by
the bootloader).
5. Identification and Mounting of the Root Filesystem
The actual discovery and mounting of the root filesystem proceed through the initramfs:
- Parameter Parsing: The initramfs parses the kernel
command line received from the UEFI environment to find the
root=specifier. - Device Enumeration: The kernel initializes storage controllers (NVMe, SATA, USB) and registers block devices.
- Udev Detection: The
udevdaemon inside the initramfs listens for kernel uevents as storage devices are registered. It reads partition headers (GPT) and filesystem superblocks, generating symlinks under/dev/disk/by-uuid/and/dev/disk/by-partuuid/. - Resolution: The initramfs matches the target UUID or PARTUUID provided in the UEFI-originating command line with the detected device nodes.
- Mount and Switch: The root device is mounted to a
temporary target (such as
/sysroot). Once mounted, the initramfs transfers execution usingswitch_rootorpivot_root, making the targeted storage volume the active root directory of the operating system.