Recently, our customer Senic asked us to integrate an Over-The-Air (OTA) mechanism in their embedded Linux system, and after some discussion, they ended up chosing Mender. This article will detail an example of Mender’s integration and how to use it.
What is Mender?
Mender is an open source remote updater for embedded devices. It is composed of a client installed on the embedded device, and a management server installed on a remote server. However, the server is not mandatory as Mender can be used standalone, with updates triggered directly on the embedded device.

In order to offer a fallback in case of failure, Mender uses the double partition layout: the device will have at least 2 rootfs partitions, one active and one inactive. Mender will deploy an update on the inactive partition, so that in case of an error during the update process, it will still have the active partition intact. If the update succeeds, it will switch to the updated partition: the active partition becomes inactive and the inactive one becomes the new active. As the kernel and the device tree are stored in the /boot folder of the root filesystem, it is possible to easily update an entire system. Note that Mender needs at least 4 partitions:
- bootloader partition
- data persistent partition
- rootfs + kernel active partition
- rootfs + kernel inactive partition
It is, of course, customizable if you need more partitions.
Two reference devices are supported: the BeagleBone Black and a virtual device. In our case, the board was a Nanopi-Neo, which is based on an Allwinner H3.
Mender provides a Yocto Project layer containing all the necessary classes and recipes to make it work. The most important thing to know is that it will produce an image ready to be written to an SD card to flash empty boards. It will also produce “artifacts” (files with .mender extension) that will be used to update an existing system.
Installation and setup
In this section, we will see how to setup the Mender client and server for your project. Most of the instructions are taken from the Mender documentation that we found well detailed and really pleasant to read. We’ll simply summarize the most important steps.
Server side
The Mender server will allow you to remotely update devices. The server can be installed in two modes:
- demo mode: Used to test a demo server. It can be nice to test it if you just want to quickly deploy a Mender solution, for testing purpose only. It includes a demo layer that simplify and configure for you a default Mender server on localhost of your workstation.
- production mode: Used for production. We will focus on this mode as we wanted to use Mender in a production context. This mode allows to customize the server configuration: IP address, certificates, etc. Because of that, some configuration will be necessary (which is not the case in the demo mode).
In order to install the Mender server, you should first install Docker CE and Docker Compose. Have a look at the corresponding Docker instructions.
Setup
- Download the
integrationrepository from Mender:
$ git clone https://github.com/mendersoftware/integration mender-server
$ cd mender-server $ git checkout 1.1.0 -b my-production-setup
$ cp -a template production $ cd production $ sed -i -e 's#/template/#/production/#g' prod.yml
$ ./run pull
$ CERT_API_CN=mender.foobar.com CERT_STORAGE_CN=s3.foobar.com ../keygen
$ docker volume create --name=mender-artifacts $ docker volume create --name=mender-deployments-db $ docker volume create --name=mender-useradm-db $ docker volume create --name=mender-inventory-db $ docker volume create --name=mender-deviceadm-db $ docker volume create --name=mender-deviceauth-db
Final configuration
This final configuration will link the generated keys with the Mender server. All the modifications will be in the prod.yml file.
- Locate the storage-proxy service in
prod.ymland set it to your domain name. In our cases3.foobar.comunder thenetworks.mender.aliases - Locate the minio service. Set
MINIO_ACCESS_KEYto“mender-deployments”and theMINIO_SECRET_KEYto a generated password (with e.g.:$ apg -n1 -a0 -m32) - Locate the mender-deployments service. Set
DEPLOYMENTS_AWS_AUTH_KEYandDEPLOYMENTS_AWS_AUTH_SECRETto respectively the value ofMINIO_ACCESS_KEYandMINIO_SECRET_KEY. SetDEPLOYMENTS_AWS_URIto point to your domain such ashttps://s3.foobar.com:9000
Start the server
Make sure that the domain names you have defined (mender.foobar.com and s3.foobar.com) are accessible, potentially by adding them to /etc/hosts if you’re just testing.
- Start the server
$ ./run up -d
$ curl -X POST -D - --cacert keys-generated/certs/api-gateway/cert.crt https://mender.foobar.com:443/api/management/v1/useradm/auth/login
$ firefox http://mender.foobar.com:443
Client side – Yocto Project
Mender has a Yocto Project layer to easily interface with your own layer.
We will see how to customize your layer and image components (U-Boot, Linux kernel) to correctly configure it for Mender use.
In this section, we will assume that you have your own U-Boot and your own kernel repositories (and thus, recipes) and that you retrieved the correct branch of this layer.
Machine and distro configurations
- Make sure that the kernel image and Device Tree files are installed in the root filesystem image
RDEPENDS_kernel-base += "kernel-image kernel-devicetree"
mender-full class and add systemd as the init manager (we only tested Mender’s integration with systemd)# Enable systemd for Mender DISTRO_FEATURES_append = " systemd" VIRTUAL-RUNTIME_init_manager = "systemd" DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit" VIRTUAL-RUNTIME_initscripts = "" INHERIT += "mender-full"
/dev/mmcblk0, that mmcblk0p1 is your boot partition (containing the bootloader), that mmcblk0p2 and mmcblk0p3 are your two root filesystem partitions, and that mmcblk0p5 is your data partition. If that’s the case for you, then everything is fine! However, if you need a different layout, you need to update your machine configuration. Mender’s client will retrieve which storage device to use by using the MENDER_STORAGE_DEVICE variable (which defaults to mmcblk0). The partitions themselves should be specified using MENDER_BOOT_PART, MENDER_ROOTFS_PART_A, MENDER_ROOTFS_PART_B and ROOTFS_DATA_PART. If you need to change the default storage or the partitions’ layout, edit in your machine configuration the different variables according to your need. Here is an example for /dev/sda:
MENDER_STORAGE_DEVICE = "/dev/sda"
MENDER_STORAGE_DEVICE_BASE = "${MENDER_STORAGE_DEVICE}"
MENDER_BOOT_PART = "${MENDER_STORAGE_DEVICE_BASE}1"
MENDER_ROOTFS_PART_A = "${MENDER_STORAGE_DEVICE_BASE}2"
MENDER_ROOTFS_PART_B = "${MENDER_STORAGE_DEVICE_BASE}3"
MENDER_DATA_PART = "${MENDER_STORAGE_DEVICE_BASE}5"
local.conf, for example:
MENDER_ARTIFACT_NAME = "release-1"
As described in Mender’s documentation, Mender will store the artifact name in its artifact image. It must be unique which is what we expect because an artifact will represent a release tag or a delivery. Note that if you forgot to update it and upload an artifact with the same name as an existing in the web UI, it will not be taken into account.
U-Boot configuration tuning
Some modifications in U-Boot are necessary to be able to perform the rollback (use a different partition after an unsuccessful update)
- Mender needs BOOTCOUNT support in U-Boot. It creates a
bootcountvariable that will be incremented each time a reboot appears (or reset to 1 after a power-on reset). Mender will use this variable in its rollback mechanism.
Make sure to enable it in your U-Boot configuration. This will most likely require a patch to your board.hconfiguration file, enabling:
#define CONFIG_BOOTCOUNT_LIMIT #define CONFIG_BOOTCOUNT_ENV
# Mender integration
require recipes-bsp/u-boot/u-boot-mender.inc
PROVIDES += "u-boot"
RPROVIDES_${PN} += "u-boot"
BOOTENV_SIZE = "0x20000"
The BOOTENV_SIZE must be set the same content as the U-Boot CONFIG_ENV_SIZE variable. It will be used by the u-boot-fw-utils tool to retrieve the U-Boot environment variables.
Mender is using u-boot-fw-utils so make sure that you have a recipe for it and that Mender include’s file is included. To do that, you can create a bbappend file on the default recipe or create your own recipe if you need a specific version. Have a look at Mender’s documentation example.
root= kernel argument to use ${mender_kernel_root}, set the bootcmd to load the kernel image and Device Tree from ${mender_uboot_root} and to run mender_setup. Make sure that you are loading the Linux kernel image and Device Tree file from the root filesystem /boot directory.
setenv bootargs 'console=${console} root=${mender_kernel_root} rootwait'
setenv mmcboot 'load ${mender_uboot_root} ${fdt_addr_r} boot/my-device-tree.dtb; load ${mender_uboot_root} ${kernel_addr_r} boot/zImage; bootz ${kernel_addr_r} - ${fdt_addr_r}'
setenv bootcmd 'run mender_setup; run mmcboot'
Mender’s client recipe
As stated in the introduction, Mender has a client, in the form of a userspace application, that will be used on the target. Mender’s layer has a Yocto recipe for it but it does not have our server certificates. To establish a connection between the client and the server, the certificates have to be installed in the image. For that, a bbappend recipe will be created. It will also allow to perform additional Mender configuration, such as defining the server URL.
- Create a
bbappendfor the Mender recipe
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI_append = " file://server.crt"
MENDER_SERVER_URL = "https://mender.senic.com"
bbappend recipe folderRecompile an image and now, we should have everything we need to be able to update an image. Do not hesitate to run the integration checklist, it is really a convenient way to know if everything is correctly configured (or not).
If you want to be more robust and secure, you can sign your artifacts to be sure that they come from a trusted source. If you want this feature, have a look at this documentation.
Usage
Standalone mode
To update an artifact using the standalone mode (i.e. without server), here are the commands to use. You will need to update them according to your needs.
- On your work station, create a simple HTTP server in your Yocto
deployfolder:
$ python -m SimpleHTTPServer
mender in standalone mode$ mender -log-level info -rootfs http://192.168.42.251:8000/foobar.mender
You can also use the mender command to start an update from a local .mender file, provided by a USB key or SD card.
$ reboot
After the first reboot, you will be on the the new active partition (if the previous one was /dev/mmcblk0p2, you should be on /dev/mmcblk0p3). Check the kernel version, artifact name or command line:
$ uname -a $ cat /etc/mender/artifact_info $ cat /proc/cmdline
If you are okay with this update, you will have to commit the modification otherwise the update will not be persistent and once you will reboot the board, Mender will rollback to the previous partition:
$ mender -commit
Using Mender’s server UI
The Mender server UI provides a management interface to deploy updates on all your devices. It knows about all your devices, their current software version, and you can plan deployments on all or a subset of your devices. Here are the basic steps to trigger a deployment:
- Login (or create an account) into the mender server UI: https://mender.foobar.com:443
- Power-up your device
- The first time, you will have to authorize the device. You will find it in your “
dashboard” or in the “devices” section. - After authorizing it, it will retrieve device information such as current software version, MAC address, network interface, and so on
- To update a partition, you will have to create a deployment using an artifact.
- Upload the new artifact in the server UI using the
“Artifacts”section - Deploy the new artifact using the
“deployment”or the“devices”section. You will retrieve the status of the deployment in the“status”field. It will be in “installing”, “rebooting”, etc. The board will reboot and the partition should be updated.
Troubleshooting
Here are some issues we faced when we integrated Mender for our device. The Mender documentation also has a troubleshooting section so have a look at it if you are facing issues. Otherwise, the community seems to be active even if we did not need to interact with it as it worked like a charm when we tried it.
Update systemd’s service starting
By default, the Mender systemd service will start after the service “resolved” the domain name. On our target device, the network was available only via WiFi. We had to wait for the wlan0 interface to be up and configured to automatically connect a network before starting Mender’s service. Otherwise, it leads to an error due to the network being unreachable. To solve this issue which is specific to our platform, we set the systemd dependencies to “network-online.target” to be sure that a network is available:
-After=systemd-resolved.service +After=network-online.target +Wants=network-online.target
It now matches our use case because the Mender service will start only if the wlan0 connection is available and working.
Certificate expired
The certificates generated and used by Mender have a validity period. In case your board does not have a RTC set, Mender can fail with the error:
systemctl status mender [...] ... level=error msg="authorize failed: transient error: authorization request failed: failed to execute authorization request: Post https:///api/devices/v1/authentication/auth_requests: x509: certificate has expired or is not yet valid" module=state
To solve this issue, update the date on your board and make sure your RTC is correctly set.
Device deletion
While testing Mender’s server (version 1.0), we always used the same board and got into the issue that the board was already registered in the Server UI but had a different Device ID (which is used by Mender to identify devices). Because of that, the server was always rejecting the authentication. The next release of the Mender server offers the possibility to remove a device so we updated the Mender’s server to the last version.
Deployments not taken into account
Note that the Mender’s client is checking by default every 30 minutes if a deployment is available for this device. During testing, you may want to reduce this period, which you can in the Mender’s configuration file using its UpdatePollIntervalSeconds variable.
Conclusion
Mender is an OTA updater for Embedded devices. It has a great documentation in the form of tutorials which makes the integration easy. While testing it, the only issues we got were related to our custom platform or were already indicated in the documentation. Deploying it on a board was not difficult, only some U-Boot/kernel and Yocto Project modifications were necessary. All in all, Mender worked perfectly fine for our project!

