Software Version Control¶
Welma includes a version control system that embeds version information and compatibility rules into software packages. This ensures that only compatible module combinations are installed, preventing system misconfiguration or malfunction due to incompatible versions.
Overview¶
The Welma version control system works by:
- Embedding version tags in software images during build time with module metadata (name, version, and compatibility rules)
- Checking compatibility before installing updates using version probing
- Enforcing dependencies between modules to ensure system consistency
Runtime architecture¶
Version Tags¶
Each software image (partition, firmware) can contain a version tag that includes all the information required to check its compatibility with the system.
Version tags are stored in a binary format that can be embedded at the end of software images. The tag contains all module metadata and compatibility rules in a compact, fixed-size structure of 2048 bytes.
Tag Structure¶
Offset Size Field Description
------ ---- ----- -----------
0 32 Module Name UTF-8 encoded module name (e.g."bootloader")
32 30 Module Version UTF-8 encoded version (e.g., "1.2.0")
62 1 Rules Count Number of active rules (0-30)
63 1920 Rules Array of 30 compatibility rules (64 bytes each)
1983 50 Padding Reserved area (filled with 0xFF)
2033 4 CRC32 CRC32 checksum of tag data
2037 11 MAGIC Magic identifier: "WELMAVMNGR1"
Maximum Rules per Tag
Each tag supports a maximum of 30 dependency rules. If a module requires
more than 30 compatibility constraints, it exceeds the tag capacity and will
result in a build-time error. The Rules Count field indicates how many of
the 30 available rule slots are actually used (0-30). Unused rule slots are
padded with 0xFF bytes.
Rule Entry Structure (64 bytes each)¶
Each rule entry contains a single dependency constraint:
Offset Size Field Description
------ ---- ----- -----------
0 32 Rule Module Name UTF-8 module name this rule applies to
32 30 Rule Version UTF-8 version string for comparison
62 2 Rule Type Comparison operator code (little-endian)
Rule Type Encoding¶
The rule type field encodes the comparison operator:
| Operator | Encoding | Description |
|---|---|---|
== |
0x0001 | Equal: version must exactly match |
> |
0x0002 | Greater: version must be strictly greater |
>= |
0x0003 | Greater or Equal: version must be greater or equal |
< |
0x0004 | Less: version must be strictly less |
<= |
0x0005 | Less or Equal: version must be le or equal |
!= |
0x0006 | Not Equal: version must not match |
Tag Placement in Images¶
The version tag placement strategy depends on the module type and whether its filesystem type is known. The Welma build system automatically determines the correct placement method during image creation.
Tags are created and installed using welma-tagtool according to the following logic:
Verity-Protected Modules¶
The Welma verity header is located at the beginning of the partition and contains metadata including the total size of verity data plus filesystem (see this page for more details). The version tag is placed immediately after this total size value, allowing runtime programs to easily locate it by reading the verity header.
A/B Filesystem Modules¶
When an A/B module with an explicit filesystem type is used (without verity protection), the build system calculates the total filesystem size and installs the tag immediately after it. This preserves the filesystem integrity and structure, while allowing version information to be probed without parsing the entire partition.
Warning
Version control requires filesystem tag support. Version tags are embedded in the partition images and depend on the filesystem type. Currently supported filesystems are:
- ext2, ext3, ext4
- vfat
Single Modules (raw data):¶
When a single-mode module is a raw binary (e.g bootloaders,...), the build system pads the image to a 2048-byte boundary. This ensures that the tag is always placed at a predictable, aligned offset.
Module File Layout:
┌─────────────────────────────────────┐
│ Original binary data │
├─────────────────────────────────────┤
│ Padding (0xFF bytes) │
│ (to align tag offset to 2048-byte) │
├─────────────────────────────────────┤
│ 2048-byte version tag │
└─────────────────────────────────────┘
Tagging Update Artifacts (SWU and Mender)¶
When creating update artifacts, a tag is embedded not only in the image installed by the artifact, but also in the SWU or Mender package itself.
This allows faster verification of the versions of the modules contained in the artifact, especially when the tagged image inside the package is compressed and would otherwise need to be fully decompressed to read the tag.
To achieve this, an update artifact contains as many tags as there are images.
Compatibility Checking During Updates¶
When installing software packages, the updated daemon automatically checks
version compatibility in the following order:
-
Parse module tags
From each artifact being installed,
updateddaemon reads the embedded tags to build a final list of modules to be updated. -
Validate inter-artifact compatibility first
If multiple artifacts are being installed together (in the same session) and an artifact (
A1) provides a moduleM1that requires a specific version of a moduleM2, andM2is provided by a second artifact (A2) being installed, thisM2module should satisfy the requirement ofM1. Otherwise, the dependency check fails and the update is aborted. -
Check dependency rules against currently running modules
If an artifact (
A1) provides a moduleM1that requires a specific versions of a module not updated in the current session, this dependency is checked against the currently running module from the active/single partitions. -
Check running modules dependencies
After verifying that all artifact module dependencies are satisfied, the
updateddaemon checks the running modules that are not updated in the current session to determine whether they have any specific dependency on the artifact modules. If any dependency check fails, the update is aborted. -
Install Artifacts and check version mismatch
When a compatible artifact instsallation is submited,
updateddaemon checks that the retreived version information from the artifact tag matches the installed tag.
Note
Untagged modules are accepted for installation only if no module in the current session, nor any running module, depends on them.
Note
When a module M is provided by multiple artifacts during installation with
InstallLocalFiles, the last artifact providing M will override the previous
versions. As a result, only the last M module dependencies are used for the
compatibility check (Step 1)
Yocto configuration¶
Default Behavior¶
Version tagging is enabled by default for all partitions with update=ab or
update=single modes. This means:
- All
A/Bupdate partitions are automatically tagged with version information - All
single-modeupdate partitions are automatically tagged - Version tags can be explicitly disabled using
tag=noin the.partfile if needed - Partitions with
update=noare not tagged
Disable tags
By default, the system supports tag management for modules. To disable
this feature, set tag=no on all modules.
Specifying Module Dependencies¶
Module dependencies are specified in the .part file using the deps keyword.
Multiple dependencies are separated by colons (:) with no spaces.
Dependency Format¶
Each dependency follows the format: modulename<operator>version, where operators
are : ==, !=, >, >=, <, <=.
Rule Limit
A single module tag can contain up to 30 dependency rules maximum. Each rule specifies one compatibility constraint. If you need more than 30 rules for a single module, the build will fail with an error indicating too many rules have been specified.
Examples¶
-
Tag without dependencies (no rules):
-
Single dependency in
.part: -
Multiple dependencies (colon-separated) in
.part: -
More complex example in
.part:
welma-tagtool Tool¶
The welma-tagtool command-line tool is used to create and embed version tags
into module images. It can be invoked directly for custom tagging scenarios or
is called automatically by the Welma build system during image creation.
Basic Syntax¶
welma-tagtool --module-file INPUT_IMAGE \
--output-file OUTPUT_IMAGE \
--module-name MODULE_NAME \
--version VERSION_STRING \
[--rules RULES] \
[--fstype FILESYSTEM_TYPE | --align-tag]
[--tag-only]
Command-Line Options¶
| Option | Short | Argument | Description |
|---|---|---|---|
--module-file |
-m |
FILE | Path to input module image file (optional with --tag-only) |
--output-file |
-o |
FILE | Path to output tagged module file (required) |
--module-name |
-n |
NAME | Module name (max 32 bytes UTF-8) (required) |
--version |
-v |
VERSION | Module version string (max 30 bytes UTF-8) (required) |
--rules |
-r |
RULES | Dependency rules as <module><op><version>:... (optional) |
--fstype |
-f |
TYPE | Filesystem type: ext2, ext3, ext4, or vfat |
--align-tag |
-a |
- | Align tag to 2048-byte boundary |
--tag-only |
- | - | Generate tag without modifying input file |
--list-fstypes |
-l |
- | List supported filesystem types |
Constraints¶
- Cannot use both
--align-tagand--fstypeat the same time - Either
--module-fileor--tag-onlyis required --tag-onlycannot be used with--align-tagor--fstype- Maximum of 30 dependency rules per tag: Specifying more than 30 rules will result in an error
Examples¶
- Example 1: Tag an ext4 filesystem image
welma-tagtool \
--module-file appro.ext4 \
--output-file appro.ext4.tagged \
--module-name appro \
--version 1.2.0 \
--fstype ext4 \
--rules "sysro>=1.0.0:boot>=2.0.0"
This embeds the version tag immediately after the ext4 filesystem data.
- Example 2: Generate tag only (no module file)
welma-tagtool \
--output-file tag.bin \
--module-name appro \
--version 1.2.0 \
--tag-only \
--rules "sysro>=1.0.0"
This creates a standalone 2048-byte tag file that can be manually appended to module images or used for inspection.
- Example 3: Complex dependencies with multiple operators
welma-tagtool \
--module-file appro.ext4 \
--output-file appro.ext4.tagged \
--module-name appro \
--version 1.3.0 \
--fstype ext4 \
--rules "sysro>=1.0.0:boot==2.1.0:kernel!=1.0.0:hal<=3.5.0"
Multiple rules are separated by colons (:) and can use different operators.
Output Information¶
When successfully completing, welma-tagtool prints:
The tag start offset indicates where in the output file the 2048-byte tag begins.
Tag Validation¶
The tag includes a CRC32 checksum covering the entire tag structure (excluding the CRC32 and MAGIC fields). The runtime version probing tools validate this checksum to ensure tag integrity when reading version information.
When Dependency Checking Occurs
Version dependencies are only validated during software updates, not during build time or at boot time. This means:
- Build time: No validation - incompatible modules CAN be built together
- Boot time: No validation - incompatible modules CAN be flashed on the same system
- Update time: Validation occurs - incompatible updates are REJECTED before installation
This design allows maximum flexibility during development and initial deployment, while ensuring system consistency is maintained during runtime updates. The tag information is embedded for documentation and runtime use, not for build-time enforcement.
During normal Yocto builds, welma-tagtool is invoked automatically by the
build system to tag all configured modules:
- The
.partfile specifies which partitions should be tagged - For each partition with
tag=yesor update mode ofab/single:- Module image is located in the build deploy directory
welma-tagtoolis called with the appropriate parameters- Tagged image is installed in the deploy directory
Welma versionctl Tool¶
versionctl tool is used to query version information from the running
system or from update artifacts.
Commands¶
List all modules:
Shows all system (active/single) modules on the system with their versions and dependencies.
Get a specific module version:
Shows version information for a specific module. Use the -i|--inactive flag to query the
inactive module in A/B systems.
Inspect an artifact:
Shows all modules and their version information contained in a software package (SWU or Mender artifact).
Probe a specific device:
The versionctl tool can also be used to query version information directly from
a specific device or a file using -d|--device argument:
In this case the probing area can be limited by specifying an offset and probing size
in bytes with -o|--offset and -s|--size:
# Query bootloader information
versionctl get bootloader --device /dev/mmcblk0 --size 3145728 --offset 32768
Example Usage¶
# List all active modules with versions
$ versionctl list
sysro (A/B):
- Version: 1.0.0
- Dependencies:
- boot >= 2.0.0
appro (A/B):
- Version: 1.2.0
- Dependencies:
- sysro >= 1.0.0
boot (A/B):
- Version: 2.1.0
# Check what's in an update artifact
$ versionctl artifact appro-v1.3.0.swu
appro (A/B):
- Version: 1.3.0
- Dependencies:
- sysro >= 1.0.0
- boot >= 2.0.0
# Query the active module after installation
$ versionctl get appro
appro (A/B):
- Version: 1.3.0
- Dependencies:
- sysro >= 1.0.0
- boot >= 2.0.0
Runtime Version Checking Example¶
Typical update sequence with version checking:
# 1. Check current system state
$ versionctl list
sysro (A/B):
- Version: 1.0.0
appro (A/B):
- Version: 1.0.0
- Dependencies:
- sysro >= 1.0.0
boot (A/B):
- Version: 2.0.0
# 2. Check what an update contains
$ versionctl artifact appro-v1.1.0.swu
appro (A/B):
- Version: 1.1.0
- Dependencies:
- sysro >= 1.0.0
- boot >= 2.0.0
# 3. Install update (version checking happens automatically)
$ updatectl install appro-v1.1.0.swu
# 4. Check inactive module before reboot
$ versionctl get appro -i
appro (A/B):
- Version: 1.1.0
- Dependencies:
- sysro >= 1.0.0
- boot >= 2.0.0
# 5. Check active module after reboot
$ versionctl get appro
appro (A/B):
- Version: 1.1.0
- Dependencies:
- sysro >= 1.0.0
- boot >= 2.0.0
# 5. Confirm the update
$ updatectl confirm
Error Example¶
If a module has incompatible dependencies, the installation will fail:
$ versionctl artifact appro-v1.2.0.swu
appro (A/B):
- Version: 1.2.0
- Dependencies:
- sysro >= 2.0.0 # Requires sysro 2.0.0 or later
$ updatectl install appro-v1.2.0.swu
ERROR: Artifact Module appro: compatibility rule 'sysro >= 2.0.0' is not satisfied.
Multiple Module Update¶
When updating multiple modules together, compatibility is checked across all artifacts in the same transaction first, then with the system:
$ versionctl artifact sysro-v2.0.0.swu
sysro (A/B):
- Version: 2.0.0
# appro requires sysro >= 2.0.0, and sysro v2.0.0 satisfies this
$ updatectl install appro-v1.2.0.swu sysro-v2.0.0.swu
# Installation OK