From a345d42d865a7d1e2f5dc4b536fc6badd1c36236 Mon Sep 17 00:00:00 2001 From: Tomasz Chyrowicz Date: Thu, 6 Feb 2025 14:02:27 +0100 Subject: [PATCH] suit: Add suupport for IPUC in cache Add support for IPUCs in DFU cache RW. Ref: NCSDK-30809 Signed-off-by: Tomasz Chyrowicz --- subsys/suit/cache/Kconfig | 12 ++ subsys/suit/cache/src/suit_dfu_cache_rw.c | 178 +++++++++++++++++- .../src/suit_orchestrator_app.c | 17 ++ 3 files changed, 201 insertions(+), 6 deletions(-) diff --git a/subsys/suit/cache/Kconfig b/subsys/suit/cache/Kconfig index 46a495cdc842..330512ec3cf1 100644 --- a/subsys/suit/cache/Kconfig +++ b/subsys/suit/cache/Kconfig @@ -39,4 +39,16 @@ config SUIT_CACHE_RW depends on SUIT_UTILS depends on !SUIT_PLATFORM_VARIANT_SDFW +config SUIT_CACHE_SDFW_IPUC_ID + int "IPUC-based parition number, capable of performing SDFW updates" + depends on SUIT_CACHE_RW + depends on FLASH_IPUC + default 254 + +config SUIT_CACHE_APP_IPUC_ID + int "IPUC-based parition number, without address restrictions" + depends on SUIT_CACHE_RW + depends on FLASH_IPUC + default 255 + endif # SUIT_CACHE diff --git a/subsys/suit/cache/src/suit_dfu_cache_rw.c b/subsys/suit/cache/src/suit_dfu_cache_rw.c index e4dff5f93513..6b039ae66977 100644 --- a/subsys/suit/cache/src/suit_dfu_cache_rw.c +++ b/subsys/suit/cache/src/suit_dfu_cache_rw.c @@ -14,10 +14,13 @@ #include #include #include - #include "suit_dfu_cache_internal.h" #include +#ifdef CONFIG_FLASH_IPUC +#include +#endif /* CONFIG_FLASH_IPUC */ + LOG_MODULE_REGISTER(suit_cache_rw, CONFIG_SUIT_LOG_LEVEL); #ifndef BSWAP_32 @@ -79,7 +82,18 @@ static struct dfu_cache_partition_ext dfu_partitions_ext[] = { { .id = 0, }, - LISTIFY(CONFIG_SUIT_CACHE_MAX_CACHES, PARTITION_DEFINE, (), dfu_cache_partition_)}; + LISTIFY(CONFIG_SUIT_CACHE_MAX_CACHES, PARTITION_DEFINE, (), dfu_cache_partition_) +#ifdef CONFIG_SUIT_CACHE_SDFW_IPUC_ID + { + .id = CONFIG_SUIT_CACHE_SDFW_IPUC_ID, + }, +#endif /* CONFIG_SUIT_CACHE_SDFW_IPUC_ID */ +#ifdef CONFIG_SUIT_CACHE_APP_IPUC_ID + { + .id = CONFIG_SUIT_CACHE_APP_IPUC_ID, + }, +#endif /* CONFIG_SUIT_CACHE_APP_IPUC_ID */ +}; /** * @brief Get cache partition of specified id @@ -197,6 +211,32 @@ static suit_plat_err_t erase_on_sink(uint8_t *address, size_t size) return SUIT_PLAT_SUCCESS; } +static void erase_cache_partition(struct dfu_cache_partition_ext *partition) +{ + if (partition == NULL) { + return; + } + +#ifdef CONFIG_SUIT_CACHE_SDFW_IPUC_ID + if (partition->id == CONFIG_SUIT_CACHE_SDFW_IPUC_ID) { + if (partition->fdev != NULL) { + flash_erase(partition->fdev, 0, partition->size); + } + return; + } +#endif /* CONFIG_SUIT_CACHE_SDFW_IPUC_ID */ +#ifdef CONFIG_SUIT_CACHE_APP_IPUC_ID + if (partition->id == CONFIG_SUIT_CACHE_APP_IPUC_ID) { + if (partition->fdev != NULL) { + flash_erase(partition->fdev, 0, partition->size); + } + return; + } +#endif /* CONFIG_SUIT_CACHE_APP_IPUC_ID */ + + erase_on_sink(partition->address, partition->size); +} + /** * @brief Check size of available free space in given cache and get allocable slot info * @@ -464,7 +504,7 @@ suit_plat_err_t suit_dfu_cache_validate_content(void) if (err == SUIT_PLAT_ERR_NOMEM) { LOG_INF("DFU Cache pool, id: %d is not empty... Erasing", partition->id); - erase_on_sink(partition->address, partition->size); + erase_cache_partition(partition); } } else if (err != SUIT_PLAT_SUCCESS) { LOG_ERR("DFU Cache pool, id: %d unavailable, err: %d", @@ -495,7 +535,7 @@ suit_plat_err_t suit_dfu_cache_drop_content(void) if (err == SUIT_PLAT_ERR_NOMEM) { LOG_INF("DFU Cache pool, id: %d is not empty... Erasing", partition->id); - erase_on_sink(partition->address, partition->size); + erase_cache_partition(partition); } } } @@ -547,6 +587,62 @@ suit_plat_err_t suit_dfu_cache_rw_slot_create(uint8_t cache_partition_id, return SUIT_PLAT_ERR_NOT_FOUND; } + /* Initialize DFU cache partition through IPUC API (erase memory). + * This operation is delayed, so only if a manifest uses IPUC-based cache partition, + * it's contents are deleted. + */ +#ifdef CONFIG_SUIT_CACHE_SDFW_IPUC_ID + if ((cache_partition_id == CONFIG_SUIT_CACHE_SDFW_IPUC_ID) && + (part->fdev == NULL)) { + uintptr_t sdfw_update_area_addr = 0; + size_t sdfw_update_area_size = 0; + + suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, + &sdfw_update_area_size); + if (sdfw_update_area_size == 0) { + /* SoC does not enforce constrains on update candidate location + */ + sdfw_update_area_addr = 0; + } + + part->fdev = flash_cache_ipuc_create( + sdfw_update_area_addr, (uintptr_t *)&part->address, &part->size); + + if (part->fdev == NULL) { + part->address = NULL; + part->size = 0; + } else { + /* Disable the area before sdfw_update_area_addr */ + if ((uintptr_t)part->address < sdfw_update_area_addr) { + part->size -= + (sdfw_update_area_addr - (uintptr_t)part->address); + part->address = (uint8_t *)sdfw_update_area_addr; + } + + /* Disable the area after sdfw_update_area_addr + + * sdfw_update_area_size + */ + if ((sdfw_update_area_size > 0) && + ((uintptr_t)part->address + part->size > + sdfw_update_area_addr + sdfw_update_area_size)) { + part->size = sdfw_update_area_addr + sdfw_update_area_size - + (uintptr_t)part->address; + } + } + } +#endif /* CONFIG_SUIT_CACHE_SDFW_IPUC_ID */ +#ifdef CONFIG_SUIT_CACHE_APP_IPUC_ID + if ((cache_partition_id == CONFIG_SUIT_CACHE_APP_IPUC_ID) && (part->fdev == NULL)) { + part->fdev = flash_cache_ipuc_create( + (uintptr_t)part->address, (uintptr_t *)&part->address, &part->size); + } +#endif /* CONFIG_SUIT_CACHE_APP_IPUC_ID */ + + if (part->fdev == NULL) { + LOG_ERR("Partition %d unavailable", cache_partition_id); + return SUIT_PLAT_ERR_NOT_FOUND; + } + slot->eb_size = part->eb_size; suit_plat_err_t ret = slot_in_cache_partition_allocate(&tmp_uri, slot, part); @@ -719,7 +815,63 @@ suit_plat_err_t suit_dfu_cache_rw_slot_drop(struct suit_cache_slot *slot) return SUIT_PLAT_ERR_INVAL; } -int suit_dfu_cache_rw_init(void) +#ifdef CONFIG_FLASH_IPUC +/** + * @brief Check the availability of IPUCs that can be used as SUIT cache parition. + */ +static void dfu_cache_ipuc_init(void) +{ + for (size_t i = 1; i < ARRAY_SIZE(dfu_partitions_ext); i++) { + /* Calculating memory-mapped address for cache pool */ + struct dfu_cache_partition_ext *partition = &dfu_partitions_ext[i]; + +#ifdef CONFIG_SUIT_CACHE_SDFW_IPUC_ID + if (partition->id == CONFIG_SUIT_CACHE_SDFW_IPUC_ID) { + uintptr_t sdfw_update_area_addr = 0; + size_t sdfw_update_area_size = 0; + + suit_memory_sdfw_update_area_info_get(&sdfw_update_area_addr, + &sdfw_update_area_size); + if (sdfw_update_area_size == 0) { + /* SoC does not enforce constrains on update candidate location + */ + sdfw_update_area_addr = 0; + } + + bool available = flash_cache_ipuc_check(sdfw_update_area_addr, + (uintptr_t *)&partition->address, + &partition->size); + + if (!available) { + partition->size = 0; + } + + partition->wb_size = 1; + partition->eb_size = 1; + + continue; + } +#endif /* CONFIG_SUIT_CACHE_SDFW_IPUC_ID */ +#ifdef CONFIG_SUIT_CACHE_APP_IPUC_ID + if (partition->id == CONFIG_SUIT_CACHE_APP_IPUC_ID) { + bool available = flash_cache_ipuc_check(0, (uintptr_t *)&partition->address, + &partition->size); + + if (!available) { + partition->size = 0; + } + + partition->wb_size = 1; + partition->eb_size = 1; + + continue; + } +#endif /* CONFIG_SUIT_CACHE_APP_IPUC_ID */ + } +} +#endif /* CONFIG_FLASH_IPUC */ + +suit_plat_err_t suit_dfu_cache_rw_init(void) { for (size_t i = 1; i < ARRAY_SIZE(dfu_partitions_ext); i++) { @@ -730,6 +882,17 @@ int suit_dfu_cache_rw_init(void) .offset = partition->offset, }; +#ifdef CONFIG_SUIT_CACHE_SDFW_IPUC_ID + if (partition->id == CONFIG_SUIT_CACHE_SDFW_IPUC_ID) { + continue; + } +#endif /* CONFIG_SUIT_CACHE_SDFW_IPUC_ID */ +#ifdef CONFIG_SUIT_CACHE_APP_IPUC_ID + if (partition->id == CONFIG_SUIT_CACHE_APP_IPUC_ID) { + continue; + } +#endif /* CONFIG_SUIT_CACHE_APP_IPUC_ID */ + uintptr_t mapped_addr = 0; if (suit_memory_nvm_address_to_global_address(&device_offset, &mapped_addr)) { @@ -756,7 +919,6 @@ int suit_dfu_cache_rw_init(void) size_t eb_size = info.size; for (uint32_t p_idx = info.index + 1; p_idx < page_count; p_idx++) { - if (0 == flash_get_page_info_by_idx(partition->fdev, p_idx, &info)) { if (info.size > eb_size) { @@ -786,6 +948,10 @@ int suit_dfu_cache_rw_init(void) } } +#ifdef CONFIG_FLASH_IPUC + dfu_cache_ipuc_init(); +#endif /* CONFIG_FLASH_IPUC */ + int err = cache_0_resize(false); if (err != SUIT_PLAT_SUCCESS) { diff --git a/subsys/suit/orchestrator_app/src/suit_orchestrator_app.c b/subsys/suit/orchestrator_app/src/suit_orchestrator_app.c index 3386ef29980e..abcc7880308b 100644 --- a/subsys/suit/orchestrator_app/src/suit_orchestrator_app.c +++ b/subsys/suit/orchestrator_app/src/suit_orchestrator_app.c @@ -247,6 +247,23 @@ int suit_dfu_update_start(void) update_regions_count++; } } + +#ifdef CONFIG_SUIT_CACHE_SDFW_IPUC_ID + if (suit_dfu_cache_rw_device_info_get(CONFIG_SUIT_CACHE_SDFW_IPUC_ID, &device_info) == + SUIT_PLAT_SUCCESS) { + update_candidate[update_regions_count].mem = device_info.mapped_address; + update_candidate[update_regions_count].size = device_info.partition_size; + update_regions_count++; + } +#endif /* CONFIG_SUIT_CACHE_SDFW_IPUC_ID */ +#ifdef CONFIG_SUIT_CACHE_APP_IPUC_ID + if (suit_dfu_cache_rw_device_info_get(CONFIG_SUIT_CACHE_APP_IPUC_ID, &device_info) == + SUIT_PLAT_SUCCESS) { + update_candidate[update_regions_count].mem = device_info.mapped_address; + update_candidate[update_regions_count].size = device_info.partition_size; + update_regions_count++; + } +#endif /* CONFIG_SUIT_CACHE_APP_IPUC_ID */ #endif return suit_trigger_update(update_candidate, update_regions_count);