LUNAROPS · OPERATIONAL UPLINK 100% UPTIME 1,247d POSTS 893 JEFF.MOON@LUNAROPS.DEV UTC --:--:--

The Linux Boot Process: From Power Button to Login Prompt

linuxbootgrubuefisystemdkernelinitramfssysadmin

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)  │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘
  1. Firmware — The CPU starts here. Firmware initializes hardware, finds a bootable device, and hands off execution.
  2. Bootloader — A small program (usually GRUB) that loads the kernel and initial RAM disk from disk.
  3. Kernel — The Linux kernel initializes itself, sets up hardware drivers, and mounts the initial filesystem.
  4. initramfs — A temporary root filesystem in RAM that prepares the real root filesystem (handles encryption, RAID, LVM).
  5. 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:

  1. The CPU is hardwired to begin executing at a fixed memory address — 0xFFFF0 on x86 — which contains a jump instruction into the BIOS ROM.
  2. 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.
  3. The BIOS reads its configuration (stored in CMOS/NVRAM) to find the boot device order.
  4. 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).
  5. 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:

  1. Firmware initializes hardware and runs UEFI drivers.
  2. The Boot Manager reads NVRAM boot entries (BootOrder, Boot0000, Boot0001, …).
  3. It finds the EFI System Partition (typically /boot/efi, formatted FAT32) and loads the specified EFI application — usually /EFI/fedora/grubx64.efi or /EFI/ubuntu/grubx64.efi.
  4. The EFI application (bootloader) takes over.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Inspect UEFI boot entries on a running system
efibootmgr -v

# Example output:
# BootCurrent: 0002
# BootOrder: 0002,0001,0000
# Boot0000* Windows Boot Manager
# Boot0001* fedora
# Boot0002* ubuntu    HD(1,GPT,...)/.../grubx64.efi

# Add/modify UEFI entries
efibootmgr --create --disk /dev/sda --part 1 \
  --loader /EFI/myos/grubx64.efi --label "My OS"

EFI System Partition

1
2
3
4
5
6
7
8
9
# Find the ESP
lsblk -o NAME,PARTTYPE,FSTYPE,MOUNTPOINT | grep -i efi

# Inspect ESP contents
ls /boot/efi/EFI/
# ubuntu/  fedora/  BOOT/

ls /boot/efi/EFI/ubuntu/
# grubx64.efi  shimx64.efi  grub.cfg

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)
1
2
3
4
5
6
7
8
9
# Check Secure Boot status
mokutil --sb-state
# SecureBoot enabled

# List enrolled keys
mokutil --list-enrolled

# Enroll your own key (for custom kernels/modules)
mokutil --import my-key.der

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Main config file (never edit directly — regenerate it)
cat /boot/grub2/grub.cfg      # RHEL/Fedora
cat /boot/grub/grub.cfg       # Debian/Ubuntu

# Human-editable defaults
cat /etc/default/grub

# Custom menu entries go here
ls /etc/grub.d/

# Regenerate grub.cfg from /etc/default/grub and /etc/grub.d/
grub2-mkconfig -o /boot/grub2/grub.cfg    # RHEL/Fedora
update-grub                                # Debian/Ubuntu

Key /etc/default/grub Options

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Timeout before default entry boots (seconds; -1 = wait forever)
GRUB_TIMEOUT=5

# Default boot entry (0-indexed, or "saved" for last booted)
GRUB_DEFAULT=0

# Kernel command line parameters appended to all entries
GRUB_CMDLINE_LINUX="quiet splash"

# Disable graphical splash for troubleshooting
GRUB_CMDLINE_LINUX="nosplash"

# Serial console (for headless servers)
GRUB_TERMINAL="serial console"
GRUB_SERIAL_COMMAND="serial --speed=115200 --unit=0 --word=8 --parity=no --stop=1"

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
1
2
3
4
5
# View the kernel parameters of the currently running system
cat /proc/cmdline
# BOOT_IMAGE=/vmlinuz-6.1.0-20-amd64 root=/dev/mapper/debian-root ro quiet

# Edit kernel parameters at boot: at GRUB menu, press 'e', edit, Ctrl+X to boot

GRUB Command Line (Interactive Recovery)

At the GRUB menu, press c to enter the GRUB command shell — useful when the config is broken:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# List detected devices
grub> ls
(hd0) (hd0,gpt1) (hd0,gpt2) (hd0,gpt3)

# List files on a partition
grub> ls (hd0,gpt2)/

