Skip to content

Commit ab3d000

Browse files
committed
bootloader: changes needed NSIB for nRF54H without PM
This commit introduces the changes needed for running the NSIB on nRF54H - currently when running an application-core only application. Note: the NSIB is still experimental, as OTP memory is not handled properly - MRAM is used instead. Signed-off-by: Artur Hadasz <[email protected]>
1 parent 4b58475 commit ab3d000

29 files changed

+681
-177
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@
345345
/include/dfu/dfu_target_suit.h @nrfconnect/ncs-charon
346346
/include/dfu/suit_dfu_fetch_source.h @nrfconnect/ncs-charon
347347
/include/dfu/suit_dfu.h @nrfconnect/ncs-charon
348+
/include/bl_partitions.h @nrfconnect/ncs-charon
348349
/include/drivers/flash/ @nrfconnect/ncs-co-drivers
349350
/include/drivers/flash/flash_ipuc.h @nrfconnect/ncs-co-drivers @nrfconnect/ncs-charon
350351
/include/drivers/gpio/ @nrfconnect/ncs-co-drivers @nrfconnect/ncs-ll-ursus

cmake/sysbuild/b0_mcuboot_signing.cmake

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
# Since this file is brought in via include(), we do the work in a
1111
# function to avoid polluting the top-level scope.
1212

13+
include(${CMAKE_CURRENT_LIST_DIR}/bootloader_dts_utils.cmake)
14+
1315
function(ncs_secure_boot_mcuboot_sign application bin_files signed_targets prefix)
1416
find_program(IMGTOOL imgtool.py HINTS ${ZEPHYR_MCUBOOT_MODULE_DIR}/scripts/ NAMES imgtool NAMES_PER_DIR)
1517
set(keyfile "${SB_CONFIG_BOOT_SIGNATURE_KEY_FILE}")
@@ -26,7 +28,20 @@ function(ncs_secure_boot_mcuboot_sign application bin_files signed_targets prefi
2628
sysbuild_get(CONFIG_BUILD_OUTPUT_HEX IMAGE ${application} VAR CONFIG_BUILD_OUTPUT_HEX KCONFIG)
2729

2830
string(TOUPPER "${application}" application_uppercase)
29-
set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign --version ${SB_CONFIG_SECURE_BOOT_MCUBOOT_VERSION} --align 4 --slot-size $<TARGET_PROPERTY:partition_manager,${prefix}PM_${application_uppercase}_SIZE> --pad-header --header-size ${SB_CONFIG_PM_MCUBOOT_PAD})
31+
if(SB_CONFIG_PARTITION_MANAGER)
32+
set(slot_size $<TARGET_PROPERTY:partition_manager,${prefix}PM_${application_uppercase}_SIZE>)
33+
set(mcuboot_pad ${SB_CONFIG_PM_MCUBOOT_PAD})
34+
set(pad_header "--pad-header")
35+
else()
36+
dt_chosen(code_partition_node TARGET ${application} PROPERTY "zephyr,code-partition")
37+
dt_reg_size(slot_size TARGET ${application} PATH ${code_partition_node})
38+
sysbuild_get(mcuboot_pad IMAGE ${application} VAR CONFIG_ROM_START_OFFSET KCONFIG)
39+
40+
# The padding has already been added to the image by CONFIG_ROM_START_OFFSET
41+
set(pad_header)
42+
endif()
43+
44+
set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign --version ${SB_CONFIG_SECURE_BOOT_MCUBOOT_VERSION} --align 4 --slot-size ${slot_size} ${pad_header} --header-size ${mcuboot_pad})
3045

3146
if(SB_CONFIG_MCUBOOT_HARDWARE_DOWNGRADE_PREVENTION)
3247
set(imgtool_extra --security-counter ${SB_CONFIG_MCUBOOT_HW_DOWNGRADE_PREVENTION_COUNTER_VALUE})
@@ -101,6 +116,11 @@ function(ncs_secure_boot_mcuboot_sign application bin_files signed_targets prefi
101116
${application_image_dir}/zephyr/.config
102117
${CMAKE_BINARY_DIR}/signed_by_b0_${application}.hex
103118
)
119+
120+
set_property(
121+
GLOBAL APPEND PROPERTY NORDIC_SECURE_BOOT_HEX_FILES_TO_MERGE
122+
${output}.hex
123+
)
104124
endif()
105125

