When you work with embedded systems long enough, sooner or later you realize that some sort of update mechanism is required. This is especially true when more complex systems, running with an operating system, are taken into account. Nowadays Linux is being picked increasingly as operating system for embedded IoT devices. In following post we will focus on those in particular.
In fact, from my experience update mechanism is vital part of many embedded applications. When project is aimed to be maintained in a long run, it is one of the first features being developed.
Update IoT device vs update on desktop
On standard Linux machines updates are generally performed using one of the package managers. This approach may seem tempting, but for embedded devices it usually leads to more issues than it has advantages. When number of possible packages reaches hundreds or thousands, it becomes impossible to test application stability with various revisions of those packages. Approach where we release one thoroughly tested rootfs image is both more reliable and less time consuming in a long term.
Our vision of update system
In most of our project where software is concerned, we are heading towards double copy approach. The main idea is to have two separate rootfs partitions, which always leaves us with at least one copy of correct software. Core of developed update systems is usually similar to the one presented on the graph below.
What is SWUpdate?
SWUpdate is application designed for updating embedded Linux devices. It is strongly focused on reliability of each update. Every update should be consistent and atomic. Major goal is to make it completely power-cut safe. Power-off in any phase of an update should not brick the device and we always should end up having fully-functional system.
Purpose of this post
My goal is not to rewrite SWUpdate documentation here. Instead, I plan to
point out it’s interesting features and present the way how it is being used in
3mdeb
. This is why I will often leave a link to related chapter in
SWUpdate documentation for more information.
In the end I will give short example of implementation of such update system
used in 3mdeb
.
SWUpdate example features
SWU image
*.swu
image is a cpio
container which contains all files needed during
update process (images, scripts, single files and so on). In addition it
requires sw-description file to be present. This file describes .swu
image
content and allows to plan various update scenarios through setting appropriate
flags in each section.
Software collections
SWUpdate
supports dual image approach by providing software collections in
sw-description
file. Such simple collection inside can be written as:
|
|
As you can see below, there are two software modes to choose from:
stable,mmcblk0p2
will install rootfs image into/dev/mmcblk0p2
partitionstable,mmcblk0p3
will install rootfs image into/dev/mmcblk0p3
partition
Selection of given mode is made by using -e
command line switch, e.g.:
|
|
In double copy approach we are using software collections mainly to point to target partition on which update will be performed. File (image) name is usually the same in both.
Hardware compatibility
It can be used to exclude the risk of installing software on the wrong platform.
sw-descrption
should contain list of compatible hardware revisions:
|
|
Hardware revision is saved in file (by default /etc/hwrevision
) using
following format:
|
|
When I last checked this, only board_revision
string was taken into account
when it came to checking for image compatibility. So in these terms, boards:
board1 revA
and board2 revA
would be compatible.
The first string (board_name
) was only used for board specific settings.
As for hwrevision
file - when using Yocto, I usually ship it through
swupdate
bbappend file - specific for each target machine.
Image downloading
Basic usage of SWUpdate
involves executing it from command line, passing
several arguments. In this scenario image can either be downloaded from given
URL, or obtained from local file shipped on USB stick for example. For obvious
reason in case of multiple IoT devices we are rather interested in downloading
images.
Download support is provided by curl library. In current SWUpdate
implementation it supports fetching from http(s)
or ftp
. However curl
supports many other protocols. In fact, at the moment we are using SWUpdate with
fetching from sftp
server with no source code modification. In this case,
private key (id_dsa
) must be located in $HOME/.ssh
path as explained in curl
documentation regarding CURLOPT_SSH_PUBLIC_KEYFILE. This behavior could be
documented in SWUpdate documentation or even another command line parameter
added for key location. This could be in scope of further contribution into the
project.
To download image from given URL, following command line parameters should be passed:
|
|
Note that there’s been syntax change a while ago. In previous releases (for example in the one present in Yocto krogoth release, which is still in use) it was just:
swupdate -d http://example.com/mysoftware.swu
Compressed images
One of the concerns while using whole rootfs image update approach may be the
size of single update image. SWUpdate offers handling of gzip compressed
images as well. From my experience, size of such compressed images is not grater
than 50 - 100 MB, depending on complexity of given application. With today’s
network speed is not that much as long as there is no serious connection
restrictions. When delivering compressed image, copressed
flag must be set in
corresponding sw-description
section. It may look like below:
|
|
I always use this feature, as it drastically decreases update image size. Thing
to remember is that you need to compress rootfs image itself (not whole SWU
image). Also it requires gz
compression, so use gzip application.
Streaming images
SWUpdate offers streaming feature that allows to stream downloaded image
directly onto second partition, without temporary copy in /tmp
. This might be
especially desired when RAM amount is not enough to store whole rootfs image.
This can be enabled by setting installed-directly
flag in given image
section. In this case it would look like this:
|
|
By default, temporary copy is done by SWUpdate
to check for image correctness.
I feel that with dual copy approach it is not really necessary as if anything
goes wrong we are always left with working software and ready to perform update
again. This is why we tend to use this feature pretty often.
GRUB support
When developing application for embedded system there can be a problem with not
enough of hardware platforms for testing. Testing on host can also be faster and
more efficient. When using Virtualbox, even update system could be tested. The
issue was that, it usually uses GRUB as a bootloader and SWUpdate
was
supporting U-Boot
only. With little effort we managed to add basic support for
GRUB environment update in SWUpdate
project and this feature
has been recently upstreamed.
Complete example
I will try to present an example setup that allows to experience mentioned
SWUpdate
features. It can be a base (and usually it is in case for our
projects) for actual update system.
Below example fits for any embedded device running Linux with U-Boot as bootloader. In my case Hummingboard from Solidrun was used.
Rootfs image
Of course you need a rootfs image to perform update with it. It can be prepared
in may ways. For test purpose, you can even perform dd
command to obtain raw
image from SD card. An example command would be:
|
|
However, preferred method would be to use Yocto build system. Along with
meta-swupdate it allows for automated building of rootfs image, as well as
.swu
container image in one run. In this case, krogoth
revision of Yocto
was used.
U-Boot boot script
In dual image approach goal is to pass information to bootloader after update
has finished successfully. In case of U-Boot
we can tell which partition to
use as rootfs when booting. With below script we will boot into newly updated
software once.
|
|
When booted into newly updated partition, some sort of sanity checks can be
made. If passed, new software is marked as default by setting fback
environment variable to point to this partition. We can modify bootloader
environment using SWU image with just sw-description
file. Below is an example
of such:
|
|
Prepare sw-description file
Below is an example sw-description
file including features mentioned above:
|
|
Creation of SWU image
Yocto based
- Follow with setup from building with Yocto section
- Create recipe for SWU image, e.g.
recipes-extended/images/test-swu-image.bb
. It could be based on bbb-swu-image recipe frommeta-swupdate
repository.sw-desciption
file should end up inimages/test-swu-image
directory. If another files (such as scripts) should as well be part of compound SWU image, they should also go there. Assuming thathummingboard
is our machine name in Yocto, such recipe could look like below:
|
|
- SWU image can be build with following command:
|
|
It can be found in standard directory for built images:
tmp/deploy/images/${MACHINE}
.
Manual
Refer to building a single image section from SWUpdate documentation.
Perform update
Assuming SWU image is already uploaded and current partition is
/dev/mmcblk0p2
:
|
|
Conclusion
I have only shortly described features that we commonly use. These are of course not all that are available. You can find out more in the list of supported features. Definitely worth to mention would be:
- suricatta daemon mode with HawkBit backend
- update from verified source
- encrypted images
- checking software version
SWUpdate
provides really powerful and reliable update mechanism. It’s job is
only to download and reliably perform update according to metadata written into
sw-description
file. The rest such as picking right software from collection,
getting current and available partitions, preparing bootloader scripts etc. is
up to user. It may be overwhelming at first, but it is the reason why SWUpdate
can be so flexible. You can pick features from (still growing) list to design
update system that is perfect for your needs. SWUpdate
will only assure that
it is safe and reliable.
Summary
We hope that content of this blog post was entertaining and useful for you. If
you have any comments or questions do not bother to drop us a note below. If you
feel this blog post contains something useful please share with the others. As
3mdeb we are always ready to give you professional support. Just let us know by
sending an email to contact@3mdeb.com
.