docs(series4): the firmware images are unencrypted and self-documenting

Both MICROMATE(CB).BIN and MICROMATE(BD).BIN are plain code and data --
entropy 6.08 bits/byte, big-endian vector table at 0x4010_30xx, ~16,700
extractable strings including the developers' own debug printf formats with
function names intact.

This answers, from strings alone, questions I had scoped as needing a live
modem capture.

The call-home state machine, verbatim:
  ACH_NOT_STARTED -> ACH_IDLE -> ACH_INITIALIZING -> ACH_CONNECTING
  -> ACH_CONNECTED -> ACH_TRANSFER_DATA -> ACH_RETRY / ACH_QUITTING

And with it:

- Retry limit is three ("three attempts and it's over").
- ExpectedCommunicationsDetected() gates the session: if the host does not say
  something the unit recognises, the call is cancelled and rescheduled after
  TimeBetweenRetries. A homebrew receiver must satisfy this check or units
  retry forever -- exactly the BE12599 failure mode.
- The unit stops monitoring to call home and restarts after
  (Send CMD_STOP_MONITOR / CMD_START_MONITOR), so monitoring state around a
  call is the device's own doing.
- Calls are not re-entrant.
- CMD_CALLHOME_CONNECTION_CONFIRMED exists as a state distinct from
  CONNECTION_COMPLETE, implying a handshake the host must complete before data
  flows.

Event delivery, inferred not confirmed: "All Events Uploaded" plus
"Mark/Unmark File" / "Delete Marked Events" / CMD_PURGE_EVENT_FLASH suggest
events are marked as transferred rather than deleted on send, with purging a
separate explicit act. If so, a receiver that fails to mark would see the same
events re-offered every call. Needs a live capture or disassembly to confirm.

The firmware also embeds its own HTML user manual, documenting modem mode
(Generic vs USB to PC), the modem baud options (9600-230400, confirming 115200
is a setting not a fixed rate), modem relay/warmup, record modes, and a
scheduler downloaded from THOR that pairs with CMD_CALLHOME_SET_SCHEDULE.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL
This commit is contained in:
2026-09-23 18:28:40 -04:00
co-authored by Claude Opus 5
parent 38ad58d4a4
commit 45007e12d8
+98
View File
@@ -426,6 +426,104 @@ memory 15,000,000 total and free (no events stored).
--- ---
## The firmware images are unencrypted — and they document themselves
`ref-stuff/micromate-firmware/MICROMATE(CB).BIN` and `MICROMATE(BD).BIN`,
~2.77 MB each and within 192 bytes of one another.
- **Entropy 6.08 bits/byte** — neither encrypted nor compressed. Plain code
and data.
- Header is a **big-endian vector table**, handlers at `0x4010_30xx`.
- **~16,700 extractable strings**, including the developers' own debug
`printf` format strings with function names intact.
This is a legitimate interoperability reference for hardware TMI owns, and it
short-circuits work I had scoped as "only answerable from a live modem
capture".
### The call-home state machine, verbatim
```
ACH_NOT_STARTED → ACH_IDLE → ACH_INITIALIZING → ACH_CONNECTING
→ ACH_CONNECTED → ACH_TRANSFER_DATA
→ ACH_RETRY / ACH_QUITTING (also ACH_STARTED)
```
Supporting strings:
```
ACH: Entry StartCallHome()
ACH: CallHome_task ; CheckAliveTime CANCEL ; TimeBetweenRetries = %d
ACH: CallHome_task ; !ExpectedCommunicationsDetected() CANCEL ; TimeBetweenRetries = %d
ACH: CallHomeCommectionCompleteProcessing() ACH=%s EAMWC=%s
ACH: %s() three attempts and it's over
ACH: %s() Send CMD_START_MONITOR
ACH: %s() Send CMD_STOP_MONITOR
ACH: Start Ignore request, Call Home is in progress
```
What this tells us without a single captured packet:
1. **Retry limit is three** — "three attempts and it's over".
2. **`ExpectedCommunicationsDetected()` gates the session.** If the host does
not say something the unit recognises, the call is *cancelled* and
rescheduled after `TimeBetweenRetries`. A homebrew receiver must satisfy
this check or units will retry forever — which is exactly the failure mode
seen on BE12599.
3. **The unit stops monitoring to call home and restarts afterwards**
(`Send CMD_STOP_MONITOR` / `CMD_START_MONITOR`). Relevant to any
wedged-unit rescue: the monitoring state around a call is the device's own
doing, not ours.
4. **Calls are not re-entrant** — "Call Home is in progress" is ignored.
### Internal command table
`CMD_CALLHOME`, `CMD_CALLHOME_CANCEL`, **`CMD_CALLHOME_CONNECTION_CONFIRMED`**,
`CMD_CALLHOME_CONNECTION_COMPLETE`, `CMD_CALLHOME_SET_SCHEDULE`,
`CMD_CALLHOME_CLEAR_SCHEDULE`, `CMD_STOP_CALLHOME_FILETRANSFER`,
`CMD_DUTYCYCLE_AUTOCALLHOME`, `CMD_PURGE_EVENT_FLASH`.
`CONNECTION_CONFIRMED` as a distinct state from `CONNECTION_COMPLETE` implies
a **handshake the host must complete before data flows** — the concrete shape
of `ExpectedCommunicationsDetected()`.
### Event delivery — the mechanism, probably
```
All Events Uploaded
Mark/Unmark File Delete Marked Events Marked Events were Deleted
MONITOR::MESG PURGE_EVENT_FLASH BEGIN / END
```
A **marking** mechanism exists, alongside a distinct "all uploaded" terminal
state. 🔶 **Inferred:** events are *marked* as transferred rather than
deleted on send, and purging is a separate explicit act. If so, a receiver
that fails to mark would see the same events re-offered every call — the
question that gates a safe homebrew receiver. **Not yet confirmed**; needs
either a live call-home capture or disassembly around these strings.
### A full user manual is embedded
The firmware carries its own HTML help, which documents configuration we would
otherwise have to infer:
- **Modem mode**: `Generic` (through a modem) vs `USB to PC`.
- **Modem baud**: 9600 / 19200 / 38400 / 57600 / 115200 / 230400 — "must match
the expected rate of the PC or modem". Confirms 115200 is a *setting*, not
a fixed rate.
- **Modem relay + warmup** (0–300 s), auxiliary mode, warning/alarm hold.
- **Record modes**: Waveform, Waveform Manual, Histogram, Histogram-Combo;
sample rates 1024 / 2048 / 4096.
- **A scheduler downloaded from THOR** that can start/stop monitoring, change
record mode, trigger a call home, or run a self check on a daily/weekly
schedule. Pairs with `CMD_CALLHOME_SET_SCHEDULE`.
### Still worth doing
Diffing the two images should isolate exactly what the CB/BD split changes —
we know the wire protocol is not it, and the flags byte (`0xC5` vs `0x03`)
gives a concrete anchor to search for.
## ⚠ Untested and unsafe-until-agreed ## ⚠ Untested and unsafe-until-agreed
Nothing below has been sent to a unit, and nothing should be without an Nothing below has been sent to a unit, and nothing should be without an