1# Copyright (c) 2020 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 # Check for misconfiguration. 24 if("${keyfile}" STREQUAL "") 25 # No signature key file, no signed binaries. No error, though: 26 # this is the documented behavior. 27 return() 28 endif() 29 30 if(NOT WEST) 31 # This feature requires west. 32 message(FATAL_ERROR "Can't sign images for MCUboot: west not found. To fix, install west and ensure it's on PATH.") 33 endif() 34 35 foreach(file keyfile keyfile_enc) 36 if(NOT "${${file}}" STREQUAL "") 37 if(NOT IS_ABSOLUTE "${${file}}") 38 # Relative paths are relative to 'west topdir'. 39 set(${file} "${WEST_TOPDIR}/${${file}}") 40 endif() 41 42 if(NOT EXISTS "${${file}}") 43 message(FATAL_ERROR "west sign can't find file ${${file}} (Note: Relative paths are relative to the west workspace topdir \"${WEST_TOPDIR}\")") 44 elseif(NOT (CONFIG_BUILD_OUTPUT_BIN OR CONFIG_BUILD_OUTPUT_HEX)) 45 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.") 46 endif() 47 endif() 48 endforeach() 49 50 # Find imgtool. Even though west is installed, imgtool might not be. 51 # The user may also have a custom manifest which doesn't include 52 # MCUboot. 53 # 54 # Therefore, go with an explicitly installed imgtool first, falling 55 # back on mcuboot/scripts/imgtool.py. 56 if(IMGTOOL) 57 set(imgtool_path "${IMGTOOL}") 58 elseif(DEFINED ZEPHYR_MCUBOOT_MODULE_DIR) 59 set(IMGTOOL_PY "${ZEPHYR_MCUBOOT_MODULE_DIR}/scripts/imgtool.py") 60 if(EXISTS "${IMGTOOL_PY}") 61 set(imgtool_path "${IMGTOOL_PY}") 62 endif() 63 endif() 64 65 # No imgtool, no signed binaries. 66 if(NOT DEFINED imgtool_path) 67 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.") 68 return() 69 endif() 70 71 # Basic 'west sign' command and output format independent arguments. 72 set(west_sign ${WEST} sign --quiet --tool imgtool 73 --tool-path "${imgtool_path}" 74 --build-dir "${APPLICATION_BINARY_DIR}") 75 76 # Arguments to imgtool. 77 if(NOT CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS STREQUAL "") 78 # Separate extra arguments into the proper format for adding to 79 # extra_post_build_commands. 80 # 81 # Use UNIX_COMMAND syntax for uniform results across host 82 # platforms. 83 separate_arguments(imgtool_extra UNIX_COMMAND ${CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS}) 84 else() 85 set(imgtool_extra) 86 endif() 87 set(imgtool_args -- --key "${keyfile}" ${imgtool_extra}) 88 89 # Extensionless prefix of any output file. 90 set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME}) 91 92 # List of additional build byproducts. 93 set(byproducts) 94 95 # 'west sign' arguments for confirmed, unconfirmed and encrypted images. 96 set(unconfirmed_args) 97 set(confirmed_args) 98 set(encrypted_args) 99 100 # Set up .bin outputs. 101 if(CONFIG_BUILD_OUTPUT_BIN) 102 list(APPEND unconfirmed_args --bin --sbin ${output}.signed.bin) 103 list(APPEND byproducts ${output}.signed.bin) 104 zephyr_runner_file(bin ${output}.signed.bin) 105 106 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 107 list(APPEND confirmed_args --bin --sbin ${output}.signed.confirmed.bin) 108 list(APPEND byproducts ${output}.signed.confirmed.bin) 109 endif() 110 111 if(NOT "${keyfile_enc}" STREQUAL "") 112 list(APPEND encrypted_args --bin --sbin ${output}.signed.encrypted.bin) 113 list(APPEND byproducts ${output}.signed.encrypted.bin) 114 endif() 115 endif() 116 117 # Set up .hex outputs. 118 if(CONFIG_BUILD_OUTPUT_HEX) 119 list(APPEND unconfirmed_args --hex --shex ${output}.signed.hex) 120 list(APPEND byproducts ${output}.signed.hex) 121 zephyr_runner_file(hex ${output}.signed.hex) 122 123 if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE) 124 list(APPEND confirmed_args --hex --shex ${output}.signed.confirmed.hex) 125 list(APPEND byproducts ${output}.signed.confirmed.hex) 126 endif() 127 128 if(NOT "${keyfile_enc}" STREQUAL "") 129 list(APPEND encrypted_args --hex --shex ${output}.signed.encrypted.hex) 130 list(APPEND byproducts ${output}.signed.encrypted.hex) 131 endif() 132 endif() 133 134 # Add the west sign calls and their byproducts to the post-processing 135 # steps for zephyr.elf. 136 # 137 # CMake guarantees that multiple COMMANDs given to 138 # add_custom_command() are run in order, so adding the 'west sign' 139 # calls to the "extra_post_build_commands" property ensures they run 140 # after the commands which generate the unsigned versions. 141 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 142 ${west_sign} ${unconfirmed_args} ${imgtool_args}) 143 if(confirmed_args) 144 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 145 ${west_sign} ${confirmed_args} ${imgtool_args} --pad --confirm) 146 endif() 147 if(encrypted_args) 148 set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND 149 ${west_sign} ${encrypted_args} ${imgtool_args} --encrypt "${keyfile_enc}") 150 endif() 151 set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${byproducts}) 152endfunction() 153 154zephyr_mcuboot_tasks() 155