The Linux Boot Process: From Power Button to Login Prompt
Most Linux users interact with their system only after it’s already running. But understanding the boot sequence pays real dividends: you can rescue a system that won’t boot, diagnose startup failures, tune boot performance, and reason confidently about what’s happening when something goes wrong before the login prompt appears.
This guide walks every stage of the modern Linux boot process, from firmware to the point where you can log in.
The Big Picture
Boot happens in five distinct stages, each handing off to the next:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Firmware │───▶│ Bootloader │───▶│ Kernel │───▶│ initramfs │───▶│ Userspace │
│ (BIOS/UEFI) │ │ (GRUB) │ │ │ │ │ │ (systemd) │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
- Firmware — The CPU starts here. Firmware initializes hardware, finds a bootable device, and hands off execution.
- Bootloader — A small program (usually GRUB) that loads the kernel and initial RAM disk from disk.
- Kernel — The Linux kernel initializes itself, sets up hardware drivers, and mounts the initial filesystem.
- initramfs — A temporary root filesystem in RAM that prepares the real root filesystem (handles encryption, RAID, LVM).
- Userspace — systemd (or another init) starts all services and presents the login prompt.
Stage 1: Firmware — BIOS and UEFI
BIOS (Legacy)
The original IBM PC firmware, still found on older hardware and some embedded systems. When power is applied:
- The CPU is hardwired to begin executing at a fixed memory address —
0xFFFF0on x86 — which contains a jump instruction into the BIOS ROM. - POST (Power-On Self-Test) runs: the BIOS tests CPU registers, RAM, and basic hardware. Beep codes indicate POST failures on systems without video output.
- The BIOS reads its configuration (stored in CMOS/NVRAM) to find the boot device order.
- It reads the Master Boot Record (MBR) — the first 512 bytes of the boot device. The MBR contains a 446-byte bootstrap program, a 64-byte partition table, and a 2-byte magic number (
0x55AA). - The MBR bootstrap is executed. On a GRUB system, this stage-1 code’s only job is to load the larger GRUB stage-2 from disk (the MBR is far too small to hold a full bootloader).
UEFI (Modern)
UEFI (Unified Extensible Firmware Interface) replaced BIOS on most hardware built after ~2012. It is substantially more capable:
- Runs in 32-bit or 64-bit protected mode (not 16-bit real mode like BIOS)
- Has its own filesystem driver — reads FAT32 on the EFI System Partition (ESP)
- Maintains a boot entry database in NVRAM — knows about OS bootloaders by path, no MBR needed
- Supports Secure Boot — cryptographically verifies bootloaders before executing them
- Exposes a richer runtime services API to the OS
UEFI boot flow:
- Firmware initializes hardware and runs UEFI drivers.
- The Boot Manager reads NVRAM boot entries (
BootOrder,Boot0000,Boot0001, …). - It finds the EFI System Partition (typically
/boot/efi, formatted FAT32) and loads the specified EFI application — usually/EFI/fedora/grubx64.efior/EFI/ubuntu/grubx64.efi. - The EFI application (bootloader) takes over.
|
|
EFI System Partition
|
|
shimx64.efi is the Secure Boot shim — a Microsoft-signed loader that in turn verifies and loads the distribution’s GRUB.
Secure Boot
With Secure Boot enabled, the firmware only executes EFI binaries signed by a key in its Secure Boot database (db). The chain is:
UEFI firmware (Microsoft root cert) → shim (signed by Microsoft) → GRUB (signed by distro) → kernel (signed by distro)
|
|
Stage 2: The Bootloader — GRUB2
GRUB (GRand Unified Bootloader) version 2 is the standard Linux bootloader. Its job is to load the kernel image and initramfs into memory and pass them control.
GRUB’s Own Boot Stages
On BIOS systems, GRUB has three stages due to space constraints:
- Stage 1 — 446 bytes in MBR, loads stage 1.5
- Stage 1.5 (
core.img) — lives in the 30KB gap between MBR and first partition, contains filesystem drivers needed to read GRUB’s config files - Stage 2 — the full GRUB, loaded from
/boot/grub2/
On UEFI systems, GRUB is a single EFI application (grubx64.efi) — no stages needed.
GRUB Configuration
|
|
Key /etc/default/grub Options
|
|
Important Kernel Parameters
These are passed from GRUB to the kernel on the command line:
| Parameter | Effect |
|---|---|
quiet |
Suppress most kernel boot messages |
splash |
Show graphical splash screen |
nomodeset |
Disable kernel mode-setting (fixes some GPU boot issues) |
single / 1 |
Boot to single-user (rescue) mode |
init=/bin/bash |
Use bash as PID 1 (emergency recovery) |
rd.break |
Drop to shell at start of initramfs (before root mount) |
rd.break=mount |
Drop to shell after mounting root, before pivot |
systemd.unit=rescue.target |
Boot to rescue target |
systemd.unit=emergency.target |
Boot to emergency target |
ro |
Mount root read-only initially (normal; fsck runs on ro mount) |
rw |
Mount root read-write immediately |
mem=4G |
Limit usable RAM (testing) |
noapic |
Disable APIC interrupt controller (hardware compatibility) |
acpi=off |
Disable ACPI (power management compatibility) |
console=ttyS0,115200 |
Serial console output |
|
|
GRUB Command Line (Interactive Recovery)
At the GRUB menu, press c to enter the GRUB command shell — useful when the config is broken:
|
|
Stage 3: The Kernel
Once GRUB loads the kernel image (vmlinuz) and initramfs into memory and jumps to the kernel entry point, the kernel takes over entirely.
Kernel Image Naming
|
|
vmlinuz = virtual memory linux, zip compressed. The kernel image is actually a self-extracting compressed archive. On x86_64 it’s a bzImage (big zImage).
Kernel Initialization Sequence
-
Decompression — The kernel’s head code decompresses the main kernel binary into a fixed memory location.
-
Architecture setup — Sets up the GDT (Global Descriptor Table), IDT (Interrupt Descriptor Table), enables paging, enters 64-bit long mode.
-
start_kernel()— The main C entry point of the kernel. This function initializes everything:- Memory management subsystem (zones, buddy allocator, slab allocator)
- CPU scheduler
- VFS (Virtual Filesystem Switch) — the abstract layer above all filesystems
- Block device layer
- Network stack skeleton
- Interrupt handlers
-
Device detection — The kernel probes for hardware. Built-in drivers initialize devices they recognize; others wait for the module loading stage.
-
PID 1 — The kernel creates the first process,
swapper(PID 0, the idle process), then spawns PID 1 by executing/sbin/init(or whateverinit=specifies). All other processes descend from PID 1.
Kernel Messages
All early kernel output goes to the kernel ring buffer:
|
|
Key things to look for in dmesg:
[ 0.000000] Linux version 6.1.0-20-amd64 (debian-kernel@...) ...
[ 0.000000] BIOS-provided physical RAM map:
[ 0.186132] ACPI: IRQ0 used by override.
[ 1.432156] nvme 0000:00:04.0: 4/0/0 default/read/poll queues
[ 2.108432] EXT4-fs (sda2): mounted filesystem
[ 3.221541] systemd[1]: systemd 252 running in system mode
Stage 4: initramfs — The Initial RAM Filesystem
Why initramfs Exists
The kernel needs to mount the root filesystem to access anything on disk. But mounting the root filesystem might require kernel modules that live on the root filesystem — a chicken-and-egg problem.
Additional complications:
- Root might be on an LVM logical volume → needs
lvmtools - Root might be LUKS-encrypted → needs
cryptsetupand a passphrase prompt - Root might be on software RAID → needs
mdadm - Root might be on iSCSI → needs network initialization first
The solution is initramfs — a compressed cpio archive containing a minimal root filesystem that the kernel extracts into a tmpfs in RAM. This temporary environment handles the complex setup needed to locate, prepare, and mount the real root filesystem.
Inspecting initramfs Contents
|
|
Inside you’ll find a miniature Linux filesystem: bin/, lib/, etc/, sbin/, the init script, and every kernel module and binary needed for early boot.
What initramfs Does
The initramfs init script (on systemd systems, this is a minimal systemd itself) does:
- Mount
sysfs,procfs,devtmpfs - Load kernel modules needed for storage (
nvme,ahci,virtio_blk, etc.) - Run
udevto populate/devwith device nodes - If LUKS encryption: prompt for passphrase, run
cryptsetup - If LVM: scan for volume groups, activate logical volumes (
vgchange -ay) - If software RAID: assemble arrays (
mdadm --assemble) - Run
fsckon the root device if needed - Mount the real root filesystem at
/sysroot pivot_rootorswitch_root— make/sysrootthe new/, discard the initramfs tmpfsexecthe real/sbin/init(systemd)
Rebuilding initramfs
Necessary after adding kernel modules, changing storage configuration, or updating cryptsetup:
|
|
Debugging initramfs with rd.break
Add rd.break to the kernel command line at the GRUB menu to drop into a shell inside the initramfs before the root filesystem is mounted:
|
|
Use rd.break=mount to break just after the root filesystem is mounted but before switch_root.
Stage 5: Userspace — systemd
Once the kernel executes /sbin/init, systemd takes over as PID 1 and is responsible for bringing up every service on the system.
Targets — systemd’s Runlevels
systemd organizes the boot into targets — groups of units that together represent a system state:
| Target | SysV Runlevel | Description |
|---|---|---|
poweroff.target |
0 | System shutdown |
rescue.target |
1 | Single-user mode, minimal services |
multi-user.target |
3 | Multi-user, no GUI |
graphical.target |
5 | Multi-user with display manager |
reboot.target |
6 | System reboot |
emergency.target |
— | Minimal shell, root filesystem read-only |
|
|
How systemd Starts Units
systemd reads unit files from:
/lib/systemd/system/— distribution-provided units/etc/systemd/system/— admin overrides (take precedence)/run/systemd/system/— runtime-generated units
A typical service unit:
|
|
The After= and Wants=/Requires= directives build the dependency graph that systemd uses to determine ordering and parallelism.
Boot Performance Analysis
|
|
Boot Logs with journalctl
|
|
Making Journal Logs Persistent
By default on some distros, journal logs are lost on reboot (stored in /run/log/journal). To keep them:
|
|
Or set Storage=persistent in /etc/systemd/journald.conf.
Putting It All Together: Boot Rescue Scenarios
Scenario 1: System Won’t Boot Past GRUB
Symptoms: GRUB menu appears, but selecting an entry gives an error.
Diagnose:
- Press
eat GRUB menu to view the boot entry - Check if the kernel path and initrd path exist:
ls (hd0,gpt2)/boot/ - Try booting an older kernel entry from the GRUB menu
Fix from GRUB command line:
|
|
Once booted, reinstall GRUB:
|
|
Scenario 2: Kernel Panic — Cannot Mount Root
Symptoms: Kernel panic - not syncing: VFS: Unable to mount root fs
Causes:
- Wrong
root=parameter in GRUB - Root device name changed (sda → nvme0n1 after hardware change)
- initramfs doesn’t include the storage driver for the root device
- Filesystem corruption
Fix:
- Boot from live USB
- Mount the root filesystem manually
chrootinto it- Check
/etc/fstab— update UUIDs if device names changed:1 2blkid # Find current UUIDs vim /etc/fstab # Update to match - Rebuild initramfs:
dracut --forceorupdate-initramfs -u - Regenerate GRUB config
Scenario 3: System Boots to Emergency Target
Symptoms: systemd drops to emergency.target — root prompt, but no services.
Diagnoses:
|
|
Fix: Edit /etc/fstab to correct bad entries. A missing or wrong UUID for a non-root filesystem is a common cause — add nofail to non-critical entries:
UUID=abc123 /data ext4 defaults,nofail 0 2
Scenario 4: Forgotten Root Password
- At GRUB menu, press
e - Find the
linuxline, addinit=/bin/bashat the end - Press
Ctrl+Xto boot - You get a root bash shell (root filesystem is read-only):
1 2 3 4 5mount -o remount,rw / passwd root # Set new password sync reboot -f
Alternatively, use rd.break for a cleaner approach (see initramfs section above).
Scenario 5: Service Fails to Start at Boot
|
|
Understanding the Filesystem Layer at Boot
/proc/mounts vs /etc/fstab
|
|
fstab Fields
# Device Mount Point FS Type Options Dump Pass
UUID=abc123... / ext4 defaults 0 1
UUID=def456... /boot ext4 defaults 0 2
UUID=789abc... /boot/efi vfat umask=0077 0 1
UUID=012def... /home xfs defaults,nofail 0 2
tmpfs /tmp tmpfs defaults,size=2G 0 0
- Dump — 0: don’t backup with
dump; 1: do - Pass — 0: don’t fsck; 1: fsck first (root only); 2: fsck after root
Quick Reference: Boot Stages
POWER ON
│
▼
FIRMWARE (BIOS/UEFI)
├─ POST: test hardware
├─ BIOS: read MBR → execute 446-byte bootstrap
└─ UEFI: read NVRAM boot entries → load EFI application from ESP
▼
BOOTLOADER (GRUB2)
├─ Load /boot/grub2/grub.cfg
├─ Present boot menu
├─ Load vmlinuz + initrd.img into RAM
└─ Pass kernel parameters, jump to kernel entry point
▼
KERNEL
├─ Decompress itself
├─ Initialize memory management, scheduler, VFS
├─ Probe and initialize hardware
└─ Unpack initramfs, exec /init inside it
▼
INITRAMFS
├─ Load storage drivers (nvme, virtio, mdraid...)
├─ Unlock LUKS, assemble LVM/RAID if needed
├─ Mount real root filesystem at /sysroot
├─ switch_root to /sysroot
└─ exec /sbin/init (systemd)
▼
SYSTEMD (PID 1)
├─ Read unit files from /lib/systemd/system/ and /etc/systemd/system/
├─ Build dependency graph
├─ Start units in parallel (respecting ordering constraints)
├─ Reach default.target (usually graphical.target or multi-user.target)
└─ Start display manager or getty → LOGIN PROMPT
Key Files and Commands Summary
|
|
Understanding the boot process transforms a mysterious black box into a predictable sequence of handoffs. When a system fails to boot, you now know exactly which stage to look at — and how to intervene at each one.
Comments