Linux Boot Process: From Power-On to Login

20 min

Understand the Linux boot process through interactive visualizations. Learn about BIOS/UEFI, bootloaders, kernel initialization, and the journey to userspace.

Best viewed on desktop for optimal interactive experience

The Journey from Silicon to Shell

Every time you press the power button, your Linux system embarks on an epic journey. In mere seconds, it transforms from inert silicon to a fully functional operating system ready for your commands. This journey involves firmware handshakes, bootloader decisions, kernel awakening, and service orchestration.

Think of the boot process as a relay race. The BIOS/UEFI firmware starts the race, performs initial checks, and passes the baton to the bootloader. The bootloader selects and loads the kernel, which then initializes hardware and mounts filesystems. Finally, the init system takes over, starting services and preparing your login prompt. Each runner must complete their leg perfectly for the system to cross the finish line.

Let's trace this fascinating journey from the moment electricity flows through your circuits to the appearance of your desktop.

Interactive Boot Process Visualization

Explore each stage of the Linux boot process, from firmware to userspace:

Linux Boot Process

Boot Time: 0.0s
BIOS/UEFI
Hardware initialization and POST
Bootloader
GRUB/systemd-boot loads kernel
Kernel
Kernel initialization
Init/Systemd
Init system starts services
User Space
Login and desktop environment
[ 0.000000] Linux version 6.1.0 x86_64

Stage 1: Firmware (BIOS/UEFI)

Power-On Self Test (POST)

The journey begins when the CPU receives power:

1. CPU starts in real mode (16-bit) 2. CPU jumps to reset vector (0xFFFFFFF0) 3. BIOS/UEFI firmware takes control 4. Hardware initialization begins

BIOS Boot Process

; Legacy BIOS boot sequence ; 1. POST - Test hardware MOV AX, 0xAA55 ; Check boot signature ; 2. Find boot device INT 0x13 ; BIOS disk services ; 3. Load MBR (Master Boot Record) ; Load first 512 bytes from disk to 0x7C00 MOV AH, 0x02 ; Read sectors MOV AL, 1 ; Number of sectors MOV CH, 0 ; Cylinder 0 MOV CL, 1 ; Sector 1 MOV DH, 0 ; Head 0 MOV BX, 0x7C00 ; Destination address INT 0x13 ; Execute ; 4. Jump to bootloader JMP 0x7C00

UEFI Boot Process

// UEFI boot sequence // 1. SEC (Security) Phase ValidateFirmware(); InitializeTrustedPlatformModule(); // 2. PEI (Pre-EFI Initialization) InitializeMemory(); DiscoverBootDevices(); // 3. DXE (Driver Execution Environment) LoadDrivers(); InitializeDevices(); // 4. BDS (Boot Device Selection) ReadBootOrder(); // From NVRAM LoadBootloader(); // From ESP partition // 5. TSL (Transient System Load) HandOffToOS(); // Start OS bootloader

EFI System Partition

# ESP structure /boot/efi/ ├── EFI/ │ ├── BOOT/ │ │ └── BOOTX64.EFI # Default bootloader │ ├── ubuntu/ │ │ ├── grubx64.efi # GRUB bootloader │ │ ├── shimx64.efi # Secure Boot shim │ │ └── grub.cfg # GRUB config │ └── Microsoft/ │ └── Boot/ # Windows bootloader └── [FAT32 filesystem required] # View EFI variables efibootmgr -v # Add boot entry efibootmgr -c -d /dev/sda -p 1 -L "Linux" -l "\EFI\ubuntu\grubx64.efi"

Stage 2: Bootloader

GRUB 2 (Grand Unified Bootloader)

The most common Linux bootloader:

# GRUB configuration (/boot/grub/grub.cfg) menuentry 'Ubuntu 22.04' { # Set root device search --fs-uuid --set=root abc12345-6789-... # Load Linux kernel linux /vmlinuz-6.1.0-generic \ root=/dev/sda2 \ ro quiet splash # Load initial ramdisk initrd /initrd.img-6.1.0-generic # Boot the system boot } # GRUB modules insmod part_gpt # GPT partition support insmod ext2 # Filesystem support insmod gzio # Compression support insmod linux # Linux protocol

systemd-boot

Simple UEFI-only bootloader:

# /boot/loader/loader.conf default arch.conf timeout 4 console-mode max editor no # /boot/loader/entries/arch.conf title Arch Linux linux /vmlinuz-linux initrd /initramfs-linux.img options root=PARTUUID=abc12345 rw

rEFInd

Graphical UEFI bootloader:

# Auto-detects kernels and OSes # Configuration in /boot/efi/EFI/refind/refind.conf timeout 20 use_graphics_for linux scan_all_linux_kernels true

Stage 3: Kernel Loading

Kernel Decompression

// arch/x86/boot/compressed/head_64.S // Decompress kernel image startup_32: // Setup stack leal boot_stack_end(%ebx), %esp // Clear BSS xorl %eax, %eax leal _bss(%ebx), %edi leal _ebss(%ebx), %ecx rep stosl // Decompress kernel call decompress_kernel // Jump to decompressed kernel jmp *%eax

Early Kernel Initialization

// init/main.c asmlinkage __visible void __init start_kernel(void) { // Architecture-specific setup setup_arch(&command_line); // Initialize memory management mm_init(); // Initialize scheduler sched_init(); // Initialize interrupts init_IRQ(); // Initialize timers init_timers(); // Initialize console console_init(); // Mount root filesystem prepare_namespace(); // Start init process rest_init(); } void __init rest_init(void) { // Create kernel threads kernel_thread(kernel_init, NULL, CLONE_FS); kernel_thread(kthreadd, NULL, CLONE_FS); // Start scheduling cpu_startup_entry(CPUHP_ONLINE); }

Stage 4: initramfs/initrd

Initial RAM Filesystem

# Create initramfs mkinitcpio -g /boot/initramfs-linux.img # Contents of initramfs lsinitcpio /boot/initramfs-linux.img # Extract initramfs mkdir /tmp/initramfs cd /tmp/initramfs zcat /boot/initramfs-linux.img | cpio -idmv # Typical structure /init # Init script /bin/ # Essential binaries /sbin/ # System binaries /lib/ # Libraries /lib/modules/ # Kernel modules /etc/ # Configuration /dev/ # Device nodes /proc/ # Proc mount point /sys/ # Sysfs mount point

Init Script

#!/bin/sh # Simple initramfs init script # Mount essential filesystems mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs none /dev # Load essential modules modprobe ahci modprobe sd_mod modprobe ext4 # Wait for root device while [ ! -e /dev/sda2 ]; do sleep 0.1 done # Mount root filesystem mount -o ro /dev/sda2 /mnt/root # Switch to real root exec switch_root /mnt/root /sbin/init

Stage 5: Init System

systemd

Modern init system with parallel service startup:

# systemd boot process 1. systemd (PID 1) starts 2. Reads /etc/systemd/system/default.target 3. Resolves dependencies 4. Starts services in parallel # Unit file example (/etc/systemd/system/myservice.service) [Unit] Description=My Custom Service After=network.target Requires=network.target [Service] Type=simple ExecStart=/usr/bin/myservice Restart=always User=myuser [Install] WantedBy=multi-user.target
# systemd targets (runlevels) poweroff.target → Power off system rescue.target → Single user mode multi-user.target → Multi-user, no GUI graphical.target → Multi-user with GUI reboot.target → Reboot system # View boot process systemd-analyze systemd-analyze blame systemd-analyze critical-chain systemd-analyze plot > boot.svg # View dependencies systemctl list-dependencies graphical.target

SysV Init

Traditional init system:

# /etc/inittab id:3:initdefault: # System initialization si::sysinit:/etc/rc.d/rc.sysinit # Runlevels l0:0:wait:/etc/rc.d/rc 0 l1:1:wait:/etc/rc.d/rc 1 l2:2:wait:/etc/rc.d/rc 2 l3:3:wait:/etc/rc.d/rc 3 l4:4:wait:/etc/rc.d/rc 4 l5:5:wait:/etc/rc.d/rc 5 l6:6:wait:/etc/rc.d/rc 6 # Getty terminals 1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2