106126
# Add the west sign calls and their byproducts to the post-processing
@@ -132,21 +152,32 @@ if(SB_CONFIG_BOOTLOADER_MCUBOOT)
132152

133153
if(SB_CONFIG_SECURE_BOOT_BUILD_S1_VARIANT_IMAGE)
134154
ncs_secure_boot_mcuboot_sign(s1_image "${bin_files}" "${signed_targets}" "")
135-
set(extra_bin_data "signed_by_mcuboot_and_b0_s1_image.binload_address=$<TARGET_PROPERTY:partition_manager,PM_S1_ADDRESS>;signed_by_mcuboot_and_b0_s1_image.binslot=1")
155+
if(SB_CONFIG_PARTITION_MANAGER)
156+
set(slot1_addr $<TARGET_PROPERTY:partition_manager,PM_S1_ADDRESS>)
157+
else()
158+
nsib_get_s1_address(slot1_addr)
159+
endif()
160+
set(extra_bin_data "signed_by_mcuboot_and_b0_s1_image.binload_address=${slot1_addr};signed_by_mcuboot_and_b0_s1_image.binslot=1")
136161
endif()
137162

138163
if(bin_files)
139164
sysbuild_get(mcuboot_fw_info_firmware_version IMAGE mcuboot VAR CONFIG_FW_INFO_FIRMWARE_VERSION KCONFIG)
140165

141166
include(${ZEPHYR_NRF_MODULE_DIR}/cmake/fw_zip.cmake)
142167

