Skip to content

Commit e5750d7

Browse files
committed
suit: Add support for DTS-defined images as IPUCs
Allow to describe a partition in DTS as a region that will be handled by the flash IPUC driver API. Any dfu_target_img_<num> partition can be modified using flash IPUC API under the <num> image ID. A dedicated allocator and deallocator is provided, so the binding between image IDs and IPUC driver instances is defined and is not affected by usage of other APIs, allocating an IPUC over the same memory region in a different context. Ref: NCSDK-32192 Signed-off-by: Tomasz Chyrowicz <tomasz.chyrowicz@nordicsemi.no>
1 parent c72c990 commit e5750d7

File tree

2 files changed

+195
-6
lines changed

2 files changed

+195
-6
lines changed

drivers/flash/flash_ipuc/flash_ipuc.c

+167
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
#include <suit_plat_decode_util.h>
1313
#include <zephyr/logging/log.h>
1414
#include <zephyr/cache.h>
15+
#include <zephyr/storage/flash_map.h>
16+
#ifdef CONFIG_FLASH_SIMULATOR
17+
#include <zephyr/drivers/flash/flash_simulator.h>
18+
#endif /* CONFIG_FLASH_SIMULATOR */
1519

1620
/* __ALIGNED macro is not defined on NATIVE POSIX. This platform uses __aligned macro. */
1721
#ifndef __ALIGNED
@@ -33,7 +37,58 @@
3337
BUILD_ASSERT(WRITE_BLOCK_SIZE > 0, "zephyr,flash: write_block_size expected to be non-zero");
3438

3539
#define IPUC_MEM_COMPONENT_MAX_SIZE 32
40+
#define FLASH_IPUC_IMG_MAX 512
41+
#define FLASH_IPUC_IMG_PREFIX dfu_target_img_
3642

