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/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt
index fb5571b..ff7d28d 100755
--- a/secure_fw/spm/CMakeLists.txt
+++ b/secure_fw/spm/CMakeLists.txt
@@ -45,6 +45,7 @@
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/arch/tfm_arch.c>
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/main.c>
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/spm_ipc.c>
+        $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/static_load.c>
         $<$<BOOL:${TFM_PSA_API}>:ffm/spm_psa_client_call.c>
         $<$<BOOL:${TFM_PSA_API}>:ffm/psa_client_service_apis.c>
         $<$<BOOL:${TFM_PSA_API}>:cmsis_psa/tfm_core_svcalls_ipc.c>
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
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.h b/secure_fw/spm/cmsis_psa/spm_ipc.h
index 52ca01a..b193b81 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.h
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.h
@@ -83,7 +83,7 @@
  * divided to structures, to keep the related fields close to each other.
  */
 struct partition_t {
-    const struct partition_load_info_t *p_static;
+    const struct partition_load_info_t *p_ldinf;
     void *p_platform;
     void *p_interrupts;
     void *p_metadata;
@@ -102,7 +102,7 @@
 
 /* RoT Service data */
 struct service_t {
-    const struct service_load_info_t *service_db;   /* Service static pointer */
+    const struct service_load_info_t *p_ldinf;      /* Service static pointer */
     struct partition_t *partition;                  /* Owner of the service   */
     struct bi_list_node_t handle_list;              /* Service handle list    */
     struct bi_list_node_t list;                     /* For list operation     */
diff --git a/secure_fw/spm/cmsis_psa/static_load.c b/secure_fw/spm/cmsis_psa/static_load.c
new file mode 100644
index 0000000..e8316c3
--- /dev/null
+++ b/secure_fw/spm/cmsis_psa/static_load.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <limits.h>
+#include <stdint.h>
+#include "lists.h"
+#include "region.h"
+#include "region_defs.h"
+#include "spm_ipc.h"
+#include "utilities.h"
+#include "load/partition_defs.h"
+#include "load/spm_load_api.h"
+#include "load/service_defs.h"
+#include "psa/client.h"
+
+#include "secure_fw/partitions/tfm_service_list.inc"
+#include "tfm_spm_db_ipc.inc"
+
+/* Partition static data region */
+REGION_DECLARE(Image$$, TFM_SP_STATIC_LIST, $$RO$$Base);
+REGION_DECLARE(Image$$, TFM_SP_STATIC_LIST, $$RO$$Limit);
+
+static uintptr_t ldinf_sa = PART_REGION_ADDR(TFM_SP_STATIC_LIST, $$RO$$Base);
+static uintptr_t ldinf_ea = PART_REGION_ADDR(TFM_SP_STATIC_LIST, $$RO$$Limit);
+
+/* Allocate runtime space for partition from the pool. Static allocation. */
+static struct partition_t *tfm_allocate_partition_assuredly(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) {
+        tfm_core_panic();
+    }
+
+    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_assuredly(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) {
+        return NULL;
+    } else if ((service_count > num_of_services) ||
+               (service_pool_pos >= num_of_services) ||
+               (service_pool_pos + service_count > num_of_services)) {
+        tfm_core_panic();
+    }
+
+    p_service_allocated = &g_services[service_pool_pos];
+    service_pool_pos += service_count;
+
+    return p_service_allocated;
+}
+
+struct partition_t *load_a_partition_assuredly(void)
+{
+    struct partition_load_info_t *p_ptldinf;
+    struct partition_t           *partition;
+
+    if ((UINTPTR_MAX - ldinf_sa < sizeof(struct partition_load_info_t)) ||
+        (ldinf_sa + sizeof(struct partition_load_info_t) >= ldinf_ea)) {
+        return NULL;
+    }
+
+    p_ptldinf = (struct partition_load_info_t *)ldinf_sa;
+
+    if ((UINTPTR_MAX - ldinf_sa < LOAD_INFSZ_BYTES(p_ptldinf)) ||
+        (ldinf_sa + LOAD_INFSZ_BYTES(p_ptldinf) > ldinf_ea))   {
+        tfm_core_panic();
+    }
+
+    /* Magic ensures data integrity */
+    if ((p_ptldinf->psa_ff_ver & PARTITION_INFO_MAGIC_MASK)
+        != PARTITION_INFO_MAGIC) {
+        tfm_core_panic();
+    }
+
+    if ((p_ptldinf->psa_ff_ver & PARTITION_INFO_VERSION_MASK)
+        > PSA_FRAMEWORK_VERSION) {
+        tfm_core_panic();
+    }
+
+    if (!(p_ptldinf->flags & SPM_PART_FLAG_IPC)) {
+        tfm_core_panic();
+    }
+
+    partition = tfm_allocate_partition_assuredly();
+    partition->p_ldinf = p_ptldinf;
+
+    ldinf_sa += LOAD_INFSZ_BYTES(p_ptldinf);
+
+    return partition;
+}
+
+void load_services_assuredly(struct partition_t *p_partition,
+                             struct service_t **list_head)
+{
+    uint32_t i, j;
+    struct service_t *services;
+    const struct partition_load_info_t *p_ptldinf;
+    const struct service_load_info_t *p_servldinf;
+
+    if (p_partition == NULL) {
+        tfm_core_panic();
+    }
+
+    p_ptldinf = p_partition->p_ldinf;
+    p_servldinf = (struct service_load_info_t *)LOAD_INFO_SERVICE(p_ptldinf);
+
+    /*
+     * 'services' CAN be NULL when no services, which is a rational result.
+     * The loop won't go in the NULL case.
+     */
+    services = tfm_allocate_service_assuredly(p_ptldinf->nservices);
+    for (i = 0; i < p_ptldinf->nservices && services; i++) {
+        p_partition->signals_allowed |= p_servldinf[i].signal;
+        services[i].p_ldinf = &p_servldinf[i];
+        services[i].partition = p_partition;
+
+        /* Populate the p_service of stateless_service_ref[] */
+        if (SERVICE_IS_STATELESS(p_servldinf[i].flags)) {
+            for (j = 0; j < STATIC_HANDLE_NUM_LIMIT; j++) {
+                if (stateless_service_ref[j].sid == p_servldinf[i].sid) {
+                    stateless_service_ref[j].p_service = &services[i];
+                    break;
+                }
+            }
+            /* Stateless service not found in tracking table */
+            if (j >= STATIC_HANDLE_NUM_LIMIT) {
+                tfm_core_panic();
+            }
+        }
+        BI_LIST_INIT_NODE(&services[i].handle_list);
+        BI_LIST_INIT_NODE(&services[i].list);
+
+        if (list_head) {
+            if (*list_head) {
+                BI_LIST_INSERT_AFTER(&(*list_head)->list, &services[i].list);
+            } else {
+                *list_head = &services[i];
+            }
+        }
+    }
+}
diff --git a/secure_fw/spm/ffm/psa_client_service_apis.c b/secure_fw/spm/ffm/psa_client_service_apis.c
index 57c1b82..87c7f3b 100644
--- a/secure_fw/spm/ffm/psa_client_service_apis.c
+++ b/secure_fw/spm/ffm/psa_client_service_apis.c
@@ -76,7 +76,7 @@
         tfm_core_panic();
     }
     privileged = tfm_spm_partition_get_privileged_mode(
-        partition->p_static->flags);
+        partition->p_ldinf->flags);
 
     type = (int32_t)(int16_t)((args[1] & TYPE_MASK) >> TYPE_OFFSET);
     in_num = (size_t)((args[1] & IN_LEN_MASK) >> IN_LEN_OFFSET);
@@ -174,7 +174,7 @@
         tfm_core_panic();
     }
     privileged = tfm_spm_partition_get_privileged_mode(
-        partition->p_static->flags);
+        partition->p_ldinf->flags);
 
     /*
      * Write the message to the service buffer. It is a fatal error if the
@@ -237,7 +237,7 @@
     }
 
     /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
-    if (SERVICE_IS_STATELESS(msg->service->service_db->flags)) {
+    if (SERVICE_IS_STATELESS(msg->service->p_ldinf->flags)) {
         tfm_core_panic();
     }
 
@@ -273,7 +273,7 @@
 
     partition = msg->service->partition;
     privileged = tfm_spm_partition_get_privileged_mode(
-        partition->p_static->flags);
+        partition->p_ldinf->flags);
 
     /*
      * It is a fatal error if message handle does not refer to a request
@@ -396,7 +396,7 @@
 
     partition = msg->service->partition;
     privileged = tfm_spm_partition_get_privileged_mode(
-        partition->p_static->flags);
+        partition->p_ldinf->flags);
 
     /*
      * It is a fatal error if message handle does not refer to a request
@@ -513,7 +513,7 @@
              * psa_call().
              */
             update_caller_outvec_len(msg);
-            if (SERVICE_IS_STATELESS(service->service_db->flags)) {
+            if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
                 tfm_spm_free_conn_handle(service, conn_handle);
             }
         } else {
@@ -585,7 +585,7 @@
         tfm_core_panic();
     }
 
