Skip to content

Add in-place mOTA delta apply for single-slot nRF52 devices - #43

Open
vk496 wants to merge 8 commits into
oltaco:masterfrom
vk496:feature/ota-delta-apply
Open

Add in-place mOTA delta apply for single-slot nRF52 devices#43
vk496 wants to merge 8 commits into
oltaco:masterfrom
vk496:feature/ota-delta-apply

Conversation

@vk496

@vk496 vk496 commented Jun 30, 2026

Copy link
Copy Markdown

TL;DR

Flash new firmware from a mOTA container stored in flash. Inplace firmware replacement. Related to: meshcore-dev/MeshCore#2864

What this adds

On-device application of compact delta firmware updates (MeshCore .mota
containers) on single-slot nRF52 devices — no A/B partition needed. This lets
a node update over a low-bandwidth link (LoRa) by applying a small patch in place
instead of transferring a full image.

How it works

The running app stages a verified, approved .mota in free flash and reboots
with a dedicated GPREGRET apply magic set. On that (and only that) boot, the
bootloader:

  1. locates the staged .mota,
  2. re-checks the delta was built against the exact running firmware
    (.mota base_hash vs the app's EndF self-identity trailer),
  3. applies the patch in place with the bundled detools decoder,
  4. verifies the result against the manifest image_hash, then marks the image valid.

Fail-safe: normal boots never scan or apply (no trigger). Any failure — no
trigger, base mismatch, bad patch, post-apply hash mismatch — leaves the bank
invalid and falls through to OTA DFU, so an interrupted apply can never boot a
corrupt image.

What's included

  • Vendored detools in-place decoder (isolated 3rd-party; decoder-only) + SHA-256.
  • ota_delta.c/.h apply logic, ota_layout.h / ota_bl_info.h (a used capability
    marker the app scans to confirm the bootloader supports in-place apply).
  • Bootloader integration: an early ota_delta_check_and_apply() hook, a reserved
    detools workspace in the linker script, and the OTA sources in the build.
  • A host apply-sim test harness (test/, make check) — no device needed.

Testing

  • cd test && make check: real delta round-trip applies and the result hash
    matches the manifest; a regression guard for an LTO-class stale-flash-readback
    bug (stale readback is refused → fails safe; device fl_read is volatile).
  • ✅ RAK4631 bootloader builds clean (sources compile in, flash fits).
  • ✅ Apply HW-validated end-to-end on RAK4631 and Heltec T114.

Notes

  • Pairs with the MeshCore firmware OTA-over-LoRa change (the app stages/approves;
    this bootloader applies). It's self-contained and additive — no behaviour change
    on boots without the apply trigger.
  • The GPREGRET magic + used capability marker are the only always-present
    additions; everything else is gated behind the trigger.

vk496 added 6 commits June 30, 2026 15:01
On approval the running app stages a verified .mota in free flash and reboots
with a GPREGRET trigger; the bootloader locates it, re-checks the delta was
built against the exact running firmware (.mota base_hash vs the app's EndF
trailer), applies the patch in place with the bundled detools decoder, and
verifies the result against the manifest image_hash before marking the image
valid. Any failure leaves the bank invalid and falls through to OTA DFU, so an
interrupted apply can never boot a corrupt image.
Call ota_delta_check_and_apply() early in boot (only when the GPREGRET apply
magic is set, so normal boots never scan/apply), reserve the detools workspace
in the linker script, and compile the OTA sources + detools into the build.
A host-side harness (no device needed) that exercises the in-place apply logic:
apply_sim applies a real delta .mota against a base image and checks the result
hash; readback_test guards the LTO-sensitive flash-readback path. Both build
with the host compiler against committed vectors (`make test`). Compiled
binaries are git-ignored. README documents the OTA delta-apply flow.
@vk496 vk496 changed the title Add in-place .mota OTA delta apply for single-slot nRF52 devices Add in-place mOTA delta apply for single-slot nRF52 devices Jun 30, 2026
benallfree and others added 2 commits July 17, 2026 13:00
Co-authored-by: Cursor <cursoragent@cursor.com>
Add Docker build for nRF52 bootloader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants