diff --git a/cmake/mcuboot.cmake b/cmake/mcuboot.cmake index 25fa1827f33..b6ab9dd5034 100644 --- a/cmake/mcuboot.cmake +++ b/cmake/mcuboot.cmake @@ -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() diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index a914ff1d5a8..2706ad6583c 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -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 diff --git a/share/sysbuild/image_configurations/MAIN_image_default.cmake b/share/sysbuild/image_configurations/MAIN_image_default.cmake index 601d8b616ec..cd447a29d0c 100644 --- a/share/sysbuild/image_configurations/MAIN_image_default.cmake +++ b/share/sysbuild/image_configurations/MAIN_image_default.cmake @@ -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() diff --git a/subsys/dfu/Kconfig b/subsys/dfu/Kconfig index 5977764016d..f621457a1e7 100644 --- a/subsys/dfu/Kconfig +++ b/subsys/dfu/Kconfig @@ -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. diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index 20015349dbc..dde9f8af579 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -19,8 +20,15 @@ #include "bootutil/bootutil_public.h" #include +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) +#include +#include +#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) { diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c index 913aec15c88..63083c96fb9 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c @@ -35,6 +35,13 @@ #include #endif +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) +#include +#include +#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, diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c index a580d7af6c3..52b2ed76f67 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c @@ -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); diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index 131f7a698b2..8d58a3b8634 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -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