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 # Basic 'west sign' command and output format independent arguments. 77 separate_arguments(west_sign_extra UNIX_COMMAND ${CONFIG_MCUBOOT_CMAKE_WEST_SIGN_PARAMS}) 78 set(west_sign ${WEST} sign ${west_sign_extra} 79 --tool imgtool 80 --tool-path "${imgtool_path}" 81 --build-dir "${APPLICATION_BINARY_DIR}") 82 83 # Arguments to imgtool. 84 if(NOT CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS STREQUAL "") 85 # Separate extra arguments into the proper format for adding to 86 # extra_post_build_commands. 87 # 88 # Use UNIX_COMMAND syntax for uniform results across host 89 # platforms. 90 separate_arguments(imgtool_extra UNIX_COMMAND ${CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS}) 91 else() 92 set(imgtool_extra) 93 endif() 94 95 if(NOT "${keyfile}" STREQUAL "") 96 set(imgtool_extra --key "${keyfile}" ${imgtool_extra}) 97 endif() 98 99 # Use overwrite-only instead of swap upgrades. 100 if(CONFIG_MCUBOOT_IMGTOOL_OVERWRITE_ONLY) 101 set(imgtool_extra --overwrite-only --align 1 ${imgtool_extra}) 102 endif() 103 104 set(imgtool_args -- ${imgtool_extra}) 105 106 # Extensionless prefix of any output file. 107 set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}) 108 109 # List of additional build byproducts. 110 set(byproducts) 111 112 # 'west sign' arguments for confirmed, unconfirmed and encrypted images. 113 set(unconfirmed_args) 114 set(confirmed_args) 115 set(encrypted_args) 116 117 # Set up .bin outputs. 118 if(CONFIG_BUILD_OUTPUT_BIN) 119 list(APPEND unconfirmed_args --bin --sbin ${output}.signed.bin) 120 list(APPEND byproducts ${output}.signed.bin) 121 zephyr_runner_file(bin ${output}.signed.bin) 122 set(BYPRODUCT_KERNEL_SIGNED_BIN_NAME "${output}.signed.bin" 123 CACHE FILEPATH "Signed kernel bin file" FORCE 124 ) 125 126 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 127 list(APPEND confirmed_args --bin --sbin ${output}.signed.confirmed.bin) 128 list(APPEND byproducts ${output}.signed.confirmed.bin) 129 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_BIN_NAME "${output}.signed.confirmed.bin" 130 CACHE FILEPATH "Signed and confirmed kernel bin file" FORCE 131 ) 132 endif() 133 134 if(NOT "${keyfile_enc}" STREQUAL "") 135 list(APPEND encrypted_args --bin --sbin ${output}.signed.encrypted.bin) 136 list(APPEND byproducts ${output}.signed.encrypted.bin) 137 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_BIN_NAME "${output}.signed.encrypted.bin" 138 CACHE FILEPATH "Signed and encrypted kernel bin file" FORCE 139 ) 140 endif() 141 endif() 142 143 # Set up .hex outputs. 144 if(CONFIG_BUILD_OUTPUT_HEX) 145 list(APPEND unconfirmed_args --hex --shex ${output}.signed.hex) 146 list(APPEND byproducts ${output}.signed.hex) 147 zephyr_runner_file(hex ${output}.signed.hex) 148 set(BYPRODUCT_KERNEL_SIGNED_HEX_NAME "${output}.signed.hex" 149 CACHE FILEPATH "Signed kernel hex file" FORCE 150 ) 151 152 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 153 list(APPEND confirmed_args --hex --shex ${output}.signed.confirmed.hex) 154 list(APPEND byproducts ${output}.signed.confirmed.hex) 155 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_HEX_NAME "${output}.signed.confirmed.hex" 156 CACHE FILEPATH "Signed and confirmed kernel hex file" FORCE 157 ) 158 endif() 159 160 if(NOT "${keyfile_enc}" STREQUAL "") 161 list(APPEND encrypted_args --hex --shex ${output}.signed.encrypted.hex) 162 list(APPEND byproducts ${output}.signed.encrypted.hex) 163 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_HEX_NAME "${output}.signed.encrypted.hex" 164 CACHE FILEPATH "Signed and encrypted kernel hex file" FORCE 165 ) 166 endif() 167 endif() 168 169 # Add the west sign calls and their byproducts to the post-processing 170 # steps for zephyr.elf. 171 # 172 # CMake guarantees that multiple COMMANDs given to 173 # add_custom_command() are run in order, so adding the 'west sign' 174 # calls to the "extra_post_build_commands" property ensures they run 175 # after the commands which generate the unsigned versions. 176 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 177 ${west_sign} ${unconfirmed_args} ${imgtool_args}) 178 if(confirmed_args) 179 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 180 ${west_sign} ${confirmed_args} ${imgtool_args} --pad --confirm) 181 endif() 182 if(encrypted_args) 183 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 184 ${west_sign} ${encrypted_args} ${imgtool_args} --encrypt "${keyfile_enc}") 185 endif() 186 set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${byproducts}) 187endfunction() 188 189zephyr_mcuboot_tasks() 190