6 Steps of Linux Boot Process Explained – The Complete Guide

By | August 14, 2023

As soon as we turn on our systems, it's very crucial for us to understand the processes that get triggered. Hence, it is really important for anyone to go through the concepts of booting to understand how an operating system behaves and also to resolve any booting error. Since we're talking about Linux systems here, let's begin with understanding the basics of booting in Linux.

Booting a Linux system involves several stages and software components, including firmware initialization, execution of a boot loader, initiation and launch of a Linux kernel image, and finally execution of various startup scripts and daemons. Here, we'll briefly be discussing all the booting processes in Linux.

The high-level stages of a typical Linux boot process are:

  • 1. BIOS / UEFI
  • 2. MBR
  • 3. GRUB
  • 4. Kernel
  • 5. Init
  • 6. Run Levels

Now, let's explore more about these stages -

1. BIOS / UEFI

BIOS stands for Basics Input/Output System. The first step in the Linux boot process is the BIOS, which performs system integrity checks. The BIOS is a firmware most commonly found in IBM PC-compatible computers, the dominant type of computers in the modern world. The main objective of the BIOS is to find the system bootloader.

So once the BIOS boots up the hard drive, it searches for the boot block to figure out how to boot up the system. Depending on how the disk partition is created, it will look at the MBR (Master Boot Record) and GPT (GUID Partition Table).

Conversely, a UEFI (Unified Extensible Firmware Interface) system stores all startup data in an .efi file. The file is on the EFI System Partition, which contains the boot loader. UEFI comes with many improvements from the traditional BIOS firmware. However, since we are using Linux, the majority of us are using BIOS.

We can check the partitions in our Linux machine by using the 'fdisk' command.

root@ubuntu:~$ sudo fdisk -l

Disk /dev/sda: 92 GiB, 98784247808 bytes, 192937984 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: DA785EC6-AB02-4D8F-9623-B1977C5CCCD5

Device       Start      End  Sectors  Size Type
/dev/sda1     2048     4095     2048    1M BIOS boot
/dev/sda2     4096  3149823  3145728  1.5G Linux filesystem
/dev/sda3  3149824 67106815 63956992 30.5G Linux filesystem

Disk /dev/sdb: 84 GiB, 90194313216 bytes, 176160768 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

Disk /dev/mapper/ubuntu--vg-ubuntu--lv: 30.5 GiB, 32744931328 bytes, 63954944 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

In summary, the bootloader is a small program that loads the operating system. It basically performs three main actions with the Linux kernel:

  • Locate on the disk
  • Insert into memory and
  • Execute with the supplied options.

2. Master Boot Record (MBR)

The MBR is situated in the first sector of the hard drive, the first 512 bytes. It contains the code to load another program somewhere on the disk, which in turn actually loads up our bootloader. It is further divided into three components - primary boot loader info in the first 446 bytes, partition table info in the next 64 bytes, and MBR validation check in the last 2 bytes.

It contains information about GRUB (or LILO in previous generation systems). So, in simpler terms MBR loads and executes the GRUB boot loader.

Note: LILO or Linux Loader was the default boot loader for most Linux distributions in the past. Today, many distributions use GRUB as the default boot loader, but LILO and its variant ELILO are still widely used.

Since we're talking about modern Linux distros here, let us understand what a GRUB boot loader is.

3. GRUB

GRUB stands for Grand Unified Bootloader.

Now that we know the primary goal of the bootloader is to load up the kernel, it is equally important for us to understand how it finds the kernel. To find it, we will need to look at our kernel or boot parameters. Now, let's look at these parameters:

  • initrd - (initial ramdisk) is a scheme to load a temporary root file system into memory for use as part of the Linux startup process.
  • BOOT_IMAGE - This is where the kernel image is located.
  • root - The location of the root filesystem; the kernel searches inside this location to find init. It is often represented by its UUID or the device name, such as /dev/sda1.
  • ro - It's a standard parameter that mounts the filesystem as read-only mode.
  • quiet - This parameter is added so that we don't see display messages that are going on in the background during boot.
  • splash - This parameter displays the splash screen.