# Manually boot a kernel
grub> set root=(hd0,gpt2)
grub> linux /vmlinuz-6.1.0 root=/dev/sda3 ro
grub> initrd /initrd.img-6.1.0
grub> boot

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

1
2
3
4
5
ls /boot/
# vmlinuz-6.1.0-20-amd64      Compressed kernel image
# initrd.img-6.1.0-20-amd64   Initial RAM disk
# System.map-6.1.0-20-amd64   Kernel symbol table (for debugging)
# config-6.1.0-20-amd64       Kernel build configuration

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

  1. Decompression — The kernel’s head code decompresses the main kernel binary into a fixed memory location.

  2. Architecture setup — Sets up the GDT (Global Descriptor Table), IDT (Interrupt Descriptor Table), enables paging, enters 64-bit long mode.

  3. 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
  4. Device detection — The kernel probes for hardware. Built-in drivers initialize devices they recognize; others wait for the module loading stage.

  5. PID 1 — The kernel creates the first process, swapper (PID 0, the idle process), then spawns PID 1 by executing /sbin/init (or whatever init= specifies). All other processes descend from PID 1.

Kernel Messages

All early kernel output goes to the kernel ring buffer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# View kernel boot messages (current boot)
dmesg | less

# Follow kernel messages in real time
dmesg -w

# Filter for specific subsystems
dmesg | grep -i "usb\|pci\|nvme\|eth\|error\|fail"

# Show timestamps
dmesg -T

# Previous boot's kernel messages (if journald is persistent)
journalctl -k -b -1

# Check for hardware errors
dmesg | grep -iE "error|fail|mce|hardware"

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 lvm tools
  • Root might be LUKS-encrypted → needs cryptsetup and 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

1
2
3
4
5
6
7
8
9
# List contents without extracting
lsinitrd /boot/initrd.img-6.1.0-20-amd64   # Fedora/RHEL tool
# or
cpio -itv < <(zcat /boot/initrd.img-6.1.0-20-amd64) 2>/dev/null | head -40

# Extract to examine (safe to do in /tmp)
mkdir /tmp/initrd-inspect && cd /tmp/initrd-inspect
zcat /boot/initrd.img-6.1.0-20-amd64 | cpio -idmv 2>/dev/null
ls -la

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:

  1. Mount sysfs, procfs, devtmpfs
  2. Load kernel modules needed for storage (nvme, ahci, virtio_blk, etc.)
  3. Run udev to populate /dev with device nodes
  4. If LUKS encryption: prompt for passphrase, run cryptsetup
  5. If LVM: scan for volume groups, activate logical volumes (vgchange -ay)
  6. If software RAID: assemble arrays (mdadm --assemble)
  7. Run fsck on the root device if needed
  8. Mount the real root filesystem at /sysroot
  9. pivot_root or switch_root — make /sysroot the new /, discard the initramfs tmpfs
  10. exec the real /sbin/init (systemd)

Rebuilding initramfs

Necessary after adding kernel modules, changing storage configuration, or updating cryptsetup:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Debian/Ubuntu
update-initramfs -u -k all       # Update all installed kernels
update-initramfs -u -k $(uname -r)  # Current kernel only
update-initramfs -c -k $(uname -r)  # Create fresh (not update)

# RHEL/Fedora
dracut --force                    # Rebuild for current kernel
dracut --force /boot/initramfs-$(uname -r).img $(uname -r)

# Verify the result
lsinitrd | grep -i crypt   # Check LUKS support included
lsinitrd | grep -i lvm     # Check LVM support included

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# You'll get a shell with the initramfs as root
# The real root filesystem is at /sysroot (mounted read-only)

# Remount it read-write
mount -o remount,rw /sysroot

# Chroot into the real system
chroot /sysroot

# Now you can fix things: reset passwords, fix fstab, reinstall GRUB, etc.
passwd root

# Exit chroot and continue boot
exit
exit

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
1
2
3
4
5
6
7
8
# Show current target
systemctl get-default

# Change default target
systemctl set-default multi-user.target

# Switch to a target immediately (like changing runlevel)
systemctl isolate rescue.target

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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# /lib/systemd/system/nginx.service
[Unit]
Description=nginx HTTP Server
After=network.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

The After= and Wants=/Requires= directives build the dependency graph that systemd uses to determine ordering and parallelism.

Boot Performance Analysis

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Show critical chain — the longest dependency path through boot
systemd-analyze critical-chain

# Time each unit took to start
systemd-analyze blame

