Break-glass recovery: :wipekv KV-reset, revert-to-stock tooling, stock-FW feature map - #76
Merged
Merged
Conversation
…al surface, Matter, storage) Synthesizes six raw analysis passes into docs/13: XIP base correction to 0x9b6e0000 (old 0x9b7d0000 was wrong; verified against ~20 pointer pools), fw2 identified as an older MP-test build (no Matter), plus the OTA acceptance, cloud/TLS, listener, and KV/sysdata layout map. Adds tools/xref.py (literal-pool and movw/movt xref finder) and gitignores the raw analysis workspace. Assisted-by: AI
ota-release.sh gains 'revert' with four paths: --flip (break-glass slot-flip back to the intact stock slot via the :slots/:revert TCP commands), --backup (stream + HMAC/bytesum-validate the inactive stock slot over :backup), --repackage (carve and re-sign the stock app as a Matter .ota), and --apply (stage + drive update_node). docs/10 §17 documents all four, the safety guards (other slot must be strictly older; cloud-binding regions stay byte-intact), and the Path-2 re-signed-image-won't-boot dead end. Assisted-by: AI
…wipekv Device-side break-glass command suffixes on the #61 listener: :slots / :revert / :backup (the #19 firmware half; host tooling in the prior commit) and the new :wipekv (>= 1.3.16). :wipekv calls deinitPref() to format both Matter DCT regions then reboots, curing the commissioning wedge on stock units with a cloud-pairing history: an orphaned stock-era root-cert blob makes every commission fail at SendTrustedRootCert (IM 0x0501), unreachable by any cluster command. docs/10 §13 gains the command inventory; docs/12 documents the wedge, the diagnosis (PASE + read fabrics), and the recovery loop. Proven on the office unit -> node 62. version.txt -> 1.3.16. Assisted-by: AI
The unused imm4i() helper computed i/imm4/imm8 then returned None; the real movw/movt decode is inline below it. Removed so ruff F841 passes CI. Assisted-by: AI
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.
Summary
Three independent pieces of break-glass / recovery work, plus a reverse-engineering deliverable. Each is its own commit.
1. Stock-firmware feature map (
reverse-engineering/docs/13)Synthesizes six raw analysis passes into one map: cloud/TLS, OTA acceptance, local attack surface, the Matter stack, and the KV/sysdata layout. Notable corrections baked in:
0x9b6e0000, not the previously recorded0x9b7d0000(string-pointer pools only resolve at the corrected base; verified against ~20 independent pools).Adds
tools/xref.py(literal-pool +movw/movtxref finder) and gitignores the raw analysis workspace.2. Revert-to-stock over the air, host side (
ota-release.sh revert, docs §17)Four paths, no CH341A clip required:
--flip— slot-flip back to the intact stock slot via the device's:slots/:revertcommands--backup— stream the inactive stock slot over:backupand validate it (HMAC + bytesum)--repackage— carve and re-sign the stock app as a Matter OTA--apply— stage and driveupdate_nodeDocuments the safety guards (the other slot must be strictly older; the cloud-binding regions stay byte-intact so a reverted unit rejoins the vendor cloud as itself) and the re-signed-image-won't-boot dead end found while testing.
3. Break-glass command handlers, device side, incl. new
:wipekv(ships v1.3.16)The device half of the recovery listener:
:slots/:revert/:backup, plus a new:wipekvthat factory-resets the Matter KV (formats both DCT regions) and reboots.Why
:wipekvexists. A stock unit that was ever cloud/app-paired carries its old fabric's KV entries through the OTA conversion. On an older-stock unit that leaves an orphaned root-cert blob the new firmware only half-reads, and then every commission attempt fails atSendTrustedRootCertwithIM 0x0501(deterministic, every controller and transport, survives reboot). Fabric indices allocate monotonically, so the next index is permanently stuck on the orphaned slot, and no cluster command can reach a cert whose index is not in the fabric table.:wipekvis the only cure short of a CH341A reflash.Like the rest of the listener,
:wipekvis compiled into both flavours and gated only by the break-glass token being set at build time (fails closed with no token). It is deliberately not a debug-console command, so it is present in exactly the release images most likely to need it.Verification
SendTrustedRootCert::revert→ re-commission stock over BLE → Matter-OTA the:wipekv-capable image →:wipekv→ re-commission → handed off to the local controller with a single fabric and the reported software version confirmed by a live attribute read..zapendpoint contiguity, monotonic version) passes; version int10316 > 10307.Notes
docs/10 §13gains a full break-glass command inventory;docs/12documents the wedge, the no-UART diagnosis (PASE in the open window grants admin, then read the fabric table), and the recovery loop.:wipekvonly exists from v1.3.16 onward, so it cannot rescue an image that shipped without it. Existing deployed nodes do not have it until they are rolled forward.AI-assisted; see the
Assisted-bytrailer on each commit.