1# Copyright (c) 2020-2023 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 23 if(NOT "${CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE}") 24 # Check for misconfiguration. 25 if("${keyfile}" STREQUAL "") 26 # No signature key file, no signed binaries. No error, though: 27 # this is the documented behavior. 28 message(WARNING "Neither CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE or " 29 "CONFIG_MCUBOOT_SIGNATURE_KEY_FILE are set, the generated build will not be " 30 "bootable by MCUboot unless it is signed manually/externally.") 31 return() 32 endif() 33 endif() 34 35 if(NOT WEST) 36 # This feature requires west. 37 message(FATAL_ERROR "Can't sign images for MCUboot: west not found. To fix, install west and ensure it's on PATH.") 38 endif() 39 40 foreach(file keyfile keyfile_enc) 41 if(NOT "${${file}}" STREQUAL "") 42 if(NOT IS_ABSOLUTE "${${file}}") 43 # Relative paths are relative to 'west topdir'. 44 set(${file} "${WEST_TOPDIR}/${${file}}") 45 endif() 46 47 if(NOT EXISTS "${${file}}" AND NOT "${CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE}") 48 message(FATAL_ERROR "west sign can't find file ${${file}} (Note: Relative paths are relative to the west workspace topdir \"${WEST_TOPDIR}\")") 49 elseif(NOT (CONFIG_BUILD_OUTPUT_BIN OR CONFIG_BUILD_OUTPUT_HEX)) 50 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.") 51 endif() 52 endif() 53 endforeach() 54 55 # Find imgtool. Even though west is installed, imgtool might not be. 56 # The user may also have a custom manifest which doesn't include 57 # MCUboot. 58 # 59 # Therefore, go with an explicitly installed imgtool first, falling 60 # back on mcuboot/scripts/imgtool.py. 61 if(IMGTOOL) 62 set(imgtool_path "${IMGTOOL}") 63 elseif(DEFINED ZEPHYR_MCUBOOT_MODULE_DIR) 64 set(IMGTOOL_PY "${ZEPHYR_MCUBOOT_MODULE_DIR}/scripts/imgtool.py") 65 if(EXISTS "${IMGTOOL_PY}") 66 set(imgtool_path "${IMGTOOL_PY}") 67 endif() 68 endif() 69 70 # No imgtool, no signed binaries. 71 if(NOT DEFINED imgtool_path) 72 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.") 73 return() 74 endif() 75 76 # Fetch devicetree details for flash and slot information 77 dt_chosen(flash_node PROPERTY "zephyr,flash") 78 dt_nodelabel(slot0_flash NODELABEL "slot0_partition" REQUIRED) 79 dt_prop(slot_size PATH "${slot0_flash}" PROPERTY "reg" INDEX 1 REQUIRED) 80 dt_prop(write_block_size PATH "${flash_node}" PROPERTY "write-block-size") 81 82 if(NOT write_block_size) 83 set(write_block_size 4) 84 message(WARNING "slot0_partition write block size devicetree parameter is missing, assuming write block size is 4") 85 endif() 86 87 # If single slot mode, or if in firmware updater mode and this is the firmware updater image, 88 # use slot 0 information 89 if(NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_SINGLE_APP AND (NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER OR CONFIG_MCUBOOT_APPLICATION_FIRMWARE_UPDATER)) 90 # Slot 1 size is used instead of slot 0 size 91 set(slot_size) 92 dt_nodelabel(slot1_flash NODELABEL "slot1_partition" REQUIRED) 93 dt_prop(slot_size PATH "${slot1_flash}" PROPERTY "reg" INDEX 1 REQUIRED) 94 endif() 95 96 # Basic 'imgtool sign' command with known image information. 97 set(imgtool_sign ${PYTHON_EXECUTABLE} ${imgtool_path} sign 98 --version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --header-size ${CONFIG_ROM_START_OFFSET} 99 --slot-size ${slot_size}) 100 101 # Arguments to imgtool. 102 if(NOT CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS STREQUAL "") 103 # Separate extra arguments into the proper format for adding to 104 # extra_post_build_commands. 105 # 106 # Use UNIX_COMMAND syntax for uniform results across host 107 # platforms. 108 separate_arguments(imgtool_args UNIX_COMMAND ${CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS}) 109 else() 110 set(imgtool_args) 111 endif() 112 113 if(NOT "${keyfile}" STREQUAL "") 114 set(imgtool_args --key "${keyfile}" ${imgtool_args}) 115 endif() 116 117 if(CONFIG_MCUBOOT_IMGTOOL_OVERWRITE_ONLY) 118 # Use overwrite-only instead of swap upgrades. 119 set(imgtool_args --overwrite-only --align 1 ${imgtool_args}) 120 elseif(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) 121 # RAM load requires setting the location of where to load the image to 122 dt_chosen(chosen_ram PROPERTY "zephyr,sram") 123 dt_reg_addr(chosen_ram_address PATH ${chosen_ram}) 124 dt_nodelabel(slot0_partition NODELABEL "slot0_partition" REQUIRED) 125 dt_reg_addr(slot0_partition_address PATH ${slot0_partition}) 126 dt_nodelabel(slot1_partition NODELABEL "slot1_partition" REQUIRED) 127 dt_reg_addr(slot1_partition_address PATH ${slot1_partition}) 128 129 set(imgtool_args --align 1 --load-addr ${chosen_ram_address} ${imgtool_args}) 130 set(imgtool_args_alt_slot ${imgtool_args} --hex-addr ${slot1_partition_address}) 131 set(imgtool_args ${imgtool_args} --hex-addr ${slot0_partition_address}) 132 else() 133 set(imgtool_args --align ${write_block_size} ${imgtool_args}) 134 endif() 135 136 # Extensionless prefix of any output file. 137 set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}) 138 139 # List of additional build byproducts. 140 set(byproducts) 141 142 # Set up .bin outputs. 143 if(CONFIG_BUILD_OUTPUT_BIN) 144 list(APPEND byproducts ${output}.signed.bin) 145 zephyr_runner_file(bin ${output}.signed.bin) 146 set(BYPRODUCT_KERNEL_SIGNED_BIN_NAME "${output}.signed.bin" 147 CACHE FILEPATH "Signed kernel bin file" FORCE 148 ) 149 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 150 ${imgtool_sign} ${imgtool_args} ${output}.bin ${output}.signed.bin) 151 152 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 153 list(APPEND byproducts ${output}.signed.confirmed.bin) 154 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_BIN_NAME "${output}.signed.confirmed.bin" 155 CACHE FILEPATH "Signed and confirmed kernel bin file" FORCE 156 ) 157 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 158 ${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.bin 159 ${output}.signed.confirmed.bin) 160 endif() 161 162 if(NOT "${keyfile_enc}" STREQUAL "") 163 list(APPEND byproducts ${output}.signed.encrypted.bin) 164 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_BIN_NAME "${output}.signed.encrypted.bin" 165 CACHE FILEPATH "Signed and encrypted kernel bin file" FORCE 166 ) 167 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 168 ${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.bin 169 ${output}.signed.encrypted.bin) 170 endif() 171 172 if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) 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} ${output}.bin 176 ${output}.slot1.signed.bin) 177 178 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 179 list(APPEND byproducts ${output}.slot1.signed.confirmed.bin) 180 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 181 ${imgtool_sign} ${imgtool_args_alt_slot} --pad --confirm ${output}.bin 182 ${output}.slot1.signed.confirmed.bin) 183 endif() 184 185 if(NOT "${keyfile_enc}" STREQUAL "") 186 list(APPEND byproducts ${output}.slot1.signed.encrypted.bin) 187 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 188 ${imgtool_sign} ${imgtool_args_alt_slot} --encrypt "${keyfile_enc}" 189 ${output}.bin ${output}.slot1.signed.encrypted.bin) 190 endif() 191 endif() 192 endif() 193 194 # Set up .hex outputs. 195 if(CONFIG_BUILD_OUTPUT_HEX) 196 list(APPEND byproducts ${output}.signed.hex) 197 zephyr_runner_file(hex ${output}.signed.hex) 198 set(BYPRODUCT_KERNEL_SIGNED_HEX_NAME "${output}.signed.hex" 199 CACHE FILEPATH "Signed kernel hex file" FORCE 200 ) 201 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 202 ${imgtool_sign} ${imgtool_args} ${output}.hex ${output}.signed.hex) 203 204 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 205 list(APPEND byproducts ${output}.signed.confirmed.hex) 206 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_HEX_NAME "${output}.signed.confirmed.hex" 207 CACHE FILEPATH "Signed and confirmed kernel hex file" FORCE 208 ) 209 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 210 ${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.hex 211 ${output}.signed.confirmed.hex) 212 endif() 213 214 if(NOT "${keyfile_enc}" STREQUAL "") 215 list(APPEND byproducts ${output}.signed.encrypted.hex) 216 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_HEX_NAME "${output}.signed.encrypted.hex" 217 CACHE FILEPATH "Signed and encrypted kernel hex file" FORCE 218 ) 219 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 220 ${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.hex 221 ${output}.signed.encrypted.hex) 222 endif() 223 224 if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) 225 list(APPEND byproducts ${output}.slot1.signed.hex) 226 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 227 ${imgtool_sign} ${imgtool_args_alt_slot} ${output}.hex 228 ${output}.slot1.signed.hex) 229 230 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 231 list(APPEND byproducts ${output}.slot1.signed.confirmed.hex) 232 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 233 ${imgtool_sign} ${imgtool_args_alt_slot} --pad --confirm ${output}.hex 234 ${output}.slot1.signed.confirmed.hex) 235 endif() 236 237 if(NOT "${keyfile_enc}" STREQUAL "") 238 list(APPEND byproducts ${output}.slot1.signed.encrypted.hex) 239 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 240 ${imgtool_sign} ${imgtool_args_alt_slot} --encrypt "${keyfile_enc}" 241 ${output}.hex ${output}.slot1.signed.encrypted.hex) 242 endif() 243 endif() 244 endif() 245 set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${byproducts}) 246endfunction() 247 248zephyr_mcuboot_tasks() 249