From f9b86393e15c1d67fcdae8e5c2e0c9c33c972fcc Mon Sep 17 00:00:00 2001 From: BlackMark Date: Mon, 20 Jul 2026 23:17:59 +0200 Subject: [PATCH] build: emit a raw .bin beside the HEX for every loader image MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The host tool takes either form — load_image() parses Intel HEX by extension and treats anything else as raw bytes — but the build emitted only the HEX, so the raw path had no artifact behind it. The reloc and update tests each shell out to objcopy at runtime to produce one for themselves. add_hex_output becomes add_image_outputs and emits both forms. The .bin is byte-identical to the plain `objcopy -O binary` those tests generate (-R .eeprom strips nothing the loaders carry), and decodes equal to the HEX payload — 504 B at 0x7e00 either way for pureboot. Sizes come out at the flash sizes exactly (504/510/836/526), so nothing stretches to the .data load address. Co-Authored-By: Claude Opus 4.8 (1M context) --- CMakeLists.txt | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca7c263..2dd7ce0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,13 +51,18 @@ if(PROJECT_IS_TOP_LEVEL) endif() endif() -# avrdude programs Intel-HEX; the ELF is only a container (symbols, section -# headers) and is never flashed. Every loader image therefore gets a .hex beside -# it at link time. .eeprom is dropped — EEPROM content is its own avrdude update. -function(add_hex_output name) +# The ELF is only a container (symbols, section headers) and is never flashed — +# and the host tool's load_image() dispatches on extension, so handing it one +# would silently program the header bytes. Every loader image therefore gets +# both flashable forms beside it at link time: .hex for avrdude, and .bin for +# the host tool's raw path (which is what the reloc and update tests convert to +# on the fly). .eeprom is dropped — EEPROM content is its own update. +function(add_image_outputs name) add_custom_command(TARGET ${name} POST_BUILD COMMAND ${CMAKE_OBJCOPY} -O ihex -R .eeprom - $ $.hex) + $ $.hex + COMMAND ${CMAKE_OBJCOPY} -O binary -R .eeprom + $ $.bin) endfunction() # The TinySafeBoot protocol reimplemented on libavr in three variants that trade @@ -99,7 +104,7 @@ function(add_tsb_variant name bytes) target_link_options(${name} PRIVATE -nostartfiles -Wl,--section-start=.text=${base_hex} -Wl,--defsym=tsb_app=0 -Wl,--pmem-wrap-around=32k) add_custom_command(TARGET ${name} POST_BUILD COMMAND ${CMAKE_SIZE} $) - add_hex_output(${name}) + add_image_outputs(${name}) if(PROJECT_IS_TOP_LEVEL) add_test(NAME ${name}.size COMMAND ${CMAKE_COMMAND} -DSIZE_TOOL=${CMAKE_SIZE} -DELF=$ @@ -176,7 +181,7 @@ target_compile_definitions(pureboot PRIVATE PUREBOOT_TIMEOUT=${PUREBOOT_TIMEOUT} target_link_options(pureboot PRIVATE -nostartfiles -Wl,--section-start=.text=${_pb_base_hex} -Wl,--defsym=pureboot_app=${_pb_app} ${_pb_wrap}) add_custom_command(TARGET pureboot POST_BUILD COMMAND ${CMAKE_SIZE} $) -add_hex_output(pureboot) +add_image_outputs(pureboot) if(PROJECT_IS_TOP_LEVEL) add_test(NAME pureboot.size COMMAND ${CMAKE_COMMAND} -DSIZE_TOOL=${CMAKE_SIZE} -DELF=$ @@ -225,7 +230,7 @@ if(PROJECT_IS_TOP_LEVEL) target_compile_definitions(pureboot9 PRIVATE PUREBOOT_TIMEOUT=9) target_link_options(pureboot9 PRIVATE -nostartfiles -Wl,--section-start=.text=${_pb_base_hex} -Wl,--defsym=pureboot_app=${_pb_app} ${_pb_wrap}) - add_hex_output(pureboot9) + add_image_outputs(pureboot9) add_test(NAME pureboot.update COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/pbupdate.py ${PB_DEVICE} $ $ ${LIBAVR_MCU}