Introduction: The Hidden Complexity of Startup

You press the power button. A few seconds later, your laptop displays a login prompt. Firmware runs, bootloaders execute, the kernel loads, initialization systems start services, filesystems mount, daemons launch. Dozens of pieces of software (some old, some new, some you've never heard of) coordinate to bring your system to life.

This article traces the complete journey from power button to login.

Part One: The Boot Sequence Overview

POWER ON ↓ BIOS/UEFI (Firmware initialization) ↓ Bootloader (GRUB, load kernel) ↓ Kernel loads and initializes ↓ Initramfs mounts (early userspace) ↓ Real root filesystem mounts ↓ Init system starts (systemd, init, runit, etc.) ↓ Services launch (networking, logging, display manager, etc.) ↓ Login prompt appears

Let's examine each stage.

Part Two: Stage 1 - Firmware (BIOS/UEFI)

What Firmware Does

Power-On Self Test (POST)

When you press power, the CPU wakes and runs instructions stored in ROM (read-only memory). This firmware, either BIOS (Basic Input/Output System) or UEFI (Unified Extensible Firmware Interface), performs initial hardware checks:
• Memory test
• CPU verification
• Disk detection
• PCI/USB device initialization

BIOS vs. UEFI

BIOS (1980s-2010s): The original firmware standard. 16-bit real mode execution. Limited to 1MB of addressable memory. Can load bootloader from first sector of disk (512 bytes). Simple but restrictive.

UEFI (2000s-present): Modern replacement. 32/64-bit execution. Larger boot partition. Can run EFI applications directly. More flexible and powerful. Has largely replaced BIOS on modern systems. UEFI also supports Secure Boot, a feature that verifies the digital signatures of bootloaders and kernels before executing them. Secure Boot prevents rootkits and bootkits from inserting malicious code early in the boot process by only allowing signed, trusted software to run.

Finding and Loading the Bootloader

After POST, firmware searches for bootable devices in order (configurable in BIOS/UEFI settings). On a BIOS system, it looks for the MBR (Master Boot Record), the first 512 bytes of the disk.

BIOS MBR format: - Bytes 0-445: Bootloader code (446 bytes) - Bytes 446-509: Partition table (4 entries, 16 bytes each) - Bytes 510-511: Boot signature (0xAA55) UEFI: - ESP (EFI System Partition) - 200MB FAT32 partition - Bootloader is a regular file (e.g., EFI/BOOT/BOOTX64.EFI)

Complexity and History

Complexity: Firmware initialization is straightforward (run POST, find bootloader, load it) but hardware-specific. Different manufacturers implement BIOS/UEFI differently. Bugs in firmware are notoriously hard to fix (requires flashing ROM).

History: BIOS originated in 1981 with the IBM PC. It remained largely unchanged for decades despite technological progress. UEFI was developed starting in 1998 by Intel and became standard by the 2010s. Modern systems use UEFI almost exclusively.

Who wrote it: Firmware is written by manufacturers (Dell, Lenovo, HP, etc.), often based on reference implementations from chipset makers (Intel, AMD). Some open-source efforts exist (Coreboot, OVMF) but closed-source firmware remains dominant.

Part Three: Stage 2 - Bootloader (GRUB)

What the Bootloader Does

The bootloader's job: locate the kernel file, load it into memory, and transfer control to it. On modern systems using GRUB (GRand Unified Bootloader), the bootloader also displays the boot menu and can pass parameters to the kernel.

GRUB's Two-Stage Process

Stage 1 (boot.img, 512 bytes): Stored in MBR. Finds Stage 2.
Stage 2 (core.img + modules): Larger code with filesystem drivers. Can locate and load kernel.

The Boot Menu

GRUB displays a menu (often with timeout). You can select which kernel to boot or edit boot parameters. This is the point where you'd boot into recovery mode or select a different OS if multi-booting.

GRUB menu (what you see): ┌─ GNU GRUB 2.06 ─────────┐ │ Ubuntu, with Linux 5.15 │ │ Ubuntu, with Linux 5.10 │ │ Windows Boot Manager │ │ System Setup │ └───────────────────────────┘ Kernel command line passed to kernel: BOOT_IMAGE=/boot/vmlinuz-5.15.0-56-generic root=/dev/mapper/vg0-root ro quiet splash

GRUB Complexity

Complexity: GRUB is substantial (~10,000 lines of code). It needs to understand multiple filesystems (ext4, btrfs, XFS, NTFS, etc.) and boot protocols (BIOS, UEFI). Configuration lives in grub.cfg, which on most distributions is auto-generated by running update-grub (or grub-mkconfig). Users rarely write grub.cfg by hand; instead, they edit defaults in /etc/default/grub and scripts in /etc/grub.d/.

History: GRUB was created in the 1990s by Gordon Matzigkeit. GRUB 2 (released 2005) is the modern version, supporting UEFI and contemporary filesystems. It replaced LILO (LInux LOader) which was simpler but less flexible.

Alternatives: systemd-boot (simpler, UEFI-only), rEFInd (works with multiple OSes), SYSLINUX (for simpler use cases).

Loading the Kernel

GRUB loads the kernel (a file like `vmlinuz-5.15.0`) and the initramfs (initial ramdisk, an uncompressed cpio archive or compressed initrd) into memory. It then jumps to the kernel entry point, passing control to Linux.

Part Four: Stage 3 - Kernel Initialization

Kernel Startup Sequence

The kernel begins in assembly code (very low-level). It:

CPU initialization Set up CPU modes (from 16-bit real mode → 32-bit protected mode → 64-bit long mode)
Memory setup Enable paging (virtual memory). Set up kernel page tables
Interrupts and exceptions Set up IDT (Interrupt Descriptor Table) and exception handlers
Early console Print boot messages. If you see "Linux version 5.15.0..." kernel is running
Memory initialization Detect available RAM. Initialize buddy allocator and slab caches
Device detection Bus enumeration (PCI, USB). Probe device drivers
Filesystem registration Register filesystems, block devices, character devices
Mount initramfs Switch to initramfs as temporary root filesystem
Execute init script Run initramfs's init script (usually provided by dracut or mkinitcpio)

The Initramfs: Early Userspace

The initramfs (initial ramdisk) is a temporary filesystem containing essential tools. Its init script:

  • Loads kernel modules needed to access the real root filesystem
  • Detects hardware (especially disks and encryption hardware)
  • Decrypts encrypted root filesystem if needed
  • Mounts the real root filesystem
  • Executes the real init system (systemd, init, etc.)
Typical initramfs structure: /init (main script) /bin/busybox (tiny shell and utilities) /lib/modules/* (kernel modules) /etc/modprobe.d (module configuration) /dev (device files) Initramfs init script: 1. Mount /proc, /sys 2. Load module for root filesystem type (ext4, btrfs, etc.) 3. Load module for disk driver (ata, nvme, etc.) 4. Unlock LUKS encryption if present 5. Mount real root at / 6. Execute /sbin/init

Kernel Complexity

Complexity: The Linux kernel is ~20-30 million lines of code. Boot code is relatively small (~100,000 lines) but critical. Any failure here causes complete boot failure with no recovery.

History: Linux kernel created by Linus Torvalds in 1991. Boot code has evolved from simple 16-bit real-mode code to sophisticated 64-bit initialization. Modern kernels support dozens of architectures (x86, ARM, RISC-V, PowerPC, etc.).

Who wrote it: Linux kernel is maintained by Linus Torvalds with thousands of contributors. Boot code is written by architecture maintainers (x86 maintainers: Thomas Gleixner, Ingo Molnar, etc.).

Part Five: Stage 4 - Init System and Userspace

PID 1: The Init System

Once the kernel has booted and mounted the real root filesystem, it executes the init system (PID 1, the first user process). Modern Linux uses systemd almost exclusively.

Systemd: The Modern Init

Systemd is a system and service manager. It:
• Reads unit files (services, timers, mounts, etc.)
• Starts essential services in dependency order
• Manages logging (journald)
• Handles shutdown and reboot

Unit Files: Declarative Configuration

/etc/systemd/system/example.service: [Unit] Description=My Service After=network.target [Service] Type=simple ExecStart=/usr/bin/myservice Restart=on-failure [Install] WantedBy=multi-user.target

Systemd reads unit files and starts services in parallel respecting dependencies. Services can depend on each other ("After="), and systemd ensures correct ordering.

Boot Targets vs. Runlevels

Systemd uses "targets" instead of runlevels:

Target Purpose Old Runlevel
graphical.target Multi-user with GUI (login manager) 5
multi-user.target Multi-user text mode (no GUI) 3
rescue.target Single-user rescue mode 1 or S
emergency.target Minimal shell, read-only filesystem 0 (halt)

Essential Services That Start

During boot, systemd starts:

  • Filesystems: Mount /dev, /sys, /proc, /run. Check and repair root filesystem.
  • Networking: Bring up network interfaces. Start DNS resolver (systemd-resolved).
  • Logging: journald starts, ready to accept log messages.
  • Timekeeping: Set system clock (systemd-timesyncd or NTP).
  • Device management: udev detects hardware and creates device files.
  • Display manager: On graphical systems, GDM, LightDM, or SDDM starts, displaying login screen.

Init Systems: Historical Context

SysVinit (1980s-2010s): Original Unix init. Simple shell scripts in /etc/init.d/. Started services sequentially. Slow but transparent.

Upstart (2006-2014): Event-based init. Used by Ubuntu. Faster than SysVinit but less flexible than systemd.

Systemd (2010-present): Modern init system. Parallel starting, declarative units, integrated logging. Controversial due to scope creep but undeniably efficient and feature-rich.

Alternatives (still used): OpenRC, runit, dinit. These are simpler and suit embedded systems or minimalist setups.

Who wrote systemd: Created by Lennart Poettering and Kay Sievers. Now maintained by freedesktop.org. Controversial but highly influential.

Systemd Complexity

Complexity: Systemd is large (~500,000 lines of code). It does much more than just start services: device management (systemd-udevd), networking (systemd-networkd), container support, tmpfiles management, user sessions. Critics argue it's too complex and violates Unix philosophy. Defenders argue modern systems need these features.

Part Six: Display Manager and Login

Display Manager

On graphical systems, a display manager (SDDM, GDM, LightDM, XDM) is started. Its job: manage the display server and user login.

Display manager startup: systemd starts display-manager.service → /usr/bin/sddm (or gdm, lightdm) → Starts X server (or Wayland) → Displays login screen → Waits for user input

When you enter credentials and click login:

  1. Display manager authenticates against /etc/passwd and /etc/shadow
  2. If successful, forks a session
  3. Executes your shell or desktop environment (GNOME, KDE, Xfce, etc.)

Part Seven: Total Time and Optimization

Modern Boot Times

On modern SSDs, a typical Linux laptop boots in 5-15 seconds:

BIOS/UEFI: 0.5s GRUB: 0.5s Kernel initialization: 2-3s Initramfs: 0.5-1s Systemd startup: 1-2s Display manager: 0.5-1s User login: 0.5-1s Desktop ready: 2-3s Total: 8-12s

Optimizations

Fast storage: NVMe SSD is 10x faster than SATA SSD. Most boot time is I/O.

Parallel startup: Systemd starts services in parallel. SysVinit started sequentially.

Minimal services: Disable unnecessary services. Server systems need fewer services than desktops.

Compress kernel/initramfs: Gzip or xz compression reduces size, though decompression takes time (usually worth it).

systemd-analyze: Tool to profile boot time and find bottlenecks.

Part Eight: Boot Failure Recovery

Where Boots Fail

  • Firmware: Usually means hardware failure. Can't do much without reflashing.
  • GRUB: "GRUB>" prompt. Usually means grub.cfg is missing. Boot from USB and reinstall GRUB.
  • Kernel: Kernel panic (unreadable error message). Usually kernel module missing or hardware failure.
  • Initramfs: "emergency mode" or "initramfs prompt". Usually root device not found or encrypted volume can't unlock. Check crypttab and fstab.
  • Systemd: "systemd[1]: Starting..." then hangs. Usually service dependency problem or timeout.

Recovery Tools

Modern systems have fallback mechanisms:

  • emergency.target: Read-only root shell with minimal services.
  • rescue.target: Single-user mode with filesystem check.
  • systemd.unit=rescue.target on kernel command line: Boot into rescue mode instead of default target.
  • USB recovery media: Boot from USB to repair system.

Conclusion

Understanding boot reveals layers of abstraction: firmware (hardware interface), bootloader (firmware interface), kernel (hardware abstraction), init system (kernel interface), and applications (system interface). Each layer does its job and passes control to the next.

This layered approach is what makes Linux portable to countless devices: you can replace firmware, bootloader, or init system without rewriting the kernel. It's modularity in action.

"The boot process is where abstraction meets reality. Below the kernel is electronics and physics. Above the kernel is software. The kernel is the translator, the thing that makes a generic OS able to run on any hardware."