168+
if(SB_CONFIG_PARTITION_MANAGER)
169+
set(slot0_addr $<TARGET_PROPERTY:partition_manager,PM_S0_ADDRESS>)
170+
else()
171+
nsib_get_s0_address(slot0_addr)
172+
endif()
173+
143174
generate_dfu_zip(
144175
OUTPUT ${CMAKE_BINARY_DIR}/dfu_mcuboot.zip
145176
BIN_FILES ${bin_files}
146177
TYPE mcuboot
147178
IMAGE mcuboot
148179
SCRIPT_PARAMS
149-
"signed_by_mcuboot_and_b0_mcuboot.binload_address=$<TARGET_PROPERTY:partition_manager,PM_S0_ADDRESS>"
180+
"signed_by_mcuboot_and_b0_mcuboot.binload_address=${slot0_addr}"
150181
${extra_bin_data}
151182
"version_MCUBOOT=${SB_CONFIG_SECURE_BOOT_MCUBOOT_VERSION}"
152183
"version_B0=${mcuboot_fw_info_firmware_version}"
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Copyright (c) 2025 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
3+
4+
# This file contains utility functions used for handling
5+
# data coming from the devicetree for configurations using
6+
# a bootloader.
7+
# It contains helper functions used to get the addresses of
8+
# specific bootloader patitions as well as
9+
# functions that are used to verify the
10+
# that devicetrees of the images are consistent with each other
11+
# and with the current bootloader configuration.
12+
13+
function(get_address_from_dt_partition_nodelabel label address)
14+
dt_nodelabel(partition_node TARGET ${DEFAULT_IMAGE} NODELABEL ${label} REQUIRED)
15+
dt_reg_addr(partition_offset TARGET ${DEFAULT_IMAGE} PATH ${partition_node})
16+
17+
# Get the parent "two levels up" (../../) of the partition node
18+
# This is the partition flash area node
19+
string(REPLACE "/" ";" partition_node_split ${partition_node})
20+
list(LENGTH partition_node_split child_path_length)
21+
math(EXPR parent_path_length "${child_path_length} - 2")
22+
list(SUBLIST partition_node_split 0 ${parent_path_length} parent_path_split)
23+
string(REPLACE ";" "/" flash_area_node "${parent_path_split}")
24+
25+
dt_reg_addr(flash_area_addr TARGET ${DEFAULT_IMAGE} PATH ${flash_area_node})
26+
27+
math(EXPR ${address} "${flash_area_addr} + ${partition_offset}")
28+
set(${address} ${${address}} PARENT_SCOPE)
29+
endfunction()
30+
31+
#
32+
# Verify that the code partition for a given image matches a specific node label.
33+
#
34+
function(code_partition_matches_label_verify label image)
35+
dt_nodelabel(label_node TARGET ${image} NODELABEL ${label})
36+
dt_chosen(code_partition_node TARGET ${image} PROPERTY "zephyr,code-partition")
37+
38+
if (NOT "${code_partition_node}" STREQUAL "${label_node}")
39+
message(FATAL_ERROR "
40+
ERROR: zephyr,code-partition for image ${image}
41+
does not match label ${label}.
42+
This is required by the current bootloader configuration.
43+
zephyr,code-partition node:
44+
${code_partition_node}
45+
${label} node:
46+
${label_node}
47+
\n"
48+
)
49+
endif()
50+
endfunction()
51+
52+
#
53+
# Verify that the required node labels for all images point to the same nodes
54+
# as for the default image
55+
#
56+
function(labels_match_for_all_images_verify labels)
57+
foreach(label ${labels})
58+
dt_nodelabel(default_image_node TARGET ${DEFAULT_IMAGE} NODELABEL ${label} REQUIRED)
59+
foreach(image ${IMAGES})
60+
dt_nodelabel(node TARGET ${image} NODELABEL ${label} REQUIRED)
61+
if (NOT "${node}" STREQUAL "${default_image_node}")
62+
message(FATAL_ERROR "
63+
ERROR: Node pointed by ${label} for image ${image}
64+
does not match the node for the default image ${DEFAULT_IMAGE}.
65+
Node for default image ${DEFAULT_IMAGE}: ${default_image_node}
66+
Node for image ${image}: ${label_node}
67+
\n"
68+
)
69+
endif()
70+
endforeach()
71+
endforeach()
72+
endfunction()
73+
74+
function(verify_bootloader_dts_configuration)
75+
set(required_labels_list)
76+
set(nordic_bootloader_vars_names)
77+
78+
# Create a list of all devicetree labels that are required for
79+
# the current bootloader configuration.
80+
if(SB_CONFIG_SECURE_BOOT)
81+
list(APPEND required_labels_list "b0_partition" "provision_partition" "s0_partition")
82+
endif()
83+
if(SB_CONFIG_BOOTLOADER_MCUBOOT)
84+
list(APPEND required_labels_list "boot_partition")
85+
list(APPEND required_labels_list "slot0_partition")
86+
list(APPEND required_labels_list "slot1_partition")
87+
endif()
88+
if(SB_CONFIG_SECURE_BOOT_BUILD_S1_VARIANT_IMAGE)
89+
list(APPEND required_labels_list "s1_partition")
90+
endif()
91+
92+
# Check that the labels are present for all images and that they point to the same nodes
93+
# for each of the images.
94+
# This way we can treat a devicetree from any of the images as the source of truth for
95+
# the whole system when it comes to the required node labels.
96+
labels_match_for_all_images_verify("${required_labels_list}")
97+
98+
# Verify that the zephyr,code-partition chosen node for each of the images
99+
# points to the expected node labels
100+
if(SB_CONFIG_BOOTLOADER_MCUBOOT)
101+
code_partition_matches_label_verify("slot0_partition" "${DEFAULT_IMAGE}")
102+
elseif(SB_CONFIG_SECURE_BOOT)
103+
code_partition_matches_label_verify("s0_partition" "${DEFAULT_IMAGE}")
104+
endif()
105+
106+
if(SB_CONFIG_SECURE_BOOT)
107+
code_partition_matches_label_verify("b0_partition" "b0")
108+
endif()
109+
if(SB_CONFIG_SECURE_BOOT_BUILD_S1_VARIANT_IMAGE)
110+
code_partition_matches_label_verify("s1_partition" "s1_image")
111+
endif()
112+
113+
if(SB_CONFIG_BOOTLOADER_MCUBOOT)
114+
code_partition_matches_label_verify("boot_partition" "mcuboot")
115+
if(SB_CONFIG_SECURE_BOOT)
116+
# In the B0 + MCUBOOT configuration s0_partition points to boot_partition
117+
code_partition_matches_label_verify("s0_partition" "mcuboot")
118+
endif()
119+
endif()
120+
endfunction()
121+
122+
function(nsib_get_s0_address address)
123+
set(s0_label "s0_partition")
124+
get_address_from_dt_partition_nodelabel(${s0_label} ${address})
125+
set(${address} ${${address}} PARENT_SCOPE)
126+
endfunction()
127+
128+
function(nsib_get_s1_address address)
129+
set(s1_label "s1_partition")
130+
get_address_from_dt_partition_nodelabel(${s1_label} ${address})
131+
set(${address} ${${address}} PARENT_SCOPE)
132+
endfunction()
133+
134+
function(nsib_get_provision_address address)
135+
get_address_from_dt_partition_nodelabel("provision_partition" ${address})
136+
set(${address} ${${address}} PARENT_SCOPE)
137+
endfunction()

cmake/sysbuild/image_signing.cmake

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ function(zephyr_mcuboot_tasks)
5858
# Fetch devicetree details for flash and slot information
5959
dt_chosen(flash_node PROPERTY "zephyr,flash")
6060
dt_nodelabel(slot0_flash NODELABEL "slot0_partition" REQUIRED)
61-
dt_prop(slot_size PATH "${slot0_flash}" PROPERTY "reg" INDEX 1 REQUIRED)
61+
dt_reg_size(slot_size PATH "${slot0_flash}" REQUIRED)
6262
dt_prop(write_block_size PATH "${flash_node}" PROPERTY "write-block-size")
6363

6464
if(NOT write_block_size)
@@ -81,13 +81,17 @@ function(zephyr_mcuboot_tasks)
8181
endif()
8282
endif()
8383

84-
# Split fields, imgtool_sign_sysbuild is stored in cache which will have fields updated by
85-
# sysbuild, imgtool_sign must not be stored in cache because it would then prevent those fields
86-
# from being updated without a pristine build
87-
# TODO: NCSDK-28461 sysbuild PM fields cannot be updated without a pristine build, will become
88-
# invalid if a static PM file is updated without pristine build
89-
set(imgtool_sign_sysbuild --slot-size @PM_MCUBOOT_PRIMARY_SIZE@ --pad-header --header-size @PM_MCUBOOT_PAD_SIZE@ ${imgtool_rom_command} CACHE STRING "imgtool sign sysbuild replacement")
90-
set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign --version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --align ${write_block_size} ${imgtool_sign_sysbuild})
84+
if(CONFIG_PARTITION_MANAGER_ENABLED)
85+
# Split fields, imgtool_sign_sysbuild is stored in cache which will have fields updated by
86+
# sysbuild, imgtool_sign must not be stored in cache because it would then prevent those fields
87+
# from being updated without a pristine build
88+
# TODO: NCSDK-28461 sysbuild PM fields cannot be updated without a pristine build, will become
89+
# invalid if a static PM file is updated without pristine build
90+
set(imgtool_sign_sysbuild --slot-size @PM_MCUBOOT_PRIMARY_SIZE@ --pad-header --header-size @PM_MCUBOOT_PAD_SIZE@ ${imgtool_rom_command} CACHE STRING "imgtool sign sysbuild replacement")
91+
set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign --version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --align ${write_block_size} ${imgtool_sign_sysbuild})
92+
else()
93+
set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign --version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --align ${write_block_size} --slot-size ${slot_size} --header-size ${CONFIG_ROM_START_OFFSET} ${imgtool_rom_command})
94+
endif()
9195

9296
# Arguments to imgtool.
9397
if(NOT CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS STREQUAL "")

0 commit comments

Comments
 (0)