SPM: Add assets info for partitions

- Define an member named 'assets' in static information for
  assets such generic memory, PPB and platform devices.
- Add macros for loading assets.
- Change SPM logic of scheduling assets.

Change-Id: I1464ea2e70f13cada2cdb45e73a6879e7e6205bb
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
Co-authored-by: Mingyang Sun <Mingyang.Sun@arm.com>
diff --git a/secure_fw/include/load/asset_defs.h b/secure_fw/include/load/asset_defs.h
new file mode 100644
index 0000000..6e5c8d0
--- /dev/null
+++ b/secure_fw/include/load/asset_defs.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __ASSET_DEFS_H__
+#define __ASSET_DEFS_H__
+
+#include <stdint.h>
+
+/* Memory-based object attributes */
+#define ASSET_MEM_RD_BIT            (1U << 0)  /* 1: readable memory address */
+#define ASSET_MEM_WR_BIT            (1U << 1)  /* 1: writable memory address */
+#define ASSET_MEM_PPB_BIT           (1U << 2)  /* 1: PPB indicator           */
+
+/* Customized objects such as device or symbol. Refer by 'dev' in the union. */
+#define ASSET_DEV_REF_BIT           (1U << 3)
+
+struct asset_desc_t {
+    union {
+        struct {                            /* Memory asset type        */
+            uintptr_t addr_x;
+            uintptr_t addr_y;
+        } mem;
+        struct {                            /* Device asset type        */
+            uintptr_t addr_ref;
+            uintptr_t reserved;
+        } dev;
+    };
+    uint32_t attr;                          /* Asset attributes         */
+} __attribute__((aligned(4)));
+
+#endif /* __ASSET_DEFS_H__ */
diff --git a/secure_fw/include/load/partition_defs.h b/secure_fw/include/load/partition_defs.h
index 573043e..014f833 100644
--- a/secure_fw/include/load/partition_defs.h
+++ b/secure_fw/include/load/partition_defs.h
@@ -36,17 +36,6 @@
 #define SPM_PART_FLAG_PSA_ROT                   (1U << 8)
 #define SPM_PART_FLAG_IPC                       (1U << 9)
 
-#if TFM_LVL == 3
-/**
- * Holds isolation memory regions used by a partition. Could be extended if
- * more isolation regions are required.
- */
-struct private_data_t {
-    uintptr_t start;
-    uintptr_t limit;
-};
-#endif
-
 /* Common partition structure type */
 struct partition_static_info_t {
     uint32_t        psa_ff_ver;         /* Encode the version with magic    */
@@ -57,10 +46,7 @@
     size_t          heap_size;          /* Heap size                        */
     uint32_t        ndeps;              /* Dependency number                */
     uint32_t        nservices;          /* Service number                   */
-    uintptr_t       plat_cookie;        /* A cookie for platform binding    */
-#if TFM_LVL == 3
-    struct private_data_t mems;         /* Partition isolation memory data  */
-#endif
+    uint32_t        nassets;            /* Asset numbers                    */
     uintptr_t       vars[];             /* Struct extendable indicator      */
 } __attribute__((aligned(4)));
 
diff --git a/secure_fw/include/load/partition_static_load.h b/secure_fw/include/load/partition_static_load.h
index 2ccaa7f..1e7b4ca 100644
--- a/secure_fw/include/load/partition_static_load.h
+++ b/secure_fw/include/load/partition_static_load.h
@@ -32,11 +32,15 @@
 #define STATIC_INFSZ_BYTES(ps_ptr)                                      \
     (sizeof(*(ps_ptr)) + STATIC_INFO_EXT_LENGTH * sizeof(uintptr_t) +   \
      (ps_ptr)->ndeps * sizeof(uint32_t) +                               \
-     (ps_ptr)->nservices * sizeof(struct service_static_info_t))
+     (ps_ptr)->nservices * sizeof(struct service_static_info_t) +       \
+     (ps_ptr)->nassets * sizeof(struct asset_desc_t))
 
 #define STATIC_INF_DEPS(ps_ptr)                                         \
     ((uintptr_t)(ps_ptr)->vars + STATIC_INFO_EXT_LENGTH * sizeof(uintptr_t))
 #define STATIC_INF_SERVICE(ps_ptr)                                      \
     ((uintptr_t)STATIC_INF_DEPS(ps_ptr) + (ps_ptr)->ndeps * sizeof(uint32_t))
