From 5022616f1d03ac796e83ce5e0af8223a8daee6d1 Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Fri, 12 Apr 2024 20:00:07 -0500 Subject: [PATCH] summarize-gp2040ce --- print information about firmware can be read from a file or over USB Signed-off-by: Brian S. Stephan --- README.md | 18 +++++++++++++++++ gp2040ce_bintools/builder.py | 39 +++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + tests/test_builder.py | 2 +- tests/test_commands.py | 7 +++++++ 5 files changed, 65 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e3826f0..22382c1 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,24 @@ Sample usage: % dump-gp2040ce `date +%Y%m%d`-backup.bin ``` +### summarize-gp2040ce + +`summarize-gp2040ce` prints information regarding the provided USB device or file. It attempts to detect the firmware +and/or board config and/or user config version, which might be useful for confirming files are built properly, or to +determine the lineage of something. + +Sample usage: + +``` +% summarize-gp2040ce --usb +USB device: + +GP2040-CE Information + detected GP2040-CE version: v0.7.8-9-g59e2d19b-dirty + detected board config version: v0.7.8-board-test + detected user config version: v0.7.8-RC2-1-g882235b3 +``` + ### visualize-config `visualize-config` reads a GP2040-CE board's configuration, either over USB or from a dump of the board's flash diff --git a/gp2040ce_bintools/builder.py b/gp2040ce_bintools/builder.py index b7ba1b7..5eb0bfe 100644 --- a/gp2040ce_bintools/builder.py +++ b/gp2040ce_bintools/builder.py @@ -141,7 +141,7 @@ def find_version_string_in_binary(binary: bytes) -> str: match = re.search(b'v[0-9]+.[0-9]+.[0-9]+[A-Za-z0-9-+.]*', binary) if match: return match.group(0).decode(encoding='ascii') - return None + return 'NONE' def get_gp2040ce_from_usb() -> tuple[bytes, object, object]: @@ -335,3 +335,40 @@ def dump_gp2040ce(): content, _, _ = get_gp2040ce_from_usb() with open(args.binary_filename, 'wb') as out_file: out_file.write(content) + + +def summarize_gp2040ce(): + """Provide information on a dump or USB device.""" + parser = argparse.ArgumentParser( + description="Read a file or USB device to determine what GP2040-CE parts are present.", + parents=[core_parser], + ) + input_group = parser.add_mutually_exclusive_group(required=True) + input_group.add_argument('--usb', action='store_true', help="inspect the RP2040 device over USB") + input_group.add_argument('--filename', help="input .bin or .uf2 file to inspect") + + args, _ = parser.parse_known_args() + if args.usb: + content, endpoint, _ = get_gp2040ce_from_usb() + print(f"USB device {hex(endpoint.device.idVendor)}:{hex(endpoint.device.idProduct)}:\n") + else: + with open(args.filename, 'rb') as file_: + content = file_.read() + print(f"File {args.filename}:\n") + + gp2040ce_version = find_version_string_in_binary(content) + try: + board_config = storage.get_config(storage.get_board_storage_section(bytes(content))) + board_config_version = board_config.boardVersion if board_config.boardVersion else "NOT SPECIFIED" + except storage.ConfigReadError: + board_config_version = "NONE" + try: + user_config = storage.get_config(storage.get_user_storage_section(bytes(content))) + user_config_version = user_config.boardVersion if user_config.boardVersion else "NOT FOUND" + except storage.ConfigReadError: + user_config_version = "NONE" + + print("GP2040-CE Information") + print(f" detected GP2040-CE version: {gp2040ce_version}") + print(f" detected board config version: {board_config_version}") + print(f" detected user config version: {user_config_version}") diff --git a/pyproject.toml b/pyproject.toml index fb79595..7bde4e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ concatenate = "gp2040ce_bintools.builder:concatenate" dump-config = "gp2040ce_bintools.storage:dump_config" dump-gp2040ce = "gp2040ce_bintools.builder:dump_gp2040ce" edit-config = "gp2040ce_bintools.gui:edit_config" +summarize-gp2040ce = "gp2040ce_bintools.builder:summarize_gp2040ce" visualize-config = "gp2040ce_bintools.storage:visualize" [tool.flake8] diff --git a/tests/test_builder.py b/tests/test_builder.py index 369ee2d..09c4f48 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -141,7 +141,7 @@ def test_find_version_string(firmware_binary): def test_dont_always_find_version_string(firmware_binary): """Test that we can find a version string in a binary.""" - assert builder.find_version_string_in_binary(b'\x00') is None + assert builder.find_version_string_in_binary(b'\x00') == 'NONE' def test_padding_firmware(firmware_binary): diff --git a/tests/test_commands.py b/tests/test_commands.py index b36abdf..6671ec4 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -64,6 +64,13 @@ def test_concatenate_invocation_json(tmpdir): assert out[2093382:2097152] == storage +def test_summarize_invocation(tmpdir): + """Test that we can get some summary information.""" + result = run(['summarize-gp2040ce', '--filename', 'tests/test-files/test-firmware.bin'], + capture_output=True, encoding='utf8') + assert 'detected GP2040-CE version: v0.7.5' in result.stdout + + def test_storage_dump_invocation(): """Test that a normal invocation against a dump works.""" result = run(['visualize-config', '-P', 'tests/test-files/proto-files',