The Linux Boot Process
From the time the power button is pushed, till the Welcome Screen is displayed
To an average computer user, the process of powering on the computer seems very mundane. Simply push the power button, wait a few seconds and the Welcome Screen is displayed. But for system admins and hardcore Linux enthusiasts, the booting of a Linux system is quite a complex one; a labyrinth between thousands of lines of codes and a couple of dozens of files making sure that the system starts smoothly. The aim of this article is to depict these complex steps into a high-level overview for beginners and experts al-alike.
Basic Input Output System (BIOS)
The BIOS is a set of instructions that is written on very low level language. It is the first program installed in computers even before the OS. BIOS is stored in a non-volatile memory called Erasable Programmable Read-only Memory (EPROM) chip and the configuration settings of BIOS is stored in the Complementary Metal-Oxide Semiconductor (CMOS) flash memory.
The lifetime of a CMOS battery is around 10 years. When the battery drains out, CMOS is reset, losing all the custom settings and system clock. It’s a regular practice to remove the battery to recall CMOS settings if there is a configuration problem.
When the computer is powered on, the CPU approaches the BIOS to check if all the basic hardware required to start the computer is ready. This checking is known as the Power of Self Test (POST). POST process only happens when performing a so-called “cold boot” (turning on a powered off system); a “warm boot” (i.e. restarting the computer) leaves a special flag in the BIOS non-volatile memory that bypasses this task of checking.
The POST checks are performed majorly on:
- Hardware elements like processor, storage devices and memory.
- Basic System Devices like keyboard, and other peripheral devices.
- CPU Registers
- DMA (Direct Memory Access)
- Timer
- Interrupt controller
When POST is successfully finalized, bootstrapping is enabled. Bootstrapping starts the initialization of the OS. The process of booting from disk works by loading its first sector to memory known as Master Boot Record (MBR) and trying to execute it. If it fails, it tries the next device until it runs out; if no device able to boot is found, it gives the user an error and stops. The first boot sector it finds that contains a valid boot record is loaded into RAM and control is then transferred to the code that was loaded from the boot sector.
Master Boot Record (MBR)
Master Boot Record (MBR) or the primary bootloader is the first sector of the Hard Disk Drive (HDD). Its physical location is in the cylinder 0, head 0, sector 1. It stores the partition table and bootloader information. The MBR is only 512 bytes in size and contains machine code instructions for booting the machine, called a boot loader, along with the partition table. The first 446 bytes are the primary boot loader, which contains both executable code and error message text. The next 64 bytes are the partition table, which contains a record for each of 4 partitions (16 Bytes each). The MBR ends with 2 bytes that are defined as the magic number (0xAA55). The magic number serves as a validation check of the MBR.
To view the contents of the MBR:sudo dd if=/dev/nvme0n1 of=mbr.bin bs=512 count=1od -xa mbr.bin
The dd command reads the first 512 bytes from /dev/nvme0n1and writes them to the mbr.bin file. The od command prints the binary file in hex and ASCII formats.
The job of MBR is to find and load the secondary boot loader. It does this by looking through the partition table for an active partition. When it finds an active partition, it scans the remaining partitions in the table to ensure that they’re all inactive. When this is verified, the active partition’s boot record is read from the device into RAM and executed.
GRand Unified Bootloader (GRUB)
The secondary bootloader is called the kernel loader. The task of this is to load the Linux kernel and optional initial RAM disk. The first- and second-stage boot loaders combined are called GRand Unified Bootloader (GRUB). GRUB includes knowledge of Linux file systems. Instead of using raw sectors on the disk, as LILO does, GRUB can load a Linux kernel from an ext2 or ext3 file system. It does this by making the two-stage boot loader into a three-stage boot loader. Stage 1 (MBR) boots a stage 1.5 boot loader that understands the particular file system containing the Linux kernel image.
GRUB cannot fit in the 446 bytes of the MBR. To locate and load the kernel, GRUB needs to support dozens of file systems and features such as encryption, software RAID and LVM.
GRUB loads itself into memory in the following stages:
The Stage 1 or primary boot loader is read into memory by the BIOS from the MBR. The primary boot loader exists on less than 512 bytes of disk space within the MBR and is capable of loading either the Stage 1.5 or Stage 2 boot loader.
The Stage 1.5 boot loader is read into memory by the Stage 1 boot loader, if necessary. Some hardware requires an intermediate step to get to the Stage 2 boot loader. This is sometimes true when the /boot/ partition is above the 1024 cylinder head of the hard drive or when using Logical Block Addressing (LBA) mode. The Stage 1.5 boot loader is found either on the /boot/ partition or on a small part of the MBR and the /boot/ partition.
The Stage 2 or secondary boot loader is read into memory. It displays a list of available kernels (defined in /etc/grub.conf
, with soft links from /etc/grub/menu.lst
and /etc/grub.conf
). This interface allows the user to select which kernel or operating system to boot, pass arguments to the kernel, or look at system parameters.
How To Change The GRUB Background ImageTo change the background image of GRUB, the configuration file is opened at /etc/default/grub.cfg and the following is appended:echo “GRUB_BACKGROUND=<path-to-the-image>” >> /etc/default/grub.cfgTo update the new configuration,the following is used:sudo update-grub
The secondary boot loader reads the operating system or kernel as well as the contents of /boot/sysroot/ into memory. Once GRUB determines which operating system or kernel to start, it loads it into memory and transfers control of the machine to that operating system.
Kernel
All of the kernels are in a self-extracting, compressed format to save space. The kernels are located in the /boot directory, along with an initial RAM disk image, and device maps of the hard drives.
After the selected kernel is loaded into memory and begins executing, it must first extract itself from the compressed version of the file before it can perform any useful work. Once the kernel has extracted itself, it loads systemd, which is the replacement for the old SysV init program, and turns control over to it.
This is the end of the boot process. At this point, the Linux kernel and systemd are running but unable to perform any productive tasks for the end user because nothing else is running.
Init
After the kernel is booted and initialized, the kernel starts the first user-space application. This is the first program invoked that is compiled with the standard C library. Prior to this point in the process, no standard C applications have been executed.
In a desktop Linux system, the first application started is commonly /sbin/init. But it need not be. Rarely do embedded systems require the extensive initialization provided by init (as configured through /etc/inittab). In many cases, you can invoke a simple shell script that starts the necessary embedded applications.
Some of most important tasks performed by init are as following:
- Check the root file system and remount it in read/write mode. Up to this point, root file system is mounted in read-only mode.
- Check and mount additional file systems.
- Initialize network cards. Some processes are triggered by the network card initialization, such ntpdate (used to synchronize local time with a network time server).
- Start daemons. Some daemons support the system processes, such as crond and syslogd. Some allow remote access, such as sshd and telnetd. And some represent actual network services such as named and httpd.
- Sets getty on physical or virtual terminals. This allows the user connected to a terminal to login and use the shell.
After the sysinit.target is fulfilled, systemd next starts the basic.target, starting all of the units required to fulfill it. The basic target provides some additional functionality by starting units that re required for the next target. These include setting up things like paths to various executable directories, communication sockets, and timers.
When one of these targets is reached, then startup has completed. If the multi-user.target is the default, then a text mode login is displayd on the console. If graphical.target is the default, then a graphical login is diplayed; the specific GUI login screen will depend on the default display manager that is used.
References:
The Scary TLDR: