Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Support tryboot helpers without ramdisk #1940

Open
bryceschober opened this issue Feb 1, 2025 · 4 comments
Open

[FEAT] Support tryboot helpers without ramdisk #1940

bryceschober opened this issue Feb 1, 2025 · 4 comments

Comments

@bryceschober
Copy link

I'm digesting the implications of the tryboot_a_b update flow, and it's becoming clear that it is more designed for boot systems that depend on a ramdisk. Since the ramdisk would be named the same on the A/B boot partitions, it doesn't need any differences in cmdline.txt, and init logic within it can then use the device tree's chosen/bootloader properties to drive its dynamic logic.

But for systems that would prefer not to have a separate ramdisk, they are currently required to modify their kernel cmdline appropriately for the A/B partition that is being booted, and set up for that during their update process along with modifying the autoboot.txt.

I can think of two possible ways that the rpi firmware could support this use-case:

  1. Support the cmdline setting in the autoboot.txt in addition to the config.txt. This way, the A/B boot partitions could be identical and contain both cmdline_A.txt and cmdline_B.txt files with the appropriate root= values.
  2. Support a [boot_partition=n] filter in config.txt that would be filled by the active configuration from the autoboot.txt logic. This way, the config.txt could conditionally point to an appropriate cmdline*.txt next to it.
@bryceschober
Copy link
Author

bryceschober commented Feb 6, 2025

  1. Support the cmdline setting in the autoboot.txt in addition to the config.txt. This way, the A/B boot partitions could be identical and contain both cmdline_A.txt and cmdline_B.txt files with the appropriate root= values.

Now that I'm reading this again, I see that this wouldn't be a great option, since the config.txt "downstream" could easily want a different cmdline setting based on other conditions.

Perhaps a third option would be to enable a way for the user to set part of the cmdline contents independently of the cmdline.txt file(s). Perhaps something like this, in autoboot.txt:

[all]
tryboot_a_b=1
boot_partition=2
cmdline_opts=root=/dev/mmcblk0p4
[tryboot]
boot_partition=3
cmdline_opts=root=/dev/mmcblk0p5

@timg236 I notice that you had submitted the rpi-eeprom package to buildroot recently... What do you think the chances are of this use-case gaining support in the rpi firmware?

@jluebbe
Copy link

jluebbe commented Feb 7, 2025

2. Support a [boot_partition=n] filter in config.txt that would be filled by the active configuration from the autoboot.txt logic. This way, the config.txt could conditionally point to an appropriate cmdline*.txt next to it.

This seems the better choice when combined with secure boot, as otherwise unauthenticated cmdline arguments could be injected via autoboot.txt

@learmj
Copy link

learmj commented Feb 7, 2025

Hi. Are you suggesting that in the following case:

[all]
tryboot_a_b=1
boot_partition=2
[tryboot]
boot_partition=3

..you would have a config.txt on both p2 and p3, but rather than read cmdline.txt from p2 (or p3), have something like the following in each config.txt (example below for p2):

[boot_partition=2]
<cmdline args specific to p2>

?

What advantage would that give you over what's supported today? If the bootloader has been instructed to boot from p2 it loads config.txt from p2 and the cmdline.txt found on p2 can be generated at build time to be specific to the OS that's loaded from p2 (e.g. it can can specify a root device that's associated to OS boot from p2 via UUID=xxx or by-label etc). I don't know what you'd gain from having a [boot_partition=2] filter in a config.txt on p2?

@bryceschober
Copy link
Author

Hi @learmj, let me explain the option 2 in a bit more detail:

First, the use-case I'm targeting is where the tryboot_a_b feature is used to switch between partitions that are identical in purpose, integrating with a software update mechanism that executes out of one set of partitions, and supports updating a new version of firmware into the other set of partitions. Because the raspberrypi firmware requires a FAT partition for the "firmware" components, this ends up meaning that an A/B-swapping update system with a separate rootfs partition will have a total of at least 5 partitions, for example on an SD card:

  1. mmcblk0p1: (FAT) shared boot partition with only autoboot.txt
  2. mmcblk0p2: (FAT) firmware "slot" 0 with config.txt, cmdline.txt, and kernel image
  3. mmcblk0p3: (FAT) firmware "slot" 1 with config.txt, cmdline.txt, and kernel image
  4. mmcblk0p4: (WhateverFS) root filesystem "slot" 0 with the remainder of the system
  5. mmcblk0p5: (WhateverFS) root filesystem "slot" 1 with the remainder of the system

(FYI, I noticed that I had the wrong root= parameters in my previous comment, which might have caused confusion, so I've fixed it.)

These "slot" 0/1 partitions must be selected in tandem. The firmware configurations and kernel image for slot 1 are built to go together with the rootfs for slot 1, and it is the responsibility of the sw update integration to maintain them in tandem.

The software update system needs to build and deliver "images" (of whatever variety) for the firmware partition that are capable of executing from either partition slot. As it is, the software update mechanism is required to modify the contents of the config.txt after installing it in a particular partition (let's say the "slot" 1), so that it can boot the corresponding rootfs partition.

What I'm suggesting for option 2 is that the firmware partition images would contain a config.txt:

...
# Select rootfs partition matching the firmware partition we're executing from
[boot_partition=2]
cmdline=cmdline.slot0.txt
[boot_partition=3]
cmdline=cmdline.slot1.txt
[all]
...

And every firmware partition image will contain both a cmdline.slot1.txt with:

root=/dev/mmcblk0p4 ...

and also a cmdline.slot2.txt with:

root=/dev/mmcblk0p5 ...

What advantage would that give you over what's supported today? If the bootloader has been instructed to boot from p2 it loads config.txt from p2 and the cmdline.txt found on p2 can be generated at build time to be specific to the OS that's loaded from p2 (e.g. it can can specify a root device that's associated to OS boot from p2 via UUID=xxx or by-label etc). I don't know what you'd gain from having a [boot_partition=2] filter in a config.txt on p2?

And now that I've written all of the above explanation, I see that you're suggesting that the software update builds generate a unique UUID or label for each build of the rootfs partition image, and that the matching cmdline.txt in the matching firmware partition image use the unique filesystem UUID or label to address the matching rootfs partition.

Is that what you meant, @learmj? I guess that does sound like it could just work at the current level of support. Our partition image generation might get a bit more complex, but that's not a big deal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants