mcuboot: Add support for RAM load mode

Adds supporting code that allows the RAM load mode of MCUboot to
be used and for applications to build successfully with it.
Sysbuild can be used to build images for this mode

Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
This commit is contained in:
Jamie McCrae 2024-07-24 13:21:33 +01:00 committed by Anas Nashif
parent 8774f15bd2
commit 646f116cca
8 changed files with 139 additions and 6 deletions

View File

@ -114,9 +114,21 @@ function(zephyr_mcuboot_tasks)
set(imgtool_args --key "${keyfile}" ${imgtool_args})
endif()
# Use overwrite-only instead of swap upgrades.
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})
else()
set(imgtool_args --align ${write_block_size} ${imgtool_args})
endif()
@ -156,6 +168,27 @@ function(zephyr_mcuboot_tasks)
${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.
@ -187,8 +220,28 @@ function(zephyr_mcuboot_tasks)
${imgtool_sign} ${imgtool_args} --encrypt "${keyfile_enc}" ${output}.hex
${output}.signed.encrypted.hex)
endif()
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()

View File

@ -183,6 +183,18 @@ config MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY
that the overwrite will not happen unless the version of secondary
slot is higher than the version in primary slot.
config MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
bool "MCUboot has been configured for RAM LOAD operation"
select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE
select MCUBOOT_BOOTLOADER_NO_DOWNGRADE
help
MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode, MCUboot
will select the image with the higher version number, copy it to RAM and begin execution
from there. The image must be linked to execute from RAM, the address that it is copied
to is specified using the load-addr argument when running imgtool.
This option automatically selectes MCUBOOT_BOOTLOADER_NO_DOWNGRADE as it is not possible
to swap back to older version of the application.
config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
bool "MCUboot has been configured for DirectXIP operation"
select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE

View File

@ -33,7 +33,10 @@ if(SB_CONFIG_BOOTLOADER_MCUBOOT)
elseif(SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT)
set_config_bool(${ZCMAKE_APPLICATION} CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT y)
elseif(SB_CONFIG_MCUBOOT_MODE_RAM_LOAD)
# Not yet supported in zephyr code
# RAM load mode requires XIP be disabled and flash size be set to 0
set_config_bool(${ZCMAKE_APPLICATION} CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD y)
set_config_bool(${ZCMAKE_APPLICATION} CONFIG_XIP n)
set_config_int(${ZCMAKE_APPLICATION} CONFIG_FLASH_SIZE 0)
elseif(SB_CONFIG_MCUBOOT_MODE_FIRMWARE_UPDATER)
set_config_bool(${ZCMAKE_APPLICATION} CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER y)
endif()

View File

@ -10,6 +10,7 @@
menuconfig IMG_MANAGER
bool "DFU image manager"
depends on STREAM_FLASH
depends on !MCUBOOT_BOOTLOADER_MODE_RAM_LOAD || RETENTION_BOOTLOADER_INFO_OUTPUT_FUNCTION
help
Enable support for managing DFU image.

View File

