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 set(imgtool_args -- ${imgtool_extra}) 100 101 # Extensionless prefix of any output file. 102 set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}) 103 104 # List of additional build byproducts. 105 set(byproducts) 106 107 # 'west sign' arguments for confirmed, unconfirmed and encrypted images. 108 set(unconfirmed_args) 109 set(confirmed_args) 110 set(encrypted_args) 111 112 # Set up .bin outputs. 113 if(CONFIG_BUILD_OUTPUT_BIN) 114 list(APPEND unconfirmed_args --bin --sbin ${output}.signed.bin) 115 list(APPEND byproducts ${output}.signed.bin) 116 zephyr_runner_file(bin ${output}.signed.bin) 117 set(BYPRODUCT_KERNEL_SIGNED_BIN_NAME "${output}.signed.bin" 118 CACHE FILEPATH "Signed kernel bin file" FORCE 119 ) 120 121 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 122 list(APPEND confirmed_args --bin --sbin ${output}.signed.confirmed.bin) 123 list(APPEND byproducts ${output}.signed.confirmed.bin) 124 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_BIN_NAME "${output}.signed.confirmed.bin" 125 CACHE FILEPATH "Signed and confirmed kernel bin file" FORCE 126 ) 127 endif() 128 129 if(NOT "${keyfile_enc}" STREQUAL "") 130 list(APPEND encrypted_args --bin --sbin ${output}.signed.encrypted.bin) 131 list(APPEND byproducts ${output}.signed.encrypted.bin) 132 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_BIN_NAME "${output}.signed.encrypted.bin" 133 CACHE FILEPATH "Signed and encrypted kernel bin file" FORCE 134 ) 135 endif() 136 endif() 137 138 # Set up .hex outputs. 139 if(CONFIG_BUILD_OUTPUT_HEX) 140 list(APPEND unconfirmed_args --hex --shex ${output}.signed.hex) 141 list(APPEND byproducts ${output}.signed.hex) 142 zephyr_runner_file(hex ${output}.signed.hex) 143 set(BYPRODUCT_KERNEL_SIGNED_HEX_NAME "${output}.signed.hex" 144 CACHE FILEPATH "Signed kernel hex file" FORCE 145 ) 146 147 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 148 list(APPEND confirmed_args --hex --shex ${output}.signed.confirmed.hex) 149 list(APPEND byproducts ${output}.signed.confirmed.hex) 150 set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_HEX_NAME "${output}.signed.confirmed.hex" 151 CACHE FILEPATH "Signed and confirmed kernel hex file" FORCE 152 ) 153 endif() 154 155 if(NOT "${keyfile_enc}" STREQUAL "") 156 list(APPEND encrypted_args --hex --shex ${output}.signed.encrypted.hex) 157 list(APPEND byproducts ${output}.signed.encrypted.hex) 158 set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_HEX_NAME "${output}.signed.encrypted.hex" 159 CACHE FILEPATH "Signed and encrypted kernel hex file" FORCE 160 ) 161 endif() 162 endif() 163 164 # Add the west sign calls and their byproducts to the post-processing 165 # steps for zephyr.elf. 166 # 167 # CMake guarantees that multiple COMMANDs given to 168 # add_custom_command() are run in order, so adding the 'west sign' 169 # calls to the "extra_post_build_commands" property ensures they run 170 # after the commands which generate the unsigned versions. 171 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 172 ${west_sign} ${unconfirmed_args} ${imgtool_args}) 173 if(confirmed_args) 174 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 175 ${west_sign} ${confirmed_args} ${imgtool_args} --pad --confirm) 176 endif() 177 if(encrypted_args) 178 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 179 ${west_sign} ${encrypted_args} ${imgtool_args} --encrypt "${keyfile_enc}") 180 endif() 181 set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${byproducts}) 182endfunction() 183 184zephyr_mcuboot_tasks() 185