From 77d94e0ffdfb58f6e9e52388d624229f229751f0 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Mon, 13 Mar 2023 16:55:13 +0100 Subject: [PATCH] doc: Expand boot procedure documentation Provide more details on the boot procedure, different image types used, how to configure the bootloader, and how to perform system upgrades. --- doc/boot.md | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 246 insertions(+), 7 deletions(-) diff --git a/doc/boot.md b/doc/boot.md index 169da027..4bd7e07f 100644 --- a/doc/boot.md +++ b/doc/boot.md @@ -1,5 +1,242 @@ -Disk Layout ------------ +Boot Procedure +============== + +Systems running Infix will typically boot in multiple phases, forming +a boot chain. Each link in the chain has three main responsibilities: + +1. Ensuring the integrity of the next link before passing control to + it. This avoids silent failures stemming from data corruption. + +2. Ensuring the authenticity of the next link before passing control + to it, commonly referred to as _Secure Boot_. This protects against + malicious attempts to modify a system's firmware. + +3. Preparing the system state according to the requirements of the + next link. E.g. the Linux kernel requires the system's RAM to be + operational. + +A typical chain consists of four stages: + + .---------. + | ROM >---. Determine the location of and load the SPL + '---------' | + .-----------------' + | .---------. + '---> SPL >---. Perform DDR training and load the TPL + '---------' | + .-----------------' + | .---------. + '---> TPL >---. Load Linux kernel, device tree, and root filesystem + '---------' | + .-----------------' + | .---------. + '---> Infix | Get down to business + '---------' + +After a reset, hardware will pass control to a program (_ROM_) which +is almost always programmed into the SoC by the vendor. This program +will determine the location of the _Secondary Program Loader_ (_SPL_), +typically by reading a set of _Sample at Reset_ (SaR) pins. + +The _SPL_ is sometimes provided by the SoC vendor in binary form, and +is sometimes built as a part of the _Tertiary Program Loader_ (_TPL_) +build. Its main responsibility is usually to set up the system's +memory controller and perform DDR training, if required, before +loading the _TPL_. + +Commonly referred to as the system's _bootloader_, the _TPL_ is is +responsible for preparing the execution environment required by the +Linux kernel. + +This document's focus is to describe the final two phases of the boot +chain, as the initial phases are very hardware dependent, better +described by existing documentation provided by the SoC vendor. + + +Bootloader +---------- + +### Configuration + +To mitigate the risk of a malicious user being able to circumvent the +bootloader's validation procedure, user configuration is kept to a +minimum. Two settings are available: + +- **Boot order**: Since Infix maintains two copies of its firmware, + and as some bootloaders support netbooting, the order in which boot + sources are considered can be configured. To select the active + source, use [RAUC][]: + + `rauc status mark-active ` + + Where `` is one of: + + | `` | Source | + |----------|---------------------------| + | rootfs.0 | Primary partition | + | rootfs.1 | Secondary partition | + | net.0 | Netboot (where supported) | + +- **Debug**: By default, the kernel will only output errors to the + console during boot. Optionally, this can be altered such that all + enabled messages are logged. + + On systems using _U-Boot_, this can be enabled by running `fw_setenv + DEBUG 1`. To restore the default behavior, run `fw_setenv DEBUG`. + + On systems running _GRUB_, this can be enabled by running + `grub-editenv /mnt/aux/grub/grubenv set DEBUG=1`. To restore the + default behavior, run `grub-editenv /mnt/aux/grub/grubenv unset + DEBUG` + + +### U-Boot + +Used on _aarch64_ based systems. It is able to verify both the +_integrity_ and _authenticity_ of an Infix image. As such, it can be +used as a part of a _Secure Boot_ chain, given that the preceding +links are able to do the same. + +Supports booting Infix from a block device using the [Disk +Image](#disk-image) layout. Currently, Virtio and MMC disks are +supported. + +An [FIT Framed Squash Image](#fit-framed-squash-image) can be used to +boot Infix over the network. DHCP is used to configure the network +and TFTP to transfer the image to the system's RAM. + +Access to U-Boot's shell is disabled to prevent side-loading of +malicious firmware. To configure the active boot partition, refer to +the [Bootloader Interface](#bootloader-interface) section. + + +### GRUB + +Used on _x86_64_ based systems. Neither the _integrity_ nor the +_authenticity_ of the Infix image is verified. It only intended to +provide a way of booting a [Disk Image](#disk-image), such that a +standard [System Upgrade](#system-upgrade) can be performed on +virtualized instances. + +Access to the GRUB shell is not limited in any way, and the boot +partition can be selected interactively at boot using the arrow +keys. It is also possible to permanently configure the default +partition from Infix using the [Bootloader +Interface](#bootloader-interface). + + +System Upgrade +============== + +Much of the minutiae of firmware upgrades is delegated to [RAUC][], +which offers lots of benefits out-of-the-box: + +- Upgrade Bundles are always signed, such that their authenticity can + be verified by the running firmware, before the new one is + installed. + +- The bureaucracy of interfacing with different bootloaders, manage + the boot order, is a simple matter of providing a compatible + configuration. + +- Updates can be sourced from the local filesystem (including external + media like USB sticks or SD-cards) and from remote servers using FTP + or HTTP(S). + +To initiate a system upgrade, run: + + rauc install + +Where the file or URL points to a [RAUC Upgrade +Bundle](#rauc-upgrade-bundle). + +This will upgrade the partition not currently running. After a +successful upgrade is completed, you can reboot your system, which +will then boot from the newly installed image. Since the partition +from which you were originally running is now inactive, running the +same upgrade command again will bring both partitions into sync. + +[RAUC]: https://rauc.io + + +Image Formats +============= + +SquashFS Image +-------------- + +**Canonical Name**: `rootfs.squashfs` + +The central read-only filesystem image containing Infix's Linux +kernel, device trees, and root filesystem. All other images bundle +this image, or is dependent on it, in one way or another. + +On its own, it can be used as an [initrd][] to efficiently boot a +virtual instance of Infix. + +[initrd]: https://docs.kernel.org/admin-guide/initrd.html + +FIT Framed Squash Image +----------------------- + +**Canonical Name**: `rootfs.itb` + +As the name suggests, this is essentially the [Squash FS +Image](#squashfs-image) with a _Flattened Image Tree_ ([FIT][]) +header. Being a native format to U-Boot, using this framing allows us +to verify the integrity and authenticity of the SquashFS image using +standard U-Boot primitives. + +In contrast to most FIT images, the kernel and device trees are not +stored as separate binaries in the image tree. Instead, Infix follows +the standard Linux layout where the kernel and related files are +stored in the `/boot` directory of the filesystem. + +On disk, this image is then stored broken up into its two components; +the _FIT header_ (`rootfs.itbh`) and the SquashFS image. The header +is stored on the [Auxiliary Data](#aux---auxiliary-data) partition of +the [Disk Image](#disk-image), while the SquashFS image is stored in +one of the [Root Filesystem](#primarysecondary---root-filesystems) +partitions. + +When the system boots, U-Boot will concatenate the two parts to +validate the SquashFS's contents. This is path was chosen because: + +- Having a separate raw SquashFS means Linux can directly mount it as + the root filesystem. + +- It decouples Infix from U-Boot. If a better way of validating our + image is introduced, we can switch to it without major changes to + Infix's boot process, as we can still use a regular SquashFS as the + root filesystem. + +- It lets us use standard interfaces to boot linux, like SYSLINUX. It + also plays well with traditional bootloaders, like GRUB. + +In its full form, it can be used to netboot Infix, as it contains all +the information needed by U-Boot in a single file. + +[FIT]: https://u-boot.readthedocs.io/en/latest/usage/fit.html + + +RAUC Upgrade Bundle +------------------- + +**Canonical Name**: `infix-${ARCH}.pkg` + +Itself a SquashFS image, it contains the Infix [SquashFS +Image](#squashfs-image) along with the header of the [FIT Framed +Squash Image](#fit-framed-squash-image), and some supporting files to +let [RAUC][] know how install it on the target system. + +When performing a [System Upgrade](#system-upgrade), this is the +format to use. + + +Disk Image +---------- + +**Canonical Name**: `disk.img` Infix runs from a block device (e.g. eMMC or virtio disk) with the following layout. The disk is expected to use the GPT partitioning @@ -38,6 +275,9 @@ scheme. Partitions marked with an asterisk are optional. Optional partition containing the system's bootloader. May also reside in a separate storage device, e.g. a serial FLASH. +On x86_64, this partition holds the EFI system partition, containing +the GRUB bootloader. + ### `aux` - Auxiliary Data @@ -68,7 +308,7 @@ binary - `uboot.env` is only used to import a few settings that is required to configure the boot order. -### `primary`/`secondary` - Infix Root Filesystem Images +### `primary`/`secondary` - Root Filesystems | Parameter | Value | |-----------|-------------------| @@ -76,10 +316,9 @@ required to configure the boot order. | Size | >= 256 MiB | | Format | Squash filesystem | -The main Infix image - the `rootfs.squashfs` image in your `images/` -directory. Two copies exist so that an incomplete upgrade does not -brick the system, and to allow fast rollbacks when upgrading to a new -version. +Holds the [SquashFS Image](#squashfs-image). Two copies exist so that +an incomplete upgrade does not brick the system, and to allow fast +rollbacks when upgrading to a new version. ### `cfg` - Configuration Data