@ -12,6 +12,7 @@
#include <zephyr/storage/flash_map.h>
#include <zephyr/kernel.h>
#include <zephyr/init.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/byteorder.h>
@ -19,8 +20,15 @@
#include "bootutil/bootutil_public.h"
#include <zephyr/dfu/mcuboot.h>
#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
#include <bootutil/boot_status.h>
#include <zephyr/retention/blinfo.h>
#endif
#include "mcuboot_priv.h"
LOG_MODULE_REGISTER(mcuboot_dfu, LOG_LEVEL_DBG);
/*
* Helpers for image headers and trailers, as defined by mcuboot.
*/
@ -34,8 +42,15 @@
#define BOOT_HEADER_MAGIC_V1 0x96f3b83d
#define BOOT_HEADER_SIZE_V1 32
#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
/* For RAM LOAD mode, the active image must be fetched from the bootloader */
static uint8_t boot_fetch_active_slot(void);
#define ACTIVE_SLOT_FLASH_AREA_ID boot_fetch_active_slot()
#define INVALID_SLOT_ID 255
#else
/* Get active partition. zephyr,code-partition chosen node must be defined */
#define ACTIVE_SLOT_FLASH_AREA_ID DT_FIXED_PARTITION_ID(DT_CHOSEN(zephyr_code_partition))
#endif
/*
* Raw (on-flash) representation of the v1 image header.
@ -60,6 +75,26 @@ struct mcuboot_v1_raw_header {
* End of strict defines
*/
#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
static uint8_t boot_fetch_active_slot(void)
{
int rc;
uint8_t slot;
rc = blinfo_lookup(BLINFO_RUNNING_SLOT, &slot, sizeof(slot));
if (rc <= 0) {
LOG_ERR("Failed to fetch active slot: %d", rc);
return INVALID_SLOT_ID;
}
LOG_DBG("Active slot: %d", slot);
return slot;
}
#endif
static int boot_read_v1_header(uint8_t area_id,
struct mcuboot_v1_raw_header *v1_raw)
{

View File

@ -35,6 +35,13 @@
#include <mgmt/mcumgr/transport/smp_internal.h>
#endif
#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
#include <bootutil/boot_status.h>
#include <zephyr/retention/blinfo.h>
#endif
#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
#ifndef CONFIG_FLASH_LOAD_OFFSET
#error MCUmgr requires application to be built with CONFIG_FLASH_LOAD_OFFSET set \
to be able to figure out application running slot.
@ -75,6 +82,10 @@ BUILD_ASSERT(sizeof(struct image_header) == IMAGE_HEADER_SIZE,
#define ACTIVE_IMAGE_IS 0
#endif
#else
#define ACTIVE_IMAGE_IS 0
#endif
#define SLOTS_PER_IMAGE 2
LOG_MODULE_REGISTER(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL);
@ -198,9 +209,23 @@ int img_mgmt_active_slot(int image)
{
int slot = 0;
/* Multi image does not support DirectXIP currently */
/* Multi image does not support DirectXIP or RAM load currently */
#if CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER > 1
slot = (image << 1);
#elif defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
/* RAM load requires querying bootloader */
int rc;
uint8_t temp_slot;
rc = blinfo_lookup(BLINFO_RUNNING_SLOT, &temp_slot, sizeof(temp_slot));
if (rc <= 0) {
LOG_ERR("Failed to fetch active slot: %d", rc);
return 255;
}
slot = (int)temp_slot;
#else
/* This covers single image, including DirectXiP */
if (FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot1_partition)) {
@ -1056,7 +1081,8 @@ static int img_mgmt_translate_error_code(uint16_t err)
static const struct mgmt_handler img_mgmt_handlers[] = {
[IMG_MGMT_ID_STATE] = {
.mh_read = img_mgmt_state_read,
#ifdef CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP
#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
.mh_write = NULL
#else
.mh_write = img_mgmt_state_write,

View File

@ -324,7 +324,8 @@ img_mgmt_slot_in_use(int slot)
int image = img_mgmt_slot_to_image(slot);
int active_slot = img_mgmt_active_slot(image);
#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP)
#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) && \
!defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
enum img_mgmt_next_boot_type type = NEXT_BOOT_TYPE_NORMAL;
int nbs = img_mgmt_get_next_boot_slot(image, &type);

View File

@ -570,6 +570,7 @@ int img_mgmt_upload_inspect(const struct img_mgmt_upload_req *req,
(defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT)) && \
CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE > 0
@ -645,6 +646,7 @@ int img_mgmt_upload_inspect(const struct img_mgmt_upload_req *req,
(defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_WITHOUT_SCRATCH) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_SCRATCH) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \
defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT)) && \
CONFIG_MCUBOOT_UPDATE_FOOTER_SIZE > 0