diff --git a/modules/mcuboot/Kconfig b/modules/mcuboot/Kconfig index 2c5110bd2de..9cf321bafe3 100644 --- a/modules/mcuboot/Kconfig +++ b/modules/mcuboot/Kconfig @@ -76,9 +76,13 @@ config MCUBOOT_USE_ALL_AVAILABLE_RAM endmenu +DT_CHOSEN_BOOTLOADER_REQUEST := nrf,bootloader-request +DT_CHOSEN_BOOTLOADER_REQUEST_BACKUP := nrf,bootloader-request-backup + config NRF_MCUBOOT_BOOT_REQUEST bool "MCUboot bootloader requests" imply MCUMGR_GRP_IMG_NRF + depends on $(dt_chosen_enabled,$(DT_CHOSEN_BOOTLOADER_REQUEST)) help Handle bootloader requests. @@ -88,12 +92,10 @@ choice NRF_MCUBOOT_BOOT_REQUEST_IMPL prompt "Shared memory backend" default NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION if RETENTION -DT_CHOSEN_BOOTLOADER_REQUEST := nrf,bootloader-request - config NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION bool "Retention" depends on RETENTION - depends on $(dt_chosen_enabled,$(DT_CHOSEN_BOOTLOADER_REQUEST)) + depends on $(dt_chosen_has_compat,$(DT_CHOSEN_BOOTLOADER_REQUEST),$(DT_COMPAT_ZEPHYR_RETENTION)) help Use zephyr,bootloader-request chosen node compatible with the zephyr,retention driver as the memory area to store and read from the @@ -102,8 +104,30 @@ config NRF_MCUBOOT_BOOT_REQUEST_IMPL_RETENTION structure version to ensure compatibility between the bootloader and the application. +config NRF_MCUBOOT_BOOT_REQUEST_IMPL_FLASH + bool "NVM partition" + depends on FLASH + depends on CRC + depends on !PARTITION_MANAGER_ENABLED # Partition manager uses an incompatible flash_map.h + help + Use zephyr,bootloader-request chosen node compatible with the + flash driver as the memory area to store and read from the bootloader + requests. + endchoice +config NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP + bool "Keep boot preference value across reboots" + depends on $(dt_chosen_enabled,$(DT_CHOSEN_BOOTLOADER_REQUEST_BACKUP)) + default y + help + Use zephyr,bootloader-request-backup chosen node compatible with the + zephyr,retention driver as the memory area to store a copy of + bootloader requests. + If this optional node is defined, the module will keep a copy of data + inside a backup region, allowing to preserve the preferred slot + selection across device resets. + config NCS_MCUBOOT_BOOT_REQUEST_TEST_SETS_BOOT_PREFERENCE bool "Set boot preference if a slot is marked for test" help diff --git a/samples/dfu/ab/Kconfig.sysbuild b/samples/dfu/ab/Kconfig.sysbuild new file mode 100644 index 00000000000..146d6e623aa --- /dev/null +++ b/samples/dfu/ab/Kconfig.sysbuild @@ -0,0 +1,21 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +if SOC_SERIES_NRF54HX + +# Enable radiocore +config NRF_DEFAULT_IPC_RADIO + default y + +config NETCORE_IPC_RADIO_BT_HCI_IPC + default y + +config MCUBOOT_IMAGES_ROM_END_OFFSET_AUTO + default "ipc_radio;ipc_radio_secondary_app" + +endif # SOC_SERIES_NRF54HX + +source "share/sysbuild/Kconfig" diff --git a/samples/dfu/ab/README.rst b/samples/dfu/ab/README.rst index 9f6c59c6cee..cf93370469c 100644 --- a/samples/dfu/ab/README.rst +++ b/samples/dfu/ab/README.rst @@ -60,7 +60,9 @@ The following conditions decide which slot will be booted (active) on the next r #. If none of the above conditions is met, slot A is selected as active. You can set the preferred slot using the ``boot_request_set_preferred_slot`` function. -Currently, this only sets the boot preference for a single reboot. +If the :kconfig:option:`CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP` option is enabled, the slot preference remains persistent across reboots. +Otherwise, the slot preference is cleared on reboot. +To enable the persistence of a preferred slot, define a backup region for the bootloader request area by using the ``nrf,bootloader-request-backup`` chosen node in the devicetree. Identifying the active slot --------------------------- diff --git a/samples/dfu/ab/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/samples/dfu/ab/boards/nrf54l15dk_nrf54l15_cpuapp.conf new file mode 100644 index 00000000000..7c93a8385b4 --- /dev/null +++ b/samples/dfu/ab/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -0,0 +1,3 @@ +# Enable boot requests through retained memory. +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y diff --git a/samples/dfu/ab/prj.conf b/samples/dfu/ab/prj.conf index 7175e6985e7..f50ec43445c 100644 --- a/samples/dfu/ab/prj.conf +++ b/samples/dfu/ab/prj.conf @@ -41,14 +41,9 @@ CONFIG_MCUBOOT_UTIL_LOG_LEVEL_WRN=y # Disable debug logging CONFIG_LOG_MAX_LEVEL=3 -# Enable boot requests through retained memory. -CONFIG_RETAINED_MEM=y -CONFIG_RETENTION=y +# Enable boot requests. CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y -CONFIG_RETENTION_BOOT_MODE=y -CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE=y - # Enable DK LED/button library CONFIG_DK_LIBRARY=y diff --git a/samples/dfu/ab/src/ab_utils.c b/samples/dfu/ab/src/ab_utils.c index 1bcfe0dec52..741afe0e0e8 100644 --- a/samples/dfu/ab/src/ab_utils.c +++ b/samples/dfu/ab/src/ab_utils.c @@ -58,12 +58,6 @@ LOG_MODULE_DECLARE(ab_sample); #define STATUS_LEDS_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1) K_THREAD_STACK_DEFINE(status_leds_thread_stack_area, STATUS_LEDS_THREAD_STACK_SIZE); -enum ab_boot_slot { - SLOT_A = 0, - SLOT_B = 1, - SLOT_INVALID, -}; - /** @brief Radio firmware self test * * @details @@ -91,14 +85,14 @@ static bool app_domain_healthy(void) return true; } -static enum ab_boot_slot active_boot_slot_get(void) +static enum boot_slot active_boot_slot_get(void) { - enum ab_boot_slot active_slot = SLOT_INVALID; + enum boot_slot active_slot = BOOT_SLOT_NONE; if (IS_SLOT_A) { - active_slot = SLOT_A; + active_slot = BOOT_SLOT_PRIMARY; } else if (IS_SLOT_B) { - active_slot = SLOT_B; + active_slot = BOOT_SLOT_SECONDARY; } else { LOG_ERR("Cannot determine current slot"); } @@ -106,26 +100,64 @@ static enum ab_boot_slot active_boot_slot_get(void) return active_slot; } -static void device_healthcheck(void) +static bool slot_confirmed(enum boot_slot slot) { - int err; - char *img_set = NULL; + struct boot_swap_state state; const struct flash_area *fa; int area_id = -1; - enum ab_boot_slot active_slot = active_boot_slot_get(); - - if (active_slot == SLOT_INVALID) { - return; - } + char *img_set = NULL; + bool confirmed = false; + int ret; - /* Confirming only in non-degraded boot states - */ - if (active_slot == SLOT_A) { + if (slot == BOOT_SLOT_PRIMARY) { img_set = "A"; area_id = SLOT_A_FLASH_AREA_ID; - } else if (active_slot == SLOT_B) { + } else if (slot == BOOT_SLOT_SECONDARY) { img_set = "B"; area_id = SLOT_B_FLASH_AREA_ID; + } else { + LOG_ERR("Cannot determine slot to check for confirmation"); + return false; + } + + if (flash_area_open(area_id, &fa) != 0) { + LOG_ERR("Cannot open flash area for slot %s", img_set); + return false; + } + + ret = boot_read_swap_state(fa, &state); + if (ret != 0) { + LOG_ERR("Cannot read swap state for slot %s", img_set); + } else if (state.image_ok == BOOT_FLAG_SET) { + confirmed = true; + } else { + confirmed = false; + } + + flash_area_close(fa); + + return confirmed; +} + +static void device_healthcheck(void) +{ + int err; + char *img_set = NULL; + enum boot_slot active_slot = active_boot_slot_get(); + + /* Confirming only in non-degraded boot states */ + if (active_slot == BOOT_SLOT_PRIMARY) { + img_set = "A"; + } else if (active_slot == BOOT_SLOT_SECONDARY) { + img_set = "B"; + } else { + LOG_ERR("Cannot determine active slot for health check"); + return; + } + + if (slot_confirmed(active_slot)) { + LOG_INF("Slot %s already confirmed, no action needed", img_set); + return; } LOG_INF("Testing image set %s...", img_set); @@ -149,14 +181,7 @@ static void device_healthcheck(void) LOG_INF("Confirming..."); - if (flash_area_open(area_id, &fa) != 0) { - LOG_ERR("Cannot open flash area for slot %s", img_set); - return; - } - - err = boot_set_next(fa, true, true); - - flash_area_close(fa); + err = boot_request_confirm_slot(ACTIVE_IMAGE, active_slot); if (err == 0) { LOG_INF("Confirmed\n"); } else { @@ -164,25 +189,32 @@ static void device_healthcheck(void) } } -static void select_slot_for_single_boot(enum ab_boot_slot slot) +static void select_slot_for_single_boot(enum boot_slot slot) { int err = 0; - char active_slot = (active_boot_slot_get() == SLOT_A) ? 'A' : 'B'; - enum boot_slot new_slot = BOOT_SLOT_NONE; + char active_slot = (active_boot_slot_get() == BOOT_SLOT_PRIMARY) ? 'A' : 'B'; - if (slot == SLOT_A) { +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP + if (slot == BOOT_SLOT_PRIMARY) { + LOG_INF("Switching slots (%c -> A)", active_slot); + } else if (slot == BOOT_SLOT_SECONDARY) { + LOG_INF("Switching slots (%c -> B)", active_slot); + } else { + LOG_ERR("Cannot determine active slot, cannot toggle"); + return; + } +#else + if (slot == BOOT_SLOT_PRIMARY) { LOG_INF("Temporarily switching slots (%c -> A)", active_slot); - new_slot = BOOT_SLOT_PRIMARY; - } else if (slot == SLOT_B) { + } else if (slot == BOOT_SLOT_SECONDARY) { LOG_INF("Temporarily switching slots (%c -> B)", active_slot); - new_slot = BOOT_SLOT_SECONDARY; } else { LOG_ERR("Cannot determine active slot, cannot toggle"); return; } +#endif - err = boot_request_set_preferred_slot(ACTIVE_IMAGE, new_slot); - + err = boot_request_set_preferred_slot(ACTIVE_IMAGE, slot); if (err == 0) { LOG_INF("Slot toggled, restart the device to enforce"); } else { @@ -192,11 +224,11 @@ static void select_slot_for_single_boot(enum ab_boot_slot slot) static void boot_state_report(void) { - enum ab_boot_slot active_slot = active_boot_slot_get(); + enum boot_slot active_slot = active_boot_slot_get(); - if (active_slot == SLOT_A) { + if (active_slot == BOOT_SLOT_PRIMARY) { LOG_INF("Booted from slot A"); - } else if (active_slot == SLOT_B) { + } else if (active_slot == BOOT_SLOT_SECONDARY) { LOG_INF("Booted from slot B"); } else { LOG_INF("Cannot determine active slot"); @@ -206,9 +238,9 @@ static void boot_state_report(void) static void button_handler(uint32_t button_state, uint32_t has_changed) { if ((has_changed & DK_BTN1_MSK) && (button_state & DK_BTN1_MSK)) { - select_slot_for_single_boot(SLOT_A); + select_slot_for_single_boot(BOOT_SLOT_PRIMARY); } else if ((has_changed & DK_BTN2_MSK) && (button_state & DK_BTN2_MSK)) { - select_slot_for_single_boot(SLOT_B); + select_slot_for_single_boot(BOOT_SLOT_SECONDARY); } } @@ -217,11 +249,11 @@ struct k_thread status_leds_thread_data; static void status_leds_thread_entry_point(void *p1, void *p2, void *p3) { int blinking_led = DK_LED1; - enum ab_boot_slot active_slot = active_boot_slot_get(); + enum boot_slot active_slot = active_boot_slot_get(); - if (active_slot == SLOT_A) { + if (active_slot == BOOT_SLOT_PRIMARY) { blinking_led = DK_LED1; - } else if (active_slot == SLOT_B) { + } else if (active_slot == BOOT_SLOT_SECONDARY) { blinking_led = DK_LED2; } else { return; diff --git a/samples/dfu/ab/sysbuild.conf b/samples/dfu/ab/sysbuild.conf index dae39d655ae..410d2d0dd1e 100644 --- a/samples/dfu/ab/sysbuild.conf +++ b/samples/dfu/ab/sysbuild.conf @@ -1,10 +1,5 @@ # Enable MCUboot bootloader support SB_CONFIG_BOOTLOADER_MCUBOOT=y -# Enable radiocore -SB_CONFIG_NETCORE_IPC_RADIO=y -SB_CONFIG_NETCORE_IPC_RADIO_BT_HCI_IPC=y - # Enable direct XIP with revert support SB_CONFIG_MCUBOOT_MODE_DIRECT_XIP_WITH_REVERT=y -SB_CONFIG_MCUBOOT_IMAGES_ROM_END_OFFSET_AUTO="ipc_radio;ipc_radio_secondary_app" diff --git a/samples/dfu/ab/sysbuild/mcuboot/boards/nrf54l15dk_nrf54l15_cpuapp.conf b/samples/dfu/ab/sysbuild/mcuboot/boards/nrf54l15dk_nrf54l15_cpuapp.conf index 077bd792d5d..56c4ca86e3a 100644 --- a/samples/dfu/ab/sysbuild/mcuboot/boards/nrf54l15dk_nrf54l15_cpuapp.conf +++ b/samples/dfu/ab/sysbuild/mcuboot/boards/nrf54l15dk_nrf54l15_cpuapp.conf @@ -7,3 +7,7 @@ CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x10800 # CONFIG_LOG=n # CONFIG_FPROTECT=y CONFIG_FPROTECT=n + +# Enable boot requests through retained memory. +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y diff --git a/samples/dfu/ab/sysbuild/mcuboot/prj.conf b/samples/dfu/ab/sysbuild/mcuboot/prj.conf index 1d44edf17d6..bd47682f8a1 100644 --- a/samples/dfu/ab/sysbuild/mcuboot/prj.conf +++ b/samples/dfu/ab/sysbuild/mcuboot/prj.conf @@ -1,12 +1,10 @@ -# Enable boot requests through retained memory. -CONFIG_RETAINED_MEM=y -CONFIG_RETENTION=y +# Enable boot requests. +CONFIG_CRC=y CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y CONFIG_NRF_SECURITY=y CONFIG_MULTITHREADING=y - # Configuration below is copied from mcuboot/boot/zephyr/prj.conf, as creating # the sysbuild/mcuboot directory inside a sample removes the default configuration. diff --git a/samples/dfu/ab/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi b/samples/dfu/ab/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi index 7b02298b764..aee86c58f7c 100644 --- a/samples/dfu/ab/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi +++ b/samples/dfu/ab/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi @@ -53,37 +53,20 @@ cpurad_slot1_partition: partition@152000 { reg = <0x152000 DT_SIZE_K(328)>; }; + + boot_request: partition@1ad000 { + reg = <0x1ad000 16>; + }; + + boot_request_backup: partition@1ad010 { + reg = <0x1ad010 16>; + }; }; }; / { chosen { nrf,bootloader-request = &boot_request; - }; -}; - -/ { - reserved-memory { - cpuapp_retained_mem: memory@e1ad000 { - compatible = "zephyr,memory-region"; - reg = <0xe1ad000 DT_SIZE_K(4)>; - zephyr,memory-region = "RetainedMem"; - status = "okay"; - - retainedmem { - compatible = "zephyr,retained-ram"; - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - - boot_request: boot_request@0 { - compatible = "zephyr,retention"; - status = "okay"; - reg = <0x0 16>; - prefix = [0B 01]; - checksum = <4>; - }; - }; - }; + nrf,bootloader-request-backup = &boot_request_backup; }; }; diff --git a/samples/dfu/ab_split/README.rst b/samples/dfu/ab_split/README.rst index 01da0a0de5b..9dabddbf302 100644 --- a/samples/dfu/ab_split/README.rst +++ b/samples/dfu/ab_split/README.rst @@ -83,7 +83,9 @@ The following conditions decide which slot is considered *active* and is booted #. For all other images, the same slot is selected. You can set the preferred slot using the ``boot_request_set_preferred_slot`` function. -Currently, this only sets the boot preference for a single reboot. +If the :kconfig:option:`CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP` option is enabled, the slot preference remains persistent across reboots.. +Otherwise, the slot preference is cleared on reboot. +To enable the persistence of a preferred slot, define a backup region for the bootloader request area by using the ``nrf,bootloader-request-backup`` chosen node in the devicetree. Identifying the active slot --------------------------- diff --git a/samples/dfu/ab_split/prj.conf b/samples/dfu/ab_split/prj.conf index f5bce24ff90..a46a995e35d 100644 --- a/samples/dfu/ab_split/prj.conf +++ b/samples/dfu/ab_split/prj.conf @@ -41,14 +41,9 @@ CONFIG_MCUBOOT_UTIL_LOG_LEVEL_WRN=y # Disable debug logging CONFIG_LOG_MAX_LEVEL=3 -# Enable boot requests through retained memory. -CONFIG_RETAINED_MEM=y -CONFIG_RETENTION=y +# Enable boot requests. CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y -CONFIG_RETENTION_BOOT_MODE=y -CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE=y - # Enable DK LED/button library CONFIG_DK_LIBRARY=y @@ -102,5 +97,7 @@ CONFIG_DEVMEM_SHELL=n CONFIG_FLASH_SHELL=n # Read bootloader version and security counters values from the retained RAM +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y CONFIG_RETENTION_BOOTLOADER_INFO=y CONFIG_RETENTION_BOOTLOADER_INFO_TYPE_MCUBOOT=y diff --git a/samples/dfu/ab_split/src/ab_utils.c b/samples/dfu/ab_split/src/ab_utils.c index f1011295336..8160366cc78 100644 --- a/samples/dfu/ab_split/src/ab_utils.c +++ b/samples/dfu/ab_split/src/ab_utils.c @@ -14,15 +14,11 @@ LOG_MODULE_DECLARE(ab_sample); -#define ACTIVE_IMAGE 0 - #define CODE_PARTITION DT_CHOSEN(zephyr_code_partition) #define CODE_PARTITION_OFFSET FIXED_PARTITION_NODE_OFFSET(CODE_PARTITION) #define SLOT_A_PARTITION cpuapp_slot0_partition #define SLOT_B_PARTITION cpuapp_slot1_partition -#define CPURAD_SLOT_A_PARTITION cpurad_slot0_partition -#define CPURAD_SLOT_B_PARTITION cpurad_slot1_partition #define SLOT_A_OFFSET FIXED_PARTITION_OFFSET(SLOT_A_PARTITION) #define SLOT_B_OFFSET FIXED_PARTITION_OFFSET(SLOT_B_PARTITION) @@ -31,8 +27,6 @@ LOG_MODULE_DECLARE(ab_sample); #define SLOT_A_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT_A_PARTITION) #define SLOT_B_FLASH_AREA_ID FIXED_PARTITION_ID(SLOT_B_PARTITION) -#define CPURAD_SLOT_A_FLASH_AREA_ID FIXED_PARTITION_ID(CPURAD_SLOT_A_PARTITION) -#define CPURAD_SLOT_B_FLASH_AREA_ID FIXED_PARTITION_ID(CPURAD_SLOT_B_PARTITION) #define IS_SLOT_A \ (CODE_PARTITION_OFFSET >= SLOT_A_OFFSET && \ @@ -45,12 +39,6 @@ LOG_MODULE_DECLARE(ab_sample); #define STATUS_LEDS_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1) K_THREAD_STACK_DEFINE(status_leds_thread_stack_area, STATUS_LEDS_THREAD_STACK_SIZE); -enum ab_boot_slot { - SLOT_A = 0, - SLOT_B = 1, - SLOT_INVALID, -}; - /** @brief Radio firmware self test * * @details @@ -78,14 +66,14 @@ static bool app_domain_healthy(void) return true; } -static enum ab_boot_slot active_boot_slot_get(void) +static enum boot_slot active_boot_slot_get(void) { - enum ab_boot_slot active_slot = SLOT_INVALID; + enum boot_slot active_slot = BOOT_SLOT_NONE; if (IS_SLOT_A) { - active_slot = SLOT_A; + active_slot = BOOT_SLOT_PRIMARY; } else if (IS_SLOT_B) { - active_slot = SLOT_B; + active_slot = BOOT_SLOT_SECONDARY; } else { LOG_ERR("Cannot determine current slot"); } @@ -93,29 +81,64 @@ static enum ab_boot_slot active_boot_slot_get(void) return active_slot; } -static void device_healthcheck(void) +static bool slot_confirmed(enum boot_slot slot) { - int err; - char *img_set = NULL; + struct boot_swap_state state; const struct flash_area *fa; int area_id = -1; - int cpurad_area_id = -1; - enum ab_boot_slot active_slot = active_boot_slot_get(); - - if (active_slot == SLOT_INVALID) { - return; - } + char *img_set = NULL; + bool confirmed = false; + int ret; - /* Confirming only in non-degraded boot states - */ - if (active_slot == SLOT_A) { + if (slot == BOOT_SLOT_PRIMARY) { img_set = "A"; area_id = SLOT_A_FLASH_AREA_ID; - cpurad_area_id = CPURAD_SLOT_A_FLASH_AREA_ID; - } else if (active_slot == SLOT_B) { + } else if (slot == BOOT_SLOT_SECONDARY) { img_set = "B"; area_id = SLOT_B_FLASH_AREA_ID; - cpurad_area_id = CPURAD_SLOT_B_FLASH_AREA_ID; + } else { + LOG_ERR("Cannot determine slot to check for confirmation"); + return false; + } + + if (flash_area_open(area_id, &fa) != 0) { + LOG_ERR("Cannot open flash area for slot %s", img_set); + return false; + } + + ret = boot_read_swap_state(fa, &state); + if (ret != 0) { + LOG_ERR("Cannot read swap state for slot %s", img_set); + } else if (state.image_ok == BOOT_FLAG_SET) { + confirmed = true; + } else { + confirmed = false; + } + + flash_area_close(fa); + + return confirmed; +} + +static void device_healthcheck(void) +{ + int err; + char *img_set = NULL; + enum boot_slot active_slot = active_boot_slot_get(); + + /* Confirming only in non-degraded boot states */ + if (active_slot == BOOT_SLOT_PRIMARY) { + img_set = "A"; + } else if (active_slot == BOOT_SLOT_SECONDARY) { + img_set = "B"; + } else { + LOG_ERR("Cannot determine active slot for health check"); + return; + } + + if (slot_confirmed(active_slot)) { + LOG_INF("Slot %s already confirmed, no action needed", img_set); + return; } LOG_INF("Testing image set %s...", img_set); @@ -139,54 +162,40 @@ static void device_healthcheck(void) LOG_INF("Confirming..."); - if (flash_area_open(area_id, &fa) != 0) { - LOG_ERR("Cannot open flash area for application slot %s", img_set); - return; - } - - err = boot_set_next(fa, true, true); - - flash_area_close(fa); - if (err == 0) { - LOG_INF("Application confirmed\n"); - } else { - LOG_ERR("Failed to confirm application, err: %d", err); - } - - if (flash_area_open(cpurad_area_id, &fa) != 0) { - LOG_ERR("Cannot open flash area for radio slot %s", img_set); - return; - } - - err = boot_set_next(fa, true, true); - - flash_area_close(fa); + err = boot_request_confirm_slot(CONFIG_NCS_MCUBOOT_MANIFEST_IMAGE_INDEX, active_slot); if (err == 0) { - LOG_INF("Radio confirmed\n"); + LOG_INF("Confirmed\n"); } else { - LOG_ERR("Failed to confirm radio, err: %d", err); + LOG_ERR("Failed to confirm, err: %d", err); } } -static void select_slot_for_single_boot(enum ab_boot_slot slot) +static void select_slot_for_single_boot(enum boot_slot slot) { int err = 0; - char active_slot = (active_boot_slot_get() == SLOT_A) ? 'A' : 'B'; - enum boot_slot new_slot = BOOT_SLOT_NONE; + char active_slot = (active_boot_slot_get() == BOOT_SLOT_PRIMARY) ? 'A' : 'B'; - if (slot == SLOT_A) { +#ifdef CONFIG_NRF_MCUBOOT_BOOT_REQUEST_PREFERENCE_KEEP + if (slot == BOOT_SLOT_PRIMARY) { + LOG_INF("Switching slots (%c -> A)", active_slot); + } else if (slot == BOOT_SLOT_SECONDARY) { + LOG_INF("Switching slots (%c -> B)", active_slot); + } else { + LOG_ERR("Cannot determine active slot, cannot toggle"); + return; + } +#else + if (slot == BOOT_SLOT_PRIMARY) { LOG_INF("Temporarily switching slots (%c -> A)", active_slot); - new_slot = BOOT_SLOT_PRIMARY; - } else if (slot == SLOT_B) { + } else if (slot == BOOT_SLOT_SECONDARY) { LOG_INF("Temporarily switching slots (%c -> B)", active_slot); - new_slot = BOOT_SLOT_SECONDARY; } else { LOG_ERR("Cannot determine active slot, cannot toggle"); return; } +#endif - err = boot_request_set_preferred_slot(ACTIVE_IMAGE, new_slot); - + err = boot_request_set_preferred_slot(CONFIG_NCS_MCUBOOT_MANIFEST_IMAGE_INDEX, slot); if (err == 0) { LOG_INF("Slot toggled, restart the device to enforce"); } else { @@ -196,11 +205,11 @@ static void select_slot_for_single_boot(enum ab_boot_slot slot) static void boot_state_report(void) { - enum ab_boot_slot active_slot = active_boot_slot_get(); + enum boot_slot active_slot = active_boot_slot_get(); - if (active_slot == SLOT_A) { + if (active_slot == BOOT_SLOT_PRIMARY) { LOG_INF("Booted from slot A"); - } else if (active_slot == SLOT_B) { + } else if (active_slot == BOOT_SLOT_SECONDARY) { LOG_INF("Booted from slot B"); } else { LOG_INF("Cannot determine active slot"); @@ -210,9 +219,9 @@ static void boot_state_report(void) static void button_handler(uint32_t button_state, uint32_t has_changed) { if ((has_changed & DK_BTN1_MSK) && (button_state & DK_BTN1_MSK)) { - select_slot_for_single_boot(SLOT_A); + select_slot_for_single_boot(BOOT_SLOT_PRIMARY); } else if ((has_changed & DK_BTN2_MSK) && (button_state & DK_BTN2_MSK)) { - select_slot_for_single_boot(SLOT_B); + select_slot_for_single_boot(BOOT_SLOT_SECONDARY); } } @@ -221,11 +230,11 @@ struct k_thread status_leds_thread_data; static void status_leds_thread_entry_point(void *p1, void *p2, void *p3) { int blinking_led = DK_LED1; - enum ab_boot_slot active_slot = active_boot_slot_get(); + enum boot_slot active_slot = active_boot_slot_get(); - if (active_slot == SLOT_A) { + if (active_slot == BOOT_SLOT_PRIMARY) { blinking_led = DK_LED1; - } else if (active_slot == SLOT_B) { + } else if (active_slot == BOOT_SLOT_SECONDARY) { blinking_led = DK_LED2; } else { return; diff --git a/samples/dfu/ab_split/sysbuild/mcuboot/prj.conf b/samples/dfu/ab_split/sysbuild/mcuboot/prj.conf index d0db88e2c8d..4bbe1c8d683 100644 --- a/samples/dfu/ab_split/sysbuild/mcuboot/prj.conf +++ b/samples/dfu/ab_split/sysbuild/mcuboot/prj.conf @@ -1,6 +1,5 @@ -# Enable boot requests through retained memory. -CONFIG_RETAINED_MEM=y -CONFIG_RETENTION=y +# Enable boot requests. +CONFIG_CRC=y CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y CONFIG_NRF_SECURITY=y @@ -32,6 +31,8 @@ CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="MCUboot" # Expose bootloader version and security counter through retention +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y CONFIG_BOOT_SHARE_DATA=y CONFIG_BOOT_SHARE_DATA_BOOTINFO=y CONFIG_BOOT_SHARE_BACKEND_RETENTION=y diff --git a/samples/dfu/ab_split/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi b/samples/dfu/ab_split/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi index 07406e34302..93fa4ee5f03 100644 --- a/samples/dfu/ab_split/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi +++ b/samples/dfu/ab_split/sysbuild/nrf54h20dk_nrf54h20_memory_map.dtsi @@ -7,35 +7,24 @@ / { chosen { nrf,bootloader-request = &boot_request; + nrf,bootloader-request-backup = &boot_request_backup; zephyr,bootloader-info = &boot_info0; }; }; -/ { - reserved-memory { - cpuapp_retained_mem: memory@e1ad000 { - compatible = "zephyr,memory-region"; - reg = <0xe1ad000 DT_SIZE_K(4)>; - zephyr,memory-region = "RetainedNvm"; - status = "okay"; - - retainedmem { - compatible = "zephyr,retained-ram"; - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; +&mram1x { + partitions { + boot_request: partition@1ad000 { + reg = <0x1ad000 16>; + }; - boot_request: boot_request@0 { - compatible = "zephyr,retention"; - status = "okay"; - reg = <0x0 16>; - prefix = [0B 01]; - checksum = <4>; - }; - }; + boot_request_backup: partition@1ad010 { + reg = <0x1ad010 16>; }; }; +}; +/ { sram@22007FC0 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x22007FC0 0x40>; diff --git a/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_requests.conf b/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_requests.conf index 093368d1bbf..2103cea6b0f 100644 --- a/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_requests.conf +++ b/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_requests.conf @@ -1,4 +1,3 @@ -# Enable boot requests through retained memory. -CONFIG_RETAINED_MEM=y -CONFIG_RETENTION=y +# Enable boot requests. +CONFIG_CRC=y CONFIG_NRF_MCUBOOT_BOOT_REQUEST=y diff --git a/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf54h20dk_nrf54h20_memory_map_requests.dtsi b/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf54h20dk_nrf54h20_memory_map_requests.dtsi index 7b02298b764..aee86c58f7c 100644 --- a/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf54h20dk_nrf54h20_memory_map_requests.dtsi +++ b/samples/zephyr/subsys/mgmt/mcumgr/smp_svr/sysbuild/nrf54h20dk_nrf54h20_memory_map_requests.dtsi @@ -53,37 +53,20 @@ cpurad_slot1_partition: partition@152000 { reg = <0x152000 DT_SIZE_K(328)>; }; + + boot_request: partition@1ad000 { + reg = <0x1ad000 16>; + }; + + boot_request_backup: partition@1ad010 { + reg = <0x1ad010 16>; + }; }; }; / { chosen { nrf,bootloader-request = &boot_request; - }; -}; - -/ { - reserved-memory { - cpuapp_retained_mem: memory@e1ad000 { - compatible = "zephyr,memory-region"; - reg = <0xe1ad000 DT_SIZE_K(4)>; - zephyr,memory-region = "RetainedMem"; - status = "okay"; - - retainedmem { - compatible = "zephyr,retained-ram"; - status = "okay"; - #address-cells = <1>; - #size-cells = <1>; - - boot_request: boot_request@0 { - compatible = "zephyr,retention"; - status = "okay"; - reg = <0x0 16>; - prefix = [0B 01]; - checksum = <4>; - }; - }; - }; + nrf,bootloader-request-backup = &boot_request_backup; }; }; diff --git a/west.yml b/west.yml index 939b9c1b89c..c1b61723feb 100644 --- a/west.yml +++ b/west.yml @@ -126,7 +126,7 @@ manifest: compare-by-default: true - name: mcuboot repo-path: sdk-mcuboot - revision: 66d5c91c080c0817b24c2e9586d26b57f8c9baf6 + revision: 024e7d58d50e2f3237c8aa4ab20dfc2cd79a8455 path: bootloader/mcuboot - name: qcbor url: https://github.com/laurencelundblade/QCBOR