1# Copyright (c) 2020-2025 Nordic Semiconductor ASA 2# SPDX-License-Identifier: Apache-2.0 3 4# This file includes extra build system logic that is enabled when 5# CONFIG_BOOTLOADER_MCUBOOT=y. 6# 7# It builds signed binaries using imgtool as a post-processing step 8# after zephyr/zephyr.elf is created in the build directory. 9# 10# Since this file is brought in via include(), we do the work in a 11# function to avoid polluting the top-level scope. 12 13function(zephyr_runner_file type path) 14 # Property magic which makes west flash choose the signed build 15 # output of a given type. 16 set_target_properties(runners_yaml_props_target PROPERTIES "${type}_file" "${path}") 17endfunction() 18 19function(zephyr_mcuboot_tasks) 20 set(keyfile "${CONFIG_MCUBOOT_SIGNATURE_KEY_FILE}") 21 set(keyfile_enc "${CONFIG_MCUBOOT_ENCRYPTION_KEY_FILE}") 22 string(CONFIGURE "${keyfile}" keyfile) 23 string(CONFIGURE "${keyfile_enc}" keyfile_enc) 24 25 if(NOT "${CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE}") 26 # Check for misconfiguration. 27 if("${keyfile}" STREQUAL "") 28 # No signature key file, no signed binaries. No error, though: 29 # this is the documented behavior. 30 message(WARNING "Neither CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE or " 31 "CONFIG_MCUBOOT_SIGNATURE_KEY_FILE are set, the generated build will not be " 32 "bootable by MCUboot unless it is signed manually/externally.") 33 return() 34 endif() 35 endif() 36 37 if(NOT WEST) 38 # This feature requires west. 39 message(FATAL_ERROR "Can't sign images for MCUboot: west not found. To fix, install west and ensure it's on PATH.") 40 endif() 41 42 foreach(file keyfile keyfile_enc) 43 if(NOT "${${file}}" STREQUAL "") 44 if(NOT IS_ABSOLUTE "${${file}}") 45 # Relative paths are relative to 'west topdir'. 46 set(${file} "${WEST_TOPDIR}/${${file}}") 47 endif() 48 49 if(NOT EXISTS "${${file}}" AND NOT "${CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE}") 50 message(FATAL_ERROR "west sign can't find file ${${file}} (Note: Relative paths are relative to the west workspace topdir \"${WEST_TOPDIR}\")") 51 elseif(NOT (CONFIG_BUILD_OUTPUT_BIN OR CONFIG_BUILD_OUTPUT_HEX)) 52 message(FATAL_ERROR "Can't sign images for MCUboot: Neither CONFIG_BUILD_OUTPUT_BIN nor CONFIG_BUILD_OUTPUT_HEX is enabled, so there's nothing to sign.") 53 endif() 54 endif() 55 endforeach() 56 57 # No imgtool, no signed binaries. 58 if(NOT DEFINED IMGTOOL) 59 message(FATAL_ERROR "Can't sign images for MCUboot: can't find imgtool. To fix, install imgtool with pip3, or add the mcuboot repository to the west manifest and ensure it has a scripts/imgtool.py file.") 60 return() 61 endif() 62 63 # Fetch devicetree details for flash and slot information 64 dt_chosen(flash_node PROPERTY "zephyr,flash") 65 dt_nodelabel(slot0_flash NODELABEL "slot0_partition" REQUIRED) 66 dt_prop(slot_size PATH "${slot0_flash}" PROPERTY "reg" INDEX 1 REQUIRED) 67 dt_prop(write_block_size PATH "${flash_node}" PROPERTY "write-block-size") 68 69 if(NOT write_block_size) 70 set(write_block_size 4) 71 message(WARNING "slot0_partition write block size devicetree parameter is missing, assuming write block size is 4") 72 endif() 73 74 # If single slot mode, or if in firmware updater mode and this is the firmware updater image, 75 # use slot 0 information 76 if(NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_SINGLE_APP AND (NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER OR CONFIG_MCUBOOT_APPLICATION_FIRMWARE_UPDATER)) 77 # Slot 1 size is used instead of slot 0 size 78 set(slot_size) 79 dt_nodelabel(slot1_flash NODELABEL "slot1_partition" REQUIRED) 80 dt_prop(slot_size PATH "${slot1_flash}" PROPERTY "reg" INDEX 1 REQUIRED) 81 endif() 82 83 # Basic 'imgtool sign' command with known image information. 84 set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign 85 --version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --header-size ${CONFIG_ROM_START_OFFSET} 86 --slot-size ${slot_size}) 87 88 # Arguments to imgtool. 89 if(NOT CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS STREQUAL "") 90 # Separate extra arguments into the proper format for adding to 91 # extra_post_build_commands. 92 # 93 # Use UNIX_COMMAND syntax for uniform results across host 94 # platforms. 95 separate_arguments(imgtool_args UNIX_COMMAND ${CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS}) 96 else() 97 set(imgtool_args) 98 endif() 99 100 if(NOT "${keyfile}" STREQUAL "") 101 set(imgtool_args --key "${keyfile}" ${imgtool_args}) 102 endif() 103 104 if(CONFIG_MCUBOOT_IMGTOOL_OVERWRITE_ONLY) 105 # Use overwrite-only instead of swap upgrades. 106 set(imgtool_args --overwrite-only --align 1 ${imgtool_args}) 107 elseif(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) 108 # RAM load requires setting the location of where to load the image to 109 dt_chosen(chosen_ram PROPERTY "zephyr,sram") 110 dt_reg_addr(chosen_ram_address PATH ${chosen_ram}) 111 dt_nodelabel(slot0_partition NODELABEL "slot0_partition" REQUIRED) 112 dt_reg_addr(slot0_partition_address PATH ${slot0_partition}) 113 dt_nodelabel(slot1_partition NODELABEL "slot1_partition" REQUIRED) 114 dt_reg_addr(slot1_partition_address PATH ${slot1_partition}) 115 116 set(imgtool_args --align 1 --load-addr ${chosen_ram_address} ${imgtool_args}) 117 set(imgtool_args_alt_slot ${imgtool_args} --hex-addr ${slot1_partition_address}) 118 set(imgtool_args ${imgtool_args} --hex-addr ${slot0_partition_address}) 119 else() 120 set(imgtool_args --align ${write_block_size} ${imgtool_args}) 121 endif() 122 123 # Extensionless prefix of any output file. 124 set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}) 125 126 # List of additional build byproducts. 127 set(byproducts) 128 129 # Set up .bin outputs. 130 if(CONFIG_BUILD_OUTPUT_BIN) 131 list(APPEND byproducts ${output}.signed.bin) 132 zephyr_runner_file(bin ${output}.signed.bin) 133 set(BYPRODUCT_KERNEL_SIGNED_BIN_NAME "${output}.signed.bin" 134 CACHE FILEPATH "Signed kernel bin file" FORCE 135 ) 136 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 137 ${imgtool_sign} ${imgtool_args} ${output}.bin ${output}.signed.bin) 138 139 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 140 list(APPEND byproducts ${output}.signed.confirmed.bin) 141 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_BIN_NAME "${output}.signed.confirmed.bin" 142 CACHE FILEPATH "Signed and confirmed kernel bin file" FORCE 143 ) 144 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 145 ${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.bin 146 ${output}.signed.confirmed.bin) 147 endif() 148 149 if(NOT "${keyfile_enc}" STREQUAL "") 150 list(APPEND byproducts ${output}.signed.encrypted.bin) 151 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_BIN_NAME "${output}.signed.encrypted.bin" 152 CACHE FILEPATH "Signed and encrypted kernel bin file" FORCE 153 ) 154 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 155 ${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.bin 156 ${output}.signed.encrypted.bin) 157 endif() 158 159 if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) 160 list(APPEND byproducts ${output}.slot1.signed.encrypted.bin) 161 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 162 ${imgtool_sign} ${imgtool_args_alt_slot} ${output}.bin 163 ${output}.slot1.signed.bin) 164 165 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 166 list(APPEND byproducts ${output}.slot1.signed.confirmed.bin) 167 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 168 ${imgtool_sign} ${imgtool_args_alt_slot} --pad --confirm ${output}.bin 169 ${output}.slot1.signed.confirmed.bin) 170 endif() 171 172 if(NOT "${keyfile_enc}" STREQUAL "") 173 list(APPEND byproducts ${output}.slot1.signed.encrypted.bin) 174 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 175 ${imgtool_sign} ${imgtool_args_alt_slot} --encrypt "${keyfile_enc}" 176 ${output}.bin ${output}.slot1.signed.encrypted.bin) 177 endif() 178 endif() 179 endif() 180 181 # Set up .hex outputs. 182 if(CONFIG_BUILD_OUTPUT_HEX) 183 list(APPEND byproducts ${output}.signed.hex) 184 zephyr_runner_file(hex ${output}.signed.hex) 185 set(BYPRODUCT_KERNEL_SIGNED_HEX_NAME "${output}.signed.hex" 186 CACHE FILEPATH "Signed kernel hex file" FORCE 187 ) 188 189 if(NOT "${keyfile_enc}" STREQUAL "") 190 # When encryption is enabled, set the encrypted bit when signing the image but do not 191 # encrypt the data, this means that when the image is moved out of the primary into the 192 # secondary, it will be encrypted rather than being in unencrypted 193 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 194 ${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" --clear 195 ${output}.hex ${output}.signed.hex) 196 else() 197 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 198 ${imgtool_sign} ${imgtool_args} ${output}.hex ${output}.signed.hex) 199 endif() 200 201 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 202 list(APPEND byproducts ${output}.signed.confirmed.hex) 203 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_HEX_NAME "${output}.signed.confirmed.hex" 204 CACHE FILEPATH "Signed and confirmed kernel hex file" FORCE 205 ) 206 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 207 ${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.hex 208 ${output}.signed.confirmed.hex) 209 endif() 210 211 if(NOT "${keyfile_enc}" STREQUAL "") 212 list(APPEND byproducts ${output}.signed.encrypted.hex) 213 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_HEX_NAME "${output}.signed.encrypted.hex" 214 CACHE FILEPATH "Signed and encrypted kernel hex file" FORCE 215 ) 216 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 217 ${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.hex 218 ${output}.signed.encrypted.hex) 219 endif() 220 221 if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) 222 list(APPEND byproducts ${output}.slot1.signed.hex) 223 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 224 ${imgtool_sign} ${imgtool_args_alt_slot} ${output}.hex 225 ${output}.slot1.signed.hex) 226 227 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 228 list(APPEND byproducts ${output}.slot1.signed.confirmed.hex) 229 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 230 ${imgtool_sign} ${imgtool_args_alt_slot} --pad --confirm ${output}.hex 231 ${output}.slot1.signed.confirmed.hex) 232 endif() 233 234 if(NOT "${keyfile_enc}" STREQUAL "") 235 list(APPEND byproducts ${output}.slot1.signed.encrypted.hex) 236 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 237 ${imgtool_sign} ${imgtool_args_alt_slot} --encrypt "${keyfile_enc}" 238 ${output}.hex ${output}.slot1.signed.encrypted.hex) 239 endif() 240 endif() 241 endif() 242 set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${byproducts}) 243endfunction() 244 245zephyr_mcuboot_tasks() 246