diff --git a/cmake/mcuboot.cmake b/cmake/mcuboot.cmake index 3cf7454265b5..c606733c09d6 100644 --- a/cmake/mcuboot.cmake +++ b/cmake/mcuboot.cmake @@ -104,7 +104,7 @@ function(zephyr_mcuboot_tasks) 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) + elseif(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD OR CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) # 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}) @@ -113,7 +113,7 @@ function(zephyr_mcuboot_tasks) 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 --align ${write_block_size} --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() @@ -145,6 +145,7 @@ function(zephyr_mcuboot_tasks) set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.bin ${output}.signed.confirmed.bin) + zephyr_runner_file(bin ${output}.signed.confirmed.bin) endif() if(NOT "${keyfile_enc}" STREQUAL "") @@ -157,7 +158,7 @@ function(zephyr_mcuboot_tasks) ${output}.signed.encrypted.bin) endif() - if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) + if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD OR CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) 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 @@ -208,6 +209,7 @@ function(zephyr_mcuboot_tasks) set_property(GLOBAL APPEND PROPERTY extra_post_build_commands COMMAND ${imgtool_sign} ${imgtool_args} --pad --confirm ${output}.hex ${output}.signed.confirmed.hex) + zephyr_runner_file(hex ${output}.signed.confirmed.hex) endif() if(NOT "${keyfile_enc}" STREQUAL "") @@ -220,7 +222,7 @@ function(zephyr_mcuboot_tasks) ${output}.signed.encrypted.hex) endif() - if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) + if(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD OR CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) 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 diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index 73a6346f89b8..bb3e95113844 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -211,6 +211,26 @@ config MCUBOOT_BOOTLOADER_MODE_RAM_LOAD 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_RAM_LOAD_WITH_REVERT + bool "MCUboot has been configured for RAM LOAD with revert" + 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. + In this mode MCUboot will boot the application with the higher + version from either slot, as long as it has been marked to be boot + next time for test or permanently. In case when application is marked + for test it needs to confirm itself, on the first boot, or it will be + removed and MCUboot will revert to booting previously approved + application. Note that in this mode MCUboot will not boot an + application if it does not have an image header, so if an application + is flashed manually it should be marked as confirmed + config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP bool "MCUboot has been configured for DirectXIP operation" select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/boards/mimxrt1050_evk_hyperflash_ram_load.conf b/samples/subsys/mgmt/mcumgr/smp_svr/boards/mimxrt1050_evk_hyperflash_ram_load.conf new file mode 100644 index 000000000000..3d5bd27bd6a0 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/boards/mimxrt1050_evk_hyperflash_ram_load.conf @@ -0,0 +1 @@ +CONFIG_USE_DT_CODE_PARTITION=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/boards/mimxrt1050_evk_hyperflash_ram_load.overlay b/samples/subsys/mgmt/mcumgr/smp_svr/boards/mimxrt1050_evk_hyperflash_ram_load.overlay new file mode 100644 index 000000000000..b8dc44b78fb5 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/boards/mimxrt1050_evk_hyperflash_ram_load.overlay @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Layout must match the hyperflash_ram_load overlay file within mcuboot + * application configuration directory + */ + +/delete-node/ &sdram0; + +/ { + sram@80007F00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x80007F00 0x100>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_info0: boot_info@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + }; + }; + }; + + chosen { + zephyr,bootloader-info = &boot_info0; + zephyr,sram = &sdram_split; + }; + + /* + * Adjust sdram0 to reserve first 30KB for MCUBoot, and + * remaining 2KB for retained memory + */ + sdram_split: sdram_split@80008000 { + reg = <0x80008000 (0x2000000 - DT_SIZE_K(32))>; + }; + +}; + +/* Reduce size of slot 0 to match slot 1 */ +&slot0_partition { + reg = <0x40000 0x300000>; +}; diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf52840dk_nrf52840_ram_load.overlay b/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf52840dk_nrf52840_ram_load.overlay index 2b59fce7065f..c00289cbb059 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf52840dk_nrf52840_ram_load.overlay +++ b/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf52840dk_nrf52840_ram_load.overlay @@ -1,6 +1,35 @@ /delete-node/ &sram0; -#include "../sysbuild/nrf52840dk_nrf52840_mcuboot_ram_load.overlay" +/* + * Layout must match the nrf52840dk_nrf52840_ram_load overlay file within mcuboot + * application configuration directory + */ + +/ { + sram@2003FF00 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003FF00 0x100>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_info0: boot_info@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x100>; + }; + }; + }; + + chosen { + zephyr,bootloader-info = &boot_info0; + }; +}; / { chosen { @@ -15,3 +44,8 @@ }; }; }; + +/* Reduce slot0 partition size so it matches slot1 */ +&slot0_partition { + reg = <0xc000 0x75000>; +}; diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml b/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml index 3d9cb6489cfb..02cc500df103 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml @@ -177,8 +177,17 @@ tests: - EXTRA_CONF_FILE="overlay-serial.conf" platform_allow: - nrf52840dk/nrf52840 + - mimxrt1050_evk/mimxrt1052/hyperflash + sample.mcumgr.smp_svr.ram_load_revert.serial: + extra_args: + - FILE_SUFFIX="ram_load" + - EXTRA_CONF_FILE="overlay-serial.conf" + - SB_CONFIG_MCUBOOT_MODE_RAM_LOAD_WITH_REVERT=y + - smp_svr_CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE=y + platform_allow: + - mimxrt1050_evk/mimxrt1052/hyperflash integration_platforms: - - nrf52840dk/nrf52840 + - mimxrt1050_evk/mimxrt1052/hyperflash sample.mcumgr.smp_svr.ram_load.serial.fs.shell: extra_args: - FILE_SUFFIX="ram_load" diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/CMakeLists.txt b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/CMakeLists.txt index 7eb859ef4697..5dfdd0610eb9 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/CMakeLists.txt +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/CMakeLists.txt @@ -1,9 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -if("${FILE_SUFFIX}" STREQUAL "ram_load") - set(mcuboot_EXTRA_DTC_OVERLAY_FILE "${CMAKE_CURRENT_LIST_DIR}/nrf52840dk_nrf52840_mcuboot_ram_load.overlay" CACHE INTERNAL "" FORCE) -endif() - find_package(Sysbuild REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(sysbuild LANGUAGES) diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf52840dk_nrf52840_mcuboot_ram_load.overlay b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf52840dk_nrf52840_mcuboot_ram_load.overlay deleted file mode 100644 index fbd19b0b74de..000000000000 --- a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf52840dk_nrf52840_mcuboot_ram_load.overlay +++ /dev/null @@ -1,25 +0,0 @@ -/ { - sram@2003FC00 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x2003FC00 DT_SIZE_K(1)>; - zephyr,memory-region = "RetainedMem"; - status = "okay"; - - retainedmem { - compatible = "zephyr,retained-ram"; - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - - boot_info0: boot_info@0 { - compatible = "zephyr,retention"; - status = "okay"; - reg = <0x0 0x100>; - }; - }; - }; - - chosen { - zephyr,bootloader-info = &boot_info0; - }; -}; diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 91bd8b428c65..54d5289efc45 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -1015,6 +1015,7 @@ def check_no_undef_outside_kconfig(self, kconf): "BOOT_FIRMWARE_LOADER", # Used in sysbuild for MCUboot configuration "BOOT_MAX_IMG_SECTORS_AUTO", # Used in sysbuild "BOOT_RAM_LOAD", # Used in sysbuild for MCUboot configuration + "BOOT_RAM_LOAD_REVERT", # Used in sysbuild for MCUboot configuration "BOOT_SERIAL_BOOT_MODE", # Used in (sysbuild-based) test/ # documentation "BOOT_SERIAL_CDC_ACM", # Used in (sysbuild-based) test diff --git a/share/sysbuild/image_configurations/BOOTLOADER_image_default.cmake b/share/sysbuild/image_configurations/BOOTLOADER_image_default.cmake index 422fdb830308..e5330764e947 100644 --- a/share/sysbuild/image_configurations/BOOTLOADER_image_default.cmake +++ b/share/sysbuild/image_configurations/BOOTLOADER_image_default.cmake @@ -26,7 +26,7 @@ elseif(SB_CONFIG_MCUBOOT_MODE_OVERWRITE_ONLY) set(bootmode CONFIG_BOOT_UPGRADE_ONLY) elseif(SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP OR SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT) set(bootmode CONFIG_BOOT_DIRECT_XIP) -elseif(SB_CONFIG_MCUBOOT_MODE_RAM_LOAD) +elseif(SB_CONFIG_MCUBOOT_MODE_RAM_LOAD OR SB_CONFIG_MCUBOOT_MODE_RAM_LOAD_WITH_REVERT) set(bootmode CONFIG_BOOT_RAM_LOAD) elseif(SB_CONFIG_MCUBOOT_MODE_FIRMWARE_UPDATER) set(bootmode CONFIG_BOOT_FIRMWARE_LOADER) @@ -46,6 +46,12 @@ else() set_config_bool(${ZCMAKE_APPLICATION} CONFIG_BOOT_DIRECT_XIP_REVERT n) endif() +if(SB_CONFIG_MCUBOOT_MODE_RAM_LOAD_WITH_REVERT) + set_config_bool(${ZCMAKE_APPLICATION} CONFIG_BOOT_RAM_LOAD_REVERT y) +else() + set_config_bool(${ZCMAKE_APPLICATION} CONFIG_BOOT_RAM_LOAD_REVERT n) +endif() + set(keytypes CONFIG_BOOT_SIGNATURE_TYPE_NONE CONFIG_BOOT_SIGNATURE_TYPE_RSA CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256 diff --git a/share/sysbuild/image_configurations/MAIN_image_default.cmake b/share/sysbuild/image_configurations/MAIN_image_default.cmake index 28dd6d0aacb7..96223cbe3a38 100644 --- a/share/sysbuild/image_configurations/MAIN_image_default.cmake +++ b/share/sysbuild/image_configurations/MAIN_image_default.cmake @@ -39,6 +39,11 @@ if(SB_CONFIG_BOOTLOADER_MCUBOOT) 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_RAM_LOAD_WITH_REVERT) + # 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_WITH_REVERT 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/share/sysbuild/images/bootloader/Kconfig b/share/sysbuild/images/bootloader/Kconfig index 1b5cdec41eae..1384ebddad85 100644 --- a/share/sysbuild/images/bootloader/Kconfig +++ b/share/sysbuild/images/bootloader/Kconfig @@ -119,6 +119,20 @@ config MCUBOOT_MODE_RAM_LOAD Note: RAM must be assigned to the bootloader that is not used by the application in this mode so that the bootloader is able to function until the application has booted. +config MCUBOOT_MODE_RAM_LOAD_WITH_REVERT + bool "RAM load with revert" + 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. MCUBoot will only boot an image if it has been marked to be boot next time + for test or permanently. In case when application is marked for test it needs to confirm + itself, on the first boot, or it will be removed and MCUboot will revert to booting + previously approved application. 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. + + Note: RAM must be assigned to the bootloader that is not used by the application in this + mode so that the bootloader is able to function until the application has booted. + config MCUBOOT_MODE_FIRMWARE_UPDATER bool "Firmware updater" help diff --git a/soc/nxp/common/Kconfig.flexspi_xip b/soc/nxp/common/Kconfig.flexspi_xip index c36336ea2f33..f804c563933e 100644 --- a/soc/nxp/common/Kconfig.flexspi_xip +++ b/soc/nxp/common/Kconfig.flexspi_xip @@ -23,6 +23,8 @@ config FLASH_SIZE config FLASH_MCUX_FLEXSPI_XIP bool default $(DT_FLASH_PARENT_IS_FLEXSPI) + depends on !(MCUBOOT_BOOTLOADER_MODE_RAM_LOAD || \ + MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) select XIP help Allows REfor the soc to safely initialize the clocks for the diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index 5683d23a87ad..f489718aa9be 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -20,9 +20,18 @@ #include "bootutil/bootutil_public.h" #include -#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) +/* For RAM LOAD mode, the active image must be fetched from the bootloader */ #include #include + +#define SLOT0_PARTITION slot0_partition +#define SLOT1_PARTITION slot1_partition +#define SLOT2_PARTITION slot2_partition +#define SLOT3_PARTITION slot3_partition +#define SLOT4_PARTITION slot4_partition +#define SLOT5_PARTITION slot5_partition #endif #include "mcuboot_priv.h" @@ -49,7 +58,8 @@ enum IMAGE_INDEXES { IMAGE_INDEX_2 }; -#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) /* For RAM LOAD mode, the active image must be fetched from the bootloader */ #define ACTIVE_SLOT_FLASH_AREA_ID boot_fetch_active_slot() #define INVALID_SLOT_ID 255 @@ -81,11 +91,12 @@ struct mcuboot_v1_raw_header { * End of strict defines */ -#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT) uint8_t boot_fetch_active_slot(void) { int rc; - uint8_t slot; + uint8_t slot, fa_id; rc = blinfo_lookup(BLINFO_RUNNING_SLOT, &slot, sizeof(slot)); @@ -96,15 +107,57 @@ uint8_t boot_fetch_active_slot(void) } LOG_DBG("Active slot: %d", slot); + /* Map slot number back to flash area ID */ + switch (slot) { + case 0: + fa_id = FIXED_PARTITION_ID(SLOT0_PARTITION); + break; + + case 1: + fa_id = FIXED_PARTITION_ID(SLOT1_PARTITION); + break; + +#if FIXED_PARTITION_EXISTS(SLOT2_PARTITION) + case 2: + fa_id = FIXED_PARTITION_ID(SLOT2_PARTITION); + break; +#endif + +#if FIXED_PARTITION_EXISTS(SLOT3_PARTITION) + case 3: + fa_id = FIXED_PARTITION_ID(SLOT3_PARTITION); + break; +#endif + +#if FIXED_PARTITION_EXISTS(SLOT4_PARTITION) + case 4: + fa_id = FIXED_PARTITION_ID(SLOT4_PARTITION); + break; +#endif + +#if FIXED_PARTITION_EXISTS(SLOT5_PARTITION) + case 5: + fa_id = FIXED_PARTITION_ID(SLOT5_PARTITION); + break; +#endif + + default: + fa_id = INVALID_SLOT_ID; + break; + } - return slot; + return fa_id; } -#else /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */ +#else /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD || + * CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT + */ uint8_t boot_fetch_active_slot(void) { return ACTIVE_SLOT_FLASH_AREA_ID; } -#endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */ +#endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD || + * CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD_WITH_REVERT + */ #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET) size_t boot_get_image_start_offset(uint8_t area_id) diff --git a/west.yml b/west.yml index 59090db9c9aa..494d00e13455 100644 --- a/west.yml +++ b/west.yml @@ -23,6 +23,8 @@ manifest: url-base: https://github.com/zephyrproject-rtos - name: babblesim url-base: https://github.com/BabbleSim + - name: mcuboot + url-base: https://github.com/mcu-tools group-filter: [-babblesim, -optional] @@ -303,7 +305,8 @@ manifest: groups: - crypto - name: mcuboot - revision: c8470fb145f8aff92696d05396fb77c3b8068b32 + revision: pull/2197/head + remote: mcuboot path: bootloader/mcuboot groups: - bootloader