1. RAUC Overview

RAUC (Robust Auto-Update Controller) is a lightweight, open-source framework designed for secure and reliable software updates in embedded Linux systems. It supports A/B update schemes, which provide redundancy by maintaining two copies of the root filesystem, allowing rollback in case of a failed update. RAUC ensures atomic updates, meaning that the update process is either fully completed or rolled back without leaving the system in a partial state. It uses cryptographic signatures to verify the integrity and authenticity of update bundles, making it suitable for critical systems where robustness and security are paramount.

In CCLinux 4.x RAUC is used for handling the bootloader, system and application updates. Both USB updates and OTA updates are supported. This documentation will try to cover the most common use-cases when using RAUC with CCLinux, but for more details please also look at the complete doucmentation at: https://rauc.readthedocs.io/en/latest/index.html

2. Changes between CCLinux 3.0 and CCLinux 4.0

In earlier versions of CCLinux, the file system was designed with a main and a rescue partition:

CC Linux 3.0
+-------------------+
|       Boot        |
+-------------------+
|      Rescue       |
|     (160 MB)      |
+-------------------+
|       Main        |
|      (1 GB)       |
+-------------------+
|       Data        |
|      (6 GB)       |
+-------------------+

With CCLinux 4.x, a new partition scheme is introduced, that makes the system designed for secure and reliable software updates. With an A/B setup for both root file system and A/B for application partition, this will change the method for updates (partition sizes can be different depending of available flash size configurations and hardware).

CC Linux 4.0
+-------------------+
|       Boot        |
+-------------------+
|       OS A        |
|      (1.3 GB)     |
+-------------------+
|       OS B        |
|      (1.3 GB)     |
+-------------------+
|      App A        |
|      (1.3 GB)     |
+-------------------+
|      App B        |
|      (1.3 GB)     |
+-------------------+
|       Data        |
|      (2.7+ GB)    |
+-------------------+
    |
    |--> Available for "Data", depending on flash size in the unit:
        - Docker containers
        - Temporary storage of files
        - Application log files
        - Application Configuration files

This partition layout creates the possibility to have OS A + Application partition (appfs) A to be active, and OS B with Application partition B inactive. The rootfs partition is “parent” to the appfs, so to enable the system to boot to the other appfs, the active rootfs must also be changed.

+-------+-------+
| rootfs| rootfs|
|   A   |   B   |
+-------+-------+
| appfs | appfs |
|   A   |   B   |
+-------+-------+

A new update will be written to the inactive partition, this can be done on a running system without the need to interfere with normal operation. In the case of an update failure, the system remains fully functional and it is possible to reattempt the update.

3. Read-only file systems

In previous versions of CCLinux, there was one OS filesystem. It was read-only with an overlay filesystem (OverlayFS) applied, making it possible to write, delete or modify any system file in the OS. Custom application data was placed in /opt folder where the default user ‘ccs’ had write access.

For CCLinux 4, this configuration has changed. Both the root file system and the application partition are now read-only, and can only be modified with RAUC updates. This change is needed for the atomic update process, and also required by other RAUC functionalty.

The only location that is writable by the application or ccs user is /data partition. This is the locataion for temporary or permanent data, where the application can log, and is also used for the /etc overlay to be able to modify certain config files.

4. Update procedure

A system using RAUC can be updated from a RAUC bundle or flashed using uuu.

A RAUC bundle is a compressed filesystem containing the software update. It typically includes the system images (e.g., root filesystem, bootloader, application data) and metadata such as cryptographic signatures for integrity and authenticity verification. Bundles are signed and verified by RAUC to ensure secure delivery and application of the update.

These bundles are applied atomically, meaning the update either fully succeeds or the system reverts to its previous state, preventing partial or corrupted installations.

CrossControl will deliver update bundles containing:
  • Bootloader

  • Root filesystem

  • Application filesystem

  • OS Update (bootloader + root filesystem)

  • System update (OS Update + Application update)

5. Signature

RAUC uses cryptographic signing to ensure the integrity and authenticity of update bundles. When creating a bundle, a private key is used to sign the bundle, generating a cryptographic signature. This signature is included in the bundle’s metadata.

On the CCPilot display, RAUC uses the corresponding public key, stored in a certificate at /etc/rauc/ folder, to verify the signature before applying the update. If the signature is valid, it ensures:

  • Integrity: The bundle has not been tampered with or corrupted during transmission.

  • Authenticity: The update came from a trusted source (i.e., the entity that holds the private key).