+#define STATIC_INF_ASSET(ps_ptr)                                        \
+    ((uintptr_t)STATIC_INF_SERVICE(ps_ptr) +                            \
+     (ps_ptr)->nservices * sizeof(struct service_static_info_t))
 
 #endif /* __PARTITION_STATIC_LOAD_H__ */
diff --git a/secure_fw/partitions/ns_proxy_partition/static_info_ns_proxy.c b/secure_fw/partitions/ns_proxy_partition/static_info_ns_proxy.c
index 700a86b..ae101e9 100644
--- a/secure_fw/partitions/ns_proxy_partition/static_info_ns_proxy.c
+++ b/secure_fw/partitions/ns_proxy_partition/static_info_ns_proxy.c
@@ -15,11 +15,15 @@
 #include "load/partition_static_load.h"
 #include "load/partition_defs.h"
 #include "load/service_defs.h"
+#include "load/asset_defs.h"
 #include "psa_manifest/pid.h"
 #include "psa_manifest/sid.h"
 
 #define TFM_SP_NS_PROXY_NDEPS                                   (0)
 #define TFM_SP_NS_PROXY_NSERVS                                  (0)
+#if TFM_LVL == 3
+#define TFM_SP_NS_PROXY_NASSETS                                 (1)
+#endif
 
 /* Memory region declaration */
 REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
@@ -34,6 +38,9 @@
     /* per-partition variable length data */
     uintptr_t                       stack_pos;
     uintptr_t                       heap_pos;
+#if TFM_LVL == 3
+    struct asset_desc_t             assets[TFM_SP_NS_PROXY_NASSETS];
+#endif
 } __attribute__((aligned(4)));
 
 /* Partition static, deps, service static data. Put to a dedicated section. */
@@ -52,14 +59,19 @@
         .heap_size                  = 0,
         .ndeps                      = TFM_SP_NS_PROXY_NDEPS,
         .nservices                  = TFM_SP_NS_PROXY_NSERVS,
-        .plat_cookie                = 0,
 #if TFM_LVL == 3
-        .mems                       = {
-            .start                    = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Base),
-            .limit                    = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Limit),
-        },
+        .nassets                    = TFM_SP_NS_PROXY_NASSETS,
 #endif
     },
     .stack_pos                      = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Base),
     .heap_pos                       = 0,
+#if TFM_LVL == 3
+    .assets                         = {
+        {
+            .mem.addr_x             = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Base),
+            .mem.addr_y             = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Limit),
+            .attr                   = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT,
+        },
+    },
+#endif
 };
diff --git a/secure_fw/partitions/partition_static_info.template b/secure_fw/partitions/partition_static_info.template
index e3a3a2b..5de343c 100644
--- a/secure_fw/partitions/partition_static_info.template
+++ b/secure_fw/partitions/partition_static_info.template
@@ -13,12 +13,13 @@
 #include "load/partition_static_load.h"
 #include "load/partition_defs.h"
 #include "load/service_defs.h"
+#include "load/asset_defs.h"
 #include "tfm_peripherals_def.h"
 #include "psa_manifest/pid.h"
 #include "psa_manifest/sid.h"
 #include "psa_manifest/{{file_name}}.h"
 
-{% set counter = namespace(dep_counter=0, service_counter=0) %}
+{% set counter = namespace(dep_counter=0, service_counter=0, asset_counter=0) %}
 {% if manifest.dependencies %}
     {% for dep in manifest.dependencies %}
         {% set counter.dep_counter = counter.dep_counter + 1 %}
@@ -29,8 +30,18 @@
         {% set counter.service_counter = counter.service_counter + 1 %}
     {% endfor %}
 {% endif %}
+{% if manifest.mmio_regions %}
+    {% for asset in manifest.mmio_regions %}
+        {% set counter.asset_counter = counter.asset_counter + 1 %}
+    {% endfor %}
+{% endif %}
 #define {{"%-55s"|format(manifest.name|upper + "_NDEPS")}} ({{"%d"|format(counter.dep_counter)}})
 #define {{"%-55s"|format(manifest.name|upper + "_NSERVS")}} ({{"%d"|format(counter.service_counter)}})
+#if TFM_LVL == 3
+#define {{"%-55s"|format(manifest.name|upper + "_NASSETS")}} ({{"%d"|format(counter.asset_counter)}} + 1)
+#else
+#define {{"%-55s"|format(manifest.name|upper + "_NASSETS")}} ({{"%d"|format(counter.asset_counter)}})
+#endif
 
 /* Memory region declaration */
 #if TFM_LVL == 3
@@ -42,23 +53,6 @@
 /* Entrypoint function declaration */
 extern void {{manifest.entry_point}}(void);
 
-{% if manifest.mmio_regions %}
-/* Platform data declaration */
-const struct platform_data_t *platform_data_list_{{manifest.name|lower}}[] =
-{
-    {% for region in manifest.mmio_regions %}
-        {% if region.conditional %}
-#ifdef {{region.conditional}}
-        {% endif %}
-    {{region.name}},
-        {% if region.conditional %}
-#endif
-        {% endif %}
-    {% endfor %}
-    NULL
-};
-{% endif %}
-
 /* partition static info type definition */
 struct partition_{{manifest.name|lower}}_static_info_t {
     /* common length data */
@@ -72,6 +66,13 @@
 {% if manifest.services %}
     struct service_static_info_t    services[{{(manifest.name|upper + "_NSERVS")}}];
 {% endif %}
+#if TFM_LVL == 3
+    struct asset_desc_t             assets[{{(manifest.name|upper + "_NASSETS")}}];
+#else
+{% if manifest.mmio_regions %}
+    struct asset_desc_t             assets[{{(manifest.name|upper + "_NASSETS")}}];
+{% endif %}
+#endif
 } __attribute__((aligned(4)));
 
 /* Partition static, deps, service static data. Put to a dedicated section. */
@@ -103,17 +104,7 @@
         .heap_size                  = 0,
         .ndeps                      = {{(manifest.name|upper + "_NDEPS")}},
         .nservices                  = {{(manifest.name|upper + "_NSERVS")}},
-{% if manifest.mmio_regions %}
-        .plat_cookie                = PTR_TO_POSITION(platform_data_list_{{manifest.name|lower}}),
-{% else %}
-        .plat_cookie                = 0,
-{% endif %}
-#if TFM_LVL == 3
-        .mems                       = {
-            .start                    = PART_REGION_ADDR(PT_{{manifest.name}}_PRIVATE, _DATA_START$$Base),
-            .limit                    = PART_REGION_ADDR(PT_{{manifest.name}}_PRIVATE, _DATA_END$$Base),
-        },
-#endif
+        .nassets                    = {{(manifest.name|upper + "_NASSETS")}},
     },
     .stack_pos                      = PTR_TO_POSITION({{manifest.name|lower}}_stack),
     .heap_pos                       = 0,
@@ -152,4 +143,42 @@
     {% endfor %}
     },
 {% endif %}
+#if TFM_LVL == 3
+    .assets                         = {
+        {
+            .mem.addr_x             = PART_REGION_ADDR(PT_{{manifest.name}}_PRIVATE, _DATA_START$$Base),
+            .mem.addr_y             = PART_REGION_ADDR(PT_{{manifest.name}}_PRIVATE, _DATA_END$$Base),
+            .attr                   = ASSET_MEM_RD_BIT | ASSET_MEM_WR_BIT,
+        },
+{% for region in manifest.mmio_regions %}
+    {% if region.conditional %}
+#ifdef {{region.conditional}}
+    {% endif %}
+        {
+            .dev.addr_ref           = PTR_TO_POSITION({{region.name}}),
+            .attr                   = ASSET_DEV_REF_BIT,
+        },
+    {% if region.conditional %}
+#endif
+    {% endif %}
+{% endfor %}
+    }
+#else
+{% if manifest.mmio_regions %}
+    .assets                         = {
+    {% for region in manifest.mmio_regions %}
+        {% if region.conditional %}
+#ifdef {{region.conditional}}
+        {% endif %}
+        {
+            .dev.addr_ref           = PTR_TO_POSITION({{region.name}}),
+            .attr                   = ASSET_DEV_REF_BIT,
+        },
+        {% if region.conditional %}
+#endif
+        {% endif %}
+    {% endfor %}
+    }
+{% endif %}
+#endif
 };
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 1e547ef..63520cf 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.c
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.c
@@ -35,6 +35,7 @@
 #include "tfm/tfm_spm_services.h"
 #include "load/partition_defs.h"
 #include "load/service_defs.h"
+#include "load/asset_defs.h"
 #include "load/partition_static_load.h"
 
 #include "secure_fw/partitions/tfm_service_list.inc"
@@ -694,10 +695,11 @@
     struct partition_t *partition;
     struct service_t *service;
     struct tfm_core_thread_t *pth, *p_ns_entry_thread = NULL;
-    const struct platform_data_t **platform_data_p;
+    const struct platform_data_t *platform_data_p;
     uintptr_t part_static_start, part_static_end;
     struct partition_static_info_t *p_cmninf;
     struct service_static_info_t *p_service_static;