-    irq_line = get_irq_line_for_signal(partition->p_static->pid, irq_signal);
+    irq_line = get_irq_line_for_signal(partition->p_ldinf->pid, irq_signal);
     /* It is a fatal error if passed signal is not an interrupt signal. */
     if (irq_line < 0) {
         tfm_core_panic();
@@ -624,7 +624,7 @@
         tfm_core_panic();
     }
 
-    irq_line = get_irq_line_for_signal(partition->p_static->pid, irq_signal);
+    irq_line = get_irq_line_for_signal(partition->p_ldinf->pid, irq_signal);
     if (irq_line < 0) {
         tfm_core_panic();
     }
@@ -645,7 +645,7 @@
         tfm_core_panic();
     }
 
-    irq_line = get_irq_line_for_signal(partition->p_static->pid, irq_signal);
+    irq_line = get_irq_line_for_signal(partition->p_ldinf->pid, irq_signal);
     if (irq_line < 0) {
         tfm_core_panic();
     }
diff --git a/secure_fw/spm/ffm/spm_psa_client_call.c b/secure_fw/spm/ffm/spm_psa_client_call.c
index 3bcf6a8..805e9f3 100644
--- a/secure_fw/spm/ffm/spm_psa_client_call.c
+++ b/secure_fw/spm/ffm/spm_psa_client_call.c
@@ -47,7 +47,7 @@
         return PSA_VERSION_NONE;
     }
 
-    return service->service_db->version;
+    return service->p_ldinf->version;
 }
 
 psa_status_t tfm_spm_client_psa_connect(uint32_t sid, uint32_t version,
@@ -85,7 +85,7 @@
     }
 
     /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
-    if (SERVICE_IS_STATELESS(service->service_db->flags)) {
+    if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
         TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
     }
 
diff --git a/secure_fw/spm/ffm/tfm_boot_data.c b/secure_fw/spm/ffm/tfm_boot_data.c
index d3bb96d..1b9ed64 100644
--- a/secure_fw/spm/ffm/tfm_boot_data.c
+++ b/secure_fw/spm/ffm/tfm_boot_data.c
@@ -174,7 +174,7 @@
         tfm_core_panic();
     }
     privileged =