43+
/* The main structure that bind image IDs to the address and size, that identifies one of the
44+
* available IPUCs.
45+
*/
46+
struct flash_ipuc_img {
47+
uintptr_t address;
48+
size_t size;
49+
uint8_t id;
50+
struct device *fdev;
51+
};
52+
53+
/* The partition offset is relative to the parent nodes.
54+
* In most cases, the direct parent is a group of partitions and the grandparent hold the offset
55+
* in the absolute (dereferenceable) address space.
56+
*/
57+
#define GPARENT_OFFSET(label) (DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(label))))
58+
59+
/* Get the absolute address of a fixed partition, identified by a label. */
60+
#define FIXED_PARTITION_ADDRESS(label) (GPARENT_OFFSET(label) + FIXED_PARTITION_OFFSET(label))
61+
62+
/* Initialize flash_ipuc_img structure, based on the partition label and image ID number. */
63+
#define PARTITION_INIT(index, label) \
64+
{ \
65+
.address = FIXED_PARTITION_ADDRESS(label), \
66+
.size = FIXED_PARTITION_SIZE(label), \
67+
.id = index, \
68+
.fdev = NULL, \
69+
},
70+
71+
/* Verify the dfu_target_img_<n> index: it should not be less than one to avoid
72+
* conflicts with DFU partition (envelope) identification schemes.
73+
*/
74+
#define INDEX_IN_RAGE(index) IN_RANGE(index, 1, (FLASH_IPUC_IMG_MAX - 1))
75+
#define PARTITION_INIT_IF_INDEX_OK(label, index) \
76+
IF_ENABLED(UTIL_BOOL(INDEX_IN_RANGE(index)), (PARTITION_INIT(index, label)))
77+
78+
/* Only partitions with a parent node compatible with "fixed-paritions" should
79+
* be taken into account.
80+
*/
81+
#define PARTITION_DEFINE_(index, label) \
82+
IF_ENABLED(FIXED_PARTITION_EXISTS(label), (PARTITION_INIT_IF_INDEX_OK(label, index)))
83+
84+
/* Concatenate prefix with the image ID and return the structure initialization code snippet. */
85+
#define PARTITION_DEFINE(index, prefix) PARTITION_DEFINE_(index, prefix##index)
86+
87+
/* Define the global list of bindings between partition address, size and image ID number. */
88+
static struct flash_ipuc_img ipuc_imgs[] = {
89+
LISTIFY(FLASH_IPUC_IMG_MAX, PARTITION_DEFINE, (), FLASH_IPUC_IMG_PREFIX)};
90+
91+
/* The main IPUC context structure. */
3792
struct ipuc_context {
3893
struct zcbor_string component_id;
3994
uint8_t component_id_buf[IPUC_MEM_COMPONENT_MAX_SIZE];
@@ -650,3 +705,115 @@ bool flash_ipuc_setup_pending(const struct device *dev)
650705

651706
return false;
652707
}
708+
709+
struct device *flash_image_ipuc_create(size_t id, struct zcbor_string *encryption_info,
710+
struct zcbor_string *compression_info,
711+
uintptr_t *ipuc_address, size_t *ipuc_size)
712+
{
713+
suit_manifest_role_t role = SUIT_MANIFEST_UNKNOWN;
714+
suit_plat_err_t plat_err = SUIT_PLAT_SUCCESS;
715+
struct ipuc_context *ctx = NULL;
716+
struct device *dev = NULL;
717+
size_t count = 0;
718+
uint8_t cpu_id = 0;
719+
size_t idx = 0;
720+
#ifdef CONFIG_FLASH_SIMULATOR
721+
size_t f_size = 0;
722+
uintptr_t base_address = (uintptr_t)flash_simulator_get_memory(NULL, &f_size);
723+
#else
724+
uintptr_t base_address = 0;
725+
#endif
726+
727+
if ((ipuc_address == NULL) || (ipuc_size == NULL)) {
728+
LOG_WRN("Invalid image input arguments: (0x%lx, 0x%lx)", (uintptr_t)ipuc_address,
729+
(uintptr_t)ipuc_size);
730+
return NULL;
731+
}
732+
733+
for (idx = 0; idx < ARRAY_SIZE(ipuc_imgs); idx++) {
734+
if (ipuc_imgs[idx].id == id) {
735+
LOG_INF("Found IPUC image %d: (0x%lx, 0x%x)", ipuc_imgs[idx].id,
736+
ipuc_imgs[idx].address, ipuc_imgs[idx].size);
737+
break;
738+
}
739+
}
740+
741+
if (idx >= ARRAY_SIZE(ipuc_imgs)) {
742+
LOG_INF("IPUC image with ID %d not found", id);
743+
return NULL;
744+
}
745+
746+
if (ipuc_imgs[idx].fdev != NULL) {
747+
LOG_WRN("IPUC for image %d already created", id);
748+
return NULL;
749+
}
750+
751+
plat_err = suit_ipuc_get_count(&count);
752+
if (plat_err != SUIT_PLAT_SUCCESS) {
753+
LOG_WRN("Unable to read IPUC count");
754+
return NULL;
755+
}
756+
757+
dev = get_free_dev();
758+
if (dev == NULL) {
759+
LOG_WRN("Unable to allocate new image IPUC device - no free instances");
760+
return NULL;
761+
}
762+
763+
ctx = (struct ipuc_context *)dev->data;
764+
765+
for (size_t i = 0; i < count; i++) {
766+
ctx->component_id.len = sizeof(ctx->component_id_buf);
767+
plat_err = suit_ipuc_get_info(i, &ctx->component_id, &role);
768+
if (plat_err != SUIT_PLAT_SUCCESS) {
769+
LOG_WRN("Failed to read IPUC %d info: %d", i, plat_err);
770+
break;
771+
}
772+
773+
plat_err = suit_plat_decode_component_id(&ctx->component_id, &cpu_id,
774+
(intptr_t *)&ctx->address, &ctx->size);
775+
if (plat_err != SUIT_PLAT_SUCCESS) {
776+
LOG_ERR("Failed to decode IPUC %d component ID: %d", i, plat_err);
777+
continue;
778+
}
779+
780+
if ((ctx->address != base_address + ipuc_imgs[idx].address) ||
781+
(ctx->size != ipuc_imgs[idx].size)) {
782+
continue;
783+
}
784+
785+
LOG_INF("IPUC for address range (0x%lx, 0x%x) created", ctx->address, ctx->size);
786+
787+
if (encryption_info == NULL) {
788+
ctx->read_access = read_access_check(role);
789+
} else {
790+
ctx->read_access = false;
791+
}
792+
793+
ipuc_imgs[idx].fdev = dev;
794+
ctx->setup_pending = true;
795+
*ipuc_address = ctx->address;
796+
*ipuc_size = ctx->size;
797+
#ifdef CONFIG_FLASH_PAGE_LAYOUT
798+
ctx->pages_layout.pages_count = 1;
799+
ctx->pages_layout.pages_size = ctx->size;
800+
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
801+
802+
return dev;
803+
}
804+
805+
flash_ipuc_release(dev);
806+
807+
return NULL;
808+
}
809+
810+
void flash_image_ipuc_release(size_t id)
811+
{
812+
for (size_t i = 0; i < ARRAY_SIZE(ipuc_imgs); i++) {
813+
if (ipuc_imgs[i].id == id) {
814+
flash_ipuc_release(ipuc_imgs[i].fdev);
815+
ipuc_imgs[i].fdev = NULL;
816+
break;
817+
}
818+
}
819+
}

