SPM: Refine 'load' interfaces

- Partitions need load info assemling MACROs, move them out of
  'partition_static_load.h'.
- Rename 'partition_static_load.h' into 'spm_load_api.h', and
  create a static load implementation 'static_load.c'.
- Refine the load logic, call API provided in 'spm_load_api.h'.
- Service lookup now list based.
- Rename 'load info' variable in partition and service runtime defs.

Change-Id: I73901094458ff1f11674100f8660eaa44a457d09
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 1642626..e812d2c 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.c
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.c
@@ -28,18 +28,16 @@
 #include "tfm_core_trustzone.h"
 #include "lists.h"
 #include "tfm_pools.h"
-#include "region.h"
-#include "region_defs.h"
 #include "spm_partition_defs.h"
 #include "psa_manifest/pid.h"
 #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 "load/spm_load_api.h"
 
-#include "secure_fw/partitions/tfm_service_list.inc"
-#include "tfm_spm_db_ipc.inc"
+extern struct spm_partition_db_t g_spm_partition_db;
+static struct service_t *all_services;
 
 /* Pools */
 TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
@@ -50,10 +48,6 @@
 
 #include "tfm_secure_irq_handlers_ipc.inc"
 
-/* Partition static data region */
-REGION_DECLARE(Image$$, TFM_SP_STATIC_LIST, $$RO$$Base);
-REGION_DECLARE(Image$$, TFM_SP_STATIC_LIST, $$RO$$Limit);
-
 /*********************** Connection handle conversion APIs *******************/
 
 #define CONVERSION_FACTOR_BITOFFSET    3
