Skip to content

NCSDK-30809: Add usage of IPUC in SUIT platform #20117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions subsys/suit/cache/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
178 changes: 172 additions & 6 deletions subsys/suit/cache/src/suit_dfu_cache_rw.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
#include <zephyr/storage/flash_map.h>
#include <zephyr/sys/util_macro.h>
#include <suit_flash_sink.h>

#include "suit_dfu_cache_internal.h"
#include <suit_envelope_info.h>

#ifdef CONFIG_FLASH_IPUC
#include <drivers/flash/flash_ipuc.h>
#endif /* CONFIG_FLASH_IPUC */

LOG_MODULE_REGISTER(suit_cache_rw, CONFIG_SUIT_LOG_LEVEL);

#ifndef BSWAP_32
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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++) {

Expand All @@ -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)) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
42 changes: 38 additions & 4 deletions subsys/suit/memory_layout/src/suit_memory_layout.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <zephyr/device.h>
#include <suit_memory_layout.h>
#include <zephyr/drivers/flash/flash_simulator.h>
#ifdef CONFIG_FLASH_IPUC
#include <drivers/flash/flash_ipuc.h>
#endif /* CONFIG_FLASH_IPUC */

/* Definitions for SOC internal nonvolatile memory */
#if (DT_NODE_EXISTS(DT_NODELABEL(mram1x))) /* nrf54H20 */
Expand Down Expand Up @@ -182,18 +185,33 @@ static const struct nvm_area *find_area_by_device(const struct device *fdev)

bool suit_memory_global_address_to_nvm_address(uintptr_t address, struct nvm_address *result)
{
const struct nvm_area *area = find_area(address);
struct nvm_area *area = (struct nvm_area *)find_area(address);

if (result == NULL) {
return false;
}

if (area == NULL) {
result->fdev = NULL;
if (area != NULL) {
result->fdev = area->na_fdev;
result->offset = address - area_address_get(area);
}
#ifdef CONFIG_FLASH_IPUC
struct nvm_area ipuc_area;

ipuc_area.na_fdev = flash_ipuc_find(address, 0, &ipuc_area.na_start, &ipuc_area.na_size);
if (ipuc_area.na_fdev != NULL) {
/* Use IPUC instead of internal NVM driver to gain write access. */
result->fdev = ipuc_area.na_fdev;
/* IPUCs use relative addressing */
result->offset = address - ipuc_area.na_start;
}
#endif /* CONFIG_FLASH_IPUC */

if (result->fdev == NULL) {
return false;
}

result->fdev = area->na_fdev;
result->offset = address - area_address_get(area);
return true;
}

Expand All @@ -216,7 +234,15 @@ bool suit_memory_nvm_address_to_global_address(struct nvm_address *address, uint

bool suit_memory_global_address_is_in_nvm(uintptr_t address)
{
#ifdef CONFIG_FLASH_IPUC
struct nvm_area ipuc_area;

ipuc_area.na_fdev = flash_ipuc_find(address, 0, &ipuc_area.na_start, &ipuc_area.na_size);

return (ipuc_area.na_fdev != NULL) && (find_area(address) != NULL);
#else /* CONFIG_FLASH_IPUC */
return find_area(address) != NULL;
#endif /* CONFIG_FLASH_IPUC */
}

bool suit_memory_global_address_range_is_in_nvm(uintptr_t address, size_t size)
Expand All @@ -227,7 +253,15 @@ bool suit_memory_global_address_range_is_in_nvm(uintptr_t address, size_t size)
const struct nvm_area *start = find_area(address);
const struct nvm_area *end = find_area(address + size - 1);

#ifdef CONFIG_FLASH_IPUC
struct nvm_area ipuc_area;

ipuc_area.na_fdev = flash_ipuc_find(address, size, &ipuc_area.na_start, &ipuc_area.na_size);

return (start != NULL && start == end) || (ipuc_area.na_fdev != NULL);
#else /* CONFIG_FLASH_IPUC */
return start != NULL && start == end;
#endif /* CONFIG_FLASH_IPUC */
}

bool suit_memory_global_address_is_in_ram(uintptr_t address)
Expand Down
17 changes: 17 additions & 0 deletions subsys/suit/orchestrator_app/src/suit_orchestrator_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading