Skip to main content

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.

  1. 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.
  2. 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-basemeta-raucmeta-ea-rauc
ea-6.1.36mickledoremickledore

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.

  1. Download and unpack a pre-built distribution, for your board, from http://imx.embeddedartists.com.
  2. 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/.
  3. 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.

  1. Program the target by using uuu togheter with the full_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 by bitbake 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.

  1. 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 called rauc-bundle-boot.
  2. 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
  1. Create a manifest file (manifest.raucm) in the rauc-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
  1. 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
  1. 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.

NameDescription
BootloaderTwo 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.
RootfsTwo 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.
BootTwo 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.
DataOne data partition. This partition is not touched by RAUC and is used for persistent data not to be modified during an update.

Example partitioning

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.

FileDescription
recipes-core/rauc/files/system_imx8.confRAUC configuration file for iMX8M Mini and iMX8M Nano
recipes-core/rauc/files/system_imx9.confRAUC configuration file for iMX93
wic/ea-image-base.wks.inOpenEmbedded Kickstart file that partitions the file system image
recipes-core/base-files/files/fstab_imx8Linux file system table for iMX8M Mini and iMX8M Nano. Mounts the data partition.
recipes-core/base-files/files/fstab_imx9Linux 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.
FileDescription
recipes-bsp/u-boot/files/bootscript_imx8_rauc.cmdBootscript for iMX8M Mini and iMX8M Nano
recipes-bsp/u-boot/files/bootscript_imx9_rauc.cmdBootscript 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"
FileDescription
recipes-ea/images/ea-image-base.bbappendThe BitBake append file that adds functionality to the ea-image-base image.