Understanding the Update Mechanism¶
Design rationale and runtime behaviour of the meta-tolomeo update mechanism.
For step-by-step configuration instructions, see Configure Update Modes. For a complete variable and file reference, see Update Mechanism Reference.
Table of Contents¶
- Understanding the Update Mechanism
- Table of Contents
- Tool-Agnostic Feature Flags
- Additive Feature Model
- Two-Layer Configuration Model
- Why SWUPDATE_SOURCE Is Derived
- Runtime Argument Composition in swupdate.sh
Tool-Agnostic Feature Flags¶
The three DISTRO_FEATURES flags — update-ota, update-ota-streaming, and update-local —
do not mention swupdate. This is intentional.
These flags describe a device's update capability at the platform level, not the tool that
implements it. A BSP layer can read these flags and wire them to whichever update tool it uses.
If meta-tolomeo-distro is replaced by a layer using a different update mechanism, the same
flags remain valid in machine and distro configurations — the platform's intent is preserved
without leaking implementation details into the hardware description.
Additive Feature Model¶
The three features are independent and composable:
update-otaandupdate-localare orthogonal — one covers remote updates, the other covers local updates from removable media. Neither implies the other. Both can be active on the same device simultaneously, sharing the EnvironmentFile and public key without conflict.update-ota-streamingis a modifier on top ofupdate-ota, not a separate mode. It changes how the OTA artifact is acquired (fetched from a URL rather than placed by an agent) but operates within the same OTA service infrastructure.
The update-ota-streaming requires update-ota constraint is enforced at build time with a
bbfatal. This prevents a configuration where the binary has curl compiled in but the base OTA
infrastructure (service, conf.d directory, key) is missing.
Two-Layer Configuration Model¶
Runtime configuration is split across two locations with distinct purposes.
/etc/default/swupdate is loaded by systemd as an EnvironmentFile before the service
starts. It contains only path topology: where the swupdate binary is, where the public key is,
and where the conf.d directories are. This information must be available before any script
runs, which is why it lives in a systemd-managed file rather than a conf.d fragment. Its
content never varies by update mode — it is the same regardless of whether the device uses file
mode, streaming mode, or USB.
/etc/swupdate/conf.d/ contains shell-sourceable fragments loaded at runtime by
swupdate.sh. These fragments set behavioural variables: which source mode to use, what file
path to check, what URL to fetch. Because they are sourced in sorted filename order, fragments
with higher names can override earlier ones. This is where the management agent writes
descriptor.env at update time — it never modifies service unit files or the EnvironmentFile.
The split keeps the systemd pre-start environment simple and stable, while allowing the behavioural configuration to be composed and overridden at runtime.
Why SWUPDATE_SOURCE Is Derived¶
SWUPDATE_SOURCE was previously a free variable set directly in local.conf or a bbappend.
This created a correctness gap: setting SWUPDATE_SOURCE=download did not automatically
compile curl support into the swupdate binary. The mismatch only surfaced at runtime when
swupdate attempted a download with no curl support available.
SWUPDATE_SOURCE is now derived from DISTRO_FEATURES:
SWUPDATE_SOURCE = "${@bb.utils.contains('DISTRO_FEATURES', 'update-ota-streaming', 'download', 'file', d)}"
When update-ota-streaming is present, the same feature flag that sets
SWUPDATE_SOURCE=download also pulls in swupdate-download.cfg, which enables curl support
in the swupdate build configuration. The runtime mode and the binary capabilities are always in
sync — correct by construction rather than by convention.
Runtime Argument Composition in swupdate.sh¶
swupdate.sh assembles the swupdate command in three stages:
Stage 1 — load_config_files() sources all files in $SWUPDATE_CONF_DIR_LIB and
$SWUPDATE_CONF_DIR_ETC in sorted order. Files in the etc directory take precedence over the
lib directory when both contain a file with the same name. After this stage, SWUPDATE_SOURCE,
UPDATE_FILE, and URL (when present) are available as shell variables.
Stage 2 — build_arguments() reads the variables from stage 1 and builds the swupdate
command as a Bash array. An array is used instead of string concatenation and eval to ensure
that argument values containing spaces or special characters are passed verbatim to the process
without shell re-parsing.
Stage 3 — run_swupdate() execs the assembled command. exec replaces the shell process
with swupdate, so swupdate inherits the same PID and systemd service tracking works correctly.
The management agent's handoff point is descriptor.env: it writes URL=<url> to that file
before starting the service. Stage 1 picks it up and makes it available to stage 2. The agent
never invokes swupdate directly.