Add one-way OTA target migration aliases

This commit is contained in:
mikecarper committed 2026-09-19 08:30:52 -07:00
1 parent 86e8c413cd
commit 5fd9d039f5
7 files changed
+102 -4

No files matched your search

+5
View File
@@ -647,6 +647,11 @@ struct OtaContext {
target_id = 0;
#endif
manager.begin(target_id, send, ctx);
#if defined(MOTA_MIGRATION_TARGET_ID)
// Legacy observer images keep their deployed target identity for serving
// and diagnostics, but automatically accept one canonical successor image.
manager.set_auto_migration_target((uint32_t)(MOTA_MIGRATION_TARGET_ID));
#endif
// Every OTA-capable application can receive ordinary raw RFC1951 transport blocks. OtaManager advertises
// that permission only because this exact, bounded decoder is registered; non-OTA builds do not compile
// OtaContext or link the decoder implementation.
+6 -2
View File
@@ -81,6 +81,7 @@ uint8_t* OtaManager::ensureScratch() {
void OtaManager::begin(uint32_t my_target_id, OtaSend send, void* ctx) {
_target = my_target_id; _send = send; _ctx = ctx;
_migration_target = 0;
_fstate = IDLE; _have = 0; _fbc = 0;
_paused_from = IDLE;
_fetch_error = FETCH_ERROR_NONE;
@@ -1099,7 +1100,8 @@ bool OtaManager::wantRow(const uint8_t* mid, uint32_t target, uint32_t fw_versio
return memcmp(mid, _desired_mid, 4) == 0 && (_desired_target == 0 || target == _desired_target);
if (_desired_target) return target == _desired_target; // cross-target want (role switch)
if (_autofetch == AUTOFETCH_OFF) return false; // discover only
if (target != _target) return false; // auto-fetch = our own target
const uint32_t auto_target = _migration_target ? _migration_target : _target;
if (target != auto_target) return false; // own target or one-way successor
if (_autofetch == AUTOFETCH_SIGNED && !(flags & MFLAG_SIGNED)) return false; // signed-only policy
if (_enforce_auto_version &&
!ota_trusted_auto_version_allows(_running_fw_version, fw_version)) return false;
@@ -1608,7 +1610,9 @@ bool OtaManager::resumeStaged(const uint8_t* want_mid) {
return false;
}
const bool automatic_resume = want_mid == nullptr;
const uint32_t expected_target = automatic_resume ? _target : _fexpected_target;
const uint32_t expected_target = automatic_resume
? (_migration_target ? _migration_target : _target)
: _fexpected_target;
if (!_fetch->reopenFor(want_mid, expected_target)) return false;
uint32_t total = _fetch->staged_size();
uint8_t hdr[8];
+9
View File
@@ -455,6 +455,14 @@ public:
static const uint8_t AUTOFETCH_OFF = 0, AUTOFETCH_ANY = 1, AUTOFETCH_SIGNED = 2;
void set_autofetch(uint8_t p) { _autofetch = p; reDiscover(); }
uint8_t autofetch() const { return _autofetch; }
// One-way release migration for a legacy identity. Automatic OTA follows the
// successor target while the running firmware continues to report its own
// target until that successor is installed. Manual pulls are unaffected.
void set_auto_migration_target(uint32_t target_id) {
_migration_target = target_id != _target ? target_id : 0;
reDiscover();
}
uint32_t auto_migration_target() const { return _migration_target; }
void set_auto_version_floor(uint32_t running_version, bool enforce = true) {
_running_fw_version = running_version;
_enforce_auto_version = enforce;
@@ -728,6 +736,7 @@ private:
MerkleAccumulator _resume_merkle;
uint32_t _req_start = 0, _req_count = 0; // most recently requested block + active flight size
uint32_t _desired_target = 0; // manual cross-target override (0 = auto / own target)
uint32_t _migration_target = 0; // one-way automatic successor target for legacy releases
uint8_t _desired_mid[4] = {0,0,0,0}; // pull a specific manifest_id (see want_mid)
bool _have_desired_mid = false;
uint8_t _apply_codec = CODEC_DETOOLS_SEQUENTIAL; // platform's delta codec (OtaContext sets it)