Linux Boot & Init — UEFI/Secure Boot, GRUB, initramfs/dracut, Early Userspace
Parent: DevOps, Infrastructure & Observability · researched 2026-06-01T05:30:58.315Z· 16 sources · 11 concepts · skill linux-boot-init
On a modern machine the boot is a chain of trust and handoffs, each stage finding, optionally
Overview
- On a modern machine the boot is a chain of trust and handoffs, each stage finding, optionally [source]
- verifying, and launching the next: [source]
- This reference covers everything up to and including switch_root. What systemd does after it [source]
- becomes PID 1 (units, targets, ordering) is references/systemd.md. Kernel internals after [source]
- decompression (scheduler, syscall ABI, module loading, init=) are references/linux-kernel-architecture.md. [source]
- Legacy BIOS/MBR boot still exists (boot.img in the MBR → core.img from the post-MBR gap or BIOS Boot [source]
- Partition), but UEFI is the default on essentially all hardware since ~2012 and is assumed throughout; [source]
- BIOS differences are called out where they matter. [source]
1. UEFI firmware, the ESP, and boot entries
- EFI System Partition (ESP): a FAT32 partition (GPT type c12a7328-...), conventionally mounted at [source]
- /boot/efi (older) or /efi (newer, when /boot is a separate XBOOTLDR). Holds .efi PE executables [source]
- under \EFI\<vendor>\. Firmware can read FAT directly - no filesystem driver needed in the OS yet. [source]
- Boot manager + NVRAM variables: firmware stores Boot0000…BootFFFF entries (each a device path + [source]
- loader path + optional args) and an ordered BootOrder, plus BootNext/BootCurrent. Manage from [source]
- Linux with efibootmgr (e.g. efibootmgr -c -d /dev/sda -p 1 -L "Linux" -l '\EFI\fedora\shimx64.efi'). [source]
- These live in efivarfs at /sys/firmware/efi/efivars/. [source]
- Fallback/removable path: \EFI\BOOT\BOOTX64.EFI (BOOTAA64.EFI on ARM) is the default the firmware [source]
- runs when no valid NVRAM entry matches - important for removable media and recovery. [source]
- DXE/BDS phases: firmware initializes silicon (PEI), loads drivers (DXE), then the Boot Device [source]
- Selection (BDS) phase walks BootOrder. Secure Boot enforcement begins here. [source]
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. [source]
- Key hierarchy: PK (Platform Key, owns the machine) → KEK (Key Exchange Keys) → [source]
- db (allowed signatures/hashes) and dbx (forbidden/revoked - blacklist wins). OEMs ship [source]
- Microsoft's certs in db by default. [source]
- shim: because distros can't get every kernel signed by Microsoft, they ship shim - a small [source]
- first-stage loader signed by Microsoft's UEFI CA. Firmware verifies shim against db; shim then [source]
- carries the distro's embedded certificate (e.g. Canonical/Red Hat) and verifies GRUB and the kernel [source]
- against it, plus a local MOK list. [source]
- MOK (Machine Owner Key): a user-enrolled key shim also trusts. Enroll with mokutil --import key.der [source]
- (sets a one-shot password; on next boot MokManager prompts to confirm - this UI cannot be scripted, [source]
- by design). Used to sign your own kernels, out-of-tree modules (NVIDIA/VirtualBox/DKMS), or custom GRUB. [source]
- The kernel honors a MOK with the module-signing KeyUsage OID 1.3.6.1.4.1.2312.16.1.2. [source]
- SBAT (UEFI Secure Boot Advanced Targeting): generation-based revocation embedded in shim/GRUB so a [source]
- vulnerable bootloader can be revoked via a metadata bump (a .sbat section + SbatLevel var) instead of [source]
- blacklisting thousands of individual hashes in dbx. This is how the 2020 BootHole and later GRUB CVEs [source]
- were rolled out; a dbx/SBAT update that outpaces your installed shim is a classic "stopped booting [source]
- after a firmware/Windows update" cause. [source]
- Lockdown: when Secure Boot is on, the kernel enters lockdown (integrity) mode, blocking [source]
- /dev/mem, kexec of unsigned images, unsigned module load, certain BPF, hibernation, etc. [source]
3. The boot loader — GRUB 2 vs systemd-boot
- GRUB 2 (the default on most general-purpose distros): [source]
- Stages: boot.img (BIOS: 446-byte MBR stub) → core.img (built by grub-mkimage/grub-install, [source]
- contains just enough modules - a filesystem driver, etc. - to read /boot/grub). On UEFI the equivalent [source]
- is grubx64.efi (loaded by shim). Stage modules (*.mod) live under /boot/grub/. [source]
- Config: /boot/grub2/grub.cfg (RHEL) or /boot/grub/grub.cfg (Debian) is **generated, not [source]
- hand-edited**: grub-mkconfig -o … (Debian: update-grub) stitches together /etc/default/grub [source]
- (e.g. GRUB_CMDLINE_LINUX) and the /etc/grub.d/ scripts (10_linux, 30_os-prober, 40_custom). [source]
- menuentry: each entry runs linux /vmlinuz-… root=… <cmdline> then initrd /initramfs-….img. [source]
- The kernel version in the linux line must match the initrd line. [source]
- BLS (Boot Loader Spec) Type 1 entries: Fedora/RHEL ≥8 no longer regenerate full menus - grub.cfg [source]
- becomes a thin loader that reads drop-in *.conf files from /boot/loader/entries/ [source]
- (<machine-id>-<kernel-version>.conf with title/linux/initrd/options keys). Managed by [source]
- kernel-install / grubby. Edit options with grubby --update-kernel. [source]
- systemd-boot (sd-boot) - a much simpler UEFI-only manager: [source]
- Drops systemd-bootx64.efi on the ESP; auto-discovers kernels from BLS Type 1 entries in [source]
- $BOOT/loader/entries/ and Type 2 UKIs in $BOOT/EFI/Linux/ - no generated config, no scripting. [source]
- Installed/updated with bootctl install|update. Global settings in loader/loader.conf. [source]
- Unified Kernel Image (UKI) - the modern direction: [source]
- A single signed UEFI PE binary bundling stub + kernel + initrd + cmdline + (optional) splash/devicetree [source]
- in named PE sections (.linux, .initrd, .cmdline, .osrel, …). The reference stub is [source]
- systemd-stub (linuxx64.efi.stub); build with ukify or dracut --uefi. [source]
- Because the cmdline and initrd are inside the signed image, Secure Boot now covers them too (a plain [source]
- GRUB+initrd setup leaves the initrd and cmdline unsigned). Place in $BOOT/EFI/Linux/*.efi; bootable [source]
- directly by firmware or auto-listed by sd-boot. Standardized by the UAPI Group (UAPI.5). [source]
4. The kernel command line
- Passed by the loader (or baked into a UKI). Selected high-value parameters: [source]
- Root: root=UUID=… / root=/dev/mapper/…, rootflags=, ro, rootfstype=. [source]
- initramfs control (dracut): rd.break[=pre-mount|mount|pre-pivot], rd.shell, rd.debug, [source]
- rd.luks.uuid=, rd.lvm.lv=vg/lv, rd.md.uuid=, rootdelay=. [source]
- Init/handoff: init=/bin/sh (override PID 1 - recovery), systemd.unit=rescue.target, [source]
- systemd.unit=emergency.target, single/1. [source]
- Diagnostics: quiet/splash (remove to see messages), loglevel=, nomodeset, systemd.log_level=debug. [source]
5. The initramfs / initrd — early userspace
- Why it exists: the kernel needs drivers and userspace logic to find the real root - but those may [source]
- live on the root (chicken-and-egg) or require assembly (LVM, LUKS decryption, mdraid, multipath, [source]
- iSCSI/NFS, ZFS). The initramfs is a CPIO archive the kernel unpacks into a tmpfs and runs as a [source]
- temporary root; it loads modules, assembles/unlocks the real root, mounts it, and pivots. [source]
- initrd vs initramfs: old initrd = a block-device image mounted as root; modern initramfs = a [source]
- CPIO archive extracted into rootfs (tmpfs). Both are commonly called "the initrd"; the file is gzip/zstd [source]
- CPIO (sometimes a concatenation, e.g. an early-cpio microcode blob + the main archive). [source]
- dracut (RHEL/Fedora/SUSE/Arch; Debian/Ubuntu historically use initramfs-tools/mkinitcpio on Arch): [source]
- builds the image event-driven and host-specific by default (hostonly, only the modules this machine [source]
- needs) vs --no-hostonly (generic, portable to other hardware - what distro installers ship). [source]
- Build: dracut [--force] /boot/initramfs-$(uname -r).img $(uname -r); inspect with lsinitrd. [source]
- Config: /etc/dracut.conf + /etc/dracut.conf.d/*.conf (add_dracutmodules, omit_dracutmodules, [source]
- add_drivers, install_items). [source]
- dracut modules (under /usr/lib/dracut/modules.d/, e.g. 90lvm, 90crypt, 90mdraid, 95nfs, [source]
- 01systemd) declare dependencies and inject scripts. [source]
- Two execution models inside the initramfs: [source]
- systemd-in-initrd (now the default on systemd distros): systemd itself is PID 1 in the initrd and [source]
- drives it via initrd.target → initrd-root-device.target → mount real root at /sysroot → [source]
- initrd-root-fs.target → initrd-switch-root.target. The contract is in systemd.io/INITRD_INTERFACE [source]
- (real root must end up at /sysroot). [source]
- legacy dracut /init script with hook directories run in order: [source]
- `cmdline → pre-udev → pre-trigger → initqueue (main loop, settles devices) → pre-mount → mount → [source]
- pre-pivot → cleanup. Custom logic drops scripts into the matching hooks/<name>/` dir. [source]
- The handoff - switch_root: once /sysroot (the real root) is mounted, early userspace kills udev, [source]
- cleans up, and calls switch_root - which deletes the initramfs tmpfs contents, chroots into the [source]
- real root, and execs the real /sbin/init (systemd) as PID 1. (pivot_root is the older mechanism; [source]
- switch_root is purpose-built for an initramfs-on-rootfs and frees the RAM.) On shutdown, systemd can [source]
- jump back into /run/initramfs/shutdown to tear down complex storage it is itself running from. [source]
6. Measured boot & TPM-bound unlock
- Distinct from Secure Boot (which gates), measured boot records: each stage hashes the next into [source]
- TPM2 PCRs before running it (PCR 4 = boot loader/EFI apps, PCR 7 = Secure Boot policy/keys, [source]
- PCR 11 = UKI sections via systemd-stub, PCR 12 = cmdline/credentials, PCR 13 = sysext). [source]
- systemd-cryptenroll --tpm2-device=auto seals a LUKS key to a PCR policy so the root disk [source]
- auto-unlocks only if the boot chain is unmodified. systemd-measure pre-computes/signs expected [source]
- PCR 11 values for a UKI so unlock survives kernel updates (signature-based PCR policy). [source]
Methodology — reading a boot end to end
- Where did it stop? Firmware screen → no entry/Secure Boot reject. GRUB prompt → loader OK, config/kernel [source]
- issue. Kernel panic "VFS: unable to mount root" or dracut emergency shell → initramfs couldn't find/assemble [source]
- root. Login/systemd errors → you're past switch_root; this is now a systemd.md problem. [source]
- Is Secure Boot involved? mokutil --sb-state. If it broke right after a firmware/Windows/dbx update, [source]
- suspect SBAT/dbx revocation outpacing your shim/GRUB. [source]
- Inspect the chain: bootctl status (loader + ESP + entries), efibootmgr -v (NVRAM order), [source]
- lsinitrd /boot/initramfs-….img (is the needed storage module/key present?). [source]
- Reproduce/interrupt: at GRUB press e, remove quiet, add rd.break (or rd.break=pre-mount) to land [source]
- in the dracut shell at the chosen stage. [source]
- Fix forward: correct the cause, then always rebuild (dracut --force) and **regenerate loader [source]
- config** so the fix is persistent and survives the next kernel update. [source]
Practical Patterns
- Sign your own boot chain (Secure Boot, your keys): sbctl is the easy path - sbctl create-keys, [source]
- sbctl enroll-keys (optionally -m to keep Microsoft certs for firmware/Option ROMs), then [source]
- sbctl sign -s /boot/vmlinuz-… / sign your UKI. Verify with sbctl verify. [source]
- Move to a UKI + systemd-boot: generate a UKI (ukify/dracut --uefi) into /efi/EFI/Linux/, [source]
- bootctl install. Gains signed cmdline+initrd and clean TPM PCR 11 measurement; drop GRUB entirely. [source]
- Recover a borked root password / fstab: boot to emergency.target or init=/bin/sh; for SELinux [source]
- systems use rd.break, mount -o remount,rw /sysroot, chroot /sysroot, fix, and touch /.autorelabel. [source]
- Persist a kernel arg the right way: edit GRUB_CMDLINE_LINUX + grub-mkconfig (classic GRUB), or [source]
- grubby --update-kernel=ALL --args="…" (BLS), or the UKI's .cmdline/kernel-install (UKI) - not the [source]
- generated grub.cfg. [source]
Anti-Patterns
- Hand-editing grub.cfg. It is regenerated on the next kernel update and your change vanishes. Edit the [source]
- source (/etc/default/grub, /etc/grub.d/, or the BLS options). [source]
- Mismatched linux/initrd versions in a menuentry → kernel boots but can't load matching modules. [source]
- hostonly initramfs cloned to different hardware → missing storage/NIC driver → unbootable. Use [source]
- --no-hostonly for portable/golden images and rescue initramfs. [source]
- Forgetting to rebuild the initramfs after adding LUKS/LVM/RAID, changing the root device, or installing [source]
- a storage driver → "unable to mount root" on next boot. [source]
- Plain GRUB+initrd and assuming Secure Boot protects you end-to-end - the cmdline and initrd are [source]
- unsigned there; only a UKI (or signed initrd scheme) closes that gap. [source]
- Enrolling a MOK and walking away - MokManager needs the physical/interactive confirmation on reboot; [source]
- unattended enrollment silently does nothing. [source]
- Sealing LUKS to PCRs without a signed/pcrlock policy → every kernel/firmware update changes the PCRs [source]
- and locks you out. Use PCR 11 signature policy (systemd-measure) or systemd-pcrlock. [source]
References
- UAPI Group - Boot Loader Specification (BLS Type 1/2, ESP+XBOOTLDR layout): https://uapi-group.org/specifications/specs/boot_loader_specification/ [source]
- UAPI Group - Unified Kernel Image (UKI) specification: https://uapi-group.org/specifications/specs/unified_kernel_image/ [source]
- systemd - Initrd Interface (the /sysroot contract, switch_root, shutdown jump-back): https://systemd.io/INITRD_INTERFACE/ [source]
- systemd-boot(7) and bootctl - UEFI boot manager + UKI/BLS discovery: https://www.man7.org/linux/man-pages/man7/sd-boot.7.html [source]
- systemd-measure(1) - pre-compute/sign TPM2 PCR 11 for a UKI: https://www.freedesktop.org/software/systemd/man/latest/systemd-measure.html [source]
- ArchWiki - UEFI Secure Boot (shim, MOK, sbctl, custom key enrollment): https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot [source]
- ArchWiki - Unified kernel image (ukify, systemd-stub, sd-boot layout): https://wiki.archlinux.org/title/Unified_kernel_image [source]
- ArchWiki - GRUB (boot.img/core.img, grub-mkconfig, BIOS vs UEFI install): https://wiki.archlinux.org/title/GRUB [source]
- ArchWiki - dracut (hostonly, modules, hooks, UKI via dracut --uefi): https://wiki.archlinux.org/title/Dracut [source]
- dracut.bootup(7) - the hook pipeline (cmdline → … → pre-pivot → cleanup, switch_root): https://man7.org/linux/man-pages/man7/dracut.bootup.7.html [source]
- Red Hat - Working with GRUB 2 / signing a kernel & modules for Secure Boot: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/signing-a-kernel-and-modules-for-secure-boot_managing-monitoring-and-updating-the-kernel [source]
- Ubuntu - UEFI Secure Boot (shim trust DB, Canonical signing, MOK): https://documentation.ubuntu.com/security/security-features/platform-protections/secure-boot/ [source]
- Debian Wiki - SecureBoot (shim/grub chain, mokutil workflow): https://wiki.debian.org/SecureBoot [source]
- Fedora Magazine - InitRAMFS, dracut, and the dracut emergency shell: https://fedoramagazine.org/initramfs-dracut-and-the-dracut-emergency-shell/ [source]
- Fedora Project Wiki - How to debug Dracut problems (rd.break, rd.shell, rd.debug): https://fedoraproject.org/wiki/How_to_debug_Dracut_problems [source]
- NSA/CISA - Guidance for Managing UEFI Secure Boot (Dec 2025): https://media.defense.gov/2025/Dec/11/2003841096/-1/-1/0/CSI_UEFI_SECURE_BOOT.PDF [source]
Children
- UEFI firmware, the ESP, and boot entries (BootOrder/Boot#### EFI vars, efibootmgr, efivarfs, PEI/DXE/BDS, fallback BOOTX64.EFI) (frontier)
- Secure Boot signature chain (PK/KEK/db/dbx, Microsoft-signed shim, distro embedded cert, MOK/MokManager/mokutil, SBAT generation-based revocation, kernel lockdown) (frontier)
- GRUB 2 (boot.img/core.img stages, grubx64.efi, generated grub.cfg via grub-mkconfig/update-grub, menuentry linux/initrd, BLS Type 1 entries, grubby/kernel-install) (frontier)
- systemd-boot / sd-boot (UEFI-only, bootctl, auto-discovery of BLS Type1 + Type2 UKIs, loader.conf) (frontier)
- Unified Kernel Image (UKI) — systemd-stub, ukify, PE sections .linux/.initrd/.cmdline, signed cmdline+initrd, UAPI.5 (frontier)
- Kernel command line (root=, rd.* dracut params, init=/systemd.unit handoff, diagnostics quiet/loglevel/nomodeset) (frontier)
- initramfs/initrd early userspace (why it exists, CPIO-into-tmpfs, dracut build + hostonly vs no-hostonly, dracut modules, config) (frontier)
- Two initramfs execution models (systemd-in-initrd targets + /sysroot contract vs legacy dracut /init hook pipeline cmdline..pre-pivot..cleanup) (frontier)
- The switch_root / pivot_root handoff to PID 1 and shutdown jump-back to /run/initramfs/shutdown (frontier)
- Measured boot & TPM-bound unlock (TPM2 PCR 4/7/11/12/13, systemd-cryptenroll, systemd-measure signed PCR11, systemd-pcrlock) (frontier)
- Boot-failure troubleshooting (dracut emergency shell, rd.break stages, VFS unable to mount root, grub rescue, rebuilding a broken initramfs) (frontier)
Frontier under this node: Boot-failure troubleshooting (dracut emergency shell, rd.break stages, VFS unable to mount root, grub rescue, rebuilding a broken initramfs), GRUB 2 (boot.img/core.img stages, grubx64.efi, generated grub.cfg via grub-mkconfig/update-grub, menuentry linux/initrd, BLS Type 1 entries, grubby/kernel-install), Kernel command line (root=, rd.* dracut params, init=/systemd.unit handoff, diagnostics quiet/loglevel/nomodeset), Measured boot & TPM-bound unlock (TPM2 PCR 4/7/11/12/13, systemd-cryptenroll, systemd-measure signed PCR11, systemd-pcrlock), Secure Boot signature chain (PK/KEK/db/dbx, Microsoft-signed shim, distro embedded cert, MOK/MokManager/mokutil, SBAT generation-based revocation, kernel lockdown), The switch_root / pivot_root handoff to PID 1 and shutdown jump-back to /run/initramfs/shutdown, Two initramfs execution models (systemd-in-initrd targets + /sysroot contract vs legacy dracut /init hook pipeline cmdline..pre-pivot..cleanup), UEFI firmware, the ESP, and boot entries (BootOrder/Boot#### EFI vars, efibootmgr, efivarfs, PEI/DXE/BDS, fallback BOOTX64.EFI), Unified Kernel Image (UKI) — systemd-stub, ukify, PE sections .linux/.initrd/.cmdline, signed cmdline+initrd, UAPI.5, initramfs/initrd early userspace (why it exists, CPIO-into-tmpfs, dracut build + hostonly vs no-hostonly, dracut modules, config), systemd-boot / sd-boot (UEFI-only, bootctl, auto-discovery of BLS Type1 + Type2 UKIs, loader.conf)