This is an old revision of the document!


04 - RAUC - A/B System Updates

Objectives

  • Best practices in OTA (Over the Air) upgrading embedded systems;
  • Installing Debian (finally!) as embedded rootfs!
  • Building fully-featured A/B images using RAUC;

Contents

Lecture

Welcome to the RAUC Image Creation exercise!

Mender (an alternative OTA solution) has a really good lecture about how A/B updates work. Though we will be using RAUC as lightweight update framework.

You will create a bootable disk image for an embedded system with multiple partitions (boot, rootfsA, rootfsB, data), install a kernel, configure U-Boot with environment support, and install RAUC in both rootfs partitions.

Oh, and you will also finally get to use a more familiar Linux distro as root filesystem: yep, Debian!

Everything will be scripted for reusability (don't worry, they are almost written, though you will need to fill in some TODOs).

Tasks

01. Preparations

Download here the starter archive containing starter (skeleton) files & scripts.

Extract it somewhere in your base working directory.

The code structure should be similar to this:

arm-summer-school/
├── staging/         # you should have this from lab02
│   ├── linux-*.its  # Two variants of Linux uImage source descriptors
│   ├── Makefile     # a Makefile to build linux.itb (finally!)
│   └── Image,imx93-11x11-frdm.dtb,rootfs.cpio   # copied by the Makefile
├── rauc-utils/      # RAUC installation 'package'!
│   ├── install.sh       # RAUC installation script (must be ran inside the chroot!)
│   ├── ca.cert.pem
│   ├── rauc-mark-good.service
│   ├── system.conf
│   └── fstab            # Optional, custom fstab to mount /boot
├── linux/               # Linux kernel source directory
├── u-boot/              # u-boot source directory
├── debian-rootfs/       # will be created by 'mk-debian-rootfs.sh'
├── Makefile             # Makefile to build flash.bin from labs 1-3 (u-boot mainline!)
├── newdefault.env       # new/recommended u-boot default environment
├── uboot-extra.config   # extra config to use (used by Makefile above)
├── mk-disk-image.sh     # script to build a FAT32 + EXT4 disk image (solved in lab02/03)
├── mk-disk-image2.sh    # new disk image script, modified to make 2*rootfs+data partitions
├── mk-debian-rootfs.sh  # script to debootstrap your debian directory
└── chroot-enter.sh      # utility script to execute commands in your debian rootfs

Prerequisites

We will need the static qemu-aarch64 binaries if we're cross-building, since we need to execute Debian install scripts on our native host archivecture (e.g., x86_64).

First, make sure you have these packages installed (they were already installed on the VM, so you can skip this):

sudo apt install qemu-user-static binfmt-support debootstrap parted dosfstools e2fsprogs u-boot-tools

Then, check that binfmt_misc is active and register the QEMU handler for aarch64:

grep aarch64 /proc/sys/fs/binfmt_misc/qemu-aarch64

If it’s empty, run:

sudo su
echo ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff:/usr/bin/qemu-aarch64-static:CF' > /proc/sys/fs/binfmt_misc/register
exit

For Arch Linux users: check out this guide for installable dependencies!

02. Bootstrapping Debian

2.1. Install Debian into a directory

Yes, really, you can easily do this!

You will use the debootstrap official tool to install a minimal Debian (you can also install deb-based derivatives like Ubuntu!) base system.

📄 Edit the mk-debian-rootfs.sh script, read the code and fill the TODOs.

Since we need to install the Debian binaries executable on a 64-bit ARM architecture, we will need to split the installation into two stages: first, the .deb (Debian install packages) are downloaded from a Debian mirror server and unpacked into the target rootfs directory. Afterwards, since Debian will need to run some scripts to setup its distro system, we must emulate the target architecture. Enter qemu which will help us to just that!

Finally, we need to obtain the debian-rootfs.tar.gz archive with the contents of our newly-created Aarch64 Debian. Use tar to create a gzipped archive, and be sure to preserve permissions:

sudo tar czpf debian-rootfs.tar.gz -C debian-rootfs/ .

Note: each time you chroot and install / modify your rootfs on your local machine, make sure to rebuild the tar.gz archive!

2.1. Installing kernel modules

We must install our kernel's external modules onto our new Debian rootfs.

As noted in Lab 3, it's quite simple, actually (adapt if paths don't match):

