Skip to content

Creating an update file

Overview

We cover how to create an update file (.swu) that can be interpreted by the SWUpdate Installer Framework. The .swu file, is a cpio archive containing all the elements required to perform the upgrade (description file, scripts, data binaries, images, etc).

What's inside a .swu

A .swu update file contains:

  1. a scriptable sw-description file with meta information about the images or files to be installed
  2. the image files or archives to be installed
  3. the sw-description signature sw-description.sig (when the signing feature is enabled)
  4. scripts to be run before or after installation (optional)

The following sections will describe two different ways to generate a .swu update file:

  • using a standalone script, as in Example 1 and Example 2. Generating .swu outside of the Yocto build system is convenient when updating non-system stuff (e.g. user application).
  • using the swupdate.bbclass in the Yocto build system, as in Example 3. Generating .swu inside of the Yocto build system is convenient when the OS is the main target of an update.

.swu files can update different parts of the system:

Example 1: installing files with a .swu generated with a script

In this example we'll show the main elements of a .swu update file aimed at writing some files to a filesystem.

The sources for this example can be downloaded here. For reference we included also the resulting working .swu file, but it can be recreated at any time using the generate_swu-1.sh update creation script file.

Note

There are often several ways to achieve the same end result using the various features of SWUpdate, we elected to provide a meaningful example showcasing the flexibility of using a custom script.

sw-description configuration file

The sw-description file is used to define elements and their metadata which are included in the .swu archive. Complete syntax details can be found in the "syntax and tags with the default parser" section of the SWUpdate manual.

The following example instructs the SWUpdate Installer Framework to install five files to the respective specified paths and to run the update.sh script for "preinst" and "postinst":

software =
{
    version = "1.0";
        files: (
                {
                        filename = "updatefactoryinfo";
                        path = "/mnt/root/usr/bin/updatefactoryinfo";
                },
                {
                        filename = "OS_VERSION.txt";
                        path = "/mnt/root/home/root/OS_VERSION.txt";
                },
                {
                        filename = "index.html";
                        path = "/mnt/root/www/pages/index.html";
                },
                {
                        filename = "style.css";
                        path = "/mnt/root/www/pages/style.css";
                },
                {
                        filename = "UF-logo.png";
                        path = "/mnt/root/www/pages/UF-logo.png";
                }
        );
        scripts: (
                {
                        filename = "update.sh";
                        type = "shellscript";
                }
        );
}

When the file device and filesystem parameters are not specified as in the example above the file is copied to the absolute path of the current rootfs swupdate is running from. This allows the freedom of mounting involved partitions in the "preinst" phase of the update.sh script.

Note

The version element is not the version of the update file. It is currently unused, so you can just ignore it.

update.sh script file

Support for optional scripts in SWUpdate is a handy way to add particular features or fill in small gaps that default behaviour of handlers might have.

The following script shows how to mount partitions by label in "preinst" and unmount in "postinst", and how to change permissions on an installed file in "postinst":

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/sh

if [ $# -lt 1 ]; then
    exit 0;
fi

mount_by_label() {
    LABEL=$1
    mkdir /mnt/$LABEL
        mount "LABEL=$LABEL" /mnt/$LABEL/
}

unmount_by_label() {
    LABEL=$1
    umount /mnt/$LABEL/
    rmdir /mnt/$LABEL
}

if [ $1 == "preinst" ]; then
    echo "Mounting root"
    mount_by_label root
    mkdir -p /mnt/root/www/pages
fi

if [ $1 == "postinst" ]; then
    chmod 755 /mnt/root/usr/bin/updatefactoryinfo
    unmount_by_label root
fi

generate_swu-1.sh update creation script file

Once all the files of the update are ready (sw-description, update.sh and the files to install) the final update file should be created using the following script from the same directory:

1
2
3
4
5
6
7
8
#!/bin/bash

CONTAINER_VER="1.1"
PRODUCT_NAME="uf-example-file-update"
FILES="sw-description updatefactoryinfo OS_VERSION.txt update.sh index.html UF-logo.png style.css"

for i in $FILES;do
        echo $i;done | cpio -ov -H crc >  ${PRODUCT_NAME}_${CONTAINER_VER}.swu

Variables

Both the CONTAINER_VER and PRODUCT_NAME variables are arbitrary. Go ahead and set them to something relevant for the update that you intend to prepare.

Warning

According to the specifications sw-description should always be the first file in the cpio archive, so don't put files before it in the FILES variable!

The output of the command should look something like this:

$ ./generate_swu-1.sh
sw-description
updatefactoryinfo
OS_VERSION.txt
update.sh
index.html
UF-logo.png
style.css
58 blocks

The resulting file uf-example-file-update_1.1.swu can be uploaded to Update Factory and assigned to a target to update a device.

Example 2: writing raw images with a manually generated.swu

In this example we'll show the main elements of a .swu update file aimed at writing raw images to a disk or a partition.

The sources for this example can be downloaded here.

sw-description configuration file

The following example instructs the SWUpdate Installer Framework to install a compressed raw ext4 partition image to a given partition device:

software =
{
        version = "1.0";
        images: (
                {
                        filename = "boundary-eval-image-nitrogen6x-rootfs.ext4.gz";
                        device = "/dev/mmcblk0p2";
                        type = "raw";
                        sha256 = "1d36580a1c52250c3a939576beb733383105e5e80d00a999f3a2f2b37200a057";
                        compressed = true;
                }
        );
}

In this case we specify the target partition in the device parameter where the raw image should be written to. Additionally we specify to verify the file SHA256 checksum before installation and that the image we provided is compressed.

generate_swu-1.sh update creation script file

As in the previous example the final update file should be created using the following script:

1
2
3
4
5
6
7
8
#!/bin/bash

CONTAINER_VER="1.0"
PRODUCT_NAME="uf-example-raw-update"
FILES="sw-description boundary-eval-image-nitrogen6x-rootfs.ext4.gz"

for i in $FILES;do
        echo $i;done | cpio -ov -H crc >  ${PRODUCT_NAME}_${CONTAINER_VER}.swu

Example 3: generating .swu in Yocto build system

Starting from release hardknott, meta-updatefactory supports the generation of .swu update files from the Yocto build system with a dedicated recipe.

Partitioning scheme in Yocto

In case the partitioning scheme used is different from meta-updatefactory default:

Partition number Partition name Size [KiB]
1 boot 100
2 root 1000
3 recovery 100
4 updates 1000
Partition number Partition name Size [KiB]
1 boot-A 100
2 boot-B 100
3 root-A 1000
4 root-B 1000

the value of variable UF_COMPRESSED_PARTITIONS should be adjusted to include the image of any additional partition to include. For example if your partitioning scheme has partition number 5 labelled app then set in your local.conf or distro configuration file:

UF_COMPRESSED_PARTITIONS = ""boot 1" "root 2" "recovery 3" "app 5""
UF_COMPRESSED_PARTITIONS = ""boot 1" "root 3" "app 5""

meta-updatefactory uses by default the fast and efficient zstd format to compress the partition images in the .swu file, but also the gzip format is supported. To use this compression format set the UF_COMPRESSION_FORMAT variable:

UF_COMPRESSION_FORMAT = "zlib"

Recipe for .swu generation

To generate a .swu file create an image recipe and include swu-image.inc.

For example to create an .swu file, from an OS image recipe called custom-image.bb, that updates only the boot partition create a new recipe called custom-image-swu.bb containing the following snippet:

require <relative-path-to>/recipes-images/images/swu-image.inc
UF_IMAGE = "custom-image"
UF_SWUPDATE_IMAGES_FSTYPES = ".boot.img.zstd"

The .zstd extension in this case refers to the default zstd compression format used in meta-updatefactory.

sw-description in Yocto

The sw-description used by the core-image-weston-swu recipe in meta-updatefactory is an example descriptor that updates three system partitions.

Warning

By default meta-updatefactory use zstd format to compress the partition images. The compressed field in the sw-description should set accordingly. Currently supported values are zlib and zstd. In case the gzip compression format is prefered, the below variables should be adjusted for consistency:

UF_SWUPDATE_IMAGES_FSTYPES = ".boot.img.gz"
...
UF_COMPRESSION_FORMAT = "zlib"

Signing the .swu

To sign the .swu file using the Yocto build system the private key and the optional passphrase paths should be provided using the following meta-swupdate variables:

SWUPDATE_PRIVATE_KEY = "<path_to_private_key>/<private_key>.pem"
SWUPDATE_PASSWORD_FILE = "<path_to_private_key>/<passphrase>"

swu-image.inc defaults to the RSA signing algorithm. This settings can be changed using the SWUPDATE_SIGNING variable.

SWUpdate will check the .swu signature with the public key in /etc/swupdate/sign_pub.pem before performing the update installation.

Bitbaking the .swu recipe

To generate the .swu update file launch bitbake as usual:

bitbake custom-image-swu

The resulting .swu update file will be found in the DEPLOYDIR.

Unpacking .swu update files

If you need to unpack a .swu file for testing or inspection purposes, this can be achieved with the following:

cpio -idv < my-software_1.0.swu

Further reading

More information on how to build an .swu file can be found at: