zephyr/cmake/mcuboot.cmake
Ederson de Souza c9a18fd487 mcuboot: Kconfig options for single app slot RAM loading mode
MCUboot has a configuration for single application slot RAM loading, in
which the single loader (or a hook thereof) can load an application from
an arbitrary flash location to RAM. Applications that are to be loaded
in this way need to specify, in their mcuboot header, the load address
in RAM they are meant to be loaded.

This patch adds a new Kconfig for this mode. The load address used comes
from devicetree chosen property "mcuboot,ram-load-dev", if it exists,
and if not, "zephyr,sram".

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
2025-04-08 16:12:33 +02:00

280 lines
12 KiB
CMake

# Copyright (c) 2020-2025 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
# This file includes extra build system logic that is enabled when
# CONFIG_BOOTLOADER_MCUBOOT=y.
#
# It builds signed binaries using imgtool as a post-processing step
# after zephyr/zephyr.elf is created in the build directory.
#
# Since this file is brought in via include(), we do the work in a
# function to avoid polluting the top-level scope.
function(zephyr_runner_file type path)
# Property magic which makes west flash choose the signed build
# output of a given type.
set_target_properties(runners_yaml_props_target PROPERTIES "${type}_file" "${path}")
endfunction()
function(zephyr_mcuboot_tasks)
set(keyfile "${CONFIG_MCUBOOT_SIGNATURE_KEY_FILE}")
set(keyfile_enc "${CONFIG_MCUBOOT_ENCRYPTION_KEY_FILE}")
string(CONFIGURE "${keyfile}" keyfile)
string(CONFIGURE "${keyfile_enc}" keyfile_enc)
if(NOT "${CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE}")
# Check for misconfiguration.
if("${keyfile}" STREQUAL "")
# No signature key file, no signed binaries. No error, though:
# this is the documented behavior.
message(WARNING "Neither CONFIG_MCUBOOT_GENERATE_UNSIGNED_IMAGE or "
"CONFIG_MCUBOOT_SIGNATURE_KEY_FILE are set, the generated build will not be "
"bootable by MCUboot unless it is signed manually/externally.")
return()
elseif(NOT (CONFIG_BUILD_OUTPUT_BIN OR CONFIG_BUILD_OUTPUT_HEX))
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.")
endif()
foreach(file keyfile keyfile_enc)
if("${${file}}" STREQUAL "")
continue()
endif()
# Find the key files in the order of preference for a simple search
# modeled by the if checks across the various locations
#
# 1. absolute
# 2. application config
# 3. west topdir (optional when the workspace is not west managed)
#
if(NOT IS_ABSOLUTE "${${file}}")
if(EXISTS "${APPLICATION_CONFIG_DIR}/${${file}}")
set(${file} "${APPLICATION_CONFIG_DIR}/${${file}}")
else()
# Relative paths are relative to 'west topdir'.
#
# This is the only file that has a relative check to topdir likely
# from the historical callouts to "west" itself before using
# imgtool. So, this is maintained here for backward compatibility
#
if(NOT WEST OR NOT WEST_TOPDIR)
message(FATAL_ERROR "Can't sign images for MCUboot: west workspace undefined. "
"To fix, ensure `west topdir` is a valid workspace directory.")
endif()
set(${file} "${WEST_TOPDIR}/${${file}}")
endif()
endif()
if(NOT EXISTS "${${file}}")
message(FATAL_ERROR "Can't sign images for MCUboot: can't find file ${${file}} "
"(Note: Relative paths are searched through "
"APPLICATION_CONFIG_DIR=\"${APPLICATION_CONFIG_DIR}\" "
"and WEST_TOPDIR=\"${WEST_TOPDIR}\")")
endif()
endforeach()
endif()
# No imgtool, no signed binaries.
if(NOT DEFINED IMGTOOL)
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.")
return()
endif()
# Fetch devicetree details for flash and slot information
dt_chosen(flash_node PROPERTY "zephyr,flash")
dt_nodelabel(slot0_flash NODELABEL "slot0_partition" REQUIRED)
dt_prop(slot_size PATH "${slot0_flash}" PROPERTY "reg" INDEX 1 REQUIRED)
dt_prop(write_block_size PATH "${flash_node}" PROPERTY "write-block-size")
if(NOT write_block_size)
set(write_block_size 4)
message(WARNING "slot0_partition write block size devicetree parameter is missing, assuming write block size is 4")
endif()
# If single slot mode, or if in firmware updater mode and this is the firmware updater image,
# use slot 0 information
if(NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_SINGLE_APP AND (NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER OR CONFIG_MCUBOOT_APPLICATION_FIRMWARE_UPDATER)
AND NOT CONFIG_MCUBOOT_BOOTLOADER_MODE_SINGLE_APP_RAM_LOAD)
# Slot 1 size is used instead of slot 0 size
set(slot_size)
dt_nodelabel(slot1_flash NODELABEL "slot1_partition" REQUIRED)
dt_prop(slot_size PATH "${slot1_flash}" PROPERTY "reg" INDEX 1 REQUIRED)
endif()
# Basic 'imgtool sign' command with known image information.
set(imgtool_sign ${PYTHON_EXECUTABLE} ${IMGTOOL} sign
--version ${CONFIG_MCUBOOT_IMGTOOL_SIGN_VERSION} --header-size ${CONFIG_ROM_START_OFFSET}
--slot-size ${slot_size})
# Arguments to imgtool.
if(NOT CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS STREQUAL "")
# Separate extra arguments into the proper format for adding to
# extra_post_build_commands.
#
# Use UNIX_COMMAND syntax for uniform results across host
# platforms.
separate_arguments(imgtool_args UNIX_COMMAND ${CONFIG_MCUBOOT_EXTRA_IMGTOOL_ARGS})
else()
set(imgtool_args)
endif()
if(NOT "${keyfile}" STREQUAL "")
set(imgtool_args --key "${keyfile}" ${imgtool_args})
endif()
if(CONFIG_MCUBOOT_IMGTOOL_OVERWRITE_ONLY)
# Use overwrite-only instead of swap upgrades.
set(imgtool_args --overwrite-only --align 1 ${imgtool_args})
elseif(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
# RAM load requires setting the location of where to load the image to
dt_chosen(chosen_ram PROPERTY "zephyr,sram")
dt_reg_addr(chosen_ram_address PATH ${chosen_ram})
dt_nodelabel(slot0_partition NODELABEL "slot0_partition" REQUIRED)
dt_reg_addr(slot0_partition_address PATH ${slot0_partition})
dt_nodelabel(slot1_partition NODELABEL "slot1_partition" REQUIRED)
dt_reg_addr(slot1_partition_address PATH ${slot1_partition})
set(imgtool_args --align 1 --load-addr ${chosen_ram_address} ${imgtool_args})
set(imgtool_args_alt_slot ${imgtool_args} --hex-addr ${slot1_partition_address})
set(imgtool_args ${imgtool_args} --hex-addr ${slot0_partition_address})
elseif(CONFIG_MCUBOOT_BOOTLOADER_MODE_SINGLE_APP_RAM_LOAD)
dt_chosen(ram_load_dev PROPERTY "mcuboot,ram-load-dev")
if(DEFINED ram_load_dev)
dt_reg_addr(load_address PATH ${ram_load_dev})
else()
dt_chosen(chosen_ram PROPERTY "zephyr,sram")
dt_reg_addr(load_address PATH ${chosen_ram})
endif()
set(imgtool_args --align 1 --load-addr ${load_address} ${imgtool_args})
else()
set(imgtool_args --align ${write_block_size} ${imgtool_args})
endif()
# Extensionless prefix of any output file.
set(output ${ZEPHYR_BINARY_DIR}/${KERNEL_NAME})
# List of additional build byproducts.
set(byproducts)
# Set up .bin outputs.
if(CONFIG_BUILD_OUTPUT_BIN)
list(APPEND byproducts ${output}.signed.bin)
zephyr_runner_file(bin ${output}.signed.bin)
set(BYPRODUCT_KERNEL_SIGNED_BIN_NAME "${output}.signed.bin"
CACHE FILEPATH "Signed kernel bin file" FORCE
)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} ${output}.bin ${output}.signed.bin)
if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE)
list(APPEND byproducts ${output}.signed.confirmed.bin)
zephyr_runner_file(bin ${output}.signed.confirmed.bin)
set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_BIN_NAME "${output}.signed.confirmed.bin"
CACHE FILEPATH "Signed and confirmed kernel bin file" FORCE
)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.bin
${output}.signed.confirmed.bin)
endif()
if(NOT "${keyfile_enc}" STREQUAL "")
list(APPEND byproducts ${output}.signed.encrypted.bin)
set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_BIN_NAME "${output}.signed.encrypted.bin"
CACHE FILEPATH "Signed and encrypted kernel bin file" FORCE
)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.bin
${output}.signed.encrypted.bin)
endif()
if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
list(APPEND byproducts ${output}.slot1.signed.encrypted.bin)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args_alt_slot} ${output}.bin
${output}.slot1.signed.bin)
if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE)
list(APPEND byproducts ${output}.slot1.signed.confirmed.bin)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args_alt_slot} --pad --confirm ${output}.bin
${output}.slot1.signed.confirmed.bin)
endif()
if(NOT "${keyfile_enc}" STREQUAL "")
list(APPEND byproducts ${output}.slot1.signed.encrypted.bin)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args_alt_slot} --encrypt "${keyfile_enc}"
${output}.bin ${output}.slot1.signed.encrypted.bin)
endif()
endif()
endif()
# Set up .hex outputs.
if(CONFIG_BUILD_OUTPUT_HEX)
list(APPEND byproducts ${output}.signed.hex)
zephyr_runner_file(hex ${output}.signed.hex)
set(BYPRODUCT_KERNEL_SIGNED_HEX_NAME "${output}.signed.hex"
CACHE FILEPATH "Signed kernel hex file" FORCE
)
if(NOT "${keyfile_enc}" STREQUAL "")
# When encryption is enabled, set the encrypted bit when signing the image but do not
# encrypt the data, this means that when the image is moved out of the primary into the
# secondary, it will be encrypted rather than being in unencrypted
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" --clear
${output}.hex ${output}.signed.hex)
else()
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} ${output}.hex ${output}.signed.hex)
endif()
if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE)
list(APPEND byproducts ${output}.signed.confirmed.hex)
zephyr_runner_file(hex ${output}.signed.confirmed.hex)
set(BYPRODUCT_KERNEL_SIGNED_CONFIRMED_HEX_NAME "${output}.signed.confirmed.hex"
CACHE FILEPATH "Signed and confirmed kernel hex file" FORCE
)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.hex
${output}.signed.confirmed.hex)
endif()
if(NOT "${keyfile_enc}" STREQUAL "")
list(APPEND byproducts ${output}.signed.encrypted.hex)
set(BYPRODUCT_KERNEL_SIGNED_ENCRYPTED_HEX_NAME "${output}.signed.encrypted.hex"
CACHE FILEPATH "Signed and encrypted kernel hex file" FORCE
)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.hex
${output}.signed.encrypted.hex)
endif()
if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
list(APPEND byproducts ${output}.slot1.signed.hex)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args_alt_slot} ${output}.hex
${output}.slot1.signed.hex)
if(CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE)
list(APPEND byproducts ${output}.slot1.signed.confirmed.hex)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args_alt_slot} --pad --confirm ${output}.hex
${output}.slot1.signed.confirmed.hex)
endif()
if(NOT "${keyfile_enc}" STREQUAL "")
list(APPEND byproducts ${output}.slot1.signed.encrypted.hex)
set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND
${imgtool_sign} ${imgtool_args_alt_slot} --encrypt "${keyfile_enc}"
${output}.hex ${output}.slot1.signed.encrypted.hex)
endif()
endif()
endif()
set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts ${byproducts})
endfunction()
zephyr_mcuboot_tasks()