Software is steadily increasing its complexity and this raises the size of a whole Update. SWUpdate allows incremental updates based on filesystem, and single file updates are possible. A good update concept will still allow lightweight updates without losing on reliability, but more care must be taken to handle all use cases. A well known way for reliable updates is to replace the whole filesystem as a single binary, but of course the size can be in term of several hundreds of megabytes or even gigabytes.

But what about to update just the part of the giant blob that was changed between two updates ? This is more complex than replacing a single file, but it guarantees the maximum reliability and the installed software will be exactly the same as the one built on your host. This is more important in case you sign the software, and in all case secure boot is required on your device.

The “Delta Handler” in SWUpdate addresses these topics. Thanks to the “rolling hash” theory, SWUpdate is able to compute on the device itself which part of the binary blobs are different and to download only the changed parts, strongly reducing the size of the downloaded data. And this maintaining all features present in SWUpdate. Do not trust to fairy tale: not any frog will turn into a prince !

And of course: still everything Open Source !

Features:

 

The Civil Infrastructure Platform (CIP)’s Software Update Working Group, has announced the immediate availability of the CIP SWUpdate Lua Round Robin Handler:

https://gitlab.com/cip-project/cip-sw-updates/swupdate-handler-roundrobin

It is meant to augment SWUpdate’s core features ― such as the recent getroot() addition ― in order to provide a generic run-time dynamic target selection handler, chain-calling other SWUpdate handlers for the heavy lifting works. In its simplest form, such can be a round robin target selection in an A/B deployment scenario, i.e., when currently running on system A, flash system B and vice versa. As with SWUpdate, contributions are more than welcome! So, be invited to poke around and take a look at https://www.cip-project.org/about


 

A new exciting SWUpdate was released ! A short changelog from previous release:

SWUpdate can be used to restore complete a device if it gets broken or it helps in the factory to install for the first time the software on a new branded device. The diskpart handler can set up partitions (for NAND flash the ubipartition) handler is used. This feature is often used together with a rescue system, that can restore even in field a broken device by initializing the device. Up now, SWUpdate was able to partition disks but it required external tools (like mkfs) to initialize a filesystem. However, an update agent like SWUpdate must be as much as possible self contained. This increase both reliability and security.

In fact, a common goal for an attacker is to replace some system tools and the shell with an own implementation to get control of the attacked device. Any call to “system” or the execution of an external tool could become potentially a security leak. SWUpdate does not call “system” with the exception of shell scripts, and it is also strongly encouraged to replace shell scripts with Lua, as Lua is called in the process context of the updater without spawning new processes.

Going on in the direction to provide a very flexible updater without reducing security, SWUpdate has now support to initialize without external tools the partitions it creates. An open source library is added to SWUpdate to support VFAT filesystem, while support to initialize a Linux ext (ext2 / ext3 or more common ext4) is implemented by porting part of the mkfs tool into SWUpdate sources and linking to the standard libextfs libraries. You can easy set in sw-description which partitions should be formatted by setting the new property fstype as done in the following example:

