Add in-place mOTA delta apply for single-slot nRF52 devices - #43
Open
vk496 wants to merge 8 commits into
Open
Conversation
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.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add Docker build for nRF52 bootloader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
.motacontainers) 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
.motain free flash and rebootswith a dedicated
GPREGRETapply magic set. On that (and only that) boot, thebootloader:
.mota,(
.motabase_hashvs the app'sEndFself-identity trailer),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
ota_delta.c/.happly logic,ota_layout.h/ota_bl_info.h(ausedcapabilitymarker the app scans to confirm the bootloader supports in-place apply).
ota_delta_check_and_apply()hook, a reserveddetools workspace in the linker script, and the OTA sources in the build.
test/,make check) — no device needed.Testing
cd test && make check: real delta round-trip applies and the result hashmatches the manifest; a regression guard for an LTO-class stale-flash-readback
bug (stale readback is refused → fails safe; device
fl_readisvolatile).Notes
this bootloader applies). It's self-contained and additive — no behaviour change
on boots without the apply trigger.
GPREGRETmagic +usedcapability marker are the only always-presentadditions; everything else is gated behind the trigger.