diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index 7aa585d4d6..864a479914 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -320,6 +320,18 @@ config BOOT_IMAGE_EXECUTABLE_RAM_SIZE default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM),0) endif +config FLASH_RUNTIME_SOURCES + bool "Images are read from flash partitions defined at runtime" + select SINGLE_APPLICATION_SLOT + help + Instead of using information on the flash slots to decide which images + to load/update, the application provides the information from which + flash slot to load in runtime. This is useful when the application + reads the state for hardware straps or other sources to decide which + image to load. The application must provide `flash_map_id_get_next` + and `flash_map_id_get_next` functions to tell mcuboot where to find + the images. + config BOOT_ENCRYPTION_SUPPORT bool help diff --git a/boot/zephyr/flash_map_extended.c b/boot/zephyr/flash_map_extended.c index 4631da75b8..c13d6adf0b 100644 --- a/boot/zephyr/flash_map_extended.c +++ b/boot/zephyr/flash_map_extended.c @@ -58,6 +58,15 @@ int flash_device_base(uint8_t fd_id, uintptr_t *ret) */ int flash_area_id_from_multi_image_slot(int image_index, int slot) { +#if defined(CONFIG_FLASH_RUNTIME_SOURCES) + uint8_t id; + + if (flash_map_id_get_current(&id)) { + return id; + } + return -1; +#endif + switch (slot) { case 0: return FLASH_AREA_IMAGE_PRIMARY(image_index); #if !defined(CONFIG_SINGLE_APPLICATION_SLOT) @@ -141,7 +150,7 @@ int flash_area_sector_from_off(off_t off, struct flash_sector *sector) uint8_t flash_area_get_device_id(const struct flash_area *fa) { -#if defined(CONFIG_ARM) +#if defined(CONFIG_ARM) || defined(CONFIG_FLASH_RUNTIME_SOURCES) return fa->fa_id; #else (void)fa; diff --git a/boot/zephyr/include/flash_runtime_sources.h b/boot/zephyr/include/flash_runtime_sources.h new file mode 100644 index 0000000000..44640b892c --- /dev/null +++ b/boot/zephyr/include/flash_runtime_sources.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __FLASH_RUNTIME_SOURCES_H__ +#define __FLASH_RUNTIME_SOURCES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Get next flash map id. + * + * Implement this function to get the next flash map id. The function should + * return true if the flash map id was successfully updated. If the reset + * parameter is true, the function should reset the flash map id to the first + * one. + * + * @param id Pointer to the flash map id. + * @param reset If true, the function will reset the flash map id to the first + * one. + * @retval true If the flash map id was successfully updated. + */ +bool flash_map_id_get_next(uint8_t *id, bool reset); + +/* + * Get current flash map id. + * + * Implement this function to get the current flash map id. The function should + * return true if the flash map id was successfully read. + * + * @param id Pointer to the flash map id. + * @retval true If the flash map id was successfully read. + */ +bool flash_map_id_get_current(uint8_t *id); + +#ifdef __cplusplus +} +#endif + +#endif /* __FLASH_RUNTIME_SOURCES_H__ */ diff --git a/boot/zephyr/single_loader.c b/boot/zephyr/single_loader.c index 858f294adb..fb62233121 100644 --- a/boot/zephyr/single_loader.c +++ b/boot/zephyr/single_loader.c @@ -20,6 +20,30 @@ BOOT_LOG_MODULE_DECLARE(mcuboot); static const struct flash_area *_fa_p; static struct image_header _hdr = { 0 }; +__weak bool +flash_map_id_get_next(uint8_t *id, bool reset) +{ + if (!reset || !id) { + return false; + } + + *id = FLASH_AREA_IMAGE_PRIMARY(0); + + return true; +} + +__weak bool +flash_map_id_get_current(uint8_t *id) +{ + if (!id) { + return false; + } + + *id = FLASH_AREA_IMAGE_PRIMARY(0); + + return true; +} + #if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) || defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) /** * Validate hash of a primary boot image. @@ -102,50 +126,65 @@ fih_ret boot_go(struct boot_rsp *rsp) { int rc = -1; + uint8_t flash_id; + bool reset = true; FIH_DECLARE(fih_rc, FIH_FAILURE); - rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p); - assert(rc == 0); + while (flash_map_id_get_next(&flash_id, reset)) { + reset = false; + rc = flash_area_open(flash_id, &_fa_p); + if (rc != 0) { + continue; + } - rc = boot_image_load_header(_fa_p, &_hdr); - if (rc != 0) - goto out; + rc = boot_image_load_header(_fa_p, &_hdr); + if (rc != 0) { + flash_area_close(_fa_p); + continue; + } #ifdef MCUBOOT_RAM_LOAD static struct boot_loader_state state; state.imgs[0][0].hdr = _hdr; rc = boot_load_image_to_sram(&state); - if (rc != 0) - goto out; + if (rc != 0) { + flash_area_close(_fa_p); + continue; + } #endif #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT - FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + flash_area_close(_fa_p); #ifdef MCUBOOT_RAM_LOAD - boot_remove_image_from_sram(&state); + boot_remove_image_from_sram(&state); #endif - goto out; - } + continue; + } #elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) - FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr); - if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr); + if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { + flash_area_close(_fa_p); #ifdef MCUBOOT_RAM_LOAD - boot_remove_image_from_sram(&state); + boot_remove_image_from_sram(&state); #endif - goto out; - } + continue; + } #else - fih_rc = FIH_SUCCESS; + fih_rc = FIH_SUCCESS; #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ - rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p); - rsp->br_image_off = flash_area_get_off(_fa_p); - rsp->br_hdr = &_hdr; + rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p); + rsp->br_image_off = flash_area_get_off(_fa_p); + rsp->br_hdr = &_hdr; + + flash_area_close(_fa_p); + + break; + } -out: - flash_area_close(_fa_p); FIH_RET(fih_rc); }