-        tfm_spm_partition_get_privileged_mode(partition->p_static->flags);
+        tfm_spm_partition_get_privileged_mode(partition->p_ldinf->flags);
 
     if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
         privileged) != SPM_SUCCESS) {
diff --git a/secure_fw/spm/include/load/asset_defs.h b/secure_fw/spm/include/load/asset_defs.h
index 6e5c8d0..af1289c 100644
--- a/secure_fw/spm/include/load/asset_defs.h
+++ b/secure_fw/spm/include/load/asset_defs.h
@@ -17,6 +17,9 @@
 /* Customized objects such as device or symbol. Refer by 'dev' in the union. */
 #define ASSET_DEV_REF_BIT           (1U << 3)
 
+#define PTR_TO_REFERENCE(x)         (uintptr_t)(x)
+#define REFERENCE_TO_PTR(x, t)      (t)(x)
+
 struct asset_desc_t {
     union {
         struct {                            /* Memory asset type        */
diff --git a/secure_fw/spm/include/load/partition_defs.h b/secure_fw/spm/include/load/partition_defs.h
index 80edfd9..119359e 100644
--- a/secure_fw/spm/include/load/partition_defs.h
+++ b/secure_fw/spm/include/load/partition_defs.h
@@ -36,6 +36,11 @@
 #define SPM_PART_FLAG_PSA_ROT                   (1U << 8)
 #define SPM_PART_FLAG_IPC                       (1U << 9)
 
+#define PARTITION_PRIORITY(flag)                ((flag) & PARTITION_PRI_MASK)
+#define TO_THREAD_PRIORITY(x)                   (x)
+
+#define ENTRY_TO_POSITION(x)                    (uintptr_t)(x)
+#define POSITION_TO_ENTRY(x, t)                 (t)(x)
 /*
  * Common partition structure type, the extendable data is right after it.
  * Extendable data has different size for each partition, and must be 4-byte
diff --git a/secure_fw/spm/include/load/partition_static_load.h b/secure_fw/spm/include/load/partition_static_load.h
deleted file mode 100644
index 698c034..0000000
--- a/secure_fw/spm/include/load/partition_static_load.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __PARTITION_STATIC_LOAD_H__
-#define __PARTITION_STATIC_LOAD_H__
-
-#include "partition_defs.h"
-#include "service_defs.h"
-
-#define PARTITION_GET_PRIOR(flag)           ((flag) & PARTITION_PRI_MASK)
-#define TO_THREAD_PRIORITY(x)               (x)
-
-#define STRID_TO_STRING_PTR(strid)          (const char *)(strid)
-#define STRING_PTR_TO_STRID(str)            (uintptr_t)(str)
-
-#define ENTRY_TO_POSITION(x)                (uintptr_t)(x)
-#define POSITION_TO_ENTRY(x, t)             (t)(x)
-
-#define PTR_TO_POSITION(x)                  (uintptr_t)(x)
-#define POSITION_TO_PTR(x, t)               (t)(x)
-
-/* Length of extendable variables in partition static type */
-#define LOAD_INFO_EXT_LENGTH                2
-/*
- * Argument "ps_ptr" must have be a "struct partition_load_info_t *" type and
- * must be validated before using.
- */
-#define LOAD_INFSZ_BYTES(ps_ptr)                                       \
-    (sizeof(*(ps_ptr)) + LOAD_INFO_EXT_LENGTH * sizeof(uintptr_t) +    \
-     (ps_ptr)->ndeps * sizeof(uint32_t) +                              \
-     (ps_ptr)->nservices * sizeof(struct service_load_info_t) +        \
-     (ps_ptr)->nassets * sizeof(struct asset_desc_t))
-
-/* 'Allocate' stack based on load info */
-#define LOAD_ALLOCED_STACK_ADDR(ps_ptr)    (*((uintptr_t *)(ps_ptr + 1)))
-
-#define LOAD_INFO_DEPS(ps_ptr)                                         \
-    ((uintptr_t)(ps_ptr + 1) + LOAD_INFO_EXT_LENGTH * sizeof(uintptr_t))
-#define LOAD_INFO_SERVICE(ps_ptr)                                      \
-    ((uintptr_t)LOAD_INFO_DEPS(ps_ptr) + (ps_ptr)->ndeps * sizeof(uint32_t))
-#define LOAD_INFO_ASSET(ps_ptr)                                        \
-    ((uintptr_t)LOAD_INFO_SERVICE(ps_ptr) +                            \
-     (ps_ptr)->nservices * sizeof(struct service_load_info_t))
-
-#endif /* __PARTITION_STATIC_LOAD_H__ */
diff --git a/secure_fw/spm/include/load/service_defs.h b/secure_fw/spm/include/load/service_defs.h
index d082507..3692846 100644
--- a/secure_fw/spm/include/load/service_defs.h
+++ b/secure_fw/spm/include/load/service_defs.h
@@ -31,6 +31,9 @@
 #define SERVICE_GET_VERSION_POLICY(flag)        \
     ((flag) & SERVICE_VERSION_POLICY_MASK)
 
+#define STRID_TO_STRING_PTR(strid)              (const char *)(strid)
+#define STRING_PTR_TO_STRID(str)                (uintptr_t)(str)
+
 /* Common service structure type */
 struct service_load_info_t {
     uintptr_t       name_strid;         /* String ID for name               */
diff --git a/secure_fw/spm/include/load/spm_load_api.h b/secure_fw/spm/include/load/spm_load_api.h
new file mode 100644
index 0000000..a047608
--- /dev/null
+++ b/secure_fw/spm/include/load/spm_load_api.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* !! For SPM load usage, no including by components out of SPM !! */
+#ifndef __SPM_LOAD_API_H__
+#define __SPM_LOAD_API_H__
+
+#include "asset_defs.h"
+#include "partition_defs.h"
+#include "service_defs.h"
+#include "spm_ipc.h"
+
+/* Length of extendable variables in partition static type */
+#define LOAD_INFO_EXT_LENGTH                2
+/* Argument "pldinf" must be a "struct partition_load_info_t *". */
+#define LOAD_INFSZ_BYTES(pldinf)                                       \
+    (sizeof(*(pldinf)) + LOAD_INFO_EXT_LENGTH * sizeof(uintptr_t) +    \
+     (pldinf)->ndeps * sizeof(uint32_t) +                              \
+     (pldinf)->nservices * sizeof(struct service_load_info_t) +        \
+     (pldinf)->nassets * sizeof(struct asset_desc_t))
+
+/* 'Allocate' stack based on load info */
+#define LOAD_ALLOCED_STACK_ADDR(pldinf)    (*((uintptr_t *)(pldinf + 1)))
+
+#define LOAD_INFO_DEPS(pldinf)                                         \
+    ((uintptr_t)(pldinf + 1) + LOAD_INFO_EXT_LENGTH * sizeof(uintptr_t))
+#define LOAD_INFO_SERVICE(pldinf)                                      \
+    ((uintptr_t)LOAD_INFO_DEPS(pldinf) + (pldinf)->ndeps * sizeof(uint32_t))
+#define LOAD_INFO_ASSET(pldinf)                                        \
+    ((uintptr_t)LOAD_INFO_SERVICE(pldinf) +                            \
+     (pldinf)->nservices * sizeof(struct service_load_info_t))
+
+/*
+ * Allocate a partition object and return if a load is successful.
+ * An 'assuredly' function, return NULL for no more partitions and
+ * return a valid pointer if succeed. Other errors simply panic
+ * the system and never return.
+ */
+struct partition_t *load_a_partition_assuredly(void);
+
+/*
+ * Allocated numbers of service objects based on given partition.
+ * Link services with 'list_head' if it is provided.
+ * An 'assuredly' function, errors simply panic the system and never
+ * return.
+ */
+void load_services_assuredly(struct partition_t *p_partition,
+                             struct service_t **list_head);
+
+#endif /* __SPM_LOAD_API_H__ */