pureboot: a version number for the loader, not for the protocol

The info block's third byte was a protocol version that never moved in the
loader's lifetime. It is the pureboot version now, and this change is
version 2: the one number that says what a deployed loader is. Every loader
already in the field answers 1.

The protocol keeps no number of its own — a pureboot version implies it, and
the host tool is what holds that map. pureboot.py states the loader-version
window it speaks (OLDEST_LOADER/NEWEST_LOADER; a version that changes the
protocol becomes the new floor there), so a loader newer than the tool is
refused by name rather than decoded on the assumption nothing moved, while an
older one is read, identified and installed like any other. The tool carries
its own version, free to drift from the loader's: --version prints it and the
window, --info leads with the device's, --update-loader names the version it
installs.

Tests: the planner unit pins the window — every version in it decodes, one
above it is refused, an older loader's image is still found — and the live
suite pins the built loader against the tool beside it, so a bump that reaches
only one of them fails. The image is byte-identical to the previous build but
for that byte.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 17:19:27 +02:00
parent a39a3c7f46
commit 6f3eb06233
5 changed files with 95 additions and 22 deletions

View File

@@ -92,6 +92,12 @@ constexpr std::uint16_t wire_page_mask = word_flash ? (page / 2 - 1) : (page - 1
#endif
constexpr std::uint8_t timeout_seconds = PUREBOOT_TIMEOUT;
// The pureboot version: the loader's one identity number, carried in the info
// block so a host can tell a deployed loader apart from another. The wire
// protocol has no number of its own — a version implies its protocol, and the
// host tool is what holds that map (README.md).
constexpr std::uint8_t version = 2;
// The 12-byte info block the host reads with the 'b' command, flash-resident
// through flash_table (there is no crt to copy a .data image, and its storage
// carries the word alignment 'b' needs to halve the address on the large
@@ -99,7 +105,7 @@ constexpr std::uint8_t timeout_seconds = PUREBOOT_TIMEOUT;
inline constexpr avr::flash_table<std::array<std::uint8_t, 12>{
'P',
'B',
1, // magic, protocol version
version, // magic, then the loader's version
avr::hw::db.signature[0],
avr::hw::db.signature[1],
avr::hw::db.signature[2],