3. Using RAUC

For using RAUC in your embedded project, you will need to build at least two instances of it:

  • One for your host (development) system, where you create new updates.
  • One that will run on the target for performing updates.

3.1. Creating Bundles

To create an update bundle on your build host, RAUC provides the bundle sub-command:

rauc bundle --cert=<certfile> --key=<keyfile> <input-dir> <output-file>

Where <input-dir> must be a directory containing all images and scripts the bundle should include, as well as a manifest file manifest.raucm that describes the content of the bundle in a way the RAUC updater on the target can handle it and knows which image to install to which slot, which scripts to execute etc. <output-file> must be the path of the bundle file to create. Note that RAUC bundles must always have a .raucb file name suffix in order to make RAUC treat them as bundles.

3.2. Resigning Bundles

Note

This feature is not fully implemented yet

RAUC allows to resign a bundle from your build host, e.g. for making a testing bundle a productive bundle that should have a key that is accepted by non-debugging platforms:

rauc resign --cert=<certfile> --key=<keyfile> <input-file> <output-file>

3.3. Obtaining Bundle Information

rauc info [--output-format=<format>] <input-file>

You can control the output type of RAUC info depending on your needs. By default it will print a human readable representation of the bundle. Alternatively you can obtain a shell-parsable description, or a JSON representation of the bundle content.

3.4. Installing Bundles

To install an update bundle on your target hardware, RAUC provides the install command:

rauc install <input-file>

Alternatively you can trigger a bundle installation via D-Bus.

3.5. See System Status

For debugging purposes and for scripts maybe it can be helpful to gain an overview over the current system as RAUC sees it. The status command allows this:

rauc status [--output-format=<format>]

You can choose the output style of RAUC status depending on your needs. By default it will print a human readable representation of your system. Alternatively you can obtain a shell-parsable description, or a JSON representation of the system status.

3.6. React to a Successfully Booted System/Failed Boot

Normally, the full system update chain is not completed before being sure the newly installed system runs without any errors. As the definition and detection of a successful operation is really system-dependent, RAUC provides commands to preserve a slot as being the preferred one to boot or to discard a slot from being bootable.

rauc status mark-good

After assessment of the currently booted system to be fully operational, one wants to signal this information to the underlying bootloader implementation which then, for example, resets a boot attempt counter.

rauc status mark-bad

If the current boot failed in some kind, this command can be used to reflect that to the underlying bootloader implementation. In most cases this will disable the currently booted slot or at least switch to another one.

3.7. Customizing the Update

RAUC provides several ways to customize the update process. Some allow to add and extend details more fine-grainedly, some allow to replace major parts of the default behavior of RAUC.

In general, there exist three major types of customization: configuration, handlers and hooks.

The first is configuration through pre-defined variables. This allows to control the update in a predefined way.

The second type is using handlers. Handlers allow to extend or replace the installation process. They are executables (most likely shell scripts) located in the root filesystem and configured in the system’s configuration file. They control static behavior of the system that should remain the same over all future updates.

The last type are hooks. They are much like handlers, except that they are contained in the update bundle. Thus they allow to flexibly extend or customize one or more updates by some special behavior. A common example would be using a per-slot post-install hook that handles configuration migration for a new system version. Hooks are especially useful to handle details of installing an update which were not considered in the previously deployed version.

In the following, handlers and hooks will be explained in more detail.

3.8. System-Based Customization: Handlers

  • system.conf
  • multiple scripts?

For a detailed list of all environment variables exported for the handler scripts, see ...

3.8.1. Pre-Install Handler

[handlers]
pre-install=/usr/lib/rauc/pre-install

RAUC will call the pre-install handler (if given) during the bundle installation process, right before calling the default or custom installation process. At this stage, the bundle is mounted and its content accessible, the target group has been determined successfully.

If calling the handler fails or the handler returns a non-zero exit code, RAUC will abort installation with an error.

3.8.2. Install Handler

[handlers]
install=/usr/lib/rauc/install

The install handler is the most powerful one RAUC has. If you provide this, you replace the entire default update procedure of RAUC. It will be executed right after the pre-install handler and right before the post-install handler.

If calling the handler fails or the handler returns a non-zero exit code, RAUC will abort installation with an error.

3.8.3. Post-Install Handler

[handlers]
post-install=/usr/lib/rauc/post-install

The post install handler will be called right after RAUC successfully performed a system update. If any error occurred during installation, the post-install handler will not be called.

Note that a failed call of the post-install handler or a non-zero exit code will cause a notification about the error but will not change the result of the performed update anymore.

A possible usage for the post-install handler could be to trigger an automatic restart of the system.

3.8.4. System-Info Handler

[handlers]
system-info=/usr/lib/rauc/system-info

The system-info handler is called after loading the configuration file. This way it can collect additional variables from the system, like the system’s serial number.

The handler script must return a system serial number by echoing RAUC_SYSTEM_SERIAL=<value> to standard out.

3.9. Bundle-Based Customization: Hooks

Unlike handlers, hooks allow the author of a bundle to add or replace functionality for the installation of a specific bundle. This can be useful for performing additional migration steps, checking for specific previously installed bundle versions or for manually handling updates of images RAUC cannot handle natively.

To reduce the complexity and number of files in a bundle, all hooks must be handled by a single executable that is registered in the bundle’s manifest:

[hooks]
filename=hook

Each hook must be activated explicitly and leads to a call of the hook executable with a specific argument that allows to distinguish between the different hook types. Multiple hooks must be separated with a ;.

In the following the available hooks are listed. Depending on their purpose, some are image-specific, i.e. they will be executed for the currently installed image only, while some other are global.

3.9.1. Install Hooks

Install hooks operate globally on the bundle installation.

The following environment variables will be passed to the hook executable:

RAUC_SYSTEM_COMPATIBLE
The compatible value set in the system configuration file
RAUC_MF_COMPATIBLE
The compatible value provided by the current bundle
RAUC_MF_VERSION
The value of the version field as provided by the current bundle
RAUC_MOUNT_PREFIX
The global RAUC mount prefix path

3.9.1.1. Install-Check Hook

[hooks]
filename=hook
hooks=install-check

This hook will be executed instead of the normal compatible check in order to allow performing a custom compatibility check based on compatible and/or version information.

To indicate that a bundle should be rejected, the script must return with an exit code >= 10.

If available, RAUC will use the last line printed to standard error by the hook executable as the rejection reason message and provide it to the user:

#!/bin/sh

case "$1" in
      install-check)
              if [[ "$RAUC_MF_COMPATIBLE" != "$RAUC_SYSTEM_COMPATIBLE" ]]; then
                      echo "Comptaible does not match!" 1>&2
                      exit 10
              fi
              ;;
      *)
              exit 1
              ;;
esac

exit 0

3.9.2. Slot Hooks

Slot hooks are called for each slot an image will be installed to. In order to enable them, you have to specify them in the hooks key under the respective image section.

Note that hook slot operations will be passed to the executable with the prefix slot-. Thus if you intend to check for the pre-install hook, you have to check for the argument to be slot-pre-install.

The following environment variables will be passed to the hook executable:

RAUC_SLOT_NAME
The name of the currently installed slot
RAUC_SLOT_CLASS
The class of the currently installed slot
RAUC_SLOT_DEVICE
The device of the currently installed slot
RAUC_SLOT_BOOTNAME
If set, the bootname of the currently installed slot
RAUC_SLOT_PARENT
If set, the parent of the currently installed slot
RAUC_SLOT_MOUNT_POINT
If available, the mount point of the currently installed slot
RAUC_IMAGE_NAME
If set, the file name of the image currently to be installed
RAUC_IMAGE_DIGEST
If set, the digest of the image currently to be installed
RAUC_IMAGE_CLASS
If set, the target class of the image currently to be installed
RAUC_MOUNT_PREFIX
The global RAUC mount prefix path

3.9.2.1. Pre-Install Hook

The pre-install hook will be called right before the update procedure for the respective slot will be started. For slot types that represent a mountable file system, the hook will be executed with having the file system mounted.

[hooks]
filename=hook

[image.rootfs]
filename=rootfs.img
size=...
sha256=...
hooks=pre-install

3.9.2.2. Post-Install Hook

The post-install hook will be called right after the update procedure for the respective slot was finished successfully. For slot types that represent a mountable file system, the hook will be executed with having the file system mounted. This allows to write some post-install information to the slot. It is also useful to copy files from the currently active system to the newly installed slot, for example to preserve application configuration data.

[hooks]
filename=hook

[image.rootfs]
filename=rootfs.img
size=...
sha256=...
hooks=post-install

An example on how to use a post-install hook:

#!/bin/sh

case "$1" in
        slot-post-install)
                # only rootfs needs to be handled
                test "$RAUC_SLOT_CLASS" = "rootfs" || exit 0

                touch "$RAUC_SLOT_MOUNT_POINT/extra-file"
                ;;
        *)
                exit 1
                ;;
esac

exit 0

3.9.2.3. Install Hook

The install hook will replace the entire default installation process for the target slot of the image it was specified for. Note that when having the install hook enabled, pre- and post-install hooks will not be executed. The install hook allows to fully customize the way an image is installed. This allows performing special installation methods that are not natively supported by RAUC, for example to upgrade the bootloader to a new version while also migrating configuration settings.

[hooks]
filename=hook

[image.rootfs]
filename=rootfs.img
size=...
sha256=...
hooks=install

3.10. Using the D-Bus API

3.10.1. Examples Using busctl Command

Triggering an installation:

busctl call de.pengutronix.rauc / de.pengutronix.rauc.Installer Install s "/path/to/bundle"

Get the operation property containing the current operation:

busctl get-property de.pengutronix.rauc / de.pengutronix.rauc.Installer Operation

Get the lasterror property, which contains the last error that occured during an installation.

busctl get-property de.pengutronix.rauc / de.pengutronix.rauc.Installer LastError

Monitor the D-Bus interface

busctl monitor de.pengutronix.rauc

3.11. Migrating to an Updated Bundle Version

RAUC will be constantly extended and new features or enhancements will make their way into RAUC. Thus, also the information contained in the bundle, or, more precise, in the manifest may extend.

Now, current RAUC versions check each option contained in the manifest and will reject the bundle if an entry in the manifest is not known. This is necessary and important to assure that the actual installation behavior does not differ from the description in the manifest.

Despite the fact, that installing bundles that use newly added features will not work, it is (of course) still possible to update your device to this new version.

For this you have to follow a simple 2 step process

  1. Create a bundle not containing the new RAUC features in the manifest but include the new RAUC version itself in the rootfs image.
  2. Now you can proceed updating your board with bundles that use the latest RAUC features.