Linux Boot & Init — UEFI/Secure Boot, GRUB, initramfs/dracut, Early Userspace

Linux Boot & Init — UEFI/Secure Boot, GRUB, initramfs/dracut, Early Userspace

Overview

On a modern machine the boot is a chain of trust and handoffs, each stage finding, optionally verifying, and launching the next:

power-on
  └─ UEFI firmware (PEI/DXE)  → reads BootOrder/Boot#### EFI vars, runs a boot entry from the ESP
       └─ shim (MS-signed)    → [Secure Boot] verifies next stage against db + MOK; loads GRUB or sd-boot
            └─ boot loader    → GRUB 2 / systemd-boot: picks a menu entry, loads kernel + initrd
                 └─ kernel    → decompresses, mounts the initramfs as a tmpfs root, runs its /init
                      └─ initramfs (early userspace, dracut) → finds/assembles/unlocks the REAL root
                           └─ switch_root → exec /sbin/init (= systemd) as PID 1 on the real root
                                └─ systemd → reaches default.target (multi-user / graphical)

This reference covers everything up to and including switch_root. What systemd does after it becomes PID 1 (units, targets, ordering) is references/systemd.md. Kernel internals after decompression (scheduler, syscall ABI, module loading, init=) are references/linux-kernel-architecture.md.

Legacy BIOS/MBR boot still exists (boot.img in the MBR → core.img from the post-MBR gap or BIOS Boot Partition), but UEFI is the default on essentially all hardware since ~2012 and is assumed throughout; BIOS differences are called out where they matter.

Core Concepts

1. UEFI firmware, the ESP, and boot entries

2. Secure Boot — the signature-verification chain

Secure Boot makes the firmware refuse to run any boot binary whose signature is not chained to a trusted key.

3. The boot loader — GRUB 2 vs systemd-boot

GRUB 2 (the default on most general-purpose distros):

systemd-boot (sd-boot) — a much simpler UEFI-only manager:

Unified Kernel Image (UKI) — the modern direction:

4. The kernel command line

Passed by the loader (or baked into a UKI). Selected high-value parameters:

5. The initramfs / initrd — early userspace

Why it exists: the kernel needs drivers and userspace logic to find the real root — but those may live on the root (chicken-and-egg) or require assembly (LVM, LUKS decryption, mdraid, multipath, iSCSI/NFS, ZFS). The initramfs is a CPIO archive the kernel unpacks into a tmpfs and runs as a temporary root; it loads modules, assembles/unlocks the real root, mounts it, and pivots.

6. Measured boot & TPM-bound unlock

Tools / Frameworks

Task Tool
List/set firmware boot entries efibootmgr, bootctl
Inspect/enroll Secure Boot keys mokutil, sbctl, sbsign/sbverify, efi-readvar, keytool
Regenerate GRUB config grub2-mkconfig/update-grub, grubby, kernel-install
Install/update systemd-boot `bootctl install
Build/inspect initramfs dracut, lsinitrd, mkinitcpio (Arch), update-initramfs (Debian)
Build a UKI ukify, dracut --uefi
TPM measured-boot unlock systemd-cryptenroll, systemd-measure, systemd-pcrlock
Inspect EFI vars / boot state /sys/firmware/efi/efivars, bootctl status, mokutil --sb-state

Methodology — reading a boot end to end

  1. Where did it stop? Firmware screen → no entry/Secure Boot reject. GRUB prompt → loader OK, config/kernel issue. Kernel panic “VFS: unable to mount root” or dracut emergency shell → initramfs couldn’t find/assemble root. Login/systemd errors → you’re past switch_root; this is now a systemd.md problem.
  2. Is Secure Boot involved? mokutil --sb-state. If it broke right after a firmware/Windows/dbx update, suspect SBAT/dbx revocation outpacing your shim/GRUB.
  3. Inspect the chain: bootctl status (loader + ESP + entries), efibootmgr -v (NVRAM order), lsinitrd /boot/initramfs-….img (is the needed storage module/key present?).
  4. Reproduce/interrupt: at GRUB press e, remove quiet, add rd.break (or rd.break=pre-mount) to land in the dracut shell at the chosen stage.
  5. Fix forward: correct the cause, then always rebuild (dracut --force) and regenerate loader config so the fix is persistent and survives the next kernel update.

Practical Patterns

Anti-Patterns

Troubleshooting

Symptom Likely cause / fix
Firmware ignores the disk / “no bootable device” No/invalid NVRAM entry or fallback \EFI\BOOT\BOOTX64.EFI; re-add with efibootmgr/bootctl install.
“Secure Boot violation” / image won’t load Unsigned or revoked binary; sign it (sbctl/MOK) or update shim. Check mokutil --sb-state, dbx/SBAT level.
Stopped booting after a firmware/Windows update dbx or SBAT revocation now outranks installed shim/GRUB — update the distro’s shim/grub packages.
GRUB rescue prompt (grub rescue>) core.img can’t find /boot/grub (moved/renamed partition, broken prefix); set prefix=…, insmod normal, normal; then reinstall GRUB.
Kernel panic “VFS: Unable to mount root fs on unknown-block” initramfs lacks the storage driver, or wrong root=; boot a working kernel, fix root=, add driver, dracut --force.
Dropped into dracut emergency shell Root device/LV/LUKS not found. Use blkid, lvm vgchange -ay, cryptsetup open, modprobe; then exit to continue or fix and rebuild.
Hang waiting for an encrypted/remote root Missing rd.luks.uuid=/rd.lvm.lv=/network in initramfs; add the dracut module and rebuild.
Boots to emergency.target after editing fstab Bad/unavailable mount; comment it or add nofail, systemctl daemon-reload.
New kernel won’t boot, old one does Broken/missing initramfs for the new kernel: dracut --force /boot/initramfs-<ver>.img <ver> then regenerate loader entries.

References