1. Overview
An important step in the Linux start-up process is mounting all necessary filesystems, including the root. To that end, initramfs is a temporary root filesystem that the kernel loads in RAM during boot time. The /etc/fstab file contains filesystems that we want automatically loaded when the system starts. Both of these concepts are part of the procedure for mounting filesystems.
In this tutorial, we’ll learn a part of the boot process, focusing on the initramfs filesystem and the /etc/fstab file.
2. The Firmware
First, let’s have an overview of the boot process.
When we press the power button of our system, the firmware of the computer takes control. In the old days, the firmware was the BIOS. In modern systems, UEFI usually replaces BIOS.
Compared to BIOS, UEFI has extended capabilities. One of them is that UEFI can understand partition tables and filesystems. As a result, it doesn’t rely on the first sectors of a disk to locate the boot loader, as BIOS did. Instead, it directly discovers the boot loader executable file in a special partition called the EFI system partition. The EFI system partition is created when we install an operating system that supports UEFI.
One way to find this partition is to use the fdisk command:
$ sudo fdisk -l
...
Device Start End Sectors Size Type
/dev/sda1 227328 10485726 10258399 4.9G Linux filesystem
/dev/sda14 2048 10239 8192 4M BIOS boot
/dev/sda15 10240 227327 217088 106M EFI System
Here, we can see that the EFI system partition is the /dev/sda15 as indicated in the Type column. Furthermore, we can find where this partition is mounted with the mount command:
$ sudo mount | grep sda15
/dev/sda15 on /boot/efi type vfat (rw, relatime, fmask=0077, dmask=0077, codepage=437, iocharset=iso8859-1, shortname=mixed, errors=remount-ro)
As a result, we can see that sda15 is mounted on the /boot/efi directory.
Another important UEFI component is the Boot Manager which manages NVRAM variables. These variables contain information that UEFI uses to locate a bootloader. As a result, the path of a bootloader that exists in the EFI system partition is included within them.
Since there can be more than one available bootloader, the Boot Manager also defines an order between them. During startup, the firmware uses the first active record of the Boot Manager. Furthermore, we can modify the NVRAM variables through the firmware user interface when the computer starts. Another option is to use the efibootmgr command.
3. The Bootloader
The EFI system partition contains EFI applications. These applications usually have an efi suffix. The bootloader itself is an EFI application.
For example, Ubuntu systems have a directory with the name ubuntu in the EFI system partition that contains the bootloader. Let’s list the contents of this directory:
$ sudo ls -al /boot/efi/EFI/ubuntu | grep efi
-rwx------ 1 root root 1726344 Dec 1 06:21 grubx64.efi
-rwx------ 1 root root 856232 Dec 1 06:21 mmx64.efi
-rwx------ 1 root root 955656 Dec 1 06:21 shimx64.efi
As we can see, there are three EFI files. The grubx64.efi file is the bootloader application. Notably, the majority of Linux distributions use GRUB.
A bootloader will perform two steps:
- load the kernel
- load a temporary root filesystem, which is the initramfs
Usually, we can find both the kernel and initramfs in the /boot directory of our system:
$ sudo ls -al /boot
total 91221
...
lrwxrwxrwx 1 root root 28 Mar 3 06:37 initrd.img -> initrd.img-5.4.0-144-generic
-rw-r--r-- 1 root root 28021498 Feb 10 06:24 initrd.img-5.4.0-139-generic
-rw-r--r-- 1 root root 28022430 Mar 9 06:10 initrd.img-5.4.0-144-generic
lrwxrwxrwx 1 root root 28 Mar 3 06:37 initrd.img.old -> initrd.img-5.4.0-139-generic
lrwxrwxrwx 1 root root 25 Mar 3 06:37 vmlinuz -> vmlinuz-5.4.0-144-generic
-rw------- 1 root root 13672712 Jan 20 17:33 vmlinuz-5.4.0-139-generic
...
In the above example, files starting with initrd.img is initramfs filesystems, and files starting with vmlinuz are kernels. The exact initramfs and kernel that the bootloader loads exist in the grub.cfg file, which keeps the GRUB menu entries. We can again find this file in the /boot/grub directory.
Let’s see a sample menu entry:
menuentry 'Ubuntu' --class ubuntu --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-44836297-8097-455e-a64d-4fc7be245184' {
...
set root='hd0,gpt1'
...
linux /boot/vmlinuz-5.4.0-144-generic root=UUID=44836297-8097-455e-a64d-4fc7be245184 ro console=tty1 console=ttyS0
initrd /boot/initrd.img-5.4.0-144-generic
}
In the above entry, we have kept three lines:
- set root line – defines the root filesystem
- linux line – sets the path to the kernel
- initrd line – has the path to the initramfs archive
We observe that besides the kernel and the initramfs, the menu entry in grub.cfg also contains a reference to the root filesystem. The kernel will use this configuration later to mount the root filesystem.
4. The initramfs Filesystem
As a temporary filesystem, initramfs is a stepping stone for loading the root filesystem. The /boot directory contains initramfs in a cpio archive. This archive is also compressed with the gzip or the lz4 tool, depending on the Linux distribution. We can find this out with the file command:
$ file /boot/initrd.img-5.4.0-144-generic
/boot/initrd.img-5.4.0-144-generic: LZ4 compressed data (v0.1-v0.9)
Here, we can see that in our case the LZ4 algorithm compressed the initramfs archive. Thus, we can use the lz4 command to decompress it with its -d option:
$ lz4 -dc /boot/initrd.img-5.4.0-144-generic | cpio -id
136611 blocks
In this case, we used the -c option to make the lz4 command write contents to the standard output. Moreover, we piped to cpio, where we used the -i option to extract the contents and the -d option to create leading directories where needed.
The kernel runs the /init script of initramfs that will eventually mount the real root filesystem. In fact, we can find the /init script in the decompressed archive:
$ ls -al init
-rwxr-xr-x 1 ubuntu ubuntu 7424 Mar 21 22:14 init
$ file init
init: POSIX shell script, ASCII text executable
Indeed, there is an init shell script in the decompressed initramfs archive.
Alternatively, we can list all the contents of an initramfs archive with the lsinitramfs command without decompressing it:
$ lsinitramfs /boot/initrd.img-5.4.0-144-generic | grep ^init$
init
The command outputs all files of the archive to the standard output. By piping the list to grep, we can confirm init is part of that.
5. The /etc/fstab File
The /etc/fstab file is a table with filesystems that we want to mount when the system starts. The records in this table are processed and mounted upon system start as part of the SysV or systemd initialization process. This happens after the root filesystem has been loaded by the kernel and the init process has been started.
Furthermore, let’s output the contents of the /etc/fstab file to see its format:
$ cat /etc/fstab
LABEL=cloudimg-rootfs / ext4 defaults 0 1
LABEL=UEFI /boot/efi vfat umask=0077 0 1
Here, we can see two filesystems in the table. The first one is the root filesystem and the second is the EFI system partition. The first column defines the partition using the LABEL option. The second column is the mount point in the filesystem and the third is the filesystem type. The rest of the columns refer to mount options.
In addition, we can find the label of a partition with the e2label command:
$ sudo e2label /dev/sda1
cloudimg-rootfs
As we can see, the label of the /dev/sda1 partition is cloudimg-rootfs.
6. The initramfs Filesystem and the /etc/fstab File
As we mentioned earlier, the initramfs is a temporary filesystem that the kernel loads before the actual root filesystem during boot time. This means that as long as initramfs is loaded, the expected /etc/fstab file of the root filesystem isn’t available and can’t be used.
Nevertheless, we saw that /etc/fstab may include the root filesystem. This means that the root filesystem will be mounted again. The second mount will happen later in the boot process when /etc/fstab is handled. Importantly, the options used to mount it then may be different than the those from the first time. This is the main reason for the second mount to happen.
Interestingly, the initramfs filesystem has its own /etc/fstab file:
$ ls -al initramfs/etc/fstab
-rw-r--r-- 1 ubuntu ubuntu 0 Mar 20 10:51 initramfs/etc/fstab
$ cat initramfs/etc/fstab
$
As we can see, initramfs has an /etc/fstab file that is empty. Another way to verify its existence is to use the lsinitramfs command for the specified initramfs archive:
$ lsinitramfs /boot/initrd.img-5.4.0-144-generic | grep fstab
etc/fstab
Indeed, lsinitramfs returns an /etc/fstab file.
Consequently, initramfs can potentially mount entries from this file.
7. Conclusion
In this article, we found out whether and how the initramfs filesystem uses the /etc/fstab file.
Initially, we started with the regular boot process of a Linux machine. Following that, we briefly discussed the /etc/fstab file and its purpose. Finally, we concluded that at the time the initramfs is loaded, the root filesystem isn’t yet available. So, at that point, there is no way for the kernel to access /etc/fstab in the root filesystem. Still, initramfs has its own /etc/fstab file that we can potentially use to mount additional filesystems.