Alexey Brodkin, an active contributor to the uClibc library, shared recent updates about this C library, trying to show people that the project was still active and making progress, after a few years during which it appeared to be stalled. Alexey works for Synopsys, the makers of the ARC architecture, which uClibc supports.
An SoC is made of multiple IP blocks from different vendors. In some cases the source or model of the hardware blocks are neither documented nor marketed by the SoC vendor. However, since there are only very few vendors of a given IP block, stakes are high that your SoC vendor’s undocumented IP block is compatible with a known one.
Maybe I should be ashamed of saying that but
Although Wolfram had a lot of troubles starting its presentation lacking a proper HDMI adaptater, he gave an illuminating talk about how, as an I2C subsystem maintainer, he would like to strengthen the robustness of I2C drivers.
Having worked recently on a number of display related drivers, it was quite natural to go see what I was probably going to work on in a quite close future.
Johan started his talk at ELCE by exposing the problem with how serial ports (UARTs) are currently handled in the Linux kernel. Serial ports are handled by the TTY layer, which allows user-space applications to send and receive data with what is connected on the other side of the UART. However, the kernel doesn’t provide a good mechanism to model the device that is connected at the other side of the UART, such as a Bluetooth chip. Due to this, people have resorted to either writing user-space drivers for such devices (which falls short when those devices need additional resources such as regulators, GPIOs, etc.) or to developing specific TTY line-discipline in the kernel. The latter also doesn’t work very well because a line discipline needs to be explicitly attached to a UART to operate, which requires a user-space program such as hciattach used in Bluetooth applications.
The purpose of this talk was to show how to shrink 

Linux 4.13 was 
