refactor(nordic): migrate away from pm_static towards DTS fixed-partitions
What changed, and why it matters
This is a build-system refactor for Trezor's Nordic Bluetooth chip firmware. It removes manually maintained flash partition files and switches to Zephyr's standard device-tree partition definitions. The change also fixes a build-time signing script bug where a duplicate image header could be inserted, which would cause the device to crash immediately on boot. There is no direct evidence this is a security vulnerability patch, but it prevents a real boot failure in the manufacturing/development workflow.
Treat as a normal build-system refactor. Verify that DTS fixed-partitions produce identical flash addresses/sizes to the removed pm_static.yml files and that signed images boot correctly. No urgent security response is indicated by the commit itself.
Security signals we found
Build script now prevents duplicate MCUboot image header that would cause immediate hardfault on jump
Partition layout source of truth moved from static YAML to DTS fixed-partitions, reducing risk of inconsistent layout definitions
Added runtime error handling for read_image_sha256 in management.c
No changelog entry suggests developer did not classify as security-relevant
Evidence from the diff
The commit migrates three Nordic applications (direct_test_mode, radio_test, trezor-ble) from Nordic Partition Manager static YAML files (pm_static.yml) to Zephyr DTS fixed-partitions by disabling SB_CONFIG_PARTITION_MANAGER. It updates the build_sign_flash.sh script to strip the Zephyr-emitted 0x200-byte ROM start offset placeholder before invoking imgtool –pad-header, preventing a double-header that would misalign the vector table. It also changes trezor-ble’s management.c to use FIXED_PARTITION_ID(slot0_partition) instead of FLASH_AREA_ID(image_0) and adds error handling for read_image_sha256. The commit is tagged [no changelog] and framed as a refactor.
Changed components
nordic/trezor/direct_test_modenordic/trezor/radio_testnordic/trezor/trezor-blenordic/trezor/scripts/build_sign_flash.shMCUboot signing and flashing pipeline for Nordic buildsInspect captured patch +28 / −93
diff --git a/nordic/trezor/direct_test_mode/pm_static.yml b/nordic/trezor/direct_test_mode/pm_static.yml
deleted file mode 100644
index db8b4b53..00000000
--- a/nordic/trezor/direct_test_mode/pm_static.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-mcuboot:
- address: 0x0
- size: 0xc000
-custom_data:
- address: 0xc000
- size: 0x2000
-mcuboot_pad:
- address: 0xe000
- size: 0x200
-app:
- address: 0xe200
- size: 0x6be00
-mcuboot_primary:
- orig_span: &id001
- - mcuboot_pad
- - app
- span: *id001
- address: 0xe000
- size: 0x6c000
-mcuboot_primary_app:
- orig_span: &id002
- - app
- span: *id002
- address: 0xe200
- size: 0x6be00
-settings_storage:
- address: 0x7a000
- size: 0x6000
-
diff --git a/nordic/trezor/direct_test_mode/sysbuild.conf b/nordic/trezor/direct_test_mode/sysbuild.conf
index 913fce04..3be85567 100644
--- a/nordic/trezor/direct_test_mode/sysbuild.conf
+++ b/nordic/trezor/direct_test_mode/sysbuild.conf
@@ -7,3 +7,6 @@
# Enable MCUboot
SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
+
+# Use DTS fixed-partitions instead of pm_static.yml
+SB_CONFIG_PARTITION_MANAGER=n
diff --git a/nordic/trezor/radio_test/pm_static.yml b/nordic/trezor/radio_test/pm_static.yml
deleted file mode 100644
index db8b4b53..00000000
--- a/nordic/trezor/radio_test/pm_static.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-mcuboot:
- address: 0x0
- size: 0xc000
-custom_data:
- address: 0xc000
- size: 0x2000
-mcuboot_pad:
- address: 0xe000
- size: 0x200
-app:
- address: 0xe200
- size: 0x6be00
-mcuboot_primary:
- orig_span: &id001
- - mcuboot_pad
- - app
- span: *id001
- address: 0xe000
- size: 0x6c000
-mcuboot_primary_app:
- orig_span: &id002
- - app
- span: *id002
- address: 0xe200
- size: 0x6be00
-settings_storage:
- address: 0x7a000
- size: 0x6000
-
diff --git a/nordic/trezor/radio_test/sysbuild.conf b/nordic/trezor/radio_test/sysbuild.conf
index 913fce04..3be85567 100644
--- a/nordic/trezor/radio_test/sysbuild.conf
+++ b/nordic/trezor/radio_test/sysbuild.conf
@@ -7,3 +7,6 @@
# Enable MCUboot
SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
+
+# Use DTS fixed-partitions instead of pm_static.yml
+SB_CONFIG_PARTITION_MANAGER=n
diff --git a/nordic/trezor/scripts/build_sign_flash.sh b/nordic/trezor/scripts/build_sign_flash.sh
index b71783c8..c498f0de 100755
--- a/nordic/trezor/scripts/build_sign_flash.sh
+++ b/nordic/trezor/scripts/build_sign_flash.sh
@@ -15,6 +15,8 @@ FLASH=0
PRISTINE=
DEBUG=
PRODUCTION=
+HEADER_SIZE=0x200
+SLOT_ADDR=0xe000
fatal() {
echo "$@"
@@ -127,9 +129,16 @@ VERSION=$(get_version_from_file)
# Update paths in signing and flashing commands
if [ "$SIGN" -eq 1 ]; then
+ # zephyr.bin already contains a HEADER_SIZE-byte zero placeholder at offset 0
+ # (emitted by Zephyr linker via CONFIG_ROM_START_OFFSET). Strip it so that
+ # --pad-header does not prepend a second copy, which would push the vector
+ # table to slot_addr+2*HEADER_SIZE and cause an immediate hardfault on jump.
+ dd if="build/$APP_DIR/zephyr/zephyr.bin" bs=1 skip="$((HEADER_SIZE))" \
+ of="build/$APP_DIR/zephyr/zephyr_nohdr.bin" \
+ || { rm -f "build/$APP_DIR/zephyr/zephyr_nohdr.bin"; fatal "dd failed to strip header from zephyr.bin"; }
+
run_under_ncs_subshell \
- "imgtool sign --version $VERSION --align 4 --header-size 0x200 -S 0x6c000 --pad-header build/$APP_DIR/zephyr/zephyr.bin build/$APP_DIR/zephyr/zephyr.prep.bin --custom-tlv 0x00A2 0x03 --custom-tlv 0x00A3 0x54335731 && \
- imgtool sign --version $VERSION --align 4 --header-size 0x200 -S 0x6c000 --pad-header build/$APP_DIR/zephyr/zephyr.hex build/$APP_DIR/zephyr/zephyr.prep.hex --custom-tlv 0x00A2 0x03 --custom-tlv 0x00A3 0x54335731 && \
+ "imgtool sign --version $VERSION --align 4 --header-size $HEADER_SIZE -S 0x6c000 --pad-header build/$APP_DIR/zephyr/zephyr_nohdr.bin build/$APP_DIR/zephyr/zephyr.prep.bin --custom-tlv 0x00A2 0x03 --custom-tlv 0x00A3 0x54335731 && \
../bootloader/mcuboot/scripts/imgtool.py dumpinfo ./build/$APP_DIR/zephyr/zephyr.prep.bin > ./build/$APP_DIR/zephyr/dump.txt"
HASH=$(python ./scripts/extract_hash.py ./build/$APP_DIR/zephyr/dump.txt)
@@ -138,12 +147,12 @@ if [ "$SIGN" -eq 1 ]; then
echo "Signed hash $HASH, signature0 $SIGNATURE0, signature1 $SIGNATURE1"
run_under_ncs_subshell \
- "python ./scripts/insert_signatures.py ./build/$APP_DIR/zephyr/zephyr.prep.hex $SIGNATURE0 $SIGNATURE1 -o ./build/$APP_DIR/zephyr/zephyr.signed_trz.hex && \
- python ./scripts/insert_signatures.py ./build/$APP_DIR/zephyr/zephyr.prep.bin $SIGNATURE0 $SIGNATURE1 -o ./build/$APP_DIR/zephyr/zephyr.signed_trz.bin && \
+ "python ./scripts/insert_signatures.py ./build/$APP_DIR/zephyr/zephyr.prep.bin $SIGNATURE0 $SIGNATURE1 -o ./build/$APP_DIR/zephyr/zephyr.signed_trz.bin && \
+ python -c \"from intelhex import IntelHex; ih = IntelHex(); ih.loadbin('build/$APP_DIR/zephyr/zephyr.signed_trz.bin', offset=$SLOT_ADDR); ih.tofile('build/$APP_DIR/zephyr/zephyr.signed_trz.hex', format='hex')\" && \
python ../zephyr/scripts/build/mergehex.py build/mcuboot/zephyr/zephyr.hex build/$APP_DIR/zephyr/zephyr.signed_trz.hex -o build/zephyr.merged.signed_trz.hex"
fi
if [ "$FLASH" -eq 1 ]; then
run_under_ncs_subshell \
- 'west flash --hex-file ./build/zephyr.merged.signed_trz.hex'
+ "west flash --domain \"$APP_DIR\" --hex-file ./build/zephyr.merged.signed_trz.hex"
fi
diff --git a/nordic/trezor/trezor-ble/pm_static.yml b/nordic/trezor/trezor-ble/pm_static.yml
deleted file mode 100644
index db8b4b53..00000000
--- a/nordic/trezor/trezor-ble/pm_static.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-mcuboot:
- address: 0x0
- size: 0xc000
-custom_data:
- address: 0xc000
- size: 0x2000
-mcuboot_pad:
- address: 0xe000
- size: 0x200
-app:
- address: 0xe200
- size: 0x6be00
-mcuboot_primary:
- orig_span: &id001
- - mcuboot_pad
- - app
- span: *id001
- address: 0xe000
- size: 0x6c000
-mcuboot_primary_app:
- orig_span: &id002
- - app
- span: *id002
- address: 0xe200
- size: 0x6be00
-settings_storage:
- address: 0x7a000
- size: 0x6000
-
diff --git a/nordic/trezor/trezor-ble/src/management/management.c b/nordic/trezor/trezor-ble/src/management/management.c
index fd300beb..be170a2b 100644
--- a/nordic/trezor/trezor-ble/src/management/management.c
+++ b/nordic/trezor/trezor-ble/src/management/management.c
@@ -155,7 +155,11 @@ static void send_info(void) {
data[7] = 0;
data[8] = signals_out_get_reserved();
- read_image_sha256(FLASH_AREA_ID(image_0), &data[9]);
+ int rc = read_image_sha256(FIXED_PARTITION_ID(slot0_partition), &data[9]);
+ if (rc < 0) {
+ LOG_ERR("Failed to read image SHA-256: %d", rc);
+ return;
+ }
trz_comm_send_msg(NRF_SERVICE_MANAGEMENT, data, sizeof(data));
}
diff --git a/nordic/trezor/trezor-ble/sysbuild.conf b/nordic/trezor/trezor-ble/sysbuild.conf
index 00dcdb4d..45f611d5 100644
--- a/nordic/trezor/trezor-ble/sysbuild.conf
+++ b/nordic/trezor/trezor-ble/sysbuild.conf
@@ -3,3 +3,6 @@
# Enable MCUboot
SB_CONFIG_BOOTLOADER_MCUBOOT=y
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
+
+# Use DTS fixed-partitions instead of pm_static.yml
+SB_CONFIG_PARTITION_MANAGER=n
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.