Firmware Updates over Wi-Fi and from the SD card
Install new firmware without a USB cable. Push it from the PC over Wi-Fi, or drop it on the SD card. Unsigned images are refused, and a broken update rolls back by itself.
Goal: install new firmware without a USB cable. Push it from the PC over Wi-Fi, or drop it on the SD card. Unsigned images are refused, and a broken update rolls back by itself.
Decisions (design round 2026-10-03)
| # | Decision |
|---|---|
| Q52 | Two sources: push over Wi-Fi from the PC, and from the SD card. Pulling from Gitea releases is deferred. |
| Q53 | Signed Update Files (ECDSA P-256 over SHA-256). The private key stays in ~/.config/roro9stack/, and the firmware embeds the public key (ADR 0003). |
| Q54 | The device always listens for pushes on the LAN while Wi-Fi is Connected. Revised in M2: it was announced over mDNS as roro9stack-<id>.local; mDNS was removed to save RAM (it never crossed the dev box's routed network anyway). Pushes go to the IP shown in Settings → Firmware. |
| Q55 | New firmware runs on Probation. It's confirmed once booted, UI drawn, Services started, 30 s without a crash, and Wi-Fi connected (if configured). Otherwise Rollback. A Toast reports either outcome. |
| Q56 | Downgrades are allowed, with "older than the installed version" shown. |
| Q57 | A valid push installs right away: progress screen, then reboot. The reboot waits for Text Entry to end, 60 s at most. |
Done when
scripts/ota_keygen.shcreates the key pair once. The public key is committed; the private key never is.scripts/flash.sh --otabuilds, signs and pushes tororo9stack-<id>.local. The device shows progress, reboots, and a Toast confirms the new version.- An Update File with a bad signature, a truncated or corrupted image, or no signature is refused, and the device keeps running.
- Settings → About → Update from SD lists the
.otafiles in/updatesand installs one. - A firmware that crashes during Probation rolls back to the previous version, and says so after the reboot.
Work breakdown
- Update File format (host-tested): header (magic, format, version, image size, SHA-256), signature, image. A streaming parser that hashes as it goes and decides accept / refuse / downgrade. The signature verifier sits behind an interface, so tests can inject one.
- PC side: key generation,
make_ota.py(wrapsfirmware.bininto a signed.ota), and the push client.flash.sh --otaties them together. - Device: the Update Service.
- A listener on TCP 3232 plus mDNS.
- Writes the image to the inactive app slot, with the ECDSA check through mbedTLS.
- A progress screen, and a reboot that waits out Text Entry.
- Probation and Rollback: the health checks, confirming the image, and detecting a rollback after reboot to report it.
- Update from SD: the same parser, fed from the Storage Service's task (all card access stays there).
This page is generated from docs/milestones/OTA.md in the repository. To change it, change that file and run site/tools/gen_dev_docs.py.