SPM: Use partition static data from data section

- Use partition and service static data from the dedicated
  partition static info data section instead of from the
  statically defined arrays.
- Adopt macros to retrieve flags since several flags are combined
  together.

Change-Id: Icc30b9f34a6f0c3c5379235e9d17603237440948
Signed-off-by: Mingyang Sun <mingyang.sun@arm.com>
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 15b22ef..9f4322e 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/partition_static_load.h"
 
 #include "secure_fw/partitions/tfm_service_list.inc"
 #include "tfm_spm_db_ipc.inc"
@@ -48,6 +49,10 @@
 
 #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
@@ -389,7 +394,7 @@
 {
     TFM_CORE_ASSERT(service);
 
-    switch (service->service_db->version_policy) {
+    switch (SERVICE_GET_VERSION_POLICY(service->service_db->flags)) {
     case TFM_VERSION_POLICY_RELAXED:
         if (version > service->service_db->version) {
             return SPM_ERROR_VERSION;
@@ -411,12 +416,13 @@
                                     bool ns_caller)
 {
     struct partition_t *partition = NULL;
+    uint32_t *dep;
     int32_t i;
 
     TFM_CORE_ASSERT(service);
 
     if (ns_caller) {
-        if (!service->service_db->non_secure_client) {
+        if (!SERVICE_IS_NS_ACCESSIBLE(service->service_db->flags)) {
             return SPM_ERROR_GENERIC;
         }
     } else {
@@ -425,8 +431,9 @@
             tfm_core_panic();
         }
 
+        dep = (uint32_t *)STATIC_INF_DEPS(partition->p_static);
         for (i = 0; i < partition->p_static->ndeps; i++) {
-            if (partition->p_static->deps[i] == sid) {
+            if (dep[i] == sid) {
                 break;
             }
         }
@@ -638,12 +645,58 @@
     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 > 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_static_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, num;
+    uint32_t i, j;
     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_static_start, part_static_end;
+    struct partition_static_info_t *p_cmninf;
+    struct service_static_info_t *p_service_static;
 #ifdef TFM_FIH_PROFILE_ON
     fih_int fih_rc = FIH_FAILURE;
 #endif
@@ -653,27 +706,45 @@
                   sizeof(struct tfm_conn_handle_t),
                   TFM_CONN_HANDLE_MAX_NUM);
 
-    /* Init partition first for it will be used when init service */
-    for (i = 0; i < g_spm_partition_db.partition_count; i++) {
+    /* Load partition and service data */
+    part_static_start = PART_REGION_ADDR(TFM_SP_STATIC_LIST, $$RO$$Base);
+    part_static_end = PART_REGION_ADDR(TFM_SP_STATIC_LIST, $$RO$$Limit);
+    while (part_static_start < part_static_end) {
+        p_cmninf = (struct partition_static_info_t *)part_static_start;
 
-        partition = &g_spm_partition_db.partitions[i];
-
-        /* Skip NULL checking on statically reserved arraries. */
-        partition->p_static = &static_data_list[i];
-
-        if (!(partition->p_static->flags & SPM_PART_FLAG_IPC)) {
+        /* Validate static info section range */
+        part_static_start += STATIC_INFSZ_BYTES(p_cmninf);
+        if (part_static_start > part_static_end) {
             tfm_core_panic();
         }
 
-        /* Check if the PSA framework version matches. */
-        if (partition->p_static->psa_ff_ver >
-            PSA_FRAMEWORK_VERSION) {
+        /* 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!");
-            continue;
+            tfm_core_panic();
         }
 
-        platform_data_p =
-            (const struct platform_data_t **)partition->p_static->platform_data;
+        /* Allocate runtime space */
+        partition = tfm_allocate_partition();
+        if (!partition) {
+            tfm_core_panic();
+        }
+        service = tfm_allocate_service(p_cmninf->nservices);
+        if (!service) {
+            tfm_core_panic();
+        }
+
+        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
@@ -692,20 +763,20 @@
             }
         }
 
-        /* Add PSA_DOORBELL signal to assigned_signals */
         partition->signals_allowed |= PSA_DOORBELL;
 
         /* TODO: This can be optimized by generating the assigned signal
          *       in code generation time.
          */
         for (j = 0; j < tfm_core_irq_signals_count; ++j) {
-            if (tfm_core_irq_signals[j].partition_id ==
-                partition->p_static->pid) {
+            if (tfm_core_irq_signals[j].partition_id == p_cmninf->pid) {
                 partition->signals_allowed |=
                                         tfm_core_irq_signals[j].signal_value;
-                if (partition->p_static->psa_ff_ver == 0x0100) {
+                if ((p_cmninf->psa_ff_ver & PARTITION_INFO_VERSION_MASK)
+                    == 0x0100) {
                     tfm_spm_hal_enable_irq(tfm_core_irq_signals[j].irq_line);
-                } else if (partition->p_static->psa_ff_ver == 0x0101) {
+                } else if ((p_cmninf->psa_ff_ver & PARTITION_INFO_VERSION_MASK)
+                           == 0x0101) {
                     tfm_spm_hal_disable_irq(tfm_core_irq_signals[j].irq_line);
                 }
             }
@@ -719,16 +790,16 @@
             tfm_core_panic();
         }
 
-        tfm_core_thrd_init(pth,
-                           (tfm_core_thrd_entry_t)partition->p_static->entry,
-                           NULL,
-                           (uintptr_t)(partition->p_static->stack_base_addr +
-                                       partition->p_static->stack_size),
-                           (uintptr_t)partition->p_static->stack_base_addr);
+        tfm_core_thrd_init(
+                    pth,
+                    POSITION_TO_ENTRY(p_cmninf->entry, tfm_core_thrd_entry_t),
+                    NULL,
+                    (uintptr_t)(p_cmninf->vars[0] + p_cmninf->stack_size),
+                    (uintptr_t)p_cmninf->vars[0]);
 
-        pth->prior = partition->p_static->priority;
+        pth->prior = TO_THREAD_PRIORITY(PARTITION_GET_PRIOR(p_cmninf->flags));
 
-        if (partition->p_static->pid == TFM_SP_NON_SECURE_ID) {
+        if (p_cmninf->pid == TFM_SP_NON_SECURE_ID) {
             p_ns_entry_thread = pth;
             pth->param = (void *)tfm_spm_hal_get_ns_entry_point();
         }
@@ -737,36 +808,33 @@
         if (tfm_core_thrd_start(pth) != THRD_SUCCESS) {
             tfm_core_panic();
         }
-    }
 
-    /* Init Service */
-    num = sizeof(g_services) / sizeof(struct service_t);
-    for (i = 0; i < num; i++) {
-        int32_t j = 0;
-        g_services[i].service_db = &service_db[i];
-        partition =
-            tfm_spm_get_partition_by_id(g_services[i].service_db->partition_id);
-        if (!partition) {
-            tfm_core_panic();
-        }
-        g_services[i].partition = partition;
-        partition->signals_allowed |= g_services[i].service_db->signal;
+        /* Init Services in the partition */
+        p_service_static =
+            (struct service_static_info_t *)STATIC_INF_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_db[i].connection_based == false) {
-            for (j = 0; j < STATIC_HANDLE_NUM_LIMIT; j++) {
-                if (stateless_service_ref[j].sid == service_db[i].sid) {
-                    stateless_service_ref[j].p_service = &g_services[i];
-                    break;
+            /* 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();
                 }
             }
-            /* Stateless service not found in tracking table */
-            if (j >= STATIC_HANDLE_NUM_LIMIT) {
-                tfm_core_panic();
-            }
-        }
 
-        BI_LIST_INIT_NODE(&g_services[i].handle_list);
+            BI_LIST_INIT_NODE(&service[i].handle_list);
+        }
     }
 
     /*
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.h b/secure_fw/spm/cmsis_psa/spm_ipc.h
index 1ed68ff..437a4bb 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.h
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.h
@@ -78,38 +78,12 @@
     struct bi_list_node_t msg_node;    /* For list operators             */
 };
 
-struct partition_memory_t {
-    uintptr_t start;
-    uintptr_t limit;
-};
-
-/**
- * Partition storage common type.
- */
-struct partition_static_t {
-    uint32_t psa_ff_ver;                /* PSA-FF version                   */
-    uint32_t pid;                       /* Partition ID                     */
-    uint32_t flags;                     /* Flags of the partition           */
-    uint32_t priority;                  /* Priority of the partition thread */
-    sp_entry_point entry;               /* Entry point of the partition     */
-    uintptr_t stack_base_addr;          /* Stack base of the partition      */
-    size_t stack_size;                  /* Stack size of the partition      */
-    uintptr_t heap_base_addr;           /* Heap base of the partition       */
-    size_t heap_size;                   /* Heap size of the partition       */
-    uintptr_t platform_data;            /* Platform specific data           */
-    uint32_t ndeps;                     /* Numbers of depended services     */
-    uint32_t *deps;                     /* Pointer to dependency arrays     */
-#if TFM_LVL == 3
-    struct partition_memory_t mems;     /* Partition memories               */
-#endif
-};
-
 /**
  * Holds the fields that define a partition for SPM. The fields are further
  * divided to structures, to keep the related fields close to each other.
  */
 struct partition_t {
-    const struct partition_static_t *p_static;
+    const struct partition_static_info_t *p_static;
     void *p_platform;
     void *p_interrupts;
     void *p_metadata;
@@ -126,27 +100,12 @@
     struct partition_t *partitions;
 };
 
-/* Service database defined by manifest */
-struct tfm_spm_service_db_t {
-    char *name;                     /* Service name                          */
-    uint32_t partition_id;          /* Partition ID which service belong to  */
-    psa_signal_t signal;            /* Service signal                        */
-    uint32_t sid;                   /* Service identifier                    */
-    bool non_secure_client;         /* If can be called by non secure client */
-    bool connection_based;          /* 'true' for connection-based service   */
-    uint32_t version;               /* Service version                       */
-    uint32_t version_policy;        /* Service version policy                */
-};
-
 /* RoT Service data */
 struct service_t {
-    const struct tfm_spm_service_db_t *service_db;/* Service database pointer */
-    struct partition_t *partition;           /*
-                                              * Point to secure partition
-                                              * data
-                                              */
-    struct bi_list_node_t handle_list;       /* Service handle list          */
-    struct bi_list_node_t list;              /* For list operation           */
+    const struct service_static_info_t *service_db; /* 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     */
 };
 
 /* Stateless RoT service tracking array item type. Indexed by static handle */
diff --git a/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template b/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template
index 503288f..9e8c992 100644
--- a/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template
+++ b/secure_fw/spm/cmsis_psa/tfm_spm_db_ipc.inc.template
@@ -36,174 +36,6 @@
     {% endif %}
 
 {% endfor %}
-/**************************************************************************/
-/** Declarations of partition init functions */
-/**************************************************************************/
-extern void tfm_nspm_thread_entry(void);
-
-{% for partition in partitions %}
-    {% if partition.attr.conditional %}
-#ifdef {{partition.attr.conditional}}
-    {% endif %}
-extern void {{partition.manifest.entry_point}}(void);
-    {% if partition.attr.conditional %}
-#endif /* {{partition.attr.conditional}} */
-    {% endif %}
-
-{% endfor %}
-/**************************************************************************/
-/** Memory region declarations */
-/**************************************************************************/
-REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
-REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit);
-
-{% for partition in partitions %}
-    {% if partition.attr.conditional %}
-#ifdef {{partition.attr.conditional}}
-    {% endif %}
-#if TFM_LVL == 3
-REGION_DECLARE(Image$$, PT_{{partition.manifest.name}}_PRIVATE, _DATA_START$$Base);
-REGION_DECLARE(Image$$, PT_{{partition.manifest.name}}_PRIVATE, _DATA_END$$Base);
-#endif
-extern uint8_t {{partition.manifest.name.lower()}}_stack[];
-    {% if partition.attr.conditional %}
-#endif /* {{partition.attr.conditional}} */
-    {% endif %}
-
-{% endfor %}
-/**************************************************************************/
-/** Dependencies array for Secure Partition */
-/**************************************************************************/
-{% for partition in partitions %}
-    {% if partition.manifest.dependencies %}
-        {% if partition.attr.conditional %}
-#ifdef {{partition.attr.conditional}}
-        {% endif %}
-static uint32_t dependencies_{{partition.manifest.name}}[] =
-{
-        {% for dependence in partition.manifest.dependencies %}
-            {% for service in partition.manifest.services %}
-                {% if dependence == service.name %}
-#error "Please DO NOT include SP's own RoT Service '{{dependence}}', which will cause a deadlock!"
-                {% endif %}
-            {% endfor %}
-    {{dependence}}_SID,
-        {% endfor %}
-};
-        {% if partition.attr.conditional %}
-#endif /* {{partition.attr.conditional}} */
-        {% endif %}
-
-    {% endif %}
-{% endfor %}
-
-/**************************************************************************/
-/** The platform data of the partition list */
-/**************************************************************************/
-{% for partition in partitions %}
-    {% if partition.manifest.mmio_regions %}
-        {% if partition.attr.conditional %}
-#ifdef {{partition.attr.conditional}}
-        {% endif %}
-const struct platform_data_t *
-    platform_data_list_{{partition.manifest.name}}[] =
-{
-        {% for region in partition.manifest.mmio_regions %}
-            {% if region.conditional %}
-#ifdef {{region.conditional}}
-            {% endif %}
-    {{region.name}},
-            {% if region.conditional %}
-#endif /* {{region.conditional}} */
-            {% endif %}
-        {% endfor %}
-    NULL
-};
-        {% if partition.attr.conditional %}
-#endif /* {{partition.attr.conditional}} */
-        {% endif %}
-
-    {% endif %}
-{% endfor %}
-
-/**************************************************************************/
-/** The static data of the partition list */
-/**************************************************************************/
-const struct partition_static_t static_data_list[] =
-{
-    {
-        .psa_ff_ver           = 0x0100,
-        .pid                  = TFM_SP_NON_SECURE_ID,
-#if TFM_MULTI_CORE_TOPOLOGY
-        .flags                = SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_IPC,
-#else
-        .flags                = SPM_PART_FLAG_IPC,
-#endif
-        .priority             = PARTITION_PRI_LOWEST,
-        .entry                = tfm_nspm_thread_entry,
-        .stack_base_addr      = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Base),
-        .stack_size           = S_PSP_STACK_SIZE,
-#if TFM_LVL == 3
-        .mems                 = {
-            .start              = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Base),
-            .limit              = PART_REGION_ADDR(ARM_LIB_STACK, $$ZI$$Limit),
-        },
-#endif
-    },
-
-{% for partition in partitions %}
-    {% if partition.attr.conditional %}
-#ifdef {{partition.attr.conditional}}
-    {% endif %}
-    {{'{'}}
-    {% if partition.manifest.psa_framework_version == 1.0 %}
-        .psa_ff_ver            = 0x0100,
-    {% elif partition.manifest.psa_framework_version == 1.1 %}
-        .psa_ff_ver            = 0x0101,
-    {% else %}
-        .psa_ff_ver            = 0,
-    {% endif %}
-        .pid                   = {{partition.manifest.name}},
-    {% if partition.attr.tfm_partition_ipc %}
-        .flags                 = SPM_PART_FLAG_IPC
-    {% else %}
-        .flags                 = 0
-    {% endif %}
-    {% if partition.manifest.type == "APPLICATION-ROT" %}
-                               | 0,
-    {% elif partition.manifest.type == "PSA-ROT" %}
-                               | SPM_PART_FLAG_PSA_ROT,
-    {% else %}
-#error "Unsupported type '{{partition.manifest.type}}' for partition '{{partition.manifest.name}}'!"
-    {% endif %}
-        .priority             = PARTITION_PRI_{{partition.manifest.priority}},
-        .entry                = {{partition.manifest.entry_point}},
-        .stack_base_addr      = (uint32_t){{partition.manifest.name.lower()}}_stack,
-        .stack_size           = (uint32_t){{partition.manifest.stack_size}},
-    {% if partition.manifest.mmio_regions %}
-        .platform_data        = (uintptr_t)platform_data_list_{{partition.manifest.name}},
-    {% else %}{# if partition.manifest.mmio_regions #}
-        .platform_data        = 0,
-    {% endif %}{# if partition.manifest.mmio_regions #}
-        .ndeps                = {{partition.manifest.dependencies | length()}},
-    {% if partition.manifest.dependencies %}
-        .deps                 = dependencies_{{partition.manifest.name}},
-    {% else %}
-        .deps                 = NULL,
-    {% endif %}
-#if TFM_LVL == 3
-        .mems                 = {
-            .start              = PART_REGION_ADDR(PT_{{partition.manifest.name}}_PRIVATE, _DATA_START$$Base),
-            .limit              = PART_REGION_ADDR(PT_{{partition.manifest.name}}_PRIVATE, _DATA_END$$Base),
-        },
-#endif
-    {{'},'}}
-    {% if partition.attr.conditional %}
-#endif /* {{partition.attr.conditional}} */
-    {% endif %}
-
-{% endfor %}
-};
 
 /**************************************************************************/
 /** The partition list for the DB */
diff --git a/secure_fw/spm/ffm/psa_client_service_apis.c b/secure_fw/spm/ffm/psa_client_service_apis.c
index 467c8c7..33b200d 100644
--- a/secure_fw/spm/ffm/psa_client_service_apis.c
+++ b/secure_fw/spm/ffm/psa_client_service_apis.c
@@ -9,11 +9,7 @@
 #include "bitops.h"
 #include "spm_psa_client_call.h"
 #include "psa/lifecycle.h"
-#ifdef TFM_PSA_API
 #include "spm_ipc.h"
-#else
-#include "spm_func.h"
-#endif
 #include "tfm_core_utils.h"
 #include "tfm_hal_defs.h"
 #include "tfm_hal_platform.h"
@@ -21,6 +17,8 @@
 #include "tfm_rpc.h"
 #include "tfm_spm_hal.h"
 #include "tfm_psa_call_param.h"
+#include "load/partition_defs.h"
+#include "load/service_defs.h"
 
 /*********************** SPM functions for PSA Client APIs *******************/
 
@@ -239,7 +237,7 @@
     }
 
     /* It is a PROGRAMMER ERROR if a stateless service sets rhandle. */
-    if (!msg->service->service_db->connection_based) {
+    if (SERVICE_IS_STATELESS(msg->service->service_db->flags)) {
         tfm_core_panic();
     }
 
@@ -515,7 +513,7 @@
              * psa_call().
              */
             update_caller_outvec_len(msg);
-            if (!service->service_db->connection_based) {
+            if (SERVICE_IS_STATELESS(service->service_db->flags)) {
                 tfm_spm_free_conn_handle(service, conn_handle);
             }
         } else {
diff --git a/secure_fw/spm/ffm/spm_psa_client_call.c b/secure_fw/spm/ffm/spm_psa_client_call.c
index a30b877..3bcf6a8 100644
--- a/secure_fw/spm/ffm/spm_psa_client_call.c
+++ b/secure_fw/spm/ffm/spm_psa_client_call.c
@@ -9,6 +9,7 @@
 #include "spm_ipc.h"
 #include "tfm_core_utils.h"
 #include "tfm_memory_utils.h"
+#include "load/service_defs.h"
 #include "spm_psa_client_call.h"
 #include "utilities.h"
 #include "tfm_wait.h"
@@ -84,7 +85,7 @@
     }
 
     /* It is a PROGRAMMER ERROR if connecting to a stateless service. */
-    if (!service->service_db->connection_based) {
+    if (SERVICE_IS_STATELESS(service->service_db->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 8003f21..d3bb96d 100644
--- a/secure_fw/spm/ffm/tfm_boot_data.c
+++ b/secure_fw/spm/ffm/tfm_boot_data.c
@@ -21,6 +21,7 @@
 #include "tfm_wait.h"
 #include "tfm_spm_hal.h"
 #include "spm_ipc.h"
+#include "load/partition_defs.h"
 #else
 #include "spm_func.h"
 #endif