From 64450ceb798e4e53c837e68b7fdfd85c31654249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20K=C3=B6hl?= Date: Fri, 24 Nov 2023 17:13:32 +0100 Subject: [PATCH] docs: improve boot flow docs --- www/docs/guide/over-the-air-updates.md | 8 +++--- www/docs/internals/boot-flows.md | 38 ++++++++++++-------------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/www/docs/guide/over-the-air-updates.md b/www/docs/guide/over-the-air-updates.md index 80f47d1..83d9efc 100644 --- a/www/docs/guide/over-the-air-updates.md +++ b/www/docs/guide/over-the-air-updates.md @@ -32,7 +32,7 @@ The usual partition layout of a Rugpi installation comprises seven partitions: - Partition 6: The root partition of the B set. - Partition 7: Contains any persistent state (see [State Management](./state-management)). -The bootloader specification specifies the default set of partitions. +The bootloader configuration specifies the default set of partitions. We call the other, non-default set, the *spare set*. An update is only possible if the hot set is also the default set. That way, if anything goes wrong while installing the update, the system will boot into the previous known-good version by default. @@ -101,10 +101,10 @@ rugpi-ctrl system commit ### On Atomicity of Commits Note that commits are the only critical operation because they modify the default set. -This is done by temporarily remounting the config partition with the `autoboot.txt` such that it is writeable. -The `autoboot.txt` is then replaced as suggested by [Raspberry Pi's documentation on the `tryboot` mechanism](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#fail-safe-os-updates-tryboot). +This is done by temporarily remounting the bootloader configuration partition such that it is writeable. +For the `tryboot` and U-Boot boot flow, the `autoboot.txt` file and `bootpart.default.env` file are then replaced as suggested by [Raspberry Pi's documentation on the `tryboot` mechanism](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#fail-safe-os-updates-tryboot). As the filesystem is FAT32, the automitcity of this operation cannot be guaranteed. -Still, Rugpi Ctrl does its best by first creating the new `autoboot.txt` and then replacing the old one with the new one by renaming it, and, the Linux kernel does guarantee atomicity for renaming. +Still, Rugpi Ctrl does its best by first creating a new file and then replacing the old one with the new one by renaming it, and, the Linux kernel does guarantee atomicity for renaming. However, should the system crash during this process, the FAT32 filesystem may still be corrupted. We think that this is an acceptable risk as the likelihood of it happening is very low and any alternatives, like swapping the MBR, may be problematic for other reasons.[^4] diff --git a/www/docs/internals/boot-flows.md b/www/docs/internals/boot-flows.md index 6cfcbd8..3224a21 100644 --- a/www/docs/internals/boot-flows.md +++ b/www/docs/internals/boot-flows.md @@ -6,32 +6,30 @@ sidebar_position: 2 ## Tryboot +The `tryboot` boot flow works almost as described in [Raspberry Pi's documentation on the `tryboot` mechanism](https://www.raspberrypi.com/documentation/computers/config_txt.html#example-update-flow-for-ab-booting). +Instead of reading the `tryboot` flag, the hot partition is compared with the default partition to determine whether a commit is necessary. + ## U-Boot On older Raspberry Pi's, without the `tryboot` bootloader feature, we use [U-Boot](https://docs.u-boot.org/en/latest/) as an intermediate bootloader. Instead of directly loading the Linux kernel, Raspberry Pi's bootloader is instructed to load U-Boot. U-Boot is then responsible for booting the Linux kernel from the correct partition set. +This works in two stages. +First, U-Boot loads the first stage boot script `boot.scr` from the first partition. +This first stage is responsible for determining the hot partition set (default or spare). +After doing so, it will load the boot environment `boot.env` and second stage boot script `second.scr` from the hot partition set. +After loading these files, the first stage invokes the second stage boot script. +This has the advantage that the second stage script can be updated via the normal update mechanism. +Hence, additional device tree overlays or other boot time configurations can be deployed in a fail-safe way. -We use three *environment files*: - -```text title="bootpart.default.env" -bootpart=2 -``` - -```text title="boot_spare.env" -boot_spare=1 -``` - -```text title="boot.env" -bootargs=console=... -... -``` +For the first stage, two U-Boot environment files are used to determine the hot partition set. +The file `bootpart.default.env` specifies the default partition set. +The file `boot_spare.env` indicates whether to boot from the spare partition. -### On Atomicity of Commits +For the second stage, one U-Boot environment file is used. +The file `boot.env` contains the kernel command line arguments (generated from `cmdline.txt`) stored in the `bootargs` variable and may also override the kernel to boot (`kernel_file`). -The file `bootpart.default.env` takes over the role of `autoboot.txt`. -As it is stored on the FAT filesystem of the first partition, it is subject to the same atomicity guarantees. +We use U-Boot environment files with a CRC32 checksum. +Hence, if files are corrupted, they will not be loaded. -The file `boot_spare.env` takes over the role of `tryboot`. -It uses a CRC32 checksum. -Should it be corrupted, the default partition will be booted. +For further details, we refer to the [boot scripts](https://github.com/silitics/rugpi/tree/main/boot/u-boot/scripts). \ No newline at end of file