allow for reading UF2 files in visualize-config

Signed-off-by: Brian S. Stephan <bss@incorporeal.org>
This commit is contained in:
Brian S. Stephan 2024-04-12 16:21:20 -05:00
parent 2ce0c4d7df
commit 6bc93f148b
Signed by: bss
GPG Key ID: 3DE06D3180895FCB
2 changed files with 46 additions and 1 deletions

View File

@ -86,6 +86,40 @@ def convert_binary_to_uf2(binary: bytearray, start: int = 0) -> bytearray:
return uf2
def convert_uf2_to_binary(uf2: bytearray) -> bytearray:
"""Convert a Microsoft's UF2 payload to a raw binary.
https://github.com/microsoft/uf2/tree/master#overview
Args:
uf2: bytearray content to convert from a UF2 payload
Returns:
the content in sequential binary format
"""
if len(uf2) % 512 != 0:
raise ValueError(f"provided binary is length {len(uf2)}, which isn't fully divisible by 512!")
binary = bytearray()
old_uf2_addr = None
for index in range(0, len(uf2), 512):
chunk = uf2[index:index+512]
_, _, _, uf2_addr, bytes_, block_num, block_count, _ = struct.unpack('<LLLLLLLL', chunk[0:32])
content = chunk[32:508]
if block_num != index // 512:
raise ValueError(f"inconsistent block number in reading UF2, got {block_num}, expected {index // 512}!")
if block_count != len(uf2) // 512:
raise ValueError(f"inconsistent block count in reading UF2, got {block_count}, expected {len(uf2) // 512}!")
# the UF2 is indexed, which we could convert to binary with padding 0s, but we don't yet
if old_uf2_addr and (uf2_addr != old_uf2_addr + 256):
raise ValueError("segmented UF2 files are not yet supported!")
binary += content[0:bytes_]
old_uf2_addr = uf2_addr
return binary
def get_config(content: bytes) -> Message:
"""Read the config from a GP2040-CE storage section.
@ -178,7 +212,10 @@ def get_config_from_file(filename: str, whole_board: bool = False, allow_no_file
"""
try:
with open(filename, 'rb') as dump:
content = dump.read()
if filename[-4:] == '.uf2':
content = bytes(convert_uf2_to_binary(dump.read()))
else:
content = dump.read()
except FileNotFoundError:
if not allow_no_file:
raise

View File

@ -158,6 +158,14 @@ def test_convert_binary_to_uf2_with_offsets(whole_board_with_board_config_dump):
assert uf2[524:528] == bytearray(b'\x00\xc1\x1f\x10') # address to write the second chunk
def test_convert_binary_to_uf2_to_binary(whole_board_with_board_config_dump):
"""Do some sanity checks in the attempt to convert a binary to a UF2."""
uf2 = storage.convert_binary_to_uf2(whole_board_with_board_config_dump)
binary = storage.convert_uf2_to_binary(uf2)
assert len(binary) == 2097152
assert whole_board_with_board_config_dump == binary
@with_pb2s
def test_serialize_config_with_footer(storage_dump, config_binary):
"""Test that reserializing a read in config matches the original.