The Internet of Things (IoT) has quickly led to the deployment of ubiquitous, unattended devices throughout our homes, offices, factories and public spaces. In this continuously expanding connected world of devices and IoT, the need to update/upgrade your product’s software/firmware is a certainty. There is no single software update approach that fits all, but there are key questions you should consider when designing your approach. They are: Why, When, What and How.
Drivers for a Software Upgrade
The following are a some key reasons for implementing a software update:
- Fixing critical bugs
- Patching security vulnerabilities
- Adding new features
- Improving performance
Stages of Software Upgrade
The following are the stages when a software update is typically applied:
- QA / Code Freeze
- Release / Production
- In-field Deployment
Types of Software Upgrade
The magnitude of software update (complete, component or single package/application) depends upon the product lifecycle stage. For example:
- During the development stage, all software including development tools can possibly be updated.
- Whereas, in the field deployment stage (having very stringent operating requirements), only software with critical bug fixes, critical security patches, and critical performance enhancements are updated.
Method Adoption Criteria
How software is updated depends upon:
- The software system architecture,
- Service interruption tolerance,
- The kind of update being performed and
- Access to the device/target — e.g. direct access to device via physical medium or over-the-air update (FOTA).
Software Upgrade Basics
A typical embedded Linux system consists of bootloaders, kernel, root filesystem, application, and user data. On one end of the update spectrum is a complete software update — a single image containing bootloader, kernel, RFS and application (Figure 1). On the other end of the spectrum is an individual component (kernel, application, a library within RFS, etc.) update. But in all cases, the user data must be preserved.
Figure 1: Complete software update
A good software system architecture builds a fallback mechanism in case of an update failure. For example, a typical software system has two non-volatile storage partitions for storing software images — one active and the other one is for update. In this case, the update partition is updated, verified and then the system is rebooted to use the new software. In case of a failure, the system reboots using the previous working active partition.
Figure 2: A good software system architecture
For an individual component upgrade/installation, a good software architecture should perform the authentication of the User privileges first.
Software Upgrade Process
In general, the software update philosophy in the early stage of a product life cycle is quite liberal (update everything), and it becomes more conservative for deployed systems, with updates only performed for critical issues. A software upgrade is usually done “as per business needs,” such as upgrading the software to add revenue-generating features, for example.
In a majority of cases, the bootloader is not updated in the field to prevent making the system inoperable if the update fails. Some systems require two stage bootloaders — first stage and second stage (e.g. U-Boot). In this case, the first stage boot loader is never updated in the field. Figure 3 is an illustration of the update process.
Figure 3: Firmware update process
The choice between a complete image update or a component update is a business decision, but this choice has implications on the selection of build technologies and the design of the system architecture.
The complete image update has the advantage that the complete software is well tested as a whole and the update is atomic. The disadvantage is doubling the non-volatile storage size. The complete software update introduces the risk that the new version (or patch) will contain a bug, causing the program to malfunction in some way or not to function at all. This makes regression testing a gating factor and sometimes prevents a quick fix for a critical security vulnerability. This risk could be minimized by keeping the changes to minimum unless new features are being introduced in the update. In the case of a power failure during the update, it might leave the system unbootable and would need a recovery mechanism such as dual partition.
An individual software component update can be done using a package manager. A big advantage of this approach is that updates can be done without rebooting the system, however, in case of a power failure during the update, it might leave the system unbootable and would need a recovery mechanism. A package manager approach also makes regression testing challenging because testers would need to test all possible combinations of software. For example, if package A is being patched but package A has a dependency on Package B which the customer decided not to previously update, it can lead to further issues and the effect can compound if Package C needs an older version of Package B. Furthermore, the package manager approach also makes software maintenance tracking (which device is using what version of software) a challenge because the software itself is not atomic anymore.
Software Upgrade Design
A commonly used design approach is to create separate partitions for different kinds of software. For example, a separate partition for OS and Open Source libraries, a partition for 3rd party and proprietary software and another partition for the user application software. This approach allows user application updates without touching the OS and filesystem.
Another related design consideration to the software update process is security. In case of remote updates, often times it’s very important to secure the update process itself. This involves paying attention not only to what additional features need to be added to the target Linux system to support it but also spending enough effort on designing and building the host side for update deployment. Update process shouldn’t affect the User-Data. Hosts, which are used to deploy firmware to field devices, must provide local security. They need to also secure the communication with each remote target they connect to. This is sometimes an overlooked requirement when designing a remote target update system and could be critical to security standards compliance.
There is no single approach to software update; however, there are core requirements such as dual images with fall back, securely preserving the user data, and ensuring that the system cannot be bricked even if the power fails during the update. The single image update vs. component update vs. multiple image updates has implications of the system architecture, build technologies selection, development and deployment processes, and support.
Timesys has extensive experience with embedded system development and lifecycle management. Timesys has been instrumental in working with global leader semiconductor manufacturers with smart, quick and quality solutions for highly complex systems with accelerated product innovation and multiple product variants.