# Generate an SVG timeline diagram
systemd-analyze plot > boot-timeline.svg

# Overall boot time breakdown
systemd-analyze
# Startup finished in 2.831s (firmware) + 3.201s (loader) + 1.782s (kernel) + 8.234s (userspace) = 16.049s

# Show units that failed to start
systemctl --failed

Boot Logs with journalctl

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# All messages from current boot
journalctl -b

# Messages from previous boot
journalctl -b -1

# Messages from 2 boots ago
journalctl -b -2

# List available boots
journalctl --list-boots

# Follow current boot messages in real time
journalctl -f

# Show only kernel messages
journalctl -k -b

# Messages from a specific service during boot
journalctl -b -u nginx.service

# Show errors and above only
journalctl -b -p err

Making Journal Logs Persistent

By default on some distros, journal logs are lost on reboot (stored in /run/log/journal). To keep them:

1
2
3
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald

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 e at 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:

1
2
3
4
5
grub> ls (hd0,gpt2)/boot/
# Identify the correct kernel filename, then:
grub> linux (hd0,gpt2)/boot/vmlinuz-6.1.0 root=/dev/sda2 ro
grub> initrd (hd0,gpt2)/boot/initrd.img-6.1.0
grub> boot

Once booted, reinstall GRUB:

1
2
grub2-install /dev/sda          # BIOS
grub2-mkconfig -o /boot/grub2/grub.cfg

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:

  1. Boot from live USB
  2. Mount the root filesystem manually
  3. chroot into it
  4. Check /etc/fstab — update UUIDs if device names changed:
    1
    2
    
    blkid                # Find current UUIDs
    vim /etc/fstab       # Update to match
    
  5. Rebuild initramfs: dracut --force or update-initramfs -u
  6. Regenerate GRUB config

Scenario 3: System Boots to Emergency Target

Symptoms: systemd drops to emergency.target — root prompt, but no services.

Diagnoses:

1
2
3
4
5
6
7
8
# Check what failed
systemctl --failed
journalctl -b -p err

# Common cause: bad /etc/fstab entry
cat /etc/fstab
# Mount all filesystems and see what fails
mount -a

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

  1. At GRUB menu, press e
  2. Find the linux line, add init=/bin/bash at the end
  3. Press Ctrl+X to boot
  4. You get a root bash shell (root filesystem is read-only):
    1
    2
    3
    4
    5
    
    mount -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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Find the failing unit
systemctl --failed

# Check its logs
journalctl -u myservice.service -b

# Try starting it manually and watch output
systemctl start myservice.service
systemctl status myservice.service -l

# Check dependencies
systemctl list-dependencies myservice.service

# See what's blocking it
systemd-analyze verify /etc/systemd/system/myservice.service

Understanding the Filesystem Layer at Boot

/proc/mounts vs /etc/fstab

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# What is actually mounted right now
cat /proc/mounts

# What should be mounted at boot
cat /etc/fstab

# Mount everything in fstab that isn't mounted yet
mount -a

# Check filesystem UUIDs (more reliable than device names across reboots)
blkid
lsblk -o NAME,UUID,FSTYPE,MOUNTPOINT

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Firmware / UEFI
efibootmgr -v                      # View/manage UEFI boot entries
mokutil --sb-state                 # Check Secure Boot status
ls /boot/efi/EFI/                  # EFI applications on ESP

# GRUB
cat /etc/default/grub              # GRUB configuration
ls /etc/grub.d/                    # GRUB menu entry scripts
grub2-mkconfig -o /boot/grub2/grub.cfg  # Regenerate GRUB config
update-grub                        # Same on Debian/Ubuntu
grub2-install /dev/sda             # Reinstall GRUB to MBR

# Kernel
cat /proc/cmdline                  # Running kernel's parameters
dmesg -T                           # Kernel ring buffer with timestamps
uname -r                           # Running kernel version

# initramfs
lsinitrd                           # List initramfs contents (Fedora)
update-initramfs -u                # Rebuild initramfs (Debian)
dracut --force                     # Rebuild initramfs (Fedora/RHEL)

# systemd boot
systemd-analyze                    # Boot time summary
systemd-analyze blame              # Per-unit startup times
systemd-analyze critical-chain     # Longest dependency path
systemctl --failed                 # Failed units
journalctl -b                      # This boot's logs
journalctl -b -1                   # Previous boot's logs
systemctl get-default              # Current default target
systemctl set-default multi-user.target  # Change default target

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