include/drivers/flash/flash_ipuc.h

+28-6
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ bool flash_component_ipuc_check(struct zcbor_string *component_id);
5656
* @brief Create a new IPUC device, dedicated for the SUIT DFU cache usage.
5757
*
5858
* @param[in] min_address The minimal start address of the new SUIT DFU cache area.
59-
* @param[out] ipuc_address The start address of the area manged by the found IPUC device.
60-
* @param[out] ipuc_size The size of the area manged by the found IPUC device.
59+
* @param[out] ipuc_address The start address of the area managed by the found IPUC device.
60+
* @param[out] ipuc_size The size of the area managed by the found IPUC device.
6161
*
6262
* @return Pointer to the device on success, NULL otherwise.
6363
*/
@@ -68,8 +68,8 @@ struct device *flash_cache_ipuc_create(uintptr_t min_address, uintptr_t *ipuc_ad
6868
* @brief Check if it is possible to create a new IPUC device, dedicated for the SUIT DFU cache.
6969
*
7070
* @param[in] min_address The minimal start address of the new SUIT DFU cache area.
71-
* @param[out] ipuc_address The start address of the area manged by the found IPUC device.
72-
* @param[out] ipuc_size The size of the area manged by the found IPUC device.
71+
* @param[out] ipuc_address The start address of the area managed by the found IPUC device.
72+
* @param[out] ipuc_size The size of the area managed by the found IPUC device.
7373
*
7474
* @retval true If it is possible to create the IPUC, based on the list of available IPUCs
7575
* @retval false If it is not possible to create such IPUC.
@@ -81,8 +81,8 @@ bool flash_cache_ipuc_check(uintptr_t min_address, uintptr_t *ipuc_address, size
8181
*
8282
* @param[in] address The start of an address range to be modified through IPUC.
8383
* @param[in] size The size of the address range.
84-
* @param[out] ipuc_address The start address of the area manged by the found IPUC device.
85-
* @param[out] ipuc_size The size of the area manged by the found IPUC device.
84+
* @param[out] ipuc_address The start address of the area managed by the found IPUC device.
85+
* @param[out] ipuc_size The size of the area managed by the found IPUC device.
8686
*
8787
* @return Pointer to the device on success, NULL otherwise.
8888
*/
@@ -96,6 +96,28 @@ struct device *flash_ipuc_find(uintptr_t address, size_t size, uintptr_t *ipuc_a
9696
*/
9797
bool flash_ipuc_setup_pending(const struct device *dev);
9898

99+
/**
100+
* @brief Create a new IPUC device, based on image ID.
101+
*
102+
* @param[in] id Image ID, defined inside DTS.
103+
* @param[in] encryption_info Pointer to the binary defining the decryption parameters.
104+
* @param[in] compression_info Pointer to the binary defining the decompression parameters.
105+
* @param[out] ipuc_address The start address of the area managed by the found IPUC device.
106+
* @param[out] ipuc_size The size of the area managed by the found IPUC device.
107+
*
108+
* @return Pointer to the device on success, NULL otherwise.
109+
*/
110+
struct device *flash_image_ipuc_create(size_t id, struct zcbor_string *encryption_info,
111+
struct zcbor_string *compression_info,
112+
uintptr_t *ipuc_address, size_t *ipuc_size);
113+
114+
/**
115+
* @brief Release one of the flash image IPUC driver context.
116+
*
117+
* @param[in] id Image ID, defined inside DTS.
118+
*/
119+
void flash_image_ipuc_release(size_t id);
120+
99121
#ifdef __cplusplus
100122
}
101123
#endif

0 commit comments

Comments
 (0)