From 11c101c2350515ddf1da2e01bb29e6bc86785b38 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 12 Apr 2026 22:22:54 +0900 Subject: [PATCH] Flash status: scan PICOBIN blocks for per-slot validity and version --- cmd/picomap/main.go | 7 ++++++- firmware/include/wire.h | 15 ++++++++++++--- firmware/lib/handlers.cpp | 40 ++++++++++++++++++++++++++++++++++----- lib/client/types.go | 10 +++++++++- 4 files changed, 62 insertions(+), 10 deletions(-) diff --git a/cmd/picomap/main.go b/cmd/picomap/main.go index f95bc25..1cde157 100644 --- a/cmd/picomap/main.go +++ b/cmd/picomap/main.go @@ -227,7 +227,12 @@ func cmdFlashStatus(args []string) error { slog.Info("flash-status", "via", t.name, "boot_partition", status.BootPartition, - "boot_type", status.BootType) + "slot_a_valid", status.SlotA.Valid, + "slot_a_version", status.SlotA.Version, + "slot_a_hash_ok", status.SlotA.HashOK, + "slot_b_valid", status.SlotB.Valid, + "slot_b_version", status.SlotB.Version, + "slot_b_hash_ok", status.SlotB.HashOK) } return nil } diff --git a/firmware/include/wire.h b/firmware/include/wire.h index c1969f5..aebfa3d 100644 --- a/firmware/include/wire.h +++ b/firmware/include/wire.h @@ -128,12 +128,21 @@ struct RequestFlashStatus { auto as_tuple() { return std::tie(); } }; +struct SlotInfo { + bool valid; + uint32_t version; + bool hash_ok; + auto as_tuple() const { return std::tie(valid, version, hash_ok); } + auto as_tuple() { return std::tie(valid, version, hash_ok); } +}; + struct ResponseFlashStatus { static constexpr int8_t ext_id = 15; int8_t boot_partition; - uint8_t boot_type; - auto as_tuple() const { return std::tie(boot_partition, boot_type); } - auto as_tuple() { return std::tie(boot_partition, boot_type); } + SlotInfo slot_a; + SlotInfo slot_b; + auto as_tuple() const { return std::tie(boot_partition, slot_a, slot_b); } + auto as_tuple() { return std::tie(boot_partition, slot_a, slot_b); } }; struct RequestListTests { diff --git a/firmware/lib/handlers.cpp b/firmware/lib/handlers.cpp index dbec25d..29e242f 100644 --- a/firmware/lib/handlers.cpp +++ b/firmware/lib/handlers.cpp @@ -3,12 +3,15 @@ #include "pico/bootrom.h" #include "hardware/flash.h" #include "hardware/watchdog.h" +#include "boot/picobin.h" #include "dispatch.h" #include "net.h" #include "debug_log.h" static constexpr uint32_t XIP_BASE_ADDR = 0x10000000; static constexpr uint32_t FLASH_SIZE = 2 * 1024 * 1024; +static constexpr uint32_t SLOT_A_OFFSET = 0x00000; +static constexpr uint32_t SLOT_B_OFFSET = 0x80000; static boot_reason detected_boot_reason; static void poke_watchdog() { @@ -88,16 +91,43 @@ std::optional handle_flash_write(const responder&, const Req return ResponseFlashWrite{}; } +static SlotInfo scan_slot(uint32_t flash_offset) { + SlotInfo info{}; + constexpr uint32_t scan_limit = 4096; + auto* scan = reinterpret_cast(XIP_BASE_ADDR + flash_offset); + auto* scan_end = scan + scan_limit / 4; + while (scan < scan_end && *scan != PICOBIN_BLOCK_MARKER_START) scan++; + if (scan >= scan_end) return info; + info.valid = true; + + auto* p = reinterpret_cast(scan + 1); + auto* end = reinterpret_cast(scan + 64); + while (p + 2 <= end) { + uint8_t type = p[0]; + uint8_t size_words = p[1]; + if (type == PICOBIN_BLOCK_ITEM_2BS_LAST) break; + uint32_t item_bytes = static_cast(size_words) * 4; + if (p + item_bytes > end) break; + if (type == PICOBIN_BLOCK_ITEM_1BS_VERSION && size_words >= 2) { + auto* words = reinterpret_cast(p + 4); + uint16_t minor = words[0]; + uint16_t major = words[1]; + info.version = (static_cast(major) << 16) | minor; + } + p += item_bytes; + } + return info; +} + std::optional handle_flash_status(const responder&, const RequestFlashStatus&) { ResponseFlashStatus resp; boot_info_t bi; - if (rom_get_boot_info(&bi)) { + if (rom_get_boot_info(&bi)) resp.boot_partition = bi.partition; - resp.boot_type = bi.boot_type; - } else { + else resp.boot_partition = -1; - resp.boot_type = 0; - } + resp.slot_a = scan_slot(SLOT_A_OFFSET); + resp.slot_b = scan_slot(SLOT_B_OFFSET); return resp; } diff --git a/lib/client/types.go b/lib/client/types.go index c7ccdcf..0bdc69c 100644 --- a/lib/client/types.go +++ b/lib/client/types.go @@ -63,9 +63,17 @@ type RequestReboot struct{} type ResponseReboot struct{} type RequestFlashStatus struct{} + +type SlotInfo struct { + Valid bool + Version uint32 + HashOK bool +} + type ResponseFlashStatus struct { BootPartition int8 - BootType uint8 + SlotA SlotInfo + SlotB SlotInfo } type RequestListTests struct{}