SWUpdate Customization
Introduction
This guide demonstrates how to customize SWUpdate configuration and behavior within a Yocto-based Linux system. You'll learn how to modify update content, adjust features, configure hardware compatibility, and fine-tune hawkBit server integration to meet your specific deployment requirements.
Prerequisites
- Yocto Version: Yocto 5.2 (Walnascar) or later
- Yocto Build Environment: Ensure your development system is configured to build Yocto projects. Refer to:
- Hardware: Target board with sufficient storage (eMMC or SD card)
- Network: Ethernet or WiFi connectivity for OTA updates
- Base SWUpdate Setup: Complete the basic setup before customization
Set Up Environment
Before customizing SWUpdate, complete Steps 1-3 from Building SWUpdate Inside RootFS From Yocto:
- Clone Yocto source code
- Set up the build environment
- Configure SWUpdate and Suricatta Settings
This ensures you have a working base configuration before making customizations.
Generate SWUpdate Encryption Keys
SWUpdate uses cryptographic signatures to verify update images. Generate RSA key pairs for signing:
# Create a passphrase file (keep this secure!)
echo 123456 > passphrase
# Generate private key (AES-256 encrypted)
openssl genrsa -aes256 -passout file:passphrase -out swu_priv.pem
# Extract public key
openssl rsa -in swu_priv.pem -passin file:passphrase -out swu_public.pem -outform PEM -pubout
Key File Placement
Place the generated keys in the following locations within your Yocto source tree:
Private key and passphrase (used during build):
source/meta-tn-imx-bsp/dynamic-layers/swupdate/recipes-extended/images/update-image/
├── swu_priv.pem
└── passphrase
Public key (embedded in rootfs for verification):
source/meta-tn-imx-bsp/dynamic-layers/swupdate/recipes-support/swupdate/swupdate/swu_public.pem
The public key will be installed to /etc/swu_public.pem
on the target board.
The passphrase
and swu_priv.pem
files contain sensitive cryptographic material. Store them securely and never commit them to version control. Consider using a hardware security module (HSM) for production environments.
For other key generation methods and signature algorithms, see the SWUpdate documentation on signed images.
Customization Overview
SWUpdate customization typically involves modifying these key components:
Component | File Location | Purpose |
---|---|---|
Update Content | sw-description | Define what gets updated and how |
Feature Configuration | defconfig | Enable/disable SWUpdate features |
Hardware Compatibility | swupdate_%.bbappend | Set hardware version matching |
Server Settings | swupdate.cfg | Configure hawkBit/Suricatta parameters |
1. Customizing Update Content
The sw-description
file defines what components are included in your update package and how they should be installed.
File Location
source/meta-tn-imx-bsp/dynamic-layers/swupdate/recipes-extended/images/update-image/sw-description
What Can Be Updated
SWUpdate supports updating various system components:
- Bootloader (U-Boot, SPL)
- Kernel (Linux kernel image)
- Device Tree (DTB files)
- Root Filesystem (Complete or partial)
- Applications (User-space programs)
- Firmware (Device firmware blobs)
- U-Boot Environment (Boot configuration variables)
Basic sw-description Structure
software =
{
version = "1.0.0";
hardware-compatibility: [ "1.0", "1.2", "1.3" ];
images: (
{
filename = "rootfs.ext4.gz";
device = "/dev/mmcblk1p2";
type = "raw";
compressed = "zlib";
installed-directly = true;
}
);
scripts: (
{
filename = "post-install.sh";
type = "shellscript";
}
);
bootenv: (
{
name = "bootcount";
value = "0";
}
);
}
Common Configuration Options
Option | Description | Example Values |
---|---|---|
filename | Name of file in .swu package | "rootfs.ext4.gz" |
device | Target device/partition | "/dev/mmcblk1p2" |
type | Handler type | "raw" , "ubifs" , "flash" |
compressed | Compression algorithm | "zlib" , "gzip" , "none" |
installed-directly | Skip temp extraction | true , false |
sha256 | Checksum for verification | Hash string |
Example: Updating Multiple Components
software =
{
version = "2.5.0";
hardware-compatibility: [ "1.0" ];
images: (
{
filename = "imx-boot";
device = "/dev/mmcblk1boot0";
type = "raw";
},
{
filename = "Image";
device = "/dev/mmcblk1p1";
type = "raw";
},
{
filename = "imx8mp-edm-g-wb.dtb";
device = "/dev/mmcblk1p1";
offset = "0x100000";
type = "raw";
},
{
filename = "rootfs.ext4.gz";
device = "/dev/mmcblk1p2";
type = "raw";
compressed = "zlib";
installed-directly = true;
}
);
scripts: (
{
filename = "pre-install.sh";
type = "shellscript";
},
{
filename = "post-install.sh";
type = "shellscript";
}
);
}
Advanced: Conditional Updates
You can use Lua scripting for conditional logic:
function check_version()
local current_version = get_bootenv("version")
if current_version == "1.0.0" then
return true, "Update allowed"
else
return false, "Version mismatch"
end
end
For complete syntax reference and advanced features, see SWUpdate: sw-description syntax and tags
2. Adjusting SWUpdate Features
The defconfig
file controls which SWUpdate features are compiled into the binary.
File Location
source/meta-tn-imx-bsp/dynamic-layers/swupdate/recipes-support/swupdate/swupdate/defconfig
Common Feature Options
# Web server interface
CONFIG_MONGOOSE=y
CONFIG_MONGOOSEIPV6=y
CONFIG_MONGOOSESSL=n
# Remote update support
CONFIG_SURICATTA=y
CONFIG_SURICATTA_HAWKBIT=y
CONFIG_SURICATTA_SSL=y
# Signature verification
CONFIG_SIGNED_IMAGES=y
CONFIG_SIGALG_RSA=y
CONFIG_SSL_IMPL_OPENSSL=y
# Download support
CONFIG_DOWNLOAD=y
CONFIG_DOWNLOAD_SSL=y
CONFIG_CHANNEL_CURL=y
# Handler support
CONFIG_HANDLER_SCRIPT=y
CONFIG_HANDLER_RAW=y
CONFIG_HANDLER_UBOOT=y
# Compression support
CONFIG_GUNZIP=y
CONFIG_ZLIB=y
CONFIG_ZSTD=y
# Logging
CONFIG_BOOTLOADER_EBG=y
CONFIG_SYSTEMD=y
Feature Categories
Category | Options | Purpose |
---|---|---|
Web Interface | CONFIG_MONGOOSE | Enable built-in web server |
Remote Updates | CONFIG_SURICATTA_* | hawkBit integration |
Security | CONFIG_SIGNED_IMAGES | Image verification |
Handlers | CONFIG_HANDLER_* | Update type support |
Compression | CONFIG_GUNZIP , CONFIG_ZSTD | Decompression algorithms |
Enabling/Disabling Features
To enable a feature:
CONFIG_FEATURE_NAME=y
To disable a feature:
CONFIG_FEATURE_NAME=n
# or comment it out:
# CONFIG_FEATURE_NAME=y
After modifying defconfig
, you must rebuild SWUpdate:
bitbake swupdate-image -c cleansstate
bitbake swupdate-image
3. Configuring Hardware Compatibility
Hardware compatibility prevents installing updates on incompatible devices, protecting against bricking devices with wrong firmware.
File Location
source/meta-tn-imx-bsp/dynamic-layers/swupdate/recipes-support/swupdate/swupdate_%.bbappend
Default Configuration
SWU_HW_REV ?= "1.0"
Setting Hardware Version
Method 1: Modify bbappend file directly
Edit swupdate_%.bbappend
:
SWU_HW_REV ?= "2.0"
Method 2: Override in local.conf
Add to conf/local.conf
:
SWU_HW_REV = "2.0"
Multiple Hardware Revisions
In your sw-description
, specify all compatible hardware versions:
hardware-compatibility: [ "1.0", "1.2", "1.3", "2.0" ];
This allows the same update package to work on multiple hardware revisions.
Hardware Version Checking
SWUpdate reads the hardware version from:
/etc/hwrevision
This file is automatically generated during build using the SWU_HW_REV
variable.
Custom Hardware Detection
For complex hardware detection, you can use a script:
Create custom hwrevision script:
#!/bin/sh
# Read hardware revision from EEPROM or other source
hw_rev=$(i2cget -y 0 0x50 0x10)
echo "$hw_rev" > /etc/hwrevision
Use meaningful version strings that reflect actual hardware changes:
"imx8mp-rev-a"
,"imx8mp-rev-b"
for board revisions"edm-g-imx8mp-v1.0"
for complete identifiers"prototype"
,"production"
for development stages
4. Configuring Suricatta for hawkBit Server
Suricatta is SWUpdate's daemon that communicates with OTA servers like hawkBit.
File Location
source/meta-tn-imx-bsp/dynamic-layers/swupdate/recipes-support/swupdate/swupdate/swupdate.cfg
Default Configuration
suricatta :
{
enable = true;
tenant = "default";
id = "@TARGETID@";
url = "@SERVERURL@";
polldelay = 60;
nocheckcert = true;
retry = 4;
retrywait = 200;
loglevel = 10;
userid = 0;
groupid = 0;
targettoken = "@TARGETTOKEN@";
};
Configuration Parameters
Parameter | Type | Description | Default | Recommended |
---|---|---|---|---|
enable | boolean | Enable Suricatta daemon | true | true |
tenant | string | hawkBit tenant name | "default" | Organization name |
id | string | Target device ID (controllerId) | @TARGETID@ | Unique per device |
url | string | hawkBit server URL | @SERVERURL@ | Your server address |
polldelay | integer | Polling interval (seconds) | 60 | 300-600 for production |
nocheckcert | boolean | Skip SSL certificate verification | true | false for production |
retry | integer | Number of retry attempts | 4 | 3-5 |
retrywait | integer | Wait between retries (seconds) | 200 | 300-600 |
loglevel | integer | Logging verbosity (0-10) | 10 | 5 for production |
userid | integer | User ID for process | 0 (root) | Non-zero for security |
groupid | integer | Group ID for process | 0 (root) | Non-zero for security |
targettoken | string | Security token | @TARGETTOKEN@ | Unique secure token |
Variable Substitution
The @VARIABLE@
placeholders are replaced during build:
@TARGETID@
→SWU_TARGETID
fromlocal.conf
@SERVERURL@
→SWU_SERVER
fromlocal.conf
@TARGETTOKEN@
→SWU_TARGETTOKEN
fromlocal.conf
Production Configuration Example
suricatta :
{
enable = true;
tenant = "production";
id = "@TARGETID@";
url = "@SERVERURL@";
polldelay = 300; // Poll every 5 minutes
nocheckcert = false; // Verify SSL certificates
retry = 5;
retrywait = 300;
loglevel = 5; // Moderate logging
userid = 1000; // Non-root user
groupid = 1000; // Non-root group
targettoken = "@TARGETTOKEN@";
// Gateway configuration (if using proxy)
gatewaytimeout = 60;
};
SSL/TLS Configuration
For production with SSL certificate verification:
suricatta :
{
nocheckcert = false;
cafile = "/etc/ssl/certs/ca-bundle.crt";
sslkey = "/etc/swupdate/client-key.pem";
sslcert = "/etc/swupdate/client-cert.pem";
};
Advanced: Custom Retry Logic
suricatta :
{
retry = 10;
retrywait = 60;
exponential_backoff = true; // If supported
max_retrywait = 3600; // Maximum 1 hour wait
};
Logging Levels
Level | Description | Use Case |
---|---|---|
0 | No logging | Never recommended |
1-2 | Critical errors only | Production (minimal) |
3-5 | Errors and warnings | Production (normal) |
6-8 | Info messages | Development |
9-10 | Debug messages | Troubleshooting |
Setting nocheckcert = true
disables SSL certificate verification, making the connection vulnerable to man-in-the-middle attacks. Only use this for testing on trusted networks.
5. Build and Deploy Custom Configuration
After making customizations, rebuild the images:
# Clean previous builds
bitbake swupdate-image -c cleansstate
bitbake update-image -c cleansstate
# Rebuild with new configuration
bitbake swupdate-image
bitbake imx-image-full
bitbake update-image
Verify Customizations
After flashing to the device, verify your customizations:
Check hardware version:
cat /etc/hwrevision
Check SWUpdate configuration:
cat /etc/swupdate.cfg
Check public key:
cat /etc/swu_public.pem
Test update with verbose logging:
swupdate -v -i /path/to/update.swu
Best Practices
Configuration Management
- Version Control: Track all customization files in git
- Documentation: Document why each customization was made
- Testing: Test customizations on development boards first
- Backup: Keep backup copies of working configurations
Security Considerations
- Key Management: Never commit private keys to version control
- Certificate Validation: Enable SSL certificate verification in production
- User Privileges: Run Suricatta as non-root user when possible
- Token Rotation: Regularly rotate security tokens
Performance Optimization
- Poll Delay: Increase
polldelay
for battery-powered devices - Compression: Choose compression algorithm based on file size and CPU capability
- Direct Installation: Use
installed-directly = true
for large images - Retry Strategy: Balance between persistence and network load
Maintenance
- Regular Updates: Keep SWUpdate version updated
- Log Monitoring: Regularly review logs for issues
- Testing: Test updates on staging environment first
- Rollback Plan: Always have a rollback strategy
Troubleshooting
Configuration Not Applied
Problem: Changes to configuration files don't take effect
Solution:
# Clean and rebuild
bitbake swupdate-image -c cleansstate
bitbake swupdate-image
Hardware Mismatch Error
Problem: Update fails with hardware compatibility error
Solution:
- Check device hardware version:
cat /etc/hwrevision
- Verify
sw-description
includes this version inhardware-compatibility
- Update
SWU_HW_REV
if needed
Suricatta Connection Failures
Problem: Device cannot connect to hawkBit server
Solution:
- Verify network connectivity:
ping <server-ip>
- Check URL and port in
/etc/swupdate.cfg
- Review logs:
journalctl -u swupdate -n 100
- Verify firewall rules allow connection
Custom Handler Not Working
Problem: Custom handler not executed during update
Solution:
- Verify handler is enabled in
defconfig
- Check handler registration in code
- Test handler independently
- Review SWUpdate logs for handler errors
Additional Resources
- SWUpdate Official Documentation
- sw-description Syntax Reference
- SWUpdate Handlers Documentation
- Suricatta Configuration Guide
Next Steps
After customizing SWUpdate:
- Test all customizations thoroughly on development hardware
- Document your configuration choices for team reference
- Set up automated testing for update procedures
- Plan for configuration management across device fleet
- Implement monitoring and alerting for update operations