# navigate to Linux's source directory
cd linux/
# ensure compiled the modules
make ARCH=arm64 modules
# install the modules inside debian-rootfs (hope you put it in parent dir):
sudo make ARCH=arm64 INSTALL_MOD_PATH="../debian-rootfs/" modules_install

2.2. Entering the rootfs

If you wish to enter your newly bootstrapped Debian rootfs, you can readily use the chroot-enter.sh script (read its code to see its arguments!)

There's one critical thing to do if we want to be able to use our rootfs live: set up a login password! So:

# in chroot, you are root, so set up a "secure" password
# (joking, you can use '1234')
passwd

You can even run apt install in there ;) try it out (we'll use it later to install RAUC packages + configuration files).

Let's also check something.. while still inside the chroot, try to ls -l /lib/modules/*. The kernel modules you installed in the previous step should be listed in there for your kernel version!

2.3. Re-build linux.itb

Since we'll be running the rootfs on a separate partition from now on, we eliminated the Bootstrap CPIO (initrd nodes) from the Linux uImage. Check out staging/linux-noinitrd.its and use the staging/Makefile included inside the skeleton to rebuild the .itb!

2.4. Create the base disk image for testing

📄 File: mk-disk-image.sh: modify it, set a bigger image size (e.g., 1500 MB) and configure it to unpack the debian-rootfs.tar on the second partition.

Note: you have two versions mk-disk-image.sh scripts! For now, we'll just use the first version (having a simple fat32+ext4 partition layout), when we get to run RAUC, we'll use the second one!

After modification, run the script to obtain the disk image.

But before booting the board, we must do some minor re-configuration to our u-boot…

2.5. Bootloader [re]configuration

You'll need the mainline u-boot for this task. Simply delete your u-boot directory (do backup your configs, if you want) and use the Makefile provided for lab02 (also found inside today's archive) to build & properly reconfigure a full Firmware Image Package.

Note the new configuration options inside uboot-extra.config and the default environment variables in new-default.env.

Now we can power up the board! Use uuu -b spl flash.bin and enter U-Boot. Let fastboot 0 start and use fastboot flash 0:0 disk.img to quickly burn the image. After the flashing finishes, use Ctrl+C on u-boot to exit fastboot mode and run linux!

Now pay attention: after testing it using uuu -b spl ,make a backup of this flash.bin file! You'll need it later to start the board with RAUC autoboot disabled, as the one you'll build in the following section will not work (it will override the boot command and become unable to use fastboot / ums!). E.g., copy & name this file as flash_spl.bin!

03. RAUC

Finally, it comes down to installing RAUC into the Debian partitions.

📄 Our script: rauc-utils/install.sh is already complete. Feel free to read and understand it.

This script will:

  1. Mount both rootfsA and rootfsB
  2. Uses QEMU and chroot to install:
    1. rauc
    2. your ca.cert.pem (certificate used to sign the update images)
    3. system.conf
    4. rauc-mark-good.service
  3. Sets up /etc/fw_env.config, fstab, and enables systemd services

But in order to run it, recursively copy the entire RAUC utils directory from host to somewhere inside the debian rootfs (e.g., /root/rauc-utils/) and run it using chroot-enter.sh (as you've done in the prev. task).

[Re]Generate the disk image

We can now run mk-disk-image2.sh. The disk.img will be updated with 4 partitions (boot, A, B + data), Debian will be copied to the first 2 EXT4 partitions and the bootloader will be installed at 32KB offset (the SoC's BL1/BOOTROM wants it there).

Custom u-boot script

📄 In order to have the A-B partitioning scheme, we'll need to add this script: rauc-utils/boot.cmd.in to our u-boot default environment. Feel free to study it (highly recommended)!

Use the rauc-utils/uboot-modify-bootcmd.sh script to just to this!

Then rebuild uboot (you must delete u-boot/.config and u-boot/flash.bin for our Makefile to trigger the recompilation of UBoot).

Flashing the board

Power up the board and go into u-boot. Let fastboot start and use fastboot flash 0:0 disk.img.

Use your root password (hope you set it!).

Once Debian booted, check:

mount | grep rootfs
cat /etc/rauc/system.conf
ass/labs-2025/04.1754558817.txt.gz · Last modified: 2025/08/07 12:26 by florin.stancu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0