RAUC
Introduction
RAUC is a fully open-source update client that runs on Embedded Linux and reliably controls the procedure of updating a device with new firmware. This is also known as an Over-the-Air (OTA) update solution or remote update solution, even though the update process for RAUC doesn't necessarily have to be executed remotely.
Read the RAUC official documentation for more details about what it is. Below are some highlights.
Highlighted features
- Secure updates: Update bundles are signed and verified using OpenSSL before being installed.
- Flexible storage partitioning: RAUC supports full image updates via A/B partitioning as well as asymmetric partitioning for systems with limited storage space.
- Streaming: Update bundles can be installed from a server, via streaming, instead of downloaded and stored locally.
Update and deployment server
RAUC is not a complete updating solution with an update and deployment server. RAUC focus on update handling on the target side. Examples of update servers are hawkBit or qbee.io.
Getting started
To get started quickly, with testing and evaluating of RAUC, the Yocto meta layer meta-ea-rauc contains an example implementation for the following Embedded Artists boards.
Prerequisite
Before continuing with the instructions in this chapter you must have done the following.
- Configured your host to build Yocto by following the instructions provided in the Linux Host Setup section. Refer to the table in Distribution with RAUC support below to determine which
ea-yocto-base
branch that supports RAUC. - Initialized a build directory as described in Initialize Build.
Distribution with RAUC support
The following table outlines the ea-yocto-base
branches you can use when testing RAUC and which corresponding meta-rauc
and meta-ea-rauc
layers to use.
ea-yocto-base | meta-rauc | meta-ea-rauc |
---|---|---|
ea-6.1.36 | mickledore | mickledore |
ea-6.6.23 | scarthgap | scarthgap |
Add new meta layers
Go to the sources
directory for your build (called ea-bsp
below).
cd ea-bsp/sources/
Clone meta-rauc
. In this example we are using the mickledore
branch.
git clone -b mickledore https://github.com/rauc/meta-rauc.git
If not already included via ea-yocto-base
, clone meta-ea-rauc
. In this example we are using the mickledore
branch.
info
December 7, 2023, meta-ea-rauc
became a part of ea-yocto-base
, commit 97510aa. If you are using this version, or later, you don't have to clone meta-ea-rauc
, but you still have to update bblayers.conf
.
git clone -b mickledore https://github.com/embeddedartists/meta-ea-rauc.git
Add the new repositories to the end of conf/bblayers.conf
.
BBLAYERS += " ${BSPDIR}/sources/meta-rauc "
BBLAYERS += " ${BSPDIR}/sources/meta-ea-rauc "
Generate development certificates
RAUC is using public key infrastructure (PKI) to sign and verify updates. If you don't already have your own certificates, a script is provided in meta-rauc
. This script generates development certificates.
info
For actual usage, it is recommended to set up a real PKI solution and not use the development certificates.
cd ea-bsp/sources/meta-rauc/scripts/
./openssl-ca.sh
This will generate the folder openssl-ca/
containing the development certificates.
Update local.conf and build image
Your ea-bsp/conf/local.conf
must be updated with the following to add RAUC support.
DISTRO_FEATURES:append = " rauc"
RAUC_KEYRING_FILE = "<your-path>/ea-bsp/sources/meta-rauc/scripts/openssl-ca/dev/ca.cert.pem"
Now you can build a new image with RAUC support
info
Currently, only ea-image-base
is supported. See Customization - Different Yocto image if you want to build a different image.
bitbake ea-image-base
Deploy image
The Universal Update Utility - UUU - is used to deploy an image to a target. Detailed instructions of how to deploy an image is available in the Yocto - Deploy Images section.
- Download and unpack a pre-built distribution, for your board, from http://imx.embeddedartists.com.
- When a build has finished the image files are available in the deploy folder. For iMX8M Mini this would be
ea-bsp/tmp/deploy/images/imx8mmea-ucom/
. - Copy the wiz.zst file (for iMX8M Mini this would be
ea-image-base-imx8mmea-ucom.wic.zst
) from the deploy folder and into the<your-uuu-folder-path>/files
folder.
info
The wic file is used since it is a complete partitioned file system image.
- Program the target by using
uuu
togheter with thefull_wic.uuu
configuration file.uuu full_wic.uuu
Check status
When the target has been programmed let it boot into Linux. Check the RAUC status and look at the output. In the example below the system has booted from the A
partition and the boot status is good
.
rauc status
=== System Info ===
Compatible: EA RAUC example
Variant:
Booted from: rootfs.0 (A)
=== Bootloader ===
Activated: rootfs.0 (A)
=== Slot States ===
[bootloader.0] (/dev/mmcblk2, boot-emmc, inactive)
o [rootfs.1] (/dev/mmcblk2p4, ext4, inactive)
bootname: B
boot status: good
[boot.1] (/dev/mmcblk2p2, vfat, inactive)
x [rootfs.0] (/dev/mmcblk2p3, ext4, booted)
bootname: A
mounted: /
boot status: good
[boot.0] (/dev/mmcblk2p1, vfat, active)
Also make sure that the rauc-mark-good
service is running. This service tells the bootloader that booting was successful.
systemctl status rauc-mark-good
* rauc-mark-good.service - RAUC Good-marking Service
Loaded: loaded (/lib/systemd/system/rauc-mark-good.service; enabled; preset: enabled)
Active: active (exited) since Fri 2023-03-03 09:51:21 UTC; 18s ago
Process: 391 ExecStartPre=/bin/sh -c /usr/sbin/fw_rw_bootpart.sh unlock (code=exited, status=0/SUCCESS)
Process: 398 ExecStart=/usr/bin/rauc status mark-good (code=exited, status=0/SUCCESS)
Process: 428 ExecStartPost=/bin/sh -c /usr/sbin/fw_rw_bootpart.sh lock (code=exited, status=0/SUCCESS)
Main PID: 398 (code=exited, status=0/SUCCESS)
Mar 03 09:51:20 imx8mmea-ucom systemd[1]: Starting RAUC Good-marking Service...
Mar 03 09:51:21 imx8mmea-ucom rauc[398]: rauc status: marked slot rootfs.0 as good
Mar 03 09:51:21 imx8mmea-ucom systemd[1]: Finished RAUC Good-marking Service.
Create an update bundle
A RAUC bundle must be created before updating the system. It consists of file system image(s) and a manifest file.
RAUC Host tool
Creating a bundle on the host requires the RAUC host tool. This tool can be built using bitbake
in your build directory.
bitbake rauc-native -caddto_recipe_sysroot
Manifest and archives
In this example we are putting two tar.gz archives into the bundle; one for the boot files and the second for the root file system.
ea-boot.tar.gz
: Contains the kernel image (Image
), device tree files (*.dtb
) and bootscript (boot.scr
).ea-image-base-imx8mmea-ucom.tar.gz
: The root file system generated bybitbake ea-image-base
.
These two archives including the manifest file (manifest.raucm
) are put in the folder rauc-bundle
. Below is the content of the manifest file for this example.
[update]
compatible=EA RAUC example
version=2023.12-1
[bundle]
format=verity
[image.rootfs]
filename=ea-image-base-imx8mmea-ucom.tar.gz
[image.boot]
filename=ea-boot.tar.gz
Run the RAUC host tool as below to create the bundle.
oe-run-native rauc-native rauc --cert ../sources/meta-rauc/scripts/openssl-ca/dev/development-1.cert.pem --key ../sources/meta-rauc/scripts/openssl-ca/dev/private/development-1.key.pem bundle rauc-bundle/ update-2023.12-1.raucb
Update the system
In this example we will update the system by putting the generated bundle on a USB memory stick. The commands below are run on the system.
Begin by mounting the USB memory stick.
mount /dev/sda1/ /mnt
By default, the U-boot environment is put in the eMMC boot partition (for example /dev/mmcblk2boot0
for iMX8M Mini) and this partition is normally read-only. We need to make it writable (a helper script is available).
/usr/sbin/fw_rw_bootpart.sh unlock
Install the update.
rauc install /mnt/update-2023.12-1.raucb
If successful you can now reboot the system.
reboot
Update the bootloader
In the above sections the root file system, Linux kernel, device tree files and bootscript were updated. It is also possible to update the bootloader.
warning
Updating the bootloader is a more sensitive operation as there is normally no automatic fallback functionality in case the update fails.
When creating an update bundle for the bootloader a raw image is needed that can be directly copied to the eMMC boot area. Such an image can be created by using the dd
utility. Follow the steps below to create an update bundle for the bootloader.
- All the currently supported boards use a bootable image called
imx-boot
. Begin by copying this file from the deploy folder, in your build, to a new folder calledrauc-bundle-boot
. - Create a raw image. The
seek
value may be different for different boards. The value is 33 for iMX8M Mini and iMX8M Nano. It is 32 for iMX93.
dd if=imx-boot of=imx-boot.img bs=1k seek=33
- Create a manifest file (
manifest.raucm
) in therauc-bundle-boot
folder. An example is given below of how it can look like.
[update]
compatible=EA RAUC example
version=2023.12-1
[bundle]
format=verity
[image.bootloader]
filename=imx-boot.img
- Run the RAUC host tool as below to create the bundle.
oe-run-native rauc-native rauc --cert ../sources/meta-rauc/scripts/openssl-ca/dev/development-1.cert.pem --key ../sources/meta-rauc/scripts/openssl-ca/dev/private/development-1.key.pem bundle rauc-bundle-boot/ update-boot-2023.12-1.raucb
- Transfer the bundle to the system or USB memory stick and run
rauc install
just as described in Update the system.
Partitioning
RAUC supports flexible partitioning with for example full image updates via symmetric A/B partitioning or asymmetric partitioning for resource constraint systems.
Default for meta-ea-rauc
The example implementation in meta-ea-rauc is using a symmetric A/B partitioning scheme with in total 7 partitions. Please see the section Customization - Partition scheme for a description of what to change if you need a different partitioning scheme.
Name | Description |
---|---|
Bootloader | Two bootloader partitions. These are the eMMC boot areas that are already part of an eMMC flash. The U-boot bootloader and the U-boot environment is put in the boot area. |
Rootfs | Two equal sized root file system partitions in the user area of the eMMC flash. These are often named "A" and "B" partitions. When running from the "A" partition, an update will be installed into the "B" partition and vice versa. |
Boot | Two equal sized boot partitions in the user area of the eMMC flash. The kernel image, device tree files, and bootscript is put in the boot partition. These are configured to have their respective root file system as parent to indicate that there is a relationship between boot and rootfs. |
Data | One data partition. This partition is not touched by RAUC and is used for persistent data not to be modified during an update. |
Configuration of RAUC
RAUC must know of the chosen partition scheme and this is specified in a configuration file called system.conf
. Below is an example for the iMX8M Mini and iMX8M Nano.
[system]
compatible=EA RAUC example
bootloader=uboot
[keyring]
path=/etc/rauc/ca.cert.pem
[slot.bootloader.0]
device=/dev/mmcblk2
type=boot-emmc
# A
[slot.rootfs.0]
device=/dev/mmcblk2p3
type=ext4
bootname=A
[slot.boot.0]
device=/dev/mmcblk2p1
type=vfat
parent=rootfs.0
# B
[slot.rootfs.1]
device=/dev/mmcblk2p4
type=ext4
bootname=B
[slot.boot.1]
device=/dev/mmcblk2p2
type=vfat
parent=rootfs.1
File system image (WIC)
A complete partitioned file system image can be created in Yocto by using Wic. Wic is configured using an OpenEmbedded kickstart file (.wks). Below is the wks file for the partition scheme chosen in meta-ea-rauc.
part u-boot --source rawcopy --sourceparams="file=imx-boot" --ondisk mmcblk --no-table --align ${IMX_BOOT_SEEK}
part --source bootimg-partition --ondisk mmcblk --fstype=vfat --label boot0 --active --align 4096 --size 64
part --source bootimg-partition --ondisk mmcblk --fstype=vfat --label boot1 --active --size 64
part / --source rootfs --ondisk mmcblk --fstype=ext4 --label rootfs_A
part / --source rootfs --ondisk mmcblk --fstype=ext4 --label rootfs_B
part /data --ondisk mmcblk --fstype=ext4 --label data --size 500M
bootloader --ptable gpt
Fallback handling
A robust system must be able to handle an unsuccessful update by using a fallback/rollback mechanism. This is normally handled by the bootloader in combination with the booted system. The bootloader must be able to decide which partition to boot and determine when to switch partition due to a failed boot attempt.
In our case, the U-boot bootloader is using a bootscript with three environment variables; BOOT_ORDER
, BOOT_A_LEFT
, and BOOT_B_LEFT
to make this decision. The BOOT_[A|B]_LEFT
variables define how many attempts to make. When it reaches zero the bootloader switch partition to boot.
It is the responsibility of the booted system (Linux) to tell the bootloader if the system booted correctly. In our case this is handled by the rauc-mark-good
service. This service will update any of the BOOT_[A|B]_LEFT
variables if the system booted successfully.
A boot attempt can fail in different ways and for this to be detected, and handled by the bootloader, a reboot of the system must in general take place.
Fail to load boot files
The bootscript for the U-boot bootloader will try to load the Linux kernel and device tree files. If this fails a reset command will be issued. This can look like below where reset
is called in the else
statement.
if run loadfdt ; then
fdt addr ${fdt_addr}
setenv fdt_high 0xffffffff
else
echo "!!!! Error loading ${fdt_file}";
reset;
fi
Invalid boot files
Another scenario is when the boot files are available, but invalid. This will not be detected by the bootscript as described in Fail to load boot files. This scenario is currently not handled in the example implementation. It can be handled by enabling a hardware watchdog before trying to load the boot files.
Kernel panic
A kernel panic can for example occur with a missing or corrupt root file system. The kernel command-line parameter panic
is added by the bootscript to tell the kernel to reboot if a panic is detected.
Customization
It is recommended to set up your own Yocto meta layer similar to meta-ea-rauc when adding RAUC support to your application.
Partition scheme
As described in the Partitioning section the RAUC system.conf
file as well as the .wks
file, for the file system image, are used when defining a partition scheme. If you want to partition the storage differently these files must be modified. The meta-ea-rauc layer also contains a fstab
file that is responsible for mounting the data partition.
Related meta-ea-rauc files
File | Description |
---|---|
recipes-core/rauc/files/system_imx8.conf | RAUC configuration file for iMX8M Mini and iMX8M Nano |
recipes-core/rauc/files/system_imx9.conf | RAUC configuration file for iMX93 |
wic/ea-image-base.wks.in | OpenEmbedded Kickstart file that partitions the file system image |
recipes-core/base-files/files/fstab_imx8 | Linux file system table for iMX8M Mini and iMX8M Nano. Mounts the data partition. |
recipes-core/base-files/files/fstab_imx9 | Linux file system table for iMX93. Mounts the data partition. |
Bootloader bootscript
The bootscript might need to be modified during the following circumstances.
- The number of failed boot attempts (currently 3), before doing a rollback to the previous known good state, must be changed.
- The storage is partitioned differently from the example implementation. The bootscript sets the path to the root file system and if partitioning is changed this path most likely need to be changed.
- You want a different timeout (currently 30 seconds) before rebooting the system during a kernel panic.
- You need to detect invalid boot files. Starting a hardware watchdog could likely be done in the bootscript.
Related meta-ea-rauc files
File | Description |
---|---|
recipes-bsp/u-boot/files/bootscript_imx8_rauc.cmd | Bootscript for iMX8M Mini and iMX8M Nano |
recipes-bsp/u-boot/files/bootscript_imx9_rauc.cmd | Bootscript for iMX93 |
Different Yocto image
RAUC support is added to the ea-image-base
image. If you want to build another image, you must at least do what is shown below in your image recipe or in local.conf
. The e2fsprogs
is added to get mkfs.ext4
support.
IMAGE_INSTALL:append = " rauc"
IMAGE_INSTALL:append = " e2fsprogs"
WKS_FILE = "ea-image-base.wks.in"
Related meta-ea-rauc files
File | Description |
---|---|
recipes-ea/images/ea-image-base.bbappend | The BitBake append file that adds functionality to the ea-image-base image. |