Guard env:versapad's upload against overwriting the bootloader

pio run -e versapad --target upload writes the app starting at
0x0000 and silently destroyed the installed UF2 bootloader twice
today during testing -- no warning, no error, just a board that
stopped responding to the boot-key hold.

upload_openocd.py now checks for the bootloader (verify_image against
the locally built bootloader/.pio/build/versapad_bootloader/firmware.bin)
before an env:versapad upload and refuses if one is present, pointing
at env:versapad_usb instead. Fails closed: an inconclusive check (e.g.
bootloader not built locally, SWD not responding) blocks rather than
proceeding on a guess -- confirmed necessary the hard way, since a
"fail open" first attempt let the destructive upload through silently.
Scoped to PIOENV == "versapad" only, since bootloader/platformio.ini's
own upload reuses this same script and must always be allowed to write
0x0000. A new erase-bootloader-and-flash custom target remains as the
explicit, deliberate override.

Documented the workflow (bootloader is its own PlatformIO project,
flashed once via SWD; versapad_usb is the normal path afterward;
versapad's upload is now guarded) in README.md and
doc/10_usb_bootloader.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Julian Appel 2026-08-05 23:27:02 +02:00
parent cd27639e44
commit 01c5e0930e
4 changed files with 151 additions and 8 deletions

View file

@ -56,6 +56,30 @@ erkennt den Schreibzugriff und springt selbständig in die neue App.
`upload_uf2.py` sucht das Laufwerk aktuell nur über die Windows-API
(`GetVolumeInformationW`) — keine macOS/Linux-Unterstützung.
## Schutz gegen versehentliches Überschreiben (env:versapad)
`env:versapad` (SWD, `boards/versapad_nobl.json`) schreibt die App-Firmware
ab `0x0000` und überschreibt damit einen installierten Bootloader
kommentarlos — genau das ist am 2026-08-05 während der Entwicklung passiert
(zweimal). `upload_openocd.py` prüft das seither vor jedem `versapad`-Upload:
- vergleicht per `verify_image` gegen die lokal gebaute
`bootloader/.pio/build/versapad_bootloader/firmware.bin`
- Bootloader erkannt → Upload wird verweigert, mit Hinweis auf
`versapad_usb` oder den expliziten Override
- lässt sich die Prüfung nicht eindeutig durchführen (z. B. `bootloader/`
noch nicht gebaut, oder die SWD-Verbindung antwortet nicht) → wird
sicherheitshalber ebenfalls verweigert, nicht durchgelassen
- gilt nur für `env:versapad``env:versapad_bootloader` nutzt dasselbe
Skript (`extra_scripts = ../upload_openocd.py`) und schreibt bewusst immer
auf `0x0000`, ungeprüft
Bewusstes Überschreiben (zurück zu reinem SWD-Betrieb ohne Bootloader):
```bash
pio run -e versapad -t erase-bootloader-and-flash
```
## Herkunft und Details
Der Bootloader ist abgeleitet und stark eingekürzt aus
@ -87,6 +111,12 @@ stehen in `bootloader/README.md` unter "Hardwaretest"; kurz zusammengefasst:
immer `.bin` mit expliziter Adresse und getrennte OpenOCD-Aufrufe
verwenden — Details in `bootloader/README.md`, "Achtung bei manuellem
SWD-Flashen".
- **`env:versapad` überschreibt den Bootloader kommentarlos.** Ein normaler
`pio run -e versapad --target upload` (der alte, gewohnte SWD-Weg für
App-Updates) schreibt ab `0x0000` und hat den Bootloader dabei zweimal
ohne jede Warnung zerstört. Fix: automatischer Presence-Check in
`upload_openocd.py`, siehe "Schutz gegen versehentliches Überschreiben"
oben.
## Bekannte Einschränkungen