[EBG] EFI Boot Guard A/B updates

119 views
Skip to first unread message

Javier

unread,
Feb 20, 2024, 9:02:11 AM2/20/24
to swupdate
Hi,

I am currently working on the integration of EFI Boot guard (0.16) and SWUpdate (2023.12.1). I have the following partition scheme:
  • EFI - vfat
  • BOOT0 - vfat - Kernel partition 0 - loads RFSA
  • BOOT1 - vfat - Kernel partition 1 - loads RFSB
  • RFSA - ext4 - Root file system A
  • RFSB - ext4 - Root file system B
Before the update the environments look like:

----------------------------
Config Partition #0 Values:
in_progress:      no
revision:         1
kernel:           C:BOOT0:vmlinuz.efi
kernelargs:       root=LABEL=rfsA rw initrd=initrd.img-6.6.4 efi=debug efi=runtime sys=a 
[--REMOVED SOME EXTRA ARGS--]
watchdog timeout: 0 seconds
ustate:           0 (OK)

user variables:
----------------------------
Config Partition #1 Values:
in_progress:      no
revision:         0
kernel:           C:BOOT1:vmlinuz.efi
kernelargs:       root=LABEL=rfsB rw initrd=initrd.img-6.6.4 efi=debug efi=runtime sys=b 
[--REMOVED SOME EXTRA ARGS--]
watchdog timeout: 0 seconds
ustate:           0 (OK)

user variables:

After a successful update of the alternative RFS (By the moment I am only generating an artifact to update the RFS, next step will be update Kernel0-rfsA or Kernel1-rfsB in the same artifact). The system boots in the same partition as it was running before, therefore I cannot test the new RFS.

----------------------------
Config Partition #0 Values:
in_progress:      no
revision:         1
kernel:           C:BOOT0:vmlinuz.efi
kernelargs:       root=LABEL=rfsA rw initrd=initrd.img-6.6.4 efi=debug efi=runtime sys=a 
[--REMOVED SOME EXTRA ARGS--]
watchdog timeout: 0 seconds
ustate:           0 (OK)

user variables:

----------------------------
Config Partition #1 Values:
in_progress:      no
revision:         2
kernel:           C:BOOT0:vmlinuz.efi
kernelargs:       root=LABEL=rfsA rw initrd=initrd.img-6.6.4 efi=debug efi=runtime sys=a [--REMOVED SOME EXTRA ARGS--]
watchdog timeout: 0 seconds
ustate:           2 (TESTING)

user variables:

During the update the current EBG configuration (BOOT0) is copied to the alternative configuration partition (BOOT1). Obviously, it is going to boot with the same arguments as the current partition. 

As far I can read in the documentation, that is not the expected behavior:

It should be copied the "last alternative boot path". Maybe that is the reason, there was not an alternative boot path. Because it is the first update.

I do not know if I misunderstood something, or it is missing some extra configuration from my side. Do I have to create a post or prescript to manage this situation? using the user space efibootguard tools?

Thank you very much,

Javier





Storm, Christian

unread,
Feb 20, 2024, 10:51:53 AM2/20/24
to swupdate
Hi Javier,
You're booting from/with Config Partition #0 as it has the highest revision number, i.e., it's the current boot path. Config Partition #1 is the (single) alternative boot path.


> After a successful update of the alternative RFS (By the moment I am only generating an artifact to update the RFS, next step will be update Kernel0-rfsA or Kernel1-rfsB in the same artifact). The system boots in the same partition as it was running before, therefore I cannot test the new RFS.
>
> ----------------------------
> Config Partition #0 Values:
> in_progress: no
> revision: 1
> kernel: C:BOOT0:vmlinuz.efi
> kernelargs: root=LABEL=rfsA rw initrd=initrd.img-6.6.4 efi=debug efi=runtime sys=a [--REMOVED SOME EXTRA ARGS--]
> watchdog timeout: 0 seconds
> ustate: 0 (OK)

Here, Config Partition #0 is not touched, instead, the alternative boot path Config Partition #1 has become the current boot path as it has the highest revision number 2.

> ----------------------------
> Config Partition #1 Values:
> in_progress: no
> revision: 2
> kernel: C:BOOT0:vmlinuz.efi
> kernelargs: root=LABEL=rfsA rw initrd=initrd.img-6.6.4 efi=debug efi=runtime sys=a [--REMOVED SOME EXTRA ARGS--]
> watchdog timeout: 0 seconds
> ustate: 2 (TESTING)