If the verification fails, RAUC will reject the bundle, preventing the installation of potentially harmful or unauthorized software. This mechanism helps to secure the update process.

6. CrossControl Demo keys

For testing purposes, CCLinux 4.x includes a pre-installed “demo key”. This public/private key pair is provided for developers and is used to generate the demo certificate that comes with the default OS installation. While the demo key can be used to create update bundles for installing application software via RAUC, it is crucial to replace it with a custom key and certificate in production environments. Since the demo key is publicly accessible, using it in production poses a security risk. A unique, customer-generated key and certificate should be used to ensure system security.

The demo certificate is included in the CCLinux SDK, in the /etc/rauc target sysroot folder. As an example for a V700 display, this would then be:

/opt/V700/sysroots/cortexa35-poky-linux/etc/rauc/ca.cert.pem

The developer.key and developer.cert is needed to sign the bundle, and this demo key is included in the virtual machine ‘LinX Software Suite 5.2” provided by CrossControl. A more detailed example of how to create update bundles is available in the “Bundle creation” section.

7. Update bundle explained

A RAUC bundle consists of the file system(s) to be installed, a manifest that lists the images to install and contains options and meta-information, and possible scripts to run before, during or after installation. A bundle may also contain files not referenced in the manifest, such as scripts or archives that are referenced by files that are included in the manifest.

To pack this together, these contents are added into a SquashFS image. This provides good compression while allowing the bundle to be mounted without having to unpack it on the target system. This way, no intermediate storage is required.

Update bundles can have three different formats: plain, verity and crypt, with different supported features:

7.1. Plain

  • The original and simplest format.

  • No built-in security or integrity measures.

  • Vulnerable to tampering and corruption.

7.2. Verity

  • Adds integrity protection using Linux’s dm-verity module.

  • Verifies the integrity of the bundle’s payload before installation.

  • Protects against unauthorized modifications and ensures the bundle’s authenticity.

7.3. Crypt

  • Builds upon the verity format by adding encryption.

  • Encrypts the bundle’s payload using symmetric encryption.

  • The encryption key is stored in the manifest, which is itself encrypted asymmetrically.

  • Provides confidentiality in addition to integrity protection.

Note that “Plain” format is disabled in CCLinux 4.0 for security.

7.4. Hooks

RAUC hooks are custom scripts or commands that can be executed at various points during the update process, providing flexibility for handling specific tasks before, during, or after an update. These hooks allow for the behavior of RAUC to be customized beyond its default operations, making it adaptable to a wide range of system requirements.

Hooks are defined in the update bundle and must be specified in the bundle’s Manifest file. All hooks are handled by a common executable that must be included in the bundle. 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.

Common usage includes Install Hooks, for example the “pre-install” or “post-install” hook. See RAUC documentation for a complete guide: https://rauc.readthedocs.io/en/latest/using.html?highlight=slot%20hooks#slot-hooks

8. Update bundle creation

Update bundles for bootloader and root filesystem (OS) are provided by CrossControl. These are built automatically from the Yocto build system for each release of CCLinux OS. Customers can create appfs update bundles, which is explained in the following section.

8.1. Create an appfs image file with customer data

Since the application partition, called appfs, is an ext4 file system that will be written in one atomic write, it is most efficient if is prepared as a .ext4 or .img file. One example of how this can be done follows:

Create a folder that should contain your application/project. In this example

mkdir v700-demo

Enter this folder. Create appfs root folder to be used to prepare the update package

mkdir appfs_root

Copy binaries to appfs_root

cp /home/ccs/qt/myApplication appfs_root
tar -xf linx-qt68-v700-ccl40_6.8.0_aarch64.tar.gz -C appfs_root

Create an empty appfs image file with the size needed for the package. This size must be smaller or equal to the appfs partition size of this device.

dd if=/dev/zero of=appfs.ext4 bs=100M count=8

Create an ext4 file system in the image

mkfs.ext4 appfs.ext4

Create a temp folder for mounting the appfs image

mkdir temp_appfs

Mount the image to be able to copy files to it

sudo mount appfs.ext4 temp_appfs

Copy all content of update folder to the image