OpenRC

Gentoo's init system:

# Runlevels /etc/runlevels/ ├── boot/ # Boot services ├── default/ # Default services ├── nonetwork/ # No network └── shutdown/ # Shutdown services # Service script #!/sbin/openrc-run depend() { need net after firewall } start() { ebegin "Starting myservice" start-stop-daemon --start --exec /usr/bin/myservice eend $? }

Boot Optimization

Measuring Boot Time

# systemd boot time systemd-analyze # Detailed timing systemd-analyze blame # Critical path systemd-analyze critical-chain # Plot boot chart systemd-analyze plot > bootchart.svg # Kernel timing dmesg | grep -E "\[[ ]*[0-9]+\.[0-9]+\]"

Optimization Techniques

# Disable unnecessary services systemctl disable bluetooth systemctl disable cups # Use systemd-boot instead of GRUB # Saves ~1-2 seconds # Compile custom kernel # Remove unused drivers and features # Enable compression # Use zstd for initramfs # Parallel service startup # systemd does this by default # Use SSD for /boot # Faster kernel/initramfs loading # Reduce GRUB timeout GRUB_TIMEOUT=1 # Silent boot quiet loglevel=3 rd.udev.log_priority=3

Troubleshooting Boot Issues

Recovery Methods

# Boot to single user mode # Add to kernel parameters: single # or 1 # or rd.break # Boot with minimal drivers nomodeset # Verbose boot remove: quiet splash add: debug # Bypass systemd init=/bin/bash # Emergency shell systemd.unit=emergency.target # Rescue mode systemd.unit=rescue.target

Common Boot Problems

# Kernel panic # - Check kernel parameters # - Verify initramfs integrity # - Check root= parameter # Cannot find root device # - Check UUID/device name # - Ensure drivers in initramfs # - Add rootdelay=10 # Black screen # - Try nomodeset # - Check video drivers # - Switch TTY (Ctrl+Alt+F2) # Stuck at service # - Boot to rescue mode # - Disable problematic service # - Check service logs # GRUB rescue mode grub> set root=(hd0,gpt2) grub> linux /vmlinuz root=/dev/sda2 grub> initrd /initrd.img grub> boot

Boot Security

Secure Boot

# UEFI Secure Boot chain 1. UEFI firmware (has Microsoft keys) 2. Shim loader (signed by Microsoft) 3. GRUB (signed by distribution) 4. Kernel (signed by distribution) # Check Secure Boot status mokutil --sb-state # Enroll MOK (Machine Owner Key) mokutil --import my-key.der # Sign kernel for Secure Boot sbsign --key db.key --cert db.crt \ --output vmlinuz.signed vmlinuz

Verified Boot

# dm-verity for root filesystem # Create hash tree veritysetup format /dev/sda2 /dev/sda3 # Kernel parameter root=/dev/mapper/root \ rootflags=ro \ verity.roothash=abc123...

Best Practices

  1. Keep /boot clean - Remove old kernels
  2. Backup boot configuration - Save GRUB/UEFI settings
  3. Test kernel updates - Keep previous kernel as fallback
  4. Monitor boot time - Detect degradation early
  5. Document customizations - Track boot parameter changes
  6. Enable persistent logging - Debug boot issues
  7. Use UUID for devices - Avoid device name changes
  8. Regular firmware updates - Security and compatibility

Conclusion

The Linux boot process is a carefully orchestrated sequence that transforms your hardware from a collection of silicon chips into a powerful operating system. From the first electrical impulse through firmware initialization, bootloader selection, kernel awakening, and service orchestration, each stage plays a crucial role.

Our interactive visualization showed how these stages connect and depend on each other. Understanding this process helps you optimize boot times, troubleshoot problems, and appreciate the complexity hidden behind that simple power button.

Remember: every successful boot is a small miracle of engineering, completed in seconds but representing decades of innovation.

Next: Package Management → ← Back to Networking Stack

If you found this explanation helpful, consider sharing it with others.

Mastodon