Last edited 2 weeks ago

How to handle secure firmware update


1. Article purpose[edit | edit source]

The purpose of this article is to explain how to handle a software update using A/B mechanism with the FWU implementation in OpenSTLinux (Example given with Rauc as "update client" and hawkbit as "software provisioning server" - aka "firmware update database"). It is highly recommended to read the page Secure Firmware Update where the FWU implementation in OpenSTLinux is explained.

2. Update the metadata content[edit | edit source]

The mkfwumdata tool (fromU-Boot) is used to generate the metadata partition.

The metadata generation is described in the following article: Metadata generation tool.

The mkfwumdata version embedded before v6.1.0 Ecosystem Release was not supporting Valid bank state (only Accepted and Invalid were supported). To support the Valid bank state, you need to apply the following patch in U-Boot: autoboot-propagate-boot-index.patch .

3. mkfwumdata versus FWU states[edit | edit source]

mkfwumdata considers three states where two of them correspond to Firmware update state machine:

4. Steps to run a secure firmware update[edit | edit source]

  • Prerequisite: system is running on bank A (fip-a, bootfs-a, rootfs-a...)
  • The "update manager", which is in touch with the software provisioning server, is notified about a new update that is written into bank B (fip-b, bootfs-b, rootfs-b...)
  • When the new image is downloaded into the bank B, the "update manager":
    • executes some scripts to adapt the new flashed image to bank B (ex: partition mount points)
    • updates the metadata partition requesting TF-A to try to boot on the new bank B: so the "update manager" changes the metadata partition by:
      • updating active_index to bank B (managed through -a option). Bank A becomes then previous_active_index (managed through -p option).
      • switching bank B as Valid (managed through -s option). Bank A is kept as Accepted, to prevent failure of bank B.
UUID_LIST="8a7a84a0-8387-40f6-ab41-a8b9a5a60d23,19d5df83-11b0-457b-be2c-7559c13142a5,4fd84c93-54ef-463f-a7ef-ae25ff887087,09c54952-d5bf-45af-acee-335303766fb3"
OPTIONS="-g -i 1 -b 2 -v 2"
bank_state="A,V"
mkfwumdata ${OPTIONS} -s ${bank_state} -a 1 -p 0 ${UUID_LIST} /dev/disk/by-partlabel/metadata1
mkfwumdata ${OPTIONS} -s ${bank_state} -a 1 -p 0 ${UUID_LIST} /dev/disk/by-partlabel/metadata2

Note that /dev/disk/by-partlabel/metadata2 is also updated, which is the backup of metadata1, and is used by TF-A in case of CRC error of metadata1 partition.

  • On reboot, TF-A boots bank B, and there are now two possibilities:
    • bank B crashs: as the watchdog is enabled, the platform reboots on crash. As bank B is in Valid mode, the "bootcount" is decremented on each reboot. After 3 attempts (default value), TF-A considers the bank B is not able to boot, so it switches back to bank A. As "active_index" is bank B, but bank A is active (Bank A is kept in Accepted), the update manager can consider bank B as Invalid, and notify the "software provisioning server" if needed.
    • bank B successfully boots: the "update manager" from bank B can update the metadata partition to switch the bank B state to Accepted: on the next reboot, TF-A considers this bank Accepted, and disables the "bootcount":
UUID_LIST="8a7a84a0-8387-40f6-ab41-a8b9a5a60d23,19d5df83-11b0-457b-be2c-7559c13142a5,4fd84c93-54ef-463f-a7ef-ae25ff887087,09c54952-d5bf-45af-acee-335303766fb3"
OPTIONS="-g -i 1 -b 2 -v 2"
bank_state="A,A"
mkfwumdata ${OPTIONS} -s ${bank_state} -a 1 -p 0 ${UUID_LIST} /dev/disk/by-partlabel/metadata1
mkfwumdata ${OPTIONS} -s ${bank_state} -a 1 -p 0 ${UUID_LIST} /dev/disk/by-partlabel/metadata2

Another alternative is to use a systemd service:

$ cat status-mark-good.service
[Unit]
Description=Good-marking Service
[Service]
ExecStart=/bin/bash /usr/bin/st-status-mark-good.sh
[Install]
WantedBy=multi-user.target

where st-status-mark-good.sh script asks the "update manager" to update the metadata partition to switch the bank B state to Accepted.


5. Yocto layer[edit | edit source]

A Yocto layer is avalaible in a private Github Yocto layer which:

  • demonstrates A/B mechanism already integrated by default in OpenSTLinux (in TF-A), using an "update manager" (Rauc[1]) and a software provisioning server (Hawkbit[2]) as example.
  • includes scripts that make the "glue" between the "update manager" and STM32MPU ecosystem, and some patches to propagate the active_index (A or B) from TF-A to the Linux kernel.

You can contact your local ST FAE to request an access to this layer if needed.

6. References[edit | edit source]