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);
+ }
}
/*