+    struct asset_desc_t *p_asset_static;
 #ifdef TFM_FIH_PROFILE_ON
     fih_int fih_rc = FIH_FAILURE;
 #endif
@@ -748,24 +750,28 @@
 
         partition->p_static = p_cmninf;
 
-        platform_data_p = POSITION_TO_PTR(p_cmninf->plat_cookie,
-                                          const struct platform_data_t **);
-        if (platform_data_p != NULL) {
-            while ((*platform_data_p) != NULL) {
-#ifdef TFM_FIH_PROFILE_ON
-                FIH_CALL(tfm_spm_hal_configure_default_isolation, fih_rc, i,
-                         *platform_data_p);
-                if (fih_not_eq(fih_rc, fih_int_encode(TFM_PLAT_ERR_SUCCESS))) {
-                    tfm_core_panic();
-                }
-#else /* TFM_FIH_PROFILE_ON */
-                if (tfm_spm_hal_configure_default_isolation(i,
-                            *platform_data_p) != TFM_PLAT_ERR_SUCCESS) {
-                    tfm_core_panic();
-                }
-#endif /* TFM_FIH_PROFILE_ON */
-                ++platform_data_p;
+        /* Init partition device object assets */
+        p_asset_static = (struct asset_desc_t *)STATIC_INF_ASSET(p_cmninf);
+        for (i = 0; i < p_cmninf->nassets; i++) {
+            /* Skip the memory-based asset */
+            if (!(p_asset_static[i].attr & ASSET_DEV_REF_BIT)) {
+                continue;
             }
+
+            platform_data_p = POSITION_TO_PTR(p_asset_static[i].dev.addr_ref,
+                                              struct platform_data_t *);
+#ifdef TFM_FIH_PROFILE_ON
+            FIH_CALL(tfm_spm_hal_configure_default_isolation, fih_rc, i,
+                     platform_data_p);
+            if (fih_not_eq(fih_rc, fih_int_encode(TFM_PLAT_ERR_SUCCESS))) {
+                tfm_core_panic();
+            }
+#else /* TFM_FIH_PROFILE_ON */
+            if (tfm_spm_hal_configure_default_isolation(i,
+                platform_data_p) != TFM_PLAT_ERR_SUCCESS) {
+                tfm_core_panic();
+            }
+#endif /* TFM_FIH_PROFILE_ON */
         }
 
         partition->signals_allowed |= PSA_DOORBELL;
@@ -862,6 +868,7 @@
 {
 #if TFM_LVL != 1
     struct partition_t *p_next_partition;
+    struct partition_static_info_t *p_part_static;
     uint32_t is_privileged;
 #endif
     struct tfm_core_thread_t *pth_next = tfm_core_thrd_get_next();
@@ -875,8 +882,8 @@
         p_next_partition = TFM_GET_CONTAINER_PTR(pth_next,
                                                  struct partition_t,
                                                  sp_thread);
-
-        if (p_next_partition->p_static->flags & SPM_PART_FLAG_PSA_ROT) {
+        p_part_static = p_next_partition->p_static;
+        if (p_part_static->flags & SPM_PART_FLAG_PSA_ROT) {
             is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
         } else {
             is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
@@ -890,18 +897,25 @@
          * PRoTs cannot work in unprivileged mode, make them privileged now.
          */
         if (is_privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+            struct asset_desc_t *p_asset =
+                (struct asset_desc_t *)STATIC_INF_ASSET(p_part_static);
+            /* Partition must have private data as the first asset in LVL3 */
+            if (p_part_static->nassets == 0) {
+                tfm_core_panic();
+            }
+            if (p_asset->attr & ASSET_DEV_REF_BIT) {
+                tfm_core_panic();
+            }
             /* FIXME: only MPU-based implementations are supported currently */
 #ifdef TFM_FIH_PROFILE_ON
             FIH_CALL(tfm_hal_mpu_update_partition_boundary, fih_rc,
-                     p_next_partition->p_static->mems.start,
-                     p_next_partition->p_static->mems.limit);
+                     p_asset->mem.addr_x, p_asset->mem.addr_y);
             if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
                 tfm_core_panic();
             }
 #else /* TFM_FIH_PROFILE_ON */
-            if (tfm_hal_mpu_update_partition_boundary(
-                                      p_next_partition->p_static->mems.start,
-                                      p_next_partition->p_static->mems.limit)
+            if (tfm_hal_mpu_update_partition_boundary(p_asset->mem.addr_x,
+                                                      p_asset->mem.addr_y)
                                                            != TFM_HAL_SUCCESS) {
                 tfm_core_panic();
             }