My Linux laptop uses full disk encryption which makes the boot process slightly more complicated.
The partion table:
/dev/nvme0n1 Device Size Type Mount /dev/nvme0n1p1 512M EFI System /boot/efi /dev/nvme0n1p2 732M Linux filesystem /boot /dev/nvme0n1p3 75G Linux filesystem (LUKS) LUKS ([SWAP] and /) /dev/nvme0n1p4 400G Unknown (LUKS) Steves Data
The disk layout:
nvme0n1 │ ├─nvme0n1p1 │ vfat FAT32 44BA-16B5 /boot/efi ├─nvme0n1p2 │ ext4 1.0 5e7309a6-6f5b-44e3-aff7-e92b969bdb97 /boot ├─nvme0n1p3 │ crypto 2 b6a7071a-e553-4e95-9544-9dc9ddcfed61 │ └─nvme0n1p3_crypt │ LVM2_m LVM2 T25pQf-qlNw-pwNV-5dvg-xOTO-KoKG-tW3CjD │ ├─vgubuntu--budgie-swap_1 │ │ swap 1 b02b828e-f0bf-4ecb-910a-b88392056049 [SWAP] │ └─vgubuntu--budgie-root │ ext4 1.0 108f19e8-9b45-48b1-9eb6-d20fd8f011d4 /
The setup is as follows:
If you are using full disk encryption or encrypted root partition, a separate /boot partition is necessary. When using encryption, the boot process needs to access the necessary bootloader and kernel from an unencrypted boot partition to allow the system to access files to decrypt the encrypted partitions and start the system. This leaves the boot-loader second stage file-system unencrypted and therefore vulnerable to tampering of the GRUB configuration, Linux kernel or more likely, the initial RAM file-system (initrd.img).
However, GRUB2 is (since Jessie) able to unlock LUKS devices with its cryptomount command, which therefore enables encryption of the /boot partition as well
It is possible, in UEFI Secure Boot mode, to have every stage cryptographically signed, in which case any tampering can be detected and boot aborted. But Secure Boot and Hibernate do not work because something to do with the random signing code and keys for swap decryption.
The UEFI-based platform (i.e. what we used to know as the BIOS, but is now called UEFI) reads the partition table on the system storage and mounts the EFI System Partition (ESP).
Turn on your computer -> UEFI (BIOS) -> EFI image (/boot/efi) -> grub -> initrd (/boot) -> LUKS decryption -> boot.
The partion table:
nvme0n1 Device Size Type Mount /dev/nvme0n1p1 512M EFI System /boot/efi /dev/nvme0n1p2 732M Linux filesystem /boot /dev/nvme0n1p3 75G Linux filesystem (LUKS) [SWAP] /dev/nvme0n1p4 400G Unknown (LUKS) Steves Data
The UEFI-based platform reads the partition table on the system storage and mounts the EFI System Partition (ESP), a VFAT partition labeled with a particular globally unique identifier (GUID). The ESP contains EFI applications such as bootloaders and utility software, stored in directories specific to software vendors. The ESP is /boot/efi/, and EFI software provided by Ubuntu is stored in /boot/efi/EFI/ubuntu/
The /boot/efi/EFI/ubuntu/ directory contains grub64.efi, a version of GRUB (Grand Unified Bootloader) compiled for the EFI firmware architecture as an EFI application. In the simplest case, the EFI boot manager selects grub.efi as the default bootloader and reads it into memory.
/boot/efi/EFI: BOOT ubuntu /boot/efi/EFI/BOOT: BOOTX64.EFI fbx64.efi mmx64.efi /boot/efi/EFI/ubuntu: BOOTX64.CSV grub.cfg grubx64.efi mmx64.efi shimx64.efi
GRUB determines which operating system or kernel to start, loads it into memory, and transfers control of the machine to that operating system. It is the kernel’s job to finish the boot process, including decrypting any disks.
grub initrd.img initrd.img-5.15.0-89-generic System.map-5.15.0-89-generic vmlinuz vmlinuz-5.15.0-89-generic
The partion /boot contains the grub config initramfs and vmlinuz.
The config file /boot/grub/grub.cfg is automatically generated by grub-mkconfig. The utility grub-mkconfig (and update-grub) runs shell scripts in /etc/grub.d. One of them is /etc/grub.d/10_linux, which uses the shell function version_find_latest to keep iterating through the list of remaining Linux kernels, from latest to oldest. It also settings from /etc/default/grub file.
To see the menus and submenus available at boot time generated by grub-mkconfig:
awk -F\' '$1=="menuentry " || $1=="submenu " {print i++ " : " $2}; /\smenuentry / {print "\t" i-1">"j++ " : " $2};' /boot/grub/grub.cfg 0 : Ubuntu 1 : Advanced options for Ubuntu 1>0 : Ubuntu, with Linux 5.15.0-89-generic 1>1 : Ubuntu, with Linux 5.15.0-89-generic (recovery mode) 1>2 : Ubuntu, with Linux 5.15.0-88-generic 1>3 : Ubuntu, with Linux 5.15.0-88-generic (recovery mode) 2 : UEFI Firmware Settings
From the GRUB_DEFAULT in /etc/default/grub file we can see which version of Ubuntu will boot if none selected:
/etc/default/grub # GRUB_DEFAULT="1>2" GRUB_DEFAULT=0
The actual setting for each Linux option are in the /boot/grub/grub.cfg, which is built by grub-mkconfig which runs script /etc/grub.d/10_linux referencing /etc/fstab and /etc/default/grub:
/etc/default/grub GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=/dev/mapper/vgubuntu--budgie-swa p_1"
Here is an example for Option 0:
grep vml /boot/grub/grub.cfg linux /vmlinuz-5.15.0-89-generic root=/dev/mapper/vgubuntu--budgie-root ro quiet splash resume=/dev/mapper/vgubuntu--budgie-swap_1 $vt_handoff
But /dev/mapper/vgubuntu--budgie-root is actually encrypted inside nvme0n1p3:
lsblk --fs nvme0n1 ├─nvme0n1p3 │ crypto 2 b6a7071a-e553-4e95-9544-9dc9ddcfed61 │ └─nvme0n1p3_crypt │ LVM2_m LVM2 T25pQf-qlNw-pwNV-5dvg-xOTO-KoKG-tW3CjD │ ├─vgubuntu--budgie-swap_1 │ │ swap 1 b02b828e-f0bf-4ecb-910a-b88392056049 [SWAP] │ └─vgubuntu--budgie-root │ ext4 1.0 108f19e8-9b45-48b1-9eb6-d20fd8f011d4 /
Physcial volume, volume group and logical volumes:
pvscan PV /dev/mapper/nvme0n1p3_crypt VG vgubuntu-budgie lvm2 [74.98 GiB / 0 free] Total: 1 [74.98 GiB] / in use: 1 [74.98 GiB] / in no VG: 0 [0 ] vgscan Found volume group "vgubuntu-budgie" using metadata type lvm2 lvscan ACTIVE '/dev/vgubuntu-budgie/swap_1' [9.00 GiB] inherit ACTIVE '/dev/vgubuntu-budgie/root' [65.98 GiB] inherit
So at what point is decryption done?
/etc/crypttab nvme0n1p3_crypt UUID=b6a7071a-e553-4e95-9544-9dc9ddcfed61 none luks,discard
It would seem that /etc/crypttab is copied into main/cryptroot/crypttab of initrd.img and this causes the boot kernel to prompt for a password for decryption. So /dev/mapper/vgubuntu--budgie-root is available when needed in the boot process.
To see all files packaged in an the initrd (Init Ram Disk) use the following command.
lsinitramfs "/boot/initrd.img-$(uname -r)"
Note it contains Plymouth files, the graphical loader responsible for Splash screens.
To generate a new initrd use the following command:
update-initramfs -k all -c
To update initrd after making changes use the following command:
update-initramfs -u