Flash status: scan PICOBIN blocks for per-slot validity and version

This commit is contained in:
Ian Gulliver
2026-04-12 22:22:54 +09:00
parent 819632a7ea
commit 11c101c235
4 changed files with 62 additions and 10 deletions

View File

@@ -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<ResponseFlashWrite> 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<const uint32_t*>(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<const uint8_t*>(scan + 1);
auto* end = reinterpret_cast<const uint8_t*>(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<uint32_t>(size_words) * 4;
if (p + item_bytes > end) break;
if (type == PICOBIN_BLOCK_ITEM_1BS_VERSION && size_words >= 2) {
auto* words = reinterpret_cast<const uint16_t*>(p + 4);
uint16_t minor = words[0];
uint16_t major = words[1];
info.version = (static_cast<uint32_t>(major) << 16) | minor;
}
p += item_bytes;
}
return info;
}
std::optional<ResponseFlashStatus> 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;
}