partitions: (
{

type = “diskpart”;
device = “/dev/sde”;
properties: {
labeltype = “gpt”;
partition-1 = [ “size=64M”, “start=2048”, “name=bigrootfs”, “type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B”];
partition-2 = [“size=256M”, “start=133120”, “name=ldata”, “type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7”, “fstype=vfat“];
partition-3 = [“size=512M”, “start=657408″,”name=log”, “fstype =ext4“, 63DAF-8483-4772-8E79-3D69D8477DE4”];
partition-4 = [“size=4G”, “start=1705984″,”name=system”, “type=0FC63DAF-8483-4772-8E79-3D69D8477DE4”];
partition-5 = [“size=512M”, “start=10094592″,”name=part5”, “type=0FC63DAF-8483-4772-8E79-3D69D8477DE4”];
}

The file sw-description is the central place to configure a release and to provide how a new sofware must be installed. Apart very simple cases, an update consists oft of several parts, some of them  are not always active, and a release can be installed on devices with different hardware revisions. This leads to have several sections inside sw-description. It is possible to factorize some parts of them using SWUpdate’s links. A link is a reference for one of the major sections (images, files, partitions, scripts and bootenv) and the whole section can be referenced by a link.  Let’s start having a device in field, but several hardware revisions are now running and the software is not exactly the same for all of them. For example, older hardware revisions are not supported by newer Linux kernels, or new application’s features are just added to later releases due to hardware limitations. SWUpdate has always supported this case, and sw-description is omething like the following:

    software =
     {
             version = "0.1.0";

             myboard = {
                 stable = {

                     hardware-compatibility: ["1.0", "1.2", "2.0", "3.0", "3.1"];
                     rev-1.0: {
                             images: (
                                     ...
                             );
                             scripts: (
                                     ...
                             );
                     }
                     rev-1.2: {
                             hardware-compatibility: ["1.2"];
                             images: (
                                     ...
                             );
                             scripts: (
                                     ...
                             );
                     }
                     rev-2.0: {
                             hardware-compatibility: ["2.0"];
                             images: (
                                     ...
                             );
                             scripts: (
                                ...
                             );
                     }

The device should recognize which hardware revision is running, and SWUpdate is started via “selection” to parse just the relevant part of the file. A lot of entries must be duplicated, for example if most releases share the same kernel or rootfs. Using links, the example above can be written as:

     software =
     {
             version = "0.1.0";

             myboard = {
                 stable = {

                     hardware-compatibility: ["1.0", "1.2", "2.0", "1.3, "3.0", "3.1"];
                     rev-1x: {
                             images: (
                                ...
                             );
                             scripts: (
                                 ...
                             );
                     }
                     rev1.0 = {
                             ref = "#./rev-1x";
                     }
                     rev1.2 = {
                             ref = "#./rev-1x";
                     }
                     rev1.3 = {
                             ref = "#./rev-1x";
                     }
                     rev-2x: {
                             images: (
                                  ...
                             );
                             scripts: (
                                  ...
                             );
                     }
                     rev2.0 = {
                             ref = "#./rev-2x";
                     }

This factorizes big blocks, that is some blocks are common between the revisions.

Links has the following syntax:

 

Anyway, it was not possible until now to split one of the sections to share a common block and some specific extensions. For example, if the application consists of more entries (image and files), but depending on hardware revision or on the mode the device is started there are some entries that differ.

 

somecommon: {
      images: (
              {
                  .............
              },
              {
                  .......
              }
      )
}
somespecific: {
      images: (
              {
                  .............
              },
              {
                  .......
              }
      )

}      
selection : {
       images: (
                {
                    ref = "#./../../somecommon/images";
                },
                {
                    ref = "#./../../somespecific/images";
                },
                {
                    filename = "somefilename";
                    device = "/dev/somedevice";
                    type = "raw";
                }
            )

Links are now available in whole sw-description and this simplify the readability and maintainability. This feature is now commited.

Proud to announce a new release for SWUpdate with exciting new features !

Siemens exposed how to combine secure boot and SWUpdate in this interesting talk (https://static.sched.com/hosted_files/ossna2020/17/Secure-OTA-Updates_elc-na-2020.pdf).

Self-driving Chevrolet Bolt by Cruise Automation undergoing testing in San Francisco. The vehicle is equipped with numerous Velodyne LiDAR sensors – San Francisco, CA, USA – 2020

Check talk at ELC 2020 how SWUpdate was used by Cruise for self driving cars in San Francisco (https://static.sched.com/hosted_files/ossna2020/56/No_Store_for_AV_Parts_ELC_NA_2020.pdf).

SWUpdate is chosen by CIP Project as Updater Agent – check on https://wiki.linuxfoundation.org/civilinfrastructureplatform/cip_comparison_report for more information.