|
12 | 12 | #include <suit_plat_decode_util.h>
|
13 | 13 | #include <zephyr/logging/log.h>
|
14 | 14 | #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 */ |
15 | 19 |
|
16 | 20 | /* __ALIGNED macro is not defined on NATIVE POSIX. This platform uses __aligned macro. */
|
17 | 21 | #ifndef __ALIGNED
|
|
33 | 37 | BUILD_ASSERT(WRITE_BLOCK_SIZE > 0, "zephyr,flash: write_block_size expected to be non-zero");
|
34 | 38 |
|
35 | 39 | #define IPUC_MEM_COMPONENT_MAX_SIZE 32
|
| 40 | +#define FLASH_IPUC_IMG_MAX 512 |
| 41 | +#define FLASH_IPUC_IMG_PREFIX dfu_target_img_ |
36 | 42 |
|
| 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. */ |
37 | 92 | struct ipuc_context {
|
38 | 93 | struct zcbor_string component_id;
|
39 | 94 | uint8_t component_id_buf[IPUC_MEM_COMPONENT_MAX_SIZE];
|
@@ -650,3 +705,115 @@ bool flash_ipuc_setup_pending(const struct device *dev)
|
650 | 705 |
|
651 | 706 | return false;
|
652 | 707 | }
|
| 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 | +} |
0 commit comments