GRUB displays a splash screen, waits for a few seconds, and loads the default kernel image (or the one that is chosen manually), as specified in the grub configuration file.

One big difference between GRUB and LILO systems is that GRUB supports booting multiple operating systems, whereas LILO can boot only one. GRUB also has knowledge of file systems, unlike the older LILO.

The main GRUB configuration file can be found in '/boot/grub/grub.cfg'. A simple configuration file could look something like this:

root@ubuntu:~$ sudo nano /boot/grub/grub.cfg
# /boot/grub/grub.cfg
#
# GRUB configuration file

# Timeout for menu
set timeout=5

# Default boot entry
set default=0

# Entry titles
menuentry "Ubuntu" {
    linux   /vmlinuz root=/dev/sda1 ro quiet splash
    initrd  /initrd.img
}

From the above output, we can see that the menuentry section represents a specific boot option. In this case, the entry is titled "Ubuntu." The Linux line specifies the kernel image file (vmlinuz) and the root device (/dev/sda1). The initrd line specifies the initial RAM disk file (initrd.img), which is used for loading additional drivers and modules during the boot process.

So, in simple terms, GRUB just loads and executes Kernel and initrd images.

You can check the grub version on your system with the following command. On my Ubuntu 23.04 system the output looks like this:

$ grub-install --version
grub-install (GRUB) 2.06-2ubuntu16
$

The commonly used versions of grub are either 0.97 (legacy) or grub 2, with grub 2 being the most recent and widely adopted.

4. Kernel

Now that our bootloader has passed on the necessary parameters, we must understand how the rest of the booting actions take place:

Initrd vs Initramfs

Initrd (initial RAM disk) and initramfs (initial RAM file system) are both used as temporary file systems loaded into memory during the boot process. Initrd is an older method that uses a compressed file system image, while initramfs is a newer approach that utilizes a cpio archive for greater flexibility and efficiency in managing the boot process.

Mounting the root filesystem

Mounting the root file system is a crucial step in the boot process to make the main file system accessible to the operating system. Now the kernel has all the modules it needs to create a root device and mount the root partition.

Before we proceed any further, the root partition is actually mounted in read-only mode so that 'fsck' can run safely and check for system integrity. Afterward, it remounts the root filesystem in read-write mode. Then the kernel locates the init program and executes it.

Kernel executes the /sbin/init file or program. Since init is the first program to be executed by kernel, it has the process id (PID/ Process ID) of 1 always. We can see the PID of the init file by executing the following command - ps -ef | grep init.

root@ubuntu:/sbin$ ps -ef | grep init
root         1     0  0 May07 ?        00:01:43 /sbin/init maybe-ubiquity

5. Init

Init checks and identifies the default init level from file "/etc/inittab" and loads all appropriate programs required for the run level. Listing down the run levels below:

  • 0 – halt
  • 1 – single-user mode
  • 2 – Multiuser, without NFS
  • 3 – Full multiuser mode
  • 4 – unused
  • 5 – X11
  • 6 – reboot

We usually set the default run level between 0 and 6 for a smooth operation.

The init system is launched via the program /sbin/init. It might be a symlink to the actual init system binary. On my ubuntu system it points to the systemd binary

$ ls -la /sbin/init 
lrwxrwxrwx 1 root root 20 Mar 20 19:47 /sbin/init -> /lib/systemd/systemd
$

There are actually three different init systems in Linux:

SysV init (System V)

It starts and stops processes in a systematic order based on startup scripts. The state of the machine is denoted by runlevels, and each runlevel behaves differently. It has now been replaced by Systemd.

Upstart

Upstart uses the idea of jobs and events and works by starting jobs that perform certain actions in response to events. This unit is found on older Ubuntu installations.

Systemd

This is the new standard for init and a more popular one. The command used to interact with systemd is systemctl that can be used to manage the system and all the services running under systemd. Inside Systemd services are identified as units, and besides services there are many other type of units like mount points, devices and sockets etc.

Systemd uses the /etc/systemd/system/default.target or /lib/systemd/system/default.target file to decide the state or target the Linux system boots into.

