From 2bb049c442c7cb05e0bb02b7037c839e09481b3c Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Sun, 14 Apr 2024 22:54:05 -0500 Subject: [PATCH] take multiple binary arguments to convert_binary_to_uf2 this is in preparation for making smaller .uf2 files buy not needing padding, instead passing multiple location+binary combos to the converter Signed-off-by: Brian S. Stephan --- gp2040ce_bintools/builder.py | 12 +++++---- gp2040ce_bintools/storage.py | 48 +++++++++++++++++++----------------- tests/test_storage.py | 10 ++++---- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/gp2040ce_bintools/builder.py b/gp2040ce_bintools/builder.py index fee7551..502545c 100644 --- a/gp2040ce_bintools/builder.py +++ b/gp2040ce_bintools/builder.py @@ -117,9 +117,10 @@ def concatenate_firmware_and_storage_files(firmware_filename: str, # the correct way to do the above would be to pass a list of {offset,binary_data} to convert..., # and have it calculate the total block size before starting to write, and then iterating over # the three lists. doable, just not on the top of my mind right now - new_binary = storage.convert_binary_to_uf2(combine_firmware_and_config(firmware_binary, board_config_binary, - user_config_binary, - replace_extra=replace_extra)) + new_binary = storage.convert_binary_to_uf2([ + (0, combine_firmware_and_config(firmware_binary, board_config_binary, user_config_binary, + replace_extra=replace_extra)), + ]) if combined_filename: with open(combined_filename, 'wb') as combined: @@ -256,8 +257,9 @@ def write_new_config_to_filename(config: Message, filename: str, inject: bool = binary = storage.serialize_config_with_footer(config) with open(filename, 'wb') as file: if filename[-4:] == '.uf2': - file.write(storage.convert_binary_to_uf2(storage.pad_config_to_storage_size(binary), - start=storage.USER_CONFIG_BINARY_LOCATION)) + file.write(storage.convert_binary_to_uf2([ + (storage.USER_CONFIG_BINARY_LOCATION, storage.pad_config_to_storage_size(binary)), + ])) else: file.write(binary) diff --git a/gp2040ce_bintools/storage.py b/gp2040ce_bintools/storage.py index b4bf517..55e4d34 100644 --- a/gp2040ce_bintools/storage.py +++ b/gp2040ce_bintools/storage.py @@ -53,36 +53,37 @@ class ConfigMagicError(ConfigReadError): """Exception raised when the config section does not have the magic value in its footer.""" -def convert_binary_to_uf2(binary: bytearray, start: int = 0) -> bytearray: +def convert_binary_to_uf2(binaries: list[tuple[int, bytearray]]) -> bytearray: """Convert a GP2040-CE binary payload to Microsoft's UF2 format. https://github.com/microsoft/uf2/tree/master#overview Args: - binary: bytearray content to convert to a UF2 payload - start: position offset to start at rather than flash start (for creating e.g. user config UF2s) + binaries: list of start,binary pairs of binary data to write at the specified memory offset in flash Returns: the content in UF2 format """ - size = len(binary) - blocks = (len(binary) // 256) + 1 if len(binary) % 256 else len(binary) // 256 - uf2 = bytearray() + total_blocks = sum([(len(binary) // 256) + 1 if len(binary) % 256 else len(binary) // 256 + for offset, binary in binaries]) - index = 0 - while index < size: - pad_count = 476 - len(binary[index:index+256]) - uf2 += struct.pack(' 512 b chunks assert uf2[0:4] == b'\x55\x46\x32\x0a' == b'UF2\n' # proper magic assert uf2[8:12] == bytearray(b'\x00\x20\x00\x00') # family ID set @@ -151,7 +151,7 @@ def test_convert_unaligned_binary_to_uf2(firmware_binary): def test_convert_binary_to_uf2_with_offsets(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, start=storage.USER_CONFIG_BINARY_LOCATION) + uf2 = storage.convert_binary_to_uf2([{storage.USER_CONFIG_BINARY_LOCATION, whole_board_with_board_config_dump}]) assert len(uf2) == 4194304 # binary is 8192 256 byte chunks, UF2 is 512 b per chunk assert uf2[0:4] == b'\x55\x46\x32\x0a' == b'UF2\n' # proper magic assert uf2[8:12] == bytearray(b'\x00\x20\x00\x00') # family ID set @@ -160,7 +160,7 @@ def test_convert_binary_to_uf2_with_offsets(whole_board_with_board_config_dump): 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) + uf2 = storage.convert_binary_to_uf2([{0, 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 @@ -168,7 +168,7 @@ def test_convert_binary_to_uf2_to_binary(whole_board_with_board_config_dump): def test_malformed_uf2(whole_board_with_board_config_dump): """Check that we expect a properly-formed UF2.""" - uf2 = storage.convert_binary_to_uf2(whole_board_with_board_config_dump) + uf2 = storage.convert_binary_to_uf2([{0, whole_board_with_board_config_dump}]) # truncated UF2 --- byte mismatch with pytest.raises(ValueError):