@@ -251,9 +245,9 @@
      */
     BI_LIST_FOR_EACH(node, head) {
         tmp_msg = TO_CONTAINER(node, struct tfm_msg_body_t, msg_node);
-        if (tmp_msg->service->service_db->signal == signal && msg) {
+        if (tmp_msg->service->p_ldinf->signal == signal && msg) {
             return msg;
-        } else if (tmp_msg->service->service_db->signal == signal) {
+        } else if (tmp_msg->service->p_ldinf->signal == signal) {
             msg = tmp_msg;
             BI_LIST_REMOVE_NODE(node);
         }
@@ -281,7 +275,7 @@
     }
 
     for (i = 0; i < g_spm_partition_db.partition_count; ++i) {
-        if (g_spm_partition_db.partitions[i].p_static->pid == partition_id) {
+        if (g_spm_partition_db.partitions[i].p_ldinf->pid == partition_id) {
             return i;
         }
     }
@@ -299,7 +293,7 @@
  */
 static uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx)
 {
-    return g_spm_partition_db.partitions[partition_idx].p_static->flags;
+    return g_spm_partition_db.partitions[partition_idx].p_ldinf->flags;
 }
 
 #if TFM_LVL != 1
@@ -349,16 +343,16 @@
 
 struct service_t *tfm_spm_get_service_by_sid(uint32_t sid)
 {
-    uint32_t i, num;
+    struct service_t *p_serv = all_services;
 
-    num = sizeof(g_services) / sizeof(struct service_t);
-    for (i = 0; i < num; i++) {
-        if (g_services[i].service_db->sid == sid) {
-            return &g_services[i];
-        }
+    while (p_serv && p_serv->p_ldinf->sid != sid) {
+        p_serv = TO_CONTAINER(BI_LIST_NEXT_NODE(&p_serv->list),
+                              struct service_t, list);
+        if (p_serv == all_services)
+            return NULL;
     }
 
-    return NULL;
+    return p_serv;
 }
 
 /**
@@ -395,14 +389,14 @@
 {
     TFM_CORE_ASSERT(service);
 
-    switch (SERVICE_GET_VERSION_POLICY(service->service_db->flags)) {
+    switch (SERVICE_GET_VERSION_POLICY(service->p_ldinf->flags)) {
     case TFM_VERSION_POLICY_RELAXED:
-        if (version > service->service_db->version) {
+        if (version > service->p_ldinf->version) {
             return SPM_ERROR_VERSION;
         }
         break;
     case TFM_VERSION_POLICY_STRICT:
-        if (version != service->service_db->version) {
+        if (version != service->p_ldinf->version) {
             return SPM_ERROR_VERSION;
         }
         break;
@@ -423,7 +417,7 @@
     TFM_CORE_ASSERT(service);
 
     if (ns_caller) {
-        if (!SERVICE_IS_NS_ACCESSIBLE(service->service_db->flags)) {
+        if (!SERVICE_IS_NS_ACCESSIBLE(service->p_ldinf->flags)) {
             return SPM_ERROR_GENERIC;
         }
     } else {
@@ -432,14 +426,14 @@
             tfm_core_panic();
         }
 
-        dep = (uint32_t *)LOAD_INFO_DEPS(partition->p_static);
-        for (i = 0; i < partition->p_static->ndeps; i++) {
+        dep = (uint32_t *)LOAD_INFO_DEPS(partition->p_ldinf);
+        for (i = 0; i < partition->p_ldinf->ndeps; i++) {
             if (dep[i] == sid) {
                 break;
             }
         }
 
-        if (i == partition->p_static->ndeps) {
+        if (i == partition->p_ldinf->ndeps) {
             return SPM_ERROR_GENERIC;
         }
     }
@@ -481,7 +475,7 @@
 
     /* Check that the running partition owns the message */
     partition_id = tfm_spm_partition_get_running_partition_id();
-    if (partition_id != p_msg->service->partition->p_static->pid) {
+    if (partition_id != p_msg->service->partition->p_ldinf->pid) {
         return NULL;
     }
 
@@ -560,12 +554,12 @@
     struct partition_t *partition = NULL;
     psa_signal_t signal = 0;
 
-    if (!msg || !service || !service->service_db || !service->partition) {
+    if (!msg || !service || !service->p_ldinf || !service->partition) {
         tfm_core_panic();
     }
 
     partition = service->partition;
-    signal = service->service_db->signal;
+    signal = service->p_ldinf->signal;
 
     /* Add message to partition message list tail */
     BI_LIST_INSERT_BEFORE(&partition->msg_list, &msg->msg_node);
@@ -594,8 +588,8 @@
     struct partition_t *partition;
 
     partition = tfm_spm_get_running_partition();
-    if (partition && partition->p_static) {
-        return partition->p_static->pid;
+    if (partition && partition->p_ldinf) {
+        return partition->p_ldinf->pid;
     } else {
         return INVALID_PARTITION_ID;
     }
@@ -646,59 +640,13 @@
     return SPM_ERROR_MEMORY_CHECK;
 }
 
-/* Allocate runtime space for partition from the pool. Static allocation. */
-static struct partition_t *tfm_allocate_partition(void)
-{
-    static uint32_t partition_pool_pos = 0;
-    struct partition_t *p_partition_allocated = NULL;
-
-    if (partition_pool_pos >= g_spm_partition_db.partition_count) {
-        return NULL;
-    }
-
-    p_partition_allocated = &g_spm_partition_db.partitions[partition_pool_pos];
-    partition_pool_pos++;
-
-    return p_partition_allocated;
-}
-
-/* Allocate runtime space for service from the pool. Static allocation. */
-static struct service_t *tfm_allocate_service(uint32_t service_count)
-{
-    static uint32_t service_pool_pos = 0;
-    struct service_t *p_service_allocated = NULL;
-    uint32_t num_of_services = sizeof(g_services) / sizeof(struct service_t);
-
-    if ((service_count == 0) ||
-        (service_count > num_of_services) ||
-        (service_pool_pos >= num_of_services) ||
-        (service_pool_pos + service_count > num_of_services)) {
-            return NULL;
-    }
-
-    p_service_allocated = &g_services[service_pool_pos];
-    service_pool_pos += service_count;
-
-    return p_service_allocated;
-}
-
-/* Check partition static data validation */
-bool tfm_validate_partition_static(struct partition_load_info_t *p_cmninf)
-{
-    return ((p_cmninf->psa_ff_ver & PARTITION_INFO_MAGIC_MASK)
-            == PARTITION_INFO_MAGIC);
-}
-
 uint32_t tfm_spm_init(void)
 {
-    uint32_t i, j, part_idx;
+    uint32_t i, j, part_idx = 0;
     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;
-    uintptr_t part_load_start, part_load_end;
-    struct partition_load_info_t *p_cmninf;
-    struct service_load_info_t *p_service_static;
+    const struct partition_load_info_t *p_cmninf;
     struct asset_desc_t *p_asset_load;
 #ifdef TFM_FIH_PROFILE_ON
     fih_int fih_rc = FIH_FAILURE;
@@ -709,49 +657,17 @@
                   sizeof(struct tfm_conn_handle_t),
                   TFM_CONN_HANDLE_MAX_NUM);
 
-    /* Load partition and service data */
-    part_idx = 0;
-    part_load_start = PART_REGION_ADDR(TFM_SP_STATIC_LIST, $$RO$$Base);
-    part_load_end = PART_REGION_ADDR(TFM_SP_STATIC_LIST, $$RO$$Limit);
-    while (part_load_start < part_load_end) {
-        p_cmninf = (struct partition_load_info_t *)part_load_start;
-
-        /* Validate static info section range */
-        part_load_start += LOAD_INFSZ_BYTES(p_cmninf);
-        if (part_load_start > part_load_end) {
-            tfm_core_panic();
+    while (1) {
+        partition = load_a_partition_assuredly();
+        if (partition == NULL) {
+            break;
         }
 
-        /* Validate partition static info */
-        if (!tfm_validate_partition_static(p_cmninf)) {
-            tfm_core_panic();
-        }
-        if (!(p_cmninf->flags & SPM_PART_FLAG_IPC)) {
-            tfm_core_panic();
-        }
-        if ((p_cmninf->psa_ff_ver & PARTITION_INFO_VERSION_MASK)
-            > PSA_FRAMEWORK_VERSION) {
-            ERROR_MSG("Warning: Partition requires higher framework version!");
-            tfm_core_panic();
-        }
+        load_services_assuredly(partition, &all_services);
 
-        /* Allocate runtime space */
-        partition = tfm_allocate_partition();
-        if (!partition) {
-            tfm_core_panic();
-        }
-        if (p_cmninf->nservices) {
-            service = tfm_allocate_service(p_cmninf->nservices);
-            if (!service) {
-                tfm_core_panic();
-            }
-        } else {
-            service = NULL;
-        }
+        p_cmninf = partition->p_ldinf;
 
-        partition->p_static = p_cmninf;
-
-        /* Init partition device object assets */
+        /* Init mmio assets */
         p_asset_load = (struct asset_desc_t *)LOAD_INFO_ASSET(p_cmninf);
         for (i = 0; i < p_cmninf->nassets; i++) {
             /* Skip the memory-based asset */
@@ -759,8 +675,8 @@
                 continue;
             }
 
-            platform_data_p = POSITION_TO_PTR(p_asset_load[i].dev.addr_ref,
-                                              struct platform_data_t *);
+            platform_data_p = REFERENCE_TO_PTR(p_asset_load[i].dev.addr_ref,
+                                               struct platform_data_t *);
 
             /*
              * TODO: some partitions declare MMIO not exist on specific
@@ -825,7 +741,7 @@
                     LOAD_ALLOCED_STACK_ADDR(p_cmninf) + p_cmninf->stack_size,
                     LOAD_ALLOCED_STACK_ADDR(p_cmninf));
 
-        pth->prior = TO_THREAD_PRIORITY(PARTITION_GET_PRIOR(p_cmninf->flags));
+        pth->prior = TO_THREAD_PRIORITY(PARTITION_PRIORITY(p_cmninf->flags));
 
         if (p_cmninf->pid == TFM_SP_NON_SECURE_ID) {
             p_ns_entry_thread = pth;
@@ -837,32 +753,6 @@
             tfm_core_panic();
         }
 
-        /* Init Services in the partition */
-        p_service_static =
-            (struct service_load_info_t *)LOAD_INFO_SERVICE(p_cmninf);
-        for (i = 0; i < p_cmninf->nservices; i++) {
-            /* Fill service runtime data */
-            partition->signals_allowed |= p_service_static[i].signal;
-            service[i].service_db = &p_service_static[i];
-            service[i].partition = partition;
-
-            /* Populate the p_service of stateless_service_ref[] */
-            if (SERVICE_IS_STATELESS(p_service_static[i].flags)) {
-                for (j = 0; j < STATIC_HANDLE_NUM_LIMIT; j++) {
-                    if (stateless_service_ref[j].sid ==
-                        p_service_static[i].sid) {
-                        stateless_service_ref[j].p_service = &service[i];
-                        break;
-                    }
-                }
-                /* Stateless service not found in tracking table */
-                if (j >= STATIC_HANDLE_NUM_LIMIT) {
-                    tfm_core_panic();
-                }
-            }
-
-            BI_LIST_INIT_NODE(&service[i].handle_list);
-        }
         part_idx++;
     }
 
@@ -900,7 +790,7 @@
         p_next_partition = TO_CONTAINER(pth_next,
                                         struct partition_t,
                                         sp_thread);
-        p_part_static = p_next_partition->p_static;
+        p_part_static = p_next_partition->p_ldinf;
         if (p_part_static->flags & SPM_PART_FLAG_PSA_ROT) {
             is_privileged = TFM_PARTITION_PRIVILEGED_MODE;
         } else {
@@ -1059,7 +949,7 @@
          * the preempted context of SP can be different with the one who
          * preempts veneer.
          */
-        if (p_cur_sp->p_static->pid != TFM_SP_NON_SECURE_ID) {
+        if (p_cur_sp->p_ldinf->pid != TFM_SP_NON_SECURE_ID) {
             tfm_core_panic();
         }
 
@@ -1084,7 +974,7 @@
         if (stacked_ctx_pos != p_cur_sp->sp_thread.stk_top) {
             tfm_core_panic();
         }
-    } else if (p_cur_sp->p_static->pid <= 0) {
+    } else if (p_cur_sp->p_ldinf->pid <= 0) {
         tfm_core_panic();
     }
 }
@@ -1104,7 +994,7 @@
         if (!partition) {
             tfm_core_panic();
         }
-        running_partition_flags = partition->p_static->flags;
+        running_partition_flags = partition->p_ldinf->flags;
 
         /* Currently only PSA Root of Trust services are allowed to make Reset
          * vote request