To check what init system is running on your linux system use the following command:

$ sudo stat /proc/1/exe
  File: /proc/1/exe -> /usr/lib/systemd/systemd
  Size: 0               Blocks: 0          IO Block: 1024   symbolic link
Device: 0,22    Inode: 16337       Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-06-24 16:30:01.644109024 +0530
Modify: 2023-06-06 12:56:01.788704998 +0530
Change: 2023-06-06 12:56:01.788704998 +0530
 Birth: -
$

6. Run Levels

Run levels, in the Linux booting process, define different operating modes or configurations that the system can be in.

Depending on the default init level setting, the system will execute the programs from one of the following directories:

  • Run level 0 – /etc/rc.d/rc0.d/
  • Run level 1 – /etc/rc.d/rc1.d/
  • Run level 2 – /etc/rc.d/rc2.d/
  • Run level 3 – /etc/rc.d/rc3.d/
  • Run level 4 – /etc/rc.d/rc4.d/
  • Run level 5 – /etc/rc.d/rc5.d/
  • Run level 6 – /etc/rc.d/rc6.d/

There are several notations to be considered under run levels:

  • There are symbolic links available for these directories under /etc directly. For example, /etc/rc0.d is linked to /etc/rc.d/rc0.d.
  • Inside /etc/rc.d/rc*.d/ directories, we'll see programs that start with S and K.
  • Programs starting with 'S' are used for startup.
  • Programs starting with 'K' are used to kill the process or shut it down.
  • We can see a number right after the letter 'S' or 'K'. This is actually the sequence number in which a program is executed (killed or started).

There we have it. This is exactly what goes on behind the Linux booting process.

How do Dual-Boot Setups Work

In a typical dual-boot setup, the system is configured to have multiple operating systems installed on the same computer, allowing us to choose between them during startup.

On modern systems, UEFI (Unified Extensible Firmware Interface) and ESP (EFI System Partition) play important roles in this process. Now, let's see how the dual-boot setup works:

As previously discussed, UEFI is the modern firmware interface that replaces the traditional BIOS. It provides a standard method for booting the operating system and managing system settings. UEFI firmware initializes the hardware, performs the necessary tests, and then looks for the bootloader.

ESP (EFI System Partition) : The ESP is a partition on the storage device that holds the necessary files for booting the operating systems. It is typically formatted with the FAT32 file system, which is compatible with UEFI firmware. The ESP contains various directories, with the "EFI" directory being the most significant.

Separate boot-loaders : The EFI directory within the ESP stores the bootloaders and related files for each installed operating system. For example, if we have Linux and Windows installed, the ESP will contain separate directories for each. Within these directories, the EFI bootloaders for Linux and Windows reside.

During startup, the UEFI firmware detects the ESP and looks for the bootloader in the EFI directory. The bootloader, such as GRUB for Linux or the Windows Boot Manager for Windows, is responsible for loading the selected operating system.

GRUB, the default bootloader in many dual-boot configurations, resides in the EFI directory within the ESP. It provides a boot menu with options for different operating systems. The GRUB configuration files, such as "grub.cfg," are typically stored in the '/boot/grub' directory (Linux).

When we select an operating system from the boot menu, the corresponding EFI bootloader is loaded from the ESP. For Linux, GRUB loads the Linux kernel and initiates the Linux operating system. For Windows, the Windows Boot Manager is invoked, starting the Windows operating system.

Related: BIOS, UEFI and the Boot process Explained along with MBR and GPT

In summary, in a dual-boot setup, the UEFI firmware looks for the bootloader in the EFI directory within the ESP. The ESP contains separate directories for each installed operating system, where the EFI bootloaders are stored. The bootloader, such as GRUB or Windows Boot Manager, loads the selected operating system based on the user's choice from the boot menu.

Links and Resources

https://www.gnu.org/software/grub/manual/grub/html_node/Images.html
https://opensource.com/article/17/2/linux-boot-and-startup

About Silver Moon

A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected].

Leave a Reply

Your email address will not be published. Required fields are marked *