Skip to content

Commit

Permalink
Update Mbed CMakeLists.txt for Mbed CE
Browse files Browse the repository at this point in the history
  • Loading branch information
multiplemonomials committed Dec 19, 2024
1 parent 7cc6005 commit e8017b7
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 20 deletions.
24 changes: 11 additions & 13 deletions boot/mbed/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Copyright (c) 2021 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Mbed-MCUboot Port
# Pull in functions for working with imgtool
include(mcuboot_imgtool.cmake)

# Mbed-MCUboot Port
cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR)

get_filename_component(BOOT_UTIL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../bootutil REALPATH)

set(LIB_TARGET mbed-mcuboot)
Expand All @@ -15,7 +16,6 @@ add_library(${LIB_TARGET} STATIC)
target_include_directories(${LIB_TARGET}
PUBLIC
include
${BOOT_UTIL_DIR}/include
${BOOT_UTIL_DIR}/src
)

Expand All @@ -33,18 +33,16 @@ target_link_libraries(${LIB_TARGET}
mbed-mbedtls
mbed-storage-flashiap
mbed-storage-blockdevice
mbed-core-flags
)

if("_RTE_" IN_LIST MBED_CONFIG_DEFINITIONS)
target_link_libraries(${LIB_TARGET}
PUBLIC
mbed-os
)
else()
target_link_libraries(${LIB_TARGET}
PUBLIC
mbed-baremetal
)
# Add signing key generated source file
mcuboot_generate_signing_keys_file(${CMAKE_CURRENT_BINARY_DIR}/signing_keys.c)
target_sources(${LIB_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/signing_keys.c)

if("MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS)
mcuboot_generate_encryption_key_file(${CMAKE_CURRENT_BINARY_DIR}/enc_keys.c)
target_sources(${LIB_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/enc_keys.c)
endif()

# The cross-dependency requires that bootutil have access to the mbed port's
Expand Down
5 changes: 5 additions & 0 deletions boot/mbed/include/flash_map_backend/flash_map_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ uint8_t flash_area_erased_val(const struct flash_area * fap);

/*
* Given flash area ID, return info about sectors within the area.
*
* Note: the sectors array has size MCUBOOT_MAX_IMG_SECTORS, and only that many elements should
* be stored into it. However, if the flash area has more than MCUBOOT_MAX_IMG_SECTORS sectors,
* the count variable should be set to indicate the real sector count. This will trigger the appropriate
* warning to be printed.
*/
int flash_area_get_sectors(int fa_id, uint32_t *count,
struct flash_sector *sectors);
Expand Down
4 changes: 2 additions & 2 deletions boot/mbed/mbed_lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"value": true
},
"max-img-sectors": {
"help": "Maximum number of flash sectors per image slot. Target-dependent, please set on a per-target basis.",
"help": "Maximum number of flash sectors per image slot. This should be set to account for the sector sizes of both the main and secondary block devices. Target-dependent, please set on a per-target basis.",
"macro_name": "MCUBOOT_MAX_IMG_SECTORS",
"required": true
},
Expand Down Expand Up @@ -119,7 +119,7 @@
"value": null
},
"encrypt-rsa": {
"help": "Encrypt images using RSA (NOT TESTED)",
"help": "Encrypt update images using RSA",
"macro_name": "MCUBOOT_ENCRYPT_RSA",
"accepted_values": [true, null],
"value": null
Expand Down
216 changes: 216 additions & 0 deletions boot/mbed/mcuboot_imgtool.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
# Copyright (c) 2024 Jamie Smith
# SPDX-License-Identifier: Apache-2.0

check_python_package(imgtool.main MCUBOOT_IMGTOOL_FOUND)

get_filename_component(IMGTOOL_SCRIPTS_DIR ${CMAKE_CURRENT_LIST_DIR}/../../scripts REALPATH)

# Find or install imgtool

if(NOT MCUBOOT_IMGTOOL_FOUND)
# If we are using the Mbed venv, we can install asn1tools automatically
if(MBED_CREATE_PYTHON_VENV)
message(STATUS "mcuboot: Installing imgtool into Mbed's Python virtualenv")
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip install ${IMGTOOL_SCRIPTS_DIR}
COMMAND_ERROR_IS_FATAL ANY
)
else()
message(FATAL_ERROR "The mcuboot imgtool python package needs to be installed (from mcuboot/scripts/) into Mbed's python interpreter (${Python3_EXECUTABLE})")
endif()
endif()

# Signing key
set(MCUBOOT_SIGNING_KEY "" CACHE STRING "Path to key file (.pem) used to sign firmware updates for your device. The public key will be stored in the bootloader. This file must be kept safe!")

# Make sure the signing key path is absolute for EXISTS, relative to the top level build dir
get_filename_component(MCUBOOT_SIGNING_KEY_ABSPATH "${MCUBOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR})
set(MCUBOOT_SIGNING_KEY_ABSPATH ${MCUBOOT_SIGNING_KEY_ABSPATH} CACHE INTERNAL "Absolute version of MCUBOOT_SIGNING_KEY" FORCE)

if("${MCUBOOT_SIGNING_KEY}" STREQUAL "" OR NOT EXISTS "${MCUBOOT_SIGNING_KEY_ABSPATH}")
message(FATAL_ERROR "Must specify path to valid image signing key via MCUBOOT_SIGNING_KEY CMake option in order to build this project.")
endif()

# Encryption key
if("MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS)
set(MCUBOOT_ENCRYPTION_KEY "" CACHE STRING "Path to key file (.pem) used to encrypt firmware updates for your device. The private key will be stored in the bootloader. This file must be kept safe!")

# Make sure the signing key path is absolute for EXISTS, relative to the top level build dir
get_filename_component(MCUBOOT_ENCRYPTION_KEY_ABSPATH "${MCUBOOT_ENCRYPTION_KEY}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR})
set(MCUBOOT_ENCRYPTION_KEY_ABSPATH ${MCUBOOT_ENCRYPTION_KEY_ABSPATH} CACHE INTERNAL "Absolute version of MCUBOOT_ENCRYPTION_KEY" FORCE)

if("${MCUBOOT_ENCRYPTION_KEY}" STREQUAL "" OR NOT EXISTS "${MCUBOOT_ENCRYPTION_KEY_ABSPATH}")
message(FATAL_ERROR "Since mcuboot.encrypt-rsa is enabled, you must specify the path to a valid image encryption key via the MCUBOOT_ENCRYPTION_KEY CMake option in order to build this project.")
endif()
endif()

# Imgtool usage functions

#
# Generate a signed image hex file for the given executable target.
#
function(_mcuboot_generate_image TARGET IMAGE_TYPE IMAGE_BASENAME)
# Figure out file name
set(IMAGE_BASE_PATH ${CMAKE_CURRENT_BINARY_DIR}/${IMAGE_BASENAME})

if("${MBED_OUTPUT_EXT}" STREQUAL "bin")
message(FATAL_ERROR "Hex file output must be enabled to use mcuboot. Set MBED_OUTPUT_EXT to empty string after including app.cmake in your top level CMakeLists.txt!")
endif()

if("${PROJECT_VERSION}" STREQUAL "")
message(FATAL_ERROR "You must set the project version to sign images by passing a version number into your app's project() command!")
endif()

# mbed_generate_bin_hex() puts the hex file at the following path
set(TARGET_HEX_FILE ${CMAKE_CURRENT_BINARY_DIR}/$<TARGET_FILE_BASE_NAME:${TARGET}>.hex)

# Grab header size
if(NOT "${MBED_CONFIG_DEFINITIONS}" MATCHES "MCUBOOT_HEADER_SIZE=(0x[0-9A-Fa-f]+)")
message(FATAL_ERROR "Couldn't find MCUBOOT_HEADER_SIZE in Mbed configuration!")
endif()
set(HEADER_SIZE_HEX ${CMAKE_MATCH_1})

# Grab slot size
if(NOT "${MBED_CONFIG_DEFINITIONS}" MATCHES "MCUBOOT_SLOT_SIZE=(0x[0-9A-Fa-f]+)")
message(FATAL_ERROR "Couldn't find MCUBOOT_SLOT_SIZE in Mbed configuration!")
endif()
set(SLOT_SIZE_HEX ${CMAKE_MATCH_1})

get_property(objcopy GLOBAL PROPERTY ELF2BIN)

if(${IMAGE_TYPE} STREQUAL "update" AND "MCUBOOT_ENCRYPT_RSA=1" IN_LIST MBED_CONFIG_DEFINITIONS)
set(IMGTOOL_EXTRA_ARGS --encrypt ${MCUBOOT_ENCRYPTION_KEY_ABSPATH})
else()
set(IMGTOOL_EXTRA_ARGS "")
endif()

add_custom_command(
TARGET ${TARGET}
POST_BUILD
DEPENDS ${MCUBOOT_SIGNING_KEY_ABSPATH}
COMMAND
${Python3_EXECUTABLE} -m imgtool.main
sign
--key ${MCUBOOT_SIGNING_KEY_ABSPATH} # this specifies the file containing the keys used to sign/verify the application
--align 4 # this lets mcuboot know the intrinsic alignment of the flash (32-bits = 4 byte alignment)
--version ${PROJECT_VERSION} # this sets the version number of the application
--header-size ${HEADER_SIZE_HEX} # this must be the same as the value specified in mcuboot.header-size configuration
--pad-header # this tells imgtool to insert the entire header, including any necessary padding bytes.
--slot-size ${SLOT_SIZE_HEX} # this specifies the maximum size of the application ("slot size"). It must be the same as the configured mcuboot.slot-size!
${IMGTOOL_EXTRA_ARGS}
${TARGET_HEX_FILE} ${IMAGE_BASE_PATH}.hex

COMMAND
${CMAKE_COMMAND} -E echo "-- built: ${IMAGE_BASE_PATH}.hex"

# Also generate bin file
COMMAND
${objcopy} -I ihex -O binary ${IMAGE_BASE_PATH}.hex ${IMAGE_BASE_PATH}.bin

COMMAND
${CMAKE_COMMAND} -E echo "-- built: ${IMAGE_BASE_PATH}.bin"

COMMENT "Generating mcuboot ${IMAGE_TYPE} image for ${TARGET}..."
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
VERBATIM
)
endfunction(_mcuboot_generate_image)

#
# Generate an initial image hex file for the given executable target.
# This initial image is what should be flashed to a blank device (along with the bootloader).
# A flash target (ninja flash-${TARGET}-update-image) will also be created.
#
# NOTE: This function must be called *after* mbed_set_post_build() for the target!
#
# If you wish to specify the base name of the initial image, pass that as the second argument to
# this function. Otherwise, it will default to $<target name>-initial-image
#
function(mcuboot_generate_initial_image TARGET) # optional 2nd arg: initial image base filename
# Figure out file name
if("${ARGN}" STREQUAL "")
set(INITIAL_IMAGE_BASENAME $<TARGET_FILE_BASE_NAME:${TARGET}>-initial-image)
else()
set(INITIAL_IMAGE_BASE_PATH ${ARGN})
endif()

_mcuboot_generate_image(${TARGET} initial ${INITIAL_IMAGE_BASENAME})

# Create a flash target.
# We need to be slightly creative here -- Mbed thinks that the application start address
# is <primary slot address> + <header size>, but we actually want to upload to <primary slot address>.
# So we need to temporarily override MBED_UPLOAD_BASE_ADDR with an offset value
if(NOT "${MBED_CONFIG_DEFINITIONS}" MATCHES "MCUBOOT_HEADER_SIZE=(0x[0-9A-Fa-f]+)")
message(FATAL_ERROR "Couldn't find MCUBOOT_HEADER_SIZE in Mbed configuration!")
endif()
set(HEADER_SIZE_HEX ${CMAKE_MATCH_1})
math(EXPR MBED_UPLOAD_BASE_ADDR "${MBED_UPLOAD_BASE_ADDR} - ${HEADER_SIZE_HEX}" OUTPUT_FORMAT HEXADECIMAL)

gen_upload_target(${TARGET}-${IMAGE_TYPE}-image ${IMAGE_BASE_PATH}.bin)
add_dependencies(flash-${TARGET}-${IMAGE_TYPE}-image ${TARGET})
endfunction(mcuboot_generate_initial_image)

#
# Generate an update image hex file for the given executable target.
# This image is what should be flashed to the secondary block device and passed to
# mcuboot as an update file.
#
# NOTE: This function must be called *after* mbed_set_post_build() for the target!
#
# NOTE 2: The hex file produced by this function will still "declare" its address as the primary slot
# address. This can cause issues if you pass it to a tool that uses this offset to decide where to load it.
# If this is a problem, we recommend the "arm-none-eabi-objcopy --change-addresses" command to change this address.
#
# If you wish to specify the base name of the update image, pass that as the second argument to
# this function. Otherwise, it will default to $<target name>-update-image
#
function(mcuboot_generate_update_image TARGET) # optional 2nd arg: update image base filename
# Figure out file name
if("${ARGN}" STREQUAL "")
set(UPDATE_IMAGE_BASENAME $<TARGET_FILE_BASE_NAME:${TARGET}>-update-image)
else()
set(UPDATE_IMAGE_BASENAME ${ARGN})
endif()

_mcuboot_generate_image(${TARGET} update ${UPDATE_IMAGE_BASENAME})
endfunction(mcuboot_generate_update_image)

#
# Generate a C source file with signing keys in it at the given location.
# The file should be added as a source file to a library built in the same directory.
#
function(mcuboot_generate_signing_keys_file SIGNING_KEYS_C_PATH)
add_custom_command(
OUTPUT ${SIGNING_KEYS_C_PATH}
COMMAND
${Python3_EXECUTABLE} -m imgtool.main
getpub
--key ${MCUBOOT_SIGNING_KEY_ABSPATH}
--output ${SIGNING_KEYS_C_PATH}

DEPENDS ${MCUBOOT_SIGNING_KEY_ABSPATH}
COMMENT "Converting signing key to C source..."
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
)
endfunction(mcuboot_generate_signing_keys_file)

#
# Generate a C source file with the encryption private key in it at the given location.
# The file should be added as a source file to a library built in the same directory.
#
function(mcuboot_generate_encryption_key_file ENC_KEY_C_PATH)
add_custom_command(
OUTPUT ${ENC_KEY_C_PATH}
COMMAND
${Python3_EXECUTABLE} -m imgtool.main
getpriv
--key ${MCUBOOT_SIGNING_KEY_ABSPATH}
> ${ENC_KEY_C_PATH}

DEPENDS ${MCUBOOT_SIGNING_KEY_ABSPATH}
COMMENT "Converting encryption key to C source..."
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
VERBATIM
)
endfunction(mcuboot_generate_encryption_key_file)
3 changes: 2 additions & 1 deletion boot/mbed/mcuboot_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#if MCUBOOT_BOOTLOADER_BUILD

#include <stdlib.h>
#include <cinttypes>
#include "bootutil/bootutil.h"
#include "bootutil/image.h"
#include "hal/serial_api.h"
Expand Down Expand Up @@ -83,7 +84,7 @@ int main()
// Workaround: The extra \n ensures the last trace gets flushed
// before mbed_start_application() destroys the stack and jumps
// to the application
tr_info("Booting firmware image at 0x%x\n", address);
tr_info("Booting firmware image at 0x%" PRIx32 "\n", address);

// Run the application in the primary slot
// Add header size offset to calculate the actual start address of application
Expand Down
12 changes: 8 additions & 4 deletions boot/mbed/src/flash_map_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <assert.h>
#include <cstring>
#include <cinttypes>
#include "flash_map_backend/flash_map_backend.h"
#include "flash_map_backend/secondary_bd.h"
#include "sysflash/sysflash.h"
Expand Down Expand Up @@ -142,7 +143,7 @@ int flash_area_read(const struct flash_area* fap, uint32_t off, void* dst, uint3
return -1;
}
if (MCUBOOT_READ_GRANULARITY < read_size) {
MCUBOOT_LOG_ERR("Please increase MCUBOOT_READ_GRANULARITY (currently %u) to be at least %u",
MCUBOOT_LOG_ERR("Please increase MCUBOOT_READ_GRANULARITY (currently %u) to be at least %" PRIu32,
MCUBOOT_READ_GRANULARITY, read_size);
return -1;
}
Expand Down Expand Up @@ -214,11 +215,14 @@ int flash_area_get_sectors(int fa_id, uint32_t* count, struct flash_sector* sect
/* Loop through sectors and collect information on them */
bd_addr_t offset = 0;
*count = 0;
while (*count < MCUBOOT_MAX_IMG_SECTORS && bd->is_valid_read(offset, bd->get_read_size())) {
while (bd->is_valid_read(offset, bd->get_read_size())) {

sectors[*count].fs_off = offset;
bd_size_t erase_size = bd->get_erase_size(offset);
sectors[*count].fs_size = erase_size;

if (*count < MCUBOOT_MAX_IMG_SECTORS) {
sectors[*count].fs_off = offset;
sectors[*count].fs_size = erase_size;
}

offset += erase_size;
*count += 1;
Expand Down

0 comments on commit e8017b7

Please sign in to comment.