Skip to content

101.2 Boot the system

The boot process

5 steps, in order:

  1. POST (Power-On Self-Test) - firmware checks basic hardware (RAM, CPU)
  2. Firmware (BIOS/UEFI) loads the bootloader
  3. Bootloader (GRUB) loads the kernel based on its config/commands
  4. Kernel loads, prepares the system (root filesystem via initramfs), runs the init program
  5. Init (systemd/SysVinit) starts services (networking, web server, graphical interface, etc.)

BIOS boot vs UEFI boot

BIOS boot sequence

  1. POST runs
  2. BIOS activates basic components (video, keyboard, storage)
  3. BIOS loads first stage bootloader from MBR (first 440 bytes of first disk)
  4. First stage bootloader calls second stage, which presents boot options and loads the kernel

  5. MBR = first 512 bytes of disk (440 bytes bootloader + 64 bytes partition table + 2 bytes signature)

  6. Limited to one sector, needs multi-stage bootloader

UEFI boot sequence

  1. POST runs
  2. UEFI activates basic components
  3. UEFI reads settings stored in NVRAM and runs the pre-defined EFI application from the ESP partition
  4. EFI application (usually a bootloader) loads the kernel

  5. Uses a dedicated ESP (EFI System Partition), FAT formatted, mounted at /boot/efi

  6. Bootloader files have .efi extension
  7. Does not rely on MBR, uses NVRAM settings instead
  8. Supports Secure Boot - only runs signed EFI applications (can make installing other OSes harder)
ESP partition (FAT, mounted at /boot/efi)
        |
        contains .efi files (EFI applications)
        |
        UEFI reads NVRAM -> knows which .efi file to run
        |
        usually: that .efi file IS the bootloader (GRUB)
        |
        bootloader loads the kernel

Check: ls /sys/firmware/efi - exists = UEFI


Bootloader (GRUB)

GRUB = Grand Unified Bootloader. Most popular bootloader for Linux on x86.

  • GRUB displays a list of installed OS/kernels to boot
  • To show GRUB menu: press Shift (BIOS) or Esc (UEFI) during boot
  • From GRUB menu you can choose a kernel and pass parameters to it

Kernel and initramfs

  • Kernel = the core of the OS, loaded into RAM by the bootloader
  • initramfs (initial RAM filesystem) = archive containing a temporary root filesystem used during boot
  • Provides modules/drivers the kernel needs to access the real root filesystem
  • Once the real root filesystem is mounted, initramfs is removed from RAM
  • The kernel mounts all filesystems in /etc/fstab, then runs the first program: init (PID 1)
Bootloader loads kernel
        v
Kernel loads initramfs into RAM
        v
initramfs gives kernel the drivers it needs
        v
Kernel mounts the REAL root filesystem (your disk)
        v
initramfs is discarded from RAM
        v
Kernel runs init (PID 1)

Kernel parameters

Parameters passed to the kernel at boot time via GRUB. Format: option=value

Parameter Effect
acpi=off Disable ACPI support
init=/bin/bash Use bash as init (drops to shell after boot)
systemd.unit=graphical.target Set systemd target to activate
1 or S Boot in single-user mode (recovery)
mem=512M Limit available RAM to 512MB
maxcpus=2 Limit visible CPUs to 2
quiet Hide most boot messages
vga=792 Set video mode (1024x768x24)
vga=ask Show list of available video modes
root=/dev/sda3 Set root partition
rootflags=... Mount options for root filesystem
ro Mount root filesystem read-only
rw Mount root filesystem read-write
  • Make persistent: add to GRUB_CMDLINE_LINUX in /etc/default/grub, then run grub-mkconfig -o /boot/grub/grub.cfg
  • See current boot parameters: cat /proc/cmdline

Kernel Ring Buffer (dmesg)

The kernel stores its messages in the kernel ring buffer - a memory area that loses all data when the system is turned off.

dmesg                        # show kernel ring buffer messages
dmesg -H                     # human-readable with pager
dmesg --clear                # clear the ring buffer
  • After boot, syslog daemon stores boot logs in /var/log/dmesg
  • Boot logs also in /var/log/boot (Debian) or /var/log/boot.log (Red Hat)
  • Can also use journalctl -k (kernel logs) or journalctl -b (boot logs) or journalctl -u kernel

/var/log/messages

  • After init starts, syslog daemon logs messages here
  • Has timestamps, persists across reboots
  • Kernel is still logging its own messages in the Kernel Ring Buffer too
  • Some systems call it /var/log/syslog
  • Many other logs in /var/log/

init

The init process is PID 1. It starts all other services and daemons.

which init                    # /sbin/init
readlink -f /sbin/init        # shows the real init (e.g. /usr/lib/systemd/systemd)
ps -p 1                       # shows init process
pstree                        # shows process hierarchy

Different init systems:

  • SysVinit - based on Unix System V, not used much anymore, but still found on older or even some recently installed machines
  • Upstart - event-based replacement for init, developed by Canonical (Ubuntu), released 2007, discontinued due to wide adoption of systemd. Ubuntu now uses systemd, but Upstart can still be found in Google's ChromeOS
  • systemd - the new replacement. Hated by Linux elitists for not following Unix principles, but widely adopted by major distros. Starts services in parallel and does lots of extra things

systemd

Built around units. A unit can be a service, group of services, or an action. Units have a name, a type, and a configuration file.

12 unit types: automount, device, mount, path, scope, service, slice, snapshot, socket, swap, target, timer.

We use systemctl to work with units and journalctl to see the logs.

systemctl list-units
systemctl list-units --type=target
systemctl get-default             # default target

Units can be found in these places (sorted by priority):

  1. /etc/systemd/system/
  2. /run/systemd/system/
  3. /usr/lib/systemd/system
systemctl list-unit-files
systemctl cat ntpd.service
systemctl cat graphical.target

Commands to work with services:

systemctl stop sshd
systemctl start sshd
systemctl status sshd
systemctl is-active sshd
systemctl is-failed sshd
systemctl restart sshd
systemctl reload sshd           # re-reads the configuration of the service configs
systemctl daemon-reload sshd    # re-reads the configuration of the systemd configs of this service
systemctl enable sshd
systemctl disable sshd

Other commands:

systemctl is-system-running    # running, degraded, maintenance, initializing, starting, stopping
systemctl --failed

To check the logs, use journalctl:

journalctl                  # show all journal
journalctl --no-pager       # do not use less
journalctl -n 10            # only 10 lines
journalctl -S -1d           # last 1 day
journalctl -xe              # last few logs
journalctl -u ntp           # only ntp unit
journalctl _PID=1234

SysV

The older init system. Still can be used on many systems. Control files are located at /etc/init.d/ and are closer to general bash scripts.

/etc/init.d/ntpd status
/etc/init.d/ntpd stop
/etc/init.d/ntpd start
/etc/init.d/ntpd restart

Summary

I have a computer with a motherboard that has firmware on it. When I press the power button, the firmware runs a Power-On Self Test (POST), checking the RAM and CPU. If everything is okay, it starts booting from the hard disk.

The motherboard firmware completes the POST and, if the hardware is fine, it starts a program called the bootloader, which is located on the hard disk. The bootloader's job is to load the Linux kernel based on its configuration.

The Linux kernel is the core of the operating system, but it needs additional data to operate. This data is in a file called initramfs, which contains the necessary drivers for the kernel to start.

So, when the system boots, the firmware loads the bootloader, the bootloader loads the kernel, and the kernel gets the initramfs. Now the kernel can control the hardware, and it runs the init program (PID 1) to start everything the system needs.