Note that this is in state TESTING now, i.e., you need to "confirm" the update. When using one of the suricatta modules, look at their `-c <confirm>` option. Else, you can use EFI Boot Guard's `bg_setenv` tool to do it. If you do not confirm, EFI Boot Guard will revert to the previous Config Partition #0 when (re)booting the next time (rollback).


> During the update the current EBG configuration (BOOT0) is copied to the alternative configuration partition (BOOT1). Obviously, it is going to boot with the same arguments as the current partition.

Yes, see https://github.com/siemens/efibootguard/blob/next/env/env_api.c#L121


> As far I can read in the documentation, that is not the expected behavior:
> https://github.com/sbabic/swupdate/blob/f185f75d8208668f9913a7c0a8d9fd3973dd0ac8/bootloader/ebg.c#L51
>
> It should be copied the "last alternative boot path". Maybe that is the reason, there was not an alternative boot path. Because it is the first update.
>
> I do not know if I misunderstood something, or it is missing some extra configuration from my side. Do I have to create a post or prescript to manage this situation? using the user space efibootguard tools?

Hm, maybe "upcycling" was/is misleading? With this I tried to explain that not the current boot path but an older one is reused, gets an incremented revision number, and hence is "upcycled".

The next paragraph (https://github.com/sbabic/swupdate/blob/f185f75d8208668f9913a7c0a8d9fd3973dd0ac8/bootloader/ebg.c#L53-L57) maybe clarifies this, it reads (emphasis added):

"An in-memory working **copy of the current boot path** environment is created
which has a by one incremented higher revision than the current boot path.
Modifications are performed on this working copy environment.
When committing the transaction, i.e., writing it to disk, the **new current
boot path** is persisted and booted next."

So, this is in line with what you're seeing, isn't it?

Note that after having started a new transaction, you're supposed to set / overwrite `kernel` and `kernelargs` otherwise you're left with the "upcycled" copy. For this, you may use something like https://gitlab.com/cip-project/cip-sw-updates/swupdate-handler-roundrobin or https://sbabic.github.io/swupdate/handlers.html#bootloader-handler or ...


Kind regards,
Christian

--
Dr. Christian Storm
Siemens AG, Technology, T CED OES-DE
Otto-Hahn-Ring 6, 81739 Munich, Germany

Javier

unread,
Feb 21, 2024, 4:20:58 AM2/21/24
to swupdate
Hi Christian,

Thank you very much for your quick answer

Got it
 



> As far I can read in the documentation, that is not the expected behavior:
> https://github.com/sbabic/swupdate/blob/f185f75d8208668f9913a7c0a8d9fd3973dd0ac8/bootloader/ebg.c#L51
>
> It should be copied the "last alternative boot path". Maybe that is the reason, there was not an alternative boot path. Because it is the first update.
>
> I do not know if I misunderstood something, or it is missing some extra configuration from my side. Do I have to create a post or prescript to manage this situation? using the user space efibootguard tools?

Hm, maybe "upcycling" was/is misleading? With this I tried to explain that not the current boot path but an older one is reused, gets an incremented revision number, and hence is "upcycled".

The next paragraph (https://github.com/sbabic/swupdate/blob/f185f75d8208668f9913a7c0a8d9fd3973dd0ac8/bootloader/ebg.c#L53-L57) maybe clarifies this, it reads (emphasis added):

"An in-memory working **copy of the current boot path** environment is created
which has a by one incremented higher revision than the current boot path.
Modifications are performed on this working copy environment.
When committing the transaction, i.e., writing it to disk, the **new current
boot path** is persisted and booted next."

So, this is in line with what you're seeing, isn't it?


Note that after having started a new transaction, you're supposed to set / overwrite `kernel` and `kernelargs` otherwise you're left with the "upcycled" copy. For this, you may use something like https://gitlab.com/cip-project/cip-sw-updates/swupdate-handler-roundrobin or https://sbabic.github.io/swupdate/handlers.html#bootloader-handler or ...


That was my main concern. I was not sure if the user would be responsible to configure the kernelargs and kernelfile, or it would be swupdate. Now is much more clear and working.
 

Kind regards,
Christian

--
Dr. Christian Storm
Siemens AG, Technology, T CED OES-DE
Otto-Hahn-Ring 6, 81739 Munich, Germany

Javier 
Reply all
Reply to author
Forward
0 new messages