-
Notifications
You must be signed in to change notification settings - Fork 158
Description
Summary:
picotool reports “hash incorrect” for a valid RP2350 packaged image when the LOAD_MAP uses a physical address (as required by bootrom). The bootrom translates physical to storage using the partition base, but picotool appears to hash from the physical address directly.
Repro (minimal):
- Use the PoC script: https://gist.github.com/u6bkep/84ea4cdfb20638765c658c0747c517b9
- Run the script to generate the UF2.
- Flash UF2 to a Pico 2 in BOOTSEL. (drag and drop)
- Run: picotool info -a
- Observe: Partition 2 shows hash incorrect.
Expected:
picotool should translate LOAD_MAP physical addresses by the partition base (lma_to_storage) and report hash correct.
Actual:
picotool hashes from the physical address (e.g., 0x10000200) and reports incorrect hash/signature.
Why this is a bug:
Bootrom source (RP2350) adds lma_to_storage for non‑relative LOAD_MAP entries before hashing/copying, so the data at partition_base + offset is used. picotool is not applying this translation, leading to a mismatch.
Notes:
- The PoC defines the hashed region fully via LOAD_MAP and places data only at the translated address.
- Bootrom behavior: adds partition base offset for LOAD_MAP absolute/physical addresses.
Bootrom translation (adds partition base before hashing/copying):
varm_blocks.c
uint32_t lma_to_storage = parsed_block->enclosing_window.base + parsed_block->slot_roll - XIP_BASE +
((const parsed_image_def_t *)parsed_block)->rolling_window_delta;
...
from_storage_addr = map_storage_address_value;
if (!picobin_load_map_is_relative(load_map)) {
if (!call_varm_is_sram_or_xip_ram(from_storage_addr)) {
from_storage_addr += lma_to_storage;
}
}picotool hashing (uses entry.storage_address directly, no partition-base translation):
bintool.cpp
for (const auto &entry : load_map->entries) {
uint32_t current_storage_address = entry.storage_address;
...
auto seg = elf->segment_from_physical_address(current_storage_address);
...
uint32_t offset = current_storage_address - seg->physical_address();
...
DEBUG_LOG("HASH %08x + %08x\n", (int)entry.storage_address, (int)data.size());
}Parsing of LOAD_MAP absolute entries also leaves storage_address unchanged:
metadata.h
if (storage_address != 0) {
if (absolute) {
size -= runtime_address;
} else {
storage_address += current_addr;
}
}picotool output
Metadata Block 2
address: 0x10000000
next block address: 0x10000000
block type: image def
target chip: RP2350
image type: ARM Secure
load map entry 0: Copy 0x10000200->0x10000300 to 0x20000000->0x20000100
hash: incorrect
hash value: 725443BF7AE1F98D6B22C1943F1FDB40A1EF1A806BB996D277F751543DE62C9B