sudo cp -rd appfs_root/* temp_appfs

Unmount the image

sudo unmount temp_appfs

The appfs.img image file now contains all files that will be installed by the update bundle. See the next section for how to create a bundle with this .img file.

8.2. Create customer application systemd script

In CCLinux 4, it is not possible to modify systemd startup scripts in /lib/systemd/system folder, but systemd will include /appfs/lib/systemd/system/ folder into the search path for systemd scripts. This makes it possible for customers to include automatic startup of applications by adding this script directly into the appfs update bundle.

As an example: * Create and put myApp.service file in /appfs/lib/systemd/system/ folder * Add link to script in ‘target.wants’ folder to automatically start it: /appfs/lib/systemd/system/multi-user.target.wants

It is also possible from the appfs update bundle to modify the content of /etc/systemd/system folder to add scripts there using the Hook file. Then it is possible to execute commands like “systemctl enable myApp.service”, or enable/disable system services.

8.3. Create a Manifest file with information about the update bundle to be created

RAUC will look for a file named “manifest.raucm” in the working folder. Create this folder and add the following details:

[update]
compatible=CrossControl V700
version=0.1
description=Appfs demo update package

[bundle]
format=verity

[image.appfs]
filename=appfs.ext4

Each CrossControl device has its own identifier, defined in /etc/rauc/system.conf. The CCpilot V700 is for example identified with the string “CrossControl V700”. This has to be set in the manifest file so that RAUC knows that the bundle is compatible with a specific device.

8.4. Create bundle

The RAUC binary is included in the device SDK. This is used to create an update bundle. To be able to sign the bundle, the CA certificate, developer key and developer certificate are also needed. Private keys should always be protected. For testing purposes, a demo certificate has been added to CCLinux 4.x and a demo developer key and cert are made publicly available.

/opt/V700/sysroots/x86_64-cclinuxsdk-linux/usr/bin/rauc bundle --keyring=/opt/V700/sysroots/cortexa35-poky-linux/etc/rauc/ca.cert.pem --key=development-1.key.pem --cert=development-1.cert.pem <folder> <package name>.raucb

Developer key:

-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCVS8cJKPyyjDke
nb7mXYMSGVeuisesWYTPd8wVB2xNoL2dx0xMDMayUSxdZnpfLEH6ZZWomFqA2jpj
yiZa5nSaf1RRVy2sODgwx1qsp7AbsxzBUy4fetSlZKcBDnMPQ45OPkHVaprkevNx
k2FoA2+JGjEicd3gGqax+HQRgHsm9fXEkf48vSaia3nfdpd1pE2lIniMT4mAxezc
J0S0Or9BRcV9R5kbh/X8tvqdHLaLlULxZzyxYbsPKaZXelYnMU/qqM3nN0rqDgEs
BfvR7uQcAfd6+Sp34ilmFTqqYQ1jsJcFziOYlAUROWu9Fw76krFi2mq5dkVPxarH
4Un7zIj5AgMBAAECggEAIqI13dDhkDz5yjmvbarvS01QOygsKnYI2oUwtYcnj3mU
y0uOzkyfcoHksBUkGbx/YMpclcQkKKSXa4tbavZvweB8a7M03/EZze0NQqTS9JYQ
O2PjvP9GYcjv+g2DURzroAiOxqbIoGzKWURmkhXL88r873/pSAH+viYELQQ4bYDC
KOj3kR+uoBCCgggr/z1WACNaIGZh1hzyznHNlQMnMEfs6jPbN2I3gnPPYbo35LMi
X9YoKMdBgyxJr3O9mjjXYHENM7oCcs5rU8YdoVehJiuZNGydmAzMxCwOOv4xknSP
NaNV0KU68+lSXp4mKziFTSZr22vJ4coUG1oJyV75RQKBgQDOUp7aXueaa+u1ykVO
OSpAoVdbv32eAjjQCNvz+3rRYnJQNyNFKwW39s9hYcggOVGXzWvK6Mh0Tj9pjF6W
skdihLKuKAhq+arulIA9Wr+CroSmBCyuoKv64Pj8ybluZJacYEeZL5oKUQEYjQKq
6v9fIKk8vhniT165zthmRO6OPQKBgQC5PiCLp0GiU3v680oUjeO4lkUT57Tsmf9V
cC9kdaLKfVd+cuX2sTWxKF82s1uZMIHCXqjfan1g5YRP6vsQPGAPd1tXkOP3Ob3x
jkIM9X6oCgQe+B4HMpMwJkmLCxwxZXgNlAIvxMq4d8jZbOZnf4KtFBBAdei43kNA
+2xgovJtbQKBgEukOL8AilKv/EOyu4P5K0d0n01wwAIc+G00wkcJzLZVLGnCPTkP
k9IlN1SRf8hom0RXOIy0mUEiqtbscoU3KTqyQbvdy3BExmkfooBb89haWSFwaF1B
ZKverQoofsY9NIZyOe2saQIdPpScpfy5mRRsKf+uBllVFfpzHh0oanlVAoGAMoes
7wtXzwTA3AqDWan+xTpQa4aYBrZXPSIV+2xPVLbuJ/MFoc5jHAksN8qjIN1nd/LE
U/VDcCwLdJVfmOUvOujPBMrkNGsO0haBE/Hfc80PpLb/0ezM06SOCRylux+3qNSH
6CnhNoKOSij3jKHurnG7oSnIqq0OYWpz/MRWJt0CgYB0Hk+WEJOmeNzIfQ5nTgdy
3f2i2Ezp6IGed4unYIAVYww8HyDbs1ajz3cSW52zLh9xu16yz6st3n3Aijfggk9V
ToP9ym3ZgB4agTD0A+ibsyj/5VVHzDxoAKdPMB6d+RDEnigLc/U6N+RSkYgk9mjB
f3Q39TySnzTCP1b/NDoQ/Q==
-----END PRIVATE KEY-----

Developer cert:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 2 (0x2)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: O=Test Org, CN=Test Org rauc CA Development
        Validity
            Not Before: Jan  1 00:00:00 1970 GMT
            Not After : Dec 31 23:59:59 9999 GMT
        Subject: O=Test Org, CN=Test Org Development-1
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:95:4b:c7:09:28:fc:b2:8c:39:1e:9d:be:e6:5d:
                    83:12:19:57:ae:8a:c7:ac:59:84:cf:77:cc:15:07:
                    6c:4d:a0:bd:9d:c7:4c:4c:0c:c6:b2:51:2c:5d:66:
                    7a:5f:2c:41:fa:65:95:a8:98:5a:80:da:3a:63:ca:
                    26:5a:e6:74:9a:7f:54:51:57:2d:ac:38:38:30:c7:
                    5a:ac:a7:b0:1b:b3:1c:c1:53:2e:1f:7a:d4:a5:64:
                    a7:01:0e:73:0f:43:8e:4e:3e:41:d5:6a:9a:e4:7a:
                    f3:71:93:61:68:03:6f:89:1a:31:22:71:dd:e0:1a:
                    a6:b1:f8:74:11:80:7b:26:f5:f5:c4:91:fe:3c:bd:
                    26:a2:6b:79:df:76:97:75:a4:4d:a5:22:78:8c:4f:
                    89:80:c5:ec:dc:27:44:b4:3a:bf:41:45:c5:7d:47:
                    99:1b:87:f5:fc:b6:fa:9d:1c:b6:8b:95:42:f1:67:
                    3c:b1:61:bb:0f:29:a6:57:7a:56:27:31:4f:ea:a8:
                    cd:e7:37:4a:ea:0e:01:2c:05:fb:d1:ee:e4:1c:01:
                    f7:7a:f9:2a:77:e2:29:66:15:3a:aa:61:0d:63:b0:
                    97:05:ce:23:98:94:05:11:39:6b:bd:17:0e:fa:92:
                    b1:62:da:6a:b9:76:45:4f:c5:aa:c7:e1:49:fb:cc:
                    88:f9
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                32:AD:1D:64:2E:8F:AA:46:AB:B1:39:7D:D6:AC:0A:A7:CB:B7:88:D5
            X509v3 Authority Key Identifier:
                keyid:AA:66:0F:64:48:5F:3B:36:A2:6E:B1:67:F9:6B:58:CB:42:6C:C3:AF
                DirName:/O=Test Org/CN=Test Org rauc CA Development
                serial:01
            X509v3 Basic Constraints:
                CA:FALSE
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        b1:a2:cc:eb:86:6c:91:98:44:3d:95:43:6b:d6:01:d0:e1:15:
        ea:08:c1:c9:28:93:29:65:24:b7:01:02:eb:74:07:0f:4d:09:
        a8:e3:d5:30:29:18:8d:da:7c:4c:6f:f4:bc:7a:75:8c:c9:1e:
        93:df:d7:7e:ff:c7:10:83:19:6a:dc:eb:5f:ab:ec:f1:23:98:
        9a:e8:d0:a3:2b:c2:20:22:8b:49:56:b4:cc:93:f7:f7:a4:1a:
        53:59:2d:99:48:c2:27:7b:86:96:ff:8c:0a:4a:5f:66:e4:e4:
        69:a5:43:d9:25:c7:17:ef:4f:bc:74:f0:a8:10:01:6c:36:17:
        40:c6:d4:60:8c:aa:47:16:15:1e:f9:b8:66:3c:d6:89:64:a7:
        63:cb:7a:48:fa:72:2a:fd:e7:64:d4:33:5e:81:47:91:10:45:
        40:f5:14:00:dd:d0:7a:48:a9:b4:fe:9e:42:eb:12:85:96:d0:
        13:34:75:24:ca:d5:2b:3e:b0:31:56:b9:78:57:0d:fe:9c:61:
        44:24:f5:0f:61:0c:6a:76:a2:1f:91:74:6a:ec:59:d5:35:e5:
        8f:b5:34:35:1f:9c:77:79:3a:db:95:b6:44:5e:a0:a4:a0:0f:
        03:5f:7c:2b:57:b4:94:8c:58:76:11:95:0d:c0:53:93:ef:5d:
        54:66:ce:97
-----BEGIN CERTIFICATE-----
MIIDfTCCAmWgAwIBAgIBAjANBgkqhkiG9w0BAQsFADA6MREwDwYDVQQKDAhUZXN0
IE9yZzElMCMGA1UEAwwcVGVzdCBPcmcgcmF1YyBDQSBEZXZlbG9wbWVudDAgFw03
MDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowNDERMA8GA1UECgwIVGVzdCBP
cmcxHzAdBgNVBAMMFlRlc3QgT3JnIERldmVsb3BtZW50LTEwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCVS8cJKPyyjDkenb7mXYMSGVeuisesWYTPd8wV
B2xNoL2dx0xMDMayUSxdZnpfLEH6ZZWomFqA2jpjyiZa5nSaf1RRVy2sODgwx1qs
p7AbsxzBUy4fetSlZKcBDnMPQ45OPkHVaprkevNxk2FoA2+JGjEicd3gGqax+HQR
gHsm9fXEkf48vSaia3nfdpd1pE2lIniMT4mAxezcJ0S0Or9BRcV9R5kbh/X8tvqd
HLaLlULxZzyxYbsPKaZXelYnMU/qqM3nN0rqDgEsBfvR7uQcAfd6+Sp34ilmFTqq
YQ1jsJcFziOYlAUROWu9Fw76krFi2mq5dkVPxarH4Un7zIj5AgMBAAGjgZEwgY4w
HQYDVR0OBBYEFDKtHWQuj6pGq7E5fdasCqfLt4jVMGIGA1UdIwRbMFmAFKpmD2RI
Xzs2om6xZ/lrWMtCbMOvoT6kPDA6MREwDwYDVQQKDAhUZXN0IE9yZzElMCMGA1UE
AwwcVGVzdCBPcmcgcmF1YyBDQSBEZXZlbG9wbWVudIIBATAJBgNVHRMEAjAAMA0G
CSqGSIb3DQEBCwUAA4IBAQCxoszrhmyRmEQ9lUNr1gHQ4RXqCMHJKJMpZSS3AQLr
dAcPTQmo49UwKRiN2nxMb/S8enWMyR6T39d+/8cQgxlq3Otfq+zxI5ia6NCjK8Ig
IotJVrTMk/f3pBpTWS2ZSMIne4aW/4wKSl9m5ORppUPZJccX70+8dPCoEAFsNhdA
xtRgjKpHFhUe+bhmPNaJZKdjy3pI+nIq/edk1DNegUeREEVA9RQA3dB6SKm0/p5C
6xKFltATNHUkytUrPrAxVrl4Vw3+nGFEJPUPYQxqdqIfkXRq7FnVNeWPtTQ1H5x3
eTrblbZEXqCkoA8DX3wrV7SUjFh2EZUNwFOT711UZs6X
-----END CERTIFICATE-----

With the developer key and certificate above, the “RAUC bundle” command will now generate a .raubc update package that can be placed on a USB stick or made accessible from a web server.

9. Rootfs + Appfs in one bundle

Currently, RAUC has no way to ensure compatibility between rootfs and appfs when installing a bundle containing only an image for one of them. Either always build bundles containing images for all required slots or ensure that incompatible updates are not installed outside of RAUC. To solve this, a bundle would need to contain the metadata (size and hash) for the missing bundle and RAUC would need to verify the state of those slots before installing the bundle.

Therefore it is not recommended to update only appfs in one bundle. It will not work, since by looking at the way RAUC slots are configured in /etc/rauc/system.conf we can see that rootfs.0 (the A configuration) is parent to appfs.0. RAUC writes the update bundle to the inactive slots, and if updating only the application part, it would also be necessary to verify that the “other” rootfs slot is used for your appfs update to be used.

...
[slot.rootfs.0]
device=/dev/mmcblk1p2
type=ext4
bootname=A

[slot.appfs.0]
device=/dev/mmcblk1p4
type=ext4
parent=rootfs.0
...

The easiest way to ensure this is to always include the rootfs image that your application has been tested with into the bundle, and this is also the approach recommended by RAUC. In this way the update package is ensured to work and RAUC can check each slot before downloading and writing so as to not overwrite identical images (if the latest version of for example rootfs is already installed in the target slot).

10. Slot skipping

In the metadata created and added into the manifest.raucm file when an update bundle is created, RAUC will add size and SHA256 hash for each slot defined in the update. This is used by the adaptive update mechanism to determine if a slot has to be updated or not. If the SHA256 hash for rootfs or appfs in the bundle is identical to the hash of the already installed slots on the target device, then that slot is not written to flash.

11. USB updates

CCLinux 4.0 has a built-in feature to look for a single rauc update bundle on a USB stick. When a USB stick is inserted into a CCpilot display, a script is executed and it will look for *.raucb packages. If only one package is found, RAUC will check the signature of it compared to the installed certificate in ‘/etc/rauc/ca.cert.pem’, and if the bundle passes the verification check, it will then be installed. After a successful installation, the system will beep to indicate that the USB stick should be removed, and then reboot.

The USB update script also has built-in protection to prevent the update from being retriggered after the reboot if the identical update file used for last update is detected on the USB stick during bootup or if inserted again. The /usr/bin/cc-update script logic will save a md5sum of the last update bundle installed using USB to /data and compare this value with the next USB update file. If identical, the update is not performed.

It is also possible to disable the USB update functionality if RAUC updates are handled by the application using RAUC API instead. This can be done by modifying the /etc/cc-update-config.sh file and set:

DO_USB_UPDATE=0

12. OTA updates

RAUC supports updates from locations other than USB, and also a http(s) address. CCLinux itself has no built-in feature to update from a web address, but customers can include this feature into their applications or scripts. The same “rauc install <bundle>” command is used if it is a local path or http(s) location. CCLinux 4.x has support for running fleet management clients like qBee, Hawkbit and other commercial alternatives, but no specific solution is pre-built into the OS image. Please contact CrossControl to discuss these alternatives if needed.

13. Adaptive updates

RAUC does not use binary delta updates. Instead RAUC has developed adaptive updates, a way to optimize the download size of bundles by enabling selective updates without needing a specific prior version. Adaptive updates use existing data on the target from the previous version or incomplete installations to reduce what needs to be downloaded.

This is achieved through block-based adaptive updates with a method called block-hash-index. In this approach, an index file with hashes of each 4kiB data block in the image is created during bundle generation. During installation, RAUC compares each block’s hash in the target slots to those in the bundle, downloading only unmatched blocks.

Adaptive updates work best with HTTP streaming, and is enabled by default on CCLinux 4.x.

14. casync updates

RAUC also supports adaptive updates with “casync,” which uses casync index files instead of full images in its bundles. This approach significantly reduces bundle size, as only the small index files are included. The actual image data is stored as individual chunks in a single repository, which can serve multiple images and versions for different systems. Using casync requires converting bundles and setting up a separate chunk repository on the server side.

Using casync is a two-step process, and first a normal rauc bundle is created. Then as a second step, the ‘rauc convert’ command is used to generate a casync bundle and a chunk store folder.

rauc convert --cert=<certfile> --key=<keyfile> --keyring=<keyring> conventional-bundle.raucb casync-bundle.raucb

The casync bundle is much smaller that the original bundle, but the chunk store has to be accessible on target for the update to be performed, either by path or http. It is possible to add combine chunks from several different update packages into the same chunk store.

15. Explaining the /data partition in CCLinux 4

The /data partition is where a customer application can write to. This can be used for database handling, logging, configuration files and more. But it is also the location for several OS-specific features, and must be handled with care to not corrupt the system.

The /data partition is automatically created on the first boot of CCLinux 4.x. It occupies the remaining free space on the flash drive after the rootfs A/B and appfs A/B partitions are set up. This is the only location where the default user, ccs, has write permissions, and this is the location of the user home directory. Additionally, it’s used by RAUC to store information about filesystem block hash indexes, which are essential for adaptive updates.

To allow for modifications to configuration files in the read-only rootfs, an overlay filesystem is used. The overlay files are located in the /data/cc-etc folder. This means that any changes made to configuration files in the /etc directory will be stored in this overlay.

If your system has Docker enabled, containers, images, and related configuration files will be stored in the /data partition. Keep in mind that Docker can consume a significant amount of flash storage, especially when working with large containers. Therefore, it’s essential to ensure that there’s sufficient free space on /data to accommodate the specific Docker usage.

15.1. /etc overlay

CCLinux 4.x uses a read-only filesystem on the rootfs partition. This means it is not possible to remove, add or modify any of the content in the Linux OS. Most configuration files in Linux are located in the /etc folder, so to be able to customize functionaliy such as IP address, firewall settings, passwords, etc, an OverlayFS is added on top of /etc folder.

The OverlayFS works so that it combines the content of a lower layer and upper layer in the running system. The lower layer is the original /etc folder from CCLinux 4.x, providing the base configuration of CCLinux.

The upper layer contains user modification and any changes made to /etc will be stored in the /data/cc-etc folder. OverlayFS merges these two directories, allowing for the modification of configuration files while preserving the read-only system.

A factory reset command using ccsettingsconsole will remove the overlay and the OS is restored to the original configuration.

By using RAUC hook script files, it is possible to modify the content of /etc folder to do customer specific modifications to the file system. Such modifications can for example be to set a static IP address or replace the CrossControl demo RAUC certificate with a customer specific one.

15.2. /data/rauc

This folder is used by the system to store RAUC related configuration files and the installation log files. For adaptive updates, RAUC creates a block-hash-index of both rootfs and appfs, and stores the hash tables in this folder. This hash index is used by RAUC for OTA updates to determine if a block needs to be downloaded or not.

There is no need to manually modify anything in this folder.

16. Resigning bundles with customer keys

CrossControl will provide update bundles for bootloader and rootfs (and the combined system bundle) signed with the demo key. RAUC allows for a bundle signature to be replaced.

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

It verifies the bundle against the given keyring, strips the old signature and attaches a new one based on the customer key and cert files provided.

For more information, see: https://rauc.readthedocs.io/en/latest/advanced.html?highlight=resign#resigning-bundles

17. Add encryption to bundles

RAUC supports encrypting the bundle. The implementation of the crypt bundle format is based on the verity bundle format (which uses Linux’s dm-verity module). It works by symmetrically encrypting the bundle payload and using Linux’s dm-crypt module to decrypt this on-demand. The symmetric encryption key is contained in the manifest, which itself is (asymmetrically) encrypted to a set of recipients. Like the verity format, the crypt format can also be used with HTTP streaming.

One of the most critical aspects in encryption is the protection of the private key. In contrast to verification, where the private signing key is only used on the build host and can be well protected, for encryption a private decryption key must be stored securely on the target device. Depending on the threat model and the level of security required, it might be sufficient to have the key stored as plain PEM file on the target. This can be of interest if the access to the transport medium (USB stick, public server) is much easier than the access to the device’s storage.

However, for a security-sensitive application, the private key requires better protection. In i.MX8 the CAAM module can be used for secure access of the encryption key using the PKCS#11 API, but in this first release of CCLinux 4, this is not supported yet.

More information: https://pengutronix.de/en/blog/2022-03-31-tutorial-rauc-bundle-encryption-using-meta-rauc.html

18. Extract a bundle

During development it can be useful to extract an existing bundle. A common example might be the official CrossControl system update bundle. This can be extracted by a developer to get the latest rootfs system .ext4 image, to be bundled together with a customer application into customer specific system bundle.

To extract the bundle signed with CrossControl demo key, the demo certificate is needed:

/opt/V700/sysroots/x86_64-cclinuxsdk-linux/usr/bin/rauc extract <bundle name> --keyring=/opt/V700/sysroots/cortexa35-poky-linux/etc/rauc/ca.cert.pem /tmp/extracted-system-bundle

The content of ‘/tmp/extracted-system-bundle’ are the images included in the bundle above and can be added to other bundles if needed.

19. Additional hardening steps of the display

The base configuration of CCLinux 4.x will need additional steps to be more secure for production systems, depending on use-case. Here follows a list of steps that should be considered to be applied during the initial configuration of the device with customer software.

19.1. Replace CrossControl demo key with a customer generated key

The certificate used (/etc/rauc/ca.cert.pem) is generated with the publicly available demo key provided in this manual, and anyone with this infomation can create install packages that can be installed in the default CCLinux 4.x image. Each customer should generate their own keys and replace the sign certificate in /etc/rauc folder on the displays.

Key handling is described in more detail in the RAUC documentation: https://rauc.readthedocs.io/en/latest/advanced.html#security

19.2. Change ccs user password or enable keyless login using openssl instead

SSH server is enabled and it is possible to log in to the display using the standard ‘ccs’ account in CCLinux 4.x. For additional security, changing password for ccs user, or even better, enabling key-based authentication:

Instead of connecting to a computer using plain text passwords, a SSH passwordless login can be used. The principle is that an SSH key-pair is generated with a private and a public key. The public key is not a secret and can be stored readable in the display. The private part is used to for logging in. Only a client that presents the correct private key can connect.

ssh-keygen -t rsa -f v700-login-key  -C "V700-login"

This will create a v700-login-key and a v700-login-key.pub file. To set up passwordless login for user ccs, copy: v700-login-key.pub to /data/home/ccs/.ssh/authorized_keys

Then you can login using the password file instead of providing a password:

ssh -i v700-login-key ccs@192.168.1.23

After SSH keyless login has been enabled, a good idea is to remove the possibility to login using plain passwords. This is disabled from file /etc/ssh/sshd_config. To disable password login change the line:

"#PasswordAuthentication yes" -> "PasswordAuthentication no"

19.3. Disable getty

The getty service in Linux is used for enabling the ‘Login screen’ when the display has booted. This is a security risk if using the default password. An application starting up during boot will by default cover the login screen, but it is still accessible in the background in some cases, by connecting a USB keyboard, or if the application unexpectedly crashes.

Disable getty with the command:

systemctl disable getty@.service

20. Advanced use cases

20.1. Manually change active rootfs partition

In some cases it could be useful to manually change the active booting configuration. To boot to the other configuration, mark the “other” boot slot to active and reboot.

rauc status mark-active [booted | other]
sudo reboot

20.2. Create an update bundle that only execute scripts

It is possible to create an update bundle that does not update any of the partitions. In this case you can only execute pre or post install scripts. This could be useful to do when only doing some configuration settings.

This example will execute a command only. Create a manifest.raubm file containing:

[update]
compatible=CrossControl V700

[hooks]
install=hook.sh

20.3. Unlock /appfs for development/testing

It is possible to unlock /appfs partition during development. This cannot be used on production setups, but while application development is in progress, the possibility to debug and deploy applications on target is useful. By default, the /appfs partition is mounted read-only. To remount it as read-write, use the following command:

sudo mount -o remount,rw /appfs
... do changes ...
sudo mount -o remount,ro /appfs

A factory new unit with CCLinux 4.x has a minimal and empty /appfs partition. To add files to the unit, either create an update bundle as described above, or during initial development it can also be an option to overwrite the minimal image with a larger image that fills the partition. These steps will remove the original appfs image and create a new that can be used for development:

First check the boot status to see if the mounted /appfs is using /dev/mmcblk1p4 or /dev/mmcblk1p5

rauc status

Then unmount

sudo umount /appfs

It is now possible to re-create the appfs image to a larger version. This command will for example create an 800MB image, big enough to fit Qt runtime and application data:

sudo dd if=/dev/zero of=/dev/mmcblk1p4 bs=100M count=8

The new image has to be of format ‘ext4’:

sudo mkfs.ext4 /dev/mmcblk1p4

The new image written can now be mounted again as a new /appfs

sudo mount /dev/mmcblk1p4 /appfs

21. Using RAUC D-Bus API

A Qt based example application for handling USB or OTA updates is available on request.