Build: Follow the 'source_structure.rst'
This is the first patch to follow the first commit of source structure
document. The items under the 'secure_fw' folder are re-organized:
- Create/Move some folders/files to follow document.
- Rename some folders to foll, for example, 'secure_fw/services' to
'secure_fw/partitions'.
- Update affected files to make it work.
This is a big change, to make the structure meet the basic shape of
the structure document defined, and make it easier to be understood
for users. Staging changes are not applicable so they are combined
into one - and because it is not the final shape yet, so:
- Upcoming updates on the 'secure_fw' folder would follow up soon.
- Fine-tune about the 'source_structure.rst' would come, too.
Change-Id: I5c11175e0a4579cd9b42d3e3519dbffb87334d0b
Signed-off-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/spm/model_func/CMakeLists.inc b/secure_fw/spm/model_func/CMakeLists.inc
new file mode 100644
index 0000000..154417c
--- /dev/null
+++ b/secure_fw/spm/model_func/CMakeLists.inc
@@ -0,0 +1,60 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#This file assumes it will be included from a project specific cmakefile.
+#
+#Inputs:
+# TFM_ROOT_DIR - directory where secure FW sourec is located.
+#
+#Outputs:
+# Will modify include directories to make the source compile.
+# ALL_SRC_C: C source files to be compiled will be added to this list.
+# This shall be added to your add_executable or add_library command.
+# ALL_SRC_CXX: C++ source files to be compiled will be added to this list.
+# This shall be added to your add_executable or add_library command.
+# ALL_SRC_ASM: assembly source files to be compiled will be added to this
+# list. This shall be added to your add_executable or add_library
+# command.
+# Include directories will be modified by using the include_directories()
+# commands as needed.
+
+if(NOT DEFINED TFM_ROOT_DIR)
+ message(FATAL_ERROR
+ "Please set TFM_ROOT_DIR before including this file.")
+endif()
+
+#Get the current directory where this file is located.
+set(SFW_FUNC_SPM_DIR ${CMAKE_CURRENT_LIST_DIR})
+set(SFW_SPM_DIR "${SFW_FUNC_SPM_DIR}/..")
+set(SFW_SPM_ARCH_DIR "${SFW_SPM_DIR}/arch")
+set(SFW_SPM_INIT_DIR "${SFW_SPM_DIR}/init")
+
+set (SFW_FUNC_SPM_SRC
+ "${SFW_SPM_INIT_DIR}/tfm_boot_data.c"
+ "${SFW_SPM_INIT_DIR}/tfm_core.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_core_svcalls_func.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_secure_api.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_spm_services.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/spm_api.c"
+ "${SFW_FUNC_SPM_DIR}/spm_func.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_nspm_func.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_utils.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_core_mem_check.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_core_utils.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_veneers.c"
+ )
+
+#Append all our source files to global lists.
+list(APPEND ALL_SRC_C ${SFW_FUNC_SPM_SRC})
+unset(SFW_FUNC_SPM_SRC)
+
+#Setting include directories
+embedded_include_directories(PATH ${SFW_FUNC_SPM_DIR} ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm/arch/include ABSOLUTE)
diff --git a/secure_fw/spm/model_func/spm_func.c b/secure_fw/spm/model_func/spm_func.c
new file mode 100644
index 0000000..cd88329
--- /dev/null
+++ b/secure_fw/spm/model_func/spm_func.c
@@ -0,0 +1,1320 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <arm_cmse.h>
+#include "tfm_nspm.h"
+#include "secure_utilities.h"
+#include "tfm_api.h"
+#include "tfm_arch.h"
+#include "tfm_irq_list.h"
+#include "psa/service.h"
+#include "tfm_core_mem_check.h"
+#include "tfm_secure_api.h"
+#include "tfm_spm_hal.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_db.h"
+#include "region_defs.h"
+#include "region.h"
+#include "tfm/tfm_spm_services_api.h"
+
+#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
+#define EXC_RETURN_SECURE_HANDLER 0xFFFFFFF1
+
+#ifndef TFM_LVL
+#error TFM_LVL is not defined!
+#endif
+
+REGION_DECLARE_T(Image$$, TFM_SECURE_STACK, $$ZI$$Base, uint32_t);
+REGION_DECLARE_T(Image$$, TFM_SECURE_STACK, $$ZI$$Limit, struct iovec_args_t)[];
+
+/*
+ * This is the "Big Lock" on the secure side, to guarantee single entry
+ * to SPE
+ */
+extern int32_t tfm_secure_lock;
+static int32_t tfm_secure_api_initializing = 1;
+
+extern struct spm_partition_db_t g_spm_partition_db;
+
+static uint32_t *prepare_partition_iovec_ctx(
+ const struct tfm_state_context_t *svc_ctx,
+ const struct tfm_sfn_req_s *desc_ptr,
+ const struct iovec_args_t *iovec_args,
+ uint32_t *dst)
+{
+ /* XPSR = as was when called, but make sure it's thread mode */
+ *(--dst) = svc_ctx->xpsr & 0xFFFFFE00U;
+ /* ReturnAddress = resume veneer in new context */
+ *(--dst) = svc_ctx->ra;
+ /* LR = sfn address */
+ *(--dst) = (uint32_t)desc_ptr->sfn;
+ /* R12 = don't care */
+ *(--dst) = 0U;
+
+ /* R0-R3 = sfn arguments */
+ *(--dst) = iovec_args->out_len;
+ *(--dst) = (uint32_t)iovec_args->out_vec;
+ *(--dst) = iovec_args->in_len;
+ *(--dst) = (uint32_t)iovec_args->in_vec;
+
+ return dst;
+}
+
+/**
+ * \brief Create a stack frame that sets the execution environment to thread
+ * mode on exception return.
+ *
+ * \param[in] svc_ctx The stacked SVC context
+ * \param[in] unpriv_handler The unprivileged IRQ handler to be called
+ * \param[in] dst A pointer where the context is to be created. (the
+ * pointer is considered to be a stack pointer, and
+ * the frame is created below it)
+ *
+ * \return A pointer pointing at the created stack frame.
+ */
+static int32_t *prepare_partition_irq_ctx(
+ const struct tfm_state_context_t *svc_ctx,
+ sfn_t unpriv_handler,
+ int32_t *dst)
+{
+ int i;
+
+ /* XPSR = as was when called, but make sure it's thread mode */
+ *(--dst) = svc_ctx->xpsr & 0xFFFFFE00;
+ /* ReturnAddress = resume to the privileged handler code, but execute it
+ * unprivileged.
+ */
+ *(--dst) = svc_ctx->ra;
+ /* LR = start address */
+ *(--dst) = (int32_t)unpriv_handler;
+
+ /* R12, R0-R3 unused arguments */
+ for (i = 0; i < 5; ++i) {
+ *(--dst) = 0;
+ }
+
+ return dst;
+}
+
+static void restore_caller_ctx(const struct tfm_state_context_t *svc_ctx,
+ struct tfm_state_context_t *target_ctx)
+{
+ /* ReturnAddress = resume veneer after second SVC */
+ target_ctx->ra = svc_ctx->ra;
+
+ /* R0 = function return value */
+ target_ctx->r0 = svc_ctx->r0;
+
+ return;
+}
+
+/**
+ * \brief Check whether the iovec parameters are valid, and the memory ranges
+ * are in the possession of the calling partition.
+ *
+ * \param[in] desc_ptr The secure function request descriptor
+ *
+ * \return Return /ref TFM_SUCCESS if the iovec parameters are valid, error code
+ * otherwise as in /ref tfm_status_e
+ */
+static enum tfm_status_e tfm_core_check_sfn_parameters(
+ const struct tfm_sfn_req_s *desc_ptr)
+{
+ struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0];
+ size_t in_len;
+ struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2];
+ size_t out_len;
+ uint32_t i;
+
+ if ((desc_ptr->args[1] < 0) || (desc_ptr->args[3] < 0)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ in_len = (size_t)(desc_ptr->args[1]);
+ out_len = (size_t)(desc_ptr->args[3]);
+
+ /* The number of vectors are within range. Extra checks to avoid overflow */
+ if ((in_len > PSA_MAX_IOVEC) || (out_len > PSA_MAX_IOVEC) ||
+ (in_len + out_len > PSA_MAX_IOVEC)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Check whether the caller partition has at write access to the iovec
+ * structures themselves. Use the TT instruction for this.
+ */
+ if (in_len > 0) {
+ if ((in_vec == NULL) ||
+ (tfm_core_has_write_access_to_region(in_vec,
+ sizeof(psa_invec)*in_len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ if (in_vec != NULL) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+ if (out_len > 0) {
+ if ((out_vec == NULL) ||
+ (tfm_core_has_write_access_to_region(out_vec,
+ sizeof(psa_outvec)*out_len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ } else {
+ if (out_vec != NULL) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ /* Check whether the caller partition has access to the data inside the
+ * iovecs
+ */
+ for (i = 0; i < in_len; ++i) {
+ if (in_vec[i].len > 0) {
+ if ((in_vec[i].base == NULL) ||
+ (tfm_core_has_read_access_to_region(in_vec[i].base,
+ in_vec[i].len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+ for (i = 0; i < out_len; ++i) {
+ if (out_vec[i].len > 0) {
+ if ((out_vec[i].base == NULL) ||
+ (tfm_core_has_write_access_to_region(out_vec[i].base,
+ out_vec[i].len, desc_ptr->ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) {
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ return TFM_SUCCESS;
+}
+
+static void tfm_copy_iovec_parameters(struct iovec_args_t *target,
+ const struct iovec_args_t *source)
+{
+ size_t i;
+
+ /* The vectors have been sanity checked already, and since then the
+ * interrupts have been kept disabled. So we can be sure that the
+ * vectors haven't been tampered with since the check. So it is safe to pass
+ * it to the called partition.
+ */
+
+ target->in_len = source->in_len;
+ for (i = 0; i < source->in_len; ++i) {
+ target->in_vec[i].base = source->in_vec[i].base;
+ target->in_vec[i].len = source->in_vec[i].len;
+ }
+ target->out_len = source->out_len;
+ for (i = 0; i < source->out_len; ++i) {
+ target->out_vec[i].base = source->out_vec[i].base;
+ target->out_vec[i].len = source->out_vec[i].len;
+ }
+}
+
+static void tfm_clear_iovec_parameters(struct iovec_args_t *args)
+{
+ int i;
+
+ args->in_len = 0;
+ for (i = 0; i < PSA_MAX_IOVEC; ++i) {
+ args->in_vec[i].base = NULL;
+ args->in_vec[i].len = 0;
+ }
+ args->out_len = 0;
+ for (i = 0; i < PSA_MAX_IOVEC; ++i) {
+ args->out_vec[i].base = NULL;
+ args->out_vec[i].len = 0;
+ }
+}
+
+/**
+ * \brief Check whether the partitions for the secure function call are in a
+ * proper state.
+ *
+ * \param[in] curr_partition_state State of the partition to be called
+ * \param[in] caller_partition_state State of the caller partition
+ *
+ * \return \ref TFM_SUCCESS if the check passes, error otherwise.
+ */
+static enum tfm_status_e check_partition_state(uint32_t curr_partition_state,
+ uint32_t caller_partition_state)
+{
+ if (caller_partition_state != SPM_PARTITION_STATE_RUNNING) {
+ /* Calling partition from non-running state (e.g. during handling IRQ)
+ * is not allowed.
+ */
+ return TFM_ERROR_INVALID_EXC_MODE;
+ }
+
+ if (curr_partition_state == SPM_PARTITION_STATE_RUNNING ||
+ curr_partition_state == SPM_PARTITION_STATE_HANDLING_IRQ ||
+ curr_partition_state == SPM_PARTITION_STATE_SUSPENDED ||
+ curr_partition_state == SPM_PARTITION_STATE_BLOCKED) {
+ /* Active partitions cannot be called! */
+ return TFM_ERROR_PARTITION_NON_REENTRANT;
+ } else if (curr_partition_state != SPM_PARTITION_STATE_IDLE) {
+ /* The partition to be called is not in a proper state */
+ return TFM_SECURE_LOCK_FAILED;
+ }
+ return TFM_SUCCESS;
+}
+
+/**
+ * \brief Check whether the partitions for the secure function call of irq are
+ * in a proper state.
+ *
+ * \param[in] called_partition_state State of the partition to be called
+ *
+ * \return \ref TFM_SUCCESS if the check passes, error otherwise.
+ */
+static enum tfm_status_e check_irq_partition_state(
+ uint32_t called_partition_state)
+{
+ if (called_partition_state == SPM_PARTITION_STATE_IDLE ||
+ called_partition_state == SPM_PARTITION_STATE_RUNNING ||
+ called_partition_state == SPM_PARTITION_STATE_HANDLING_IRQ ||
+ called_partition_state == SPM_PARTITION_STATE_SUSPENDED ||
+ called_partition_state == SPM_PARTITION_STATE_BLOCKED) {
+ return TFM_SUCCESS;
+ }
+ return TFM_SECURE_LOCK_FAILED;
+}
+
+/**
+ * \brief Calculate the address where the iovec parameters are to be saved for
+ * the called partition.
+ *
+ * \param[in] partition_idx The index of the partition to be called.
+ *
+ * \return The address where the iovec parameters should be saved.
+ */
+static struct iovec_args_t *get_iovec_args_stack_address(uint32_t partition_idx)
+{
+ /* Save the iovecs on the common stack. */
+ return ®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
+}
+
+static enum tfm_status_e tfm_start_partition(
+ const struct tfm_sfn_req_s *desc_ptr,
+ uint32_t excReturn)
+{
+ enum tfm_status_e res;
+ uint32_t caller_partition_idx = desc_ptr->caller_part_idx;
+ const struct spm_partition_runtime_data_t *curr_part_data;
+ const struct spm_partition_runtime_data_t *caller_part_data;
+ uint32_t caller_flags;
+ register uint32_t partition_idx;
+ uint32_t psp;
+ uint32_t partition_psp, partition_psplim;
+ uint32_t partition_state;
+ uint32_t caller_partition_state;
+ struct tfm_state_context_t *svc_ctx;
+ uint32_t caller_partition_id;
+ int32_t client_id;
+ struct iovec_args_t *iovec_args;
+
+ psp = __get_PSP();
+ svc_ctx = (struct tfm_state_context_t *)psp;
+ caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
+
+ /* Check partition state consistency */
+ if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0)
+ != (!desc_ptr->ns_caller)) {
+ /* Partition state inconsistency detected */
+ return TFM_SECURE_LOCK_FAILED;
+ }
+
+ partition_idx = get_partition_idx(desc_ptr->sp_id);
+
+ curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx);
+ caller_part_data = tfm_spm_partition_get_runtime_data(caller_partition_idx);
+ partition_state = curr_part_data->partition_state;
+ caller_partition_state = caller_part_data->partition_state;
+ caller_partition_id = tfm_spm_partition_get_partition_id(
+ caller_partition_idx);
+
+ if (!tfm_secure_api_initializing) {
+ res = check_partition_state(partition_state, caller_partition_state);
+ if (res != TFM_SUCCESS) {
+ return res;
+ }
+ }
+
+ /* Prepare switch to shared secure partition stack */
+ /* In case the call is coming from the non-secure world, we save the iovecs
+ * on the stop of the stack. So the memory area, that can actually be used
+ * as stack by the partitions starts at a lower address
+ */
+ partition_psp =
+ (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
+ partition_psplim =
+ (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
+
+ /* Store the context for the partition call */
+ tfm_spm_partition_set_caller_partition_idx(partition_idx,
+ caller_partition_idx);
+ tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn);
+
+ if ((caller_flags & SPM_PART_FLAG_APP_ROT)) {
+ tfm_spm_partition_set_caller_client_id(partition_idx,
+ caller_partition_id);
+ } else {
+ client_id = tfm_nspm_get_current_client_id();
+ if (client_id >= 0) {
+ return TFM_SECURE_LOCK_FAILED;
+ }
+ tfm_spm_partition_set_caller_client_id(partition_idx, client_id);
+ }
+
+ /* In level one, only switch context and return from exception if in
+ * handler mode
+ */
+ if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) {
+ if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) !=
+ SPM_ERR_OK) {
+ return TFM_ERROR_GENERIC;
+ }
+ iovec_args = get_iovec_args_stack_address(partition_idx);
+ tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args));
+
+ /* Prepare the partition context, update stack ptr */
+ psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
+ iovec_args,
+ (uint32_t *)partition_psp);
+ __set_PSP(psp);
+ tfm_arch_set_psplim(partition_psplim);
+ }
+
+ tfm_spm_partition_set_state(caller_partition_idx,
+ SPM_PARTITION_STATE_BLOCKED);
+ tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING);
+ tfm_secure_lock++;
+
+ return TFM_SUCCESS;
+}
+
+static enum tfm_status_e tfm_start_partition_for_irq_handling(
+ uint32_t excReturn,
+ struct tfm_state_context_t *svc_ctx)
+{
+ uint32_t handler_partition_id = svc_ctx->r0;
+ sfn_t unpriv_handler = (sfn_t)svc_ctx->r1;
+ uint32_t irq_signal = svc_ctx->r2;
+ IRQn_Type irq_line = (IRQn_Type) svc_ctx->r3;
+ enum tfm_status_e res;
+ uint32_t psp = __get_PSP();
+ uint32_t handler_partition_psp;
+ uint32_t handler_partition_state;
+ uint32_t interrupted_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *handler_part_data;
+ uint32_t handler_partition_idx;
+
+ handler_partition_idx = get_partition_idx(handler_partition_id);
+ handler_part_data = tfm_spm_partition_get_runtime_data(
+ handler_partition_idx);
+ handler_partition_state = handler_part_data->partition_state;
+
+ res = check_irq_partition_state(handler_partition_state);
+ if (res != TFM_SUCCESS) {
+ return res;
+ }
+
+ /* set mask for the partition */
+ tfm_spm_partition_set_signal_mask(
+ handler_partition_idx,
+ handler_part_data->signal_mask | irq_signal);
+
+ tfm_spm_hal_disable_irq(irq_line);
+
+ /* save the current context of the interrupted partition */
+ tfm_spm_partition_push_interrupted_ctx(interrupted_partition_idx);
+
+ handler_partition_psp = psp;
+
+ /* save the current context of the handler partition */
+ tfm_spm_partition_push_handler_ctx(handler_partition_idx);
+
+ /* Store caller for the partition */
+ tfm_spm_partition_set_caller_partition_idx(handler_partition_idx,
+ interrupted_partition_idx);
+
+ psp = (uint32_t)prepare_partition_irq_ctx(svc_ctx, unpriv_handler,
+ (int32_t *)handler_partition_psp);
+ __set_PSP(psp);
+
+ tfm_spm_partition_set_state(interrupted_partition_idx,
+ SPM_PARTITION_STATE_SUSPENDED);
+ tfm_spm_partition_set_state(handler_partition_idx,
+ SPM_PARTITION_STATE_HANDLING_IRQ);
+
+ return TFM_SUCCESS;
+}
+
+static enum tfm_status_e tfm_return_from_partition(uint32_t *excReturn)
+{
+ uint32_t current_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data;
+ uint32_t return_partition_idx;
+ uint32_t return_partition_flags;
+ uint32_t psp = __get_PSP();
+ size_t i;
+ struct tfm_state_context_t *svc_ctx = (struct tfm_state_context_t *)psp;
+ struct iovec_args_t *iovec_args;
+
+ if (current_partition_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_SECURE_UNLOCK_FAILED;
+ }
+
+ curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx);
+ return_partition_idx = curr_part_data->caller_partition_idx;
+
+ if (return_partition_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_SECURE_UNLOCK_FAILED;
+ }
+
+ ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx);
+
+ return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx);
+
+ tfm_secure_lock--;
+
+ if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) ||
+ (tfm_secure_api_initializing)) {
+ /* In TFM level 1 context restore is only done when
+ * returning to NS or after initialization
+ */
+ /* Restore caller context */
+ restore_caller_ctx(svc_ctx,
+ (struct tfm_state_context_t *)ret_part_data->stack_ptr);
+ *excReturn = ret_part_data->lr;
+ __set_PSP(ret_part_data->stack_ptr);
+ REGION_DECLARE_T(Image$$, ARM_LIB_STACK, $$ZI$$Base, uint32_t)[];
+ uint32_t psp_stack_bottom =
+ (uint32_t)REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
+ tfm_arch_set_psplim(psp_stack_bottom);
+
+ iovec_args = ®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
+
+ for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) {
+ curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len;
+ }
+ tfm_clear_iovec_parameters(iovec_args);
+ }
+
+ tfm_spm_partition_cleanup_context(current_partition_idx);
+
+ tfm_spm_partition_set_state(current_partition_idx,
+ SPM_PARTITION_STATE_IDLE);
+ tfm_spm_partition_set_state(return_partition_idx,
+ SPM_PARTITION_STATE_RUNNING);
+
+ return TFM_SUCCESS;
+}
+
+static enum tfm_status_e tfm_return_from_partition_irq_handling(
+ uint32_t *excReturn)
+{
+ uint32_t handler_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *handler_part_data;
+ uint32_t interrupted_partition_idx;
+ uint32_t psp = __get_PSP();
+ struct tfm_state_context_t *svc_ctx = (struct tfm_state_context_t *)psp;
+
+ if (handler_partition_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_SECURE_UNLOCK_FAILED;
+ }
+
+ handler_part_data = tfm_spm_partition_get_runtime_data(
+ handler_partition_idx);
+ interrupted_partition_idx = handler_part_data->caller_partition_idx;
+
+ if (interrupted_partition_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_SECURE_UNLOCK_FAILED;
+ }
+
+ /* For level 1, modify PSP, so that the SVC stack frame disappears,
+ * and return to the privileged handler using the stack frame still on the
+ * MSP stack.
+ */
+ *excReturn = svc_ctx->ra;
+ psp += sizeof(struct tfm_state_context_t);
+
+ tfm_spm_partition_pop_handler_ctx(handler_partition_idx);
+ tfm_spm_partition_pop_interrupted_ctx(interrupted_partition_idx);
+
+ __set_PSP(psp);
+
+ return TFM_SUCCESS;
+}
+
+static enum tfm_status_e tfm_check_sfn_req_integrity(
+ const struct tfm_sfn_req_s *desc_ptr)
+{
+ if ((desc_ptr == NULL) ||
+ (desc_ptr->sp_id == 0) ||
+ (desc_ptr->sfn == NULL)) {
+ /* invalid parameter */
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+ return TFM_SUCCESS;
+}
+
+static enum tfm_status_e tfm_core_check_sfn_req_rules(
+ const struct tfm_sfn_req_s *desc_ptr)
+{
+ /* Check partition idx validity */
+ if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) {
+ return TFM_ERROR_NO_ACTIVE_PARTITION;
+ }
+
+ if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) {
+ /* Secure domain is already locked!
+ * This should only happen if caller is secure partition!
+ */
+ /* This scenario is a potential security breach.
+ * Error is handled in caller.
+ */
+ return TFM_ERROR_SECURE_DOMAIN_LOCKED;
+ }
+
+ if (tfm_secure_api_initializing) {
+ int32_t id =
+ tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx);
+
+ if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) {
+ /* Invalid request during system initialization */
+ ERROR_MSG("Invalid service request during initialization!");
+ return TFM_ERROR_NOT_INITIALIZED;
+ }
+ }
+
+ return TFM_SUCCESS;
+}
+
+void tfm_spm_secure_api_init_done(void)
+{
+ tfm_secure_api_initializing = 0;
+}
+
+enum tfm_status_e tfm_spm_sfn_request_handler(
+ struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn)
+{
+ enum tfm_status_e res;
+
+ res = tfm_check_sfn_req_integrity(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ ERROR_MSG("Invalid service request!");
+ tfm_secure_api_error_handler();
+ }
+
+ __disable_irq();
+
+ desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx();
+
+ res = tfm_core_check_sfn_parameters(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ /* The sanity check of iovecs failed. */
+ __enable_irq();
+ tfm_secure_api_error_handler();
+ }
+
+ res = tfm_core_check_sfn_req_rules(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ /* FixMe: error compartmentalization TBD */
+ tfm_spm_partition_set_state(
+ desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED);
+ __enable_irq();
+ ERROR_MSG("Unauthorized service request!");
+ tfm_secure_api_error_handler();
+ }
+
+ res = tfm_start_partition(desc_ptr, excReturn);
+ if (res != TFM_SUCCESS) {
+ /* FixMe: consider possible fault scenarios */
+ __enable_irq();
+ ERROR_MSG("Failed to process service request!");
+ tfm_secure_api_error_handler();
+ }
+
+ __enable_irq();
+
+ return res;
+}
+
+int32_t tfm_spm_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr)
+{
+ enum tfm_status_e res;
+ int32_t *args;
+ int32_t retVal;
+
+ res = tfm_core_check_sfn_parameters(desc_ptr);
+ if (res != TFM_SUCCESS) {
+ /* The sanity check of iovecs failed. */
+ return (int32_t)res;
+ }
+
+ /* No excReturn value is needed as no exception handling is used */
+ res = tfm_spm_sfn_request_handler(desc_ptr, 0);
+
+ if (res != TFM_SUCCESS) {
+ tfm_secure_api_error_handler();
+ }
+
+ /* Secure partition to secure partition call in TFM level 1 */
+ args = desc_ptr->args;
+ retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]);
+
+ /* return handler should restore original exc_return value... */
+ res = tfm_return_from_partition(NULL);
+ if (res == TFM_SUCCESS) {
+ /* If unlock successful, pass SS return value to caller */
+ return retVal;
+ } else {
+ /* Unlock errors indicate ctx database corruption or unknown
+ * anomalies. Halt execution
+ */
+ ERROR_MSG("Secure API error during unlock!");
+ tfm_secure_api_error_handler();
+ }
+ return (int32_t)res;
+}
+
+void tfm_spm_validate_secure_caller_handler(uint32_t *svc_args)
+{
+
+ enum tfm_status_e res = TFM_ERROR_GENERIC;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(running_partition_idx);
+ uint32_t running_partition_flags =
+ tfm_spm_partition_get_flags(running_partition_idx);
+ uint32_t caller_partition_flags =
+ tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx);
+
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) ||
+ curr_part_data->partition_state == SPM_PARTITION_STATE_HANDLING_IRQ ||
+ curr_part_data->partition_state == SPM_PARTITION_STATE_SUSPENDED) {
+ /* This handler shouldn't be called from outside partition context.
+ * Also if the current partition is handling IRQ, the caller partition
+ * index might not be valid;
+ * Partitions are only allowed to run while S domain is locked.
+ */
+ svc_args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Store return value in r0 */
+ if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) {
+ res = TFM_SUCCESS;
+ }
+ svc_args[0] = (uint32_t)res;
+}
+
+int32_t tfm_spm_check_buffer_access(uint32_t partition_idx,
+ void *start_addr,
+ size_t len,
+ uint32_t alignment)
+{
+ uintptr_t start_addr_value = (uintptr_t)start_addr;
+ uintptr_t end_addr_value = (uintptr_t)start_addr + len;
+ uintptr_t alignment_mask;
+
+ alignment_mask = (((uintptr_t)1) << alignment) - 1;
+
+ /* Check that the pointer is aligned properly */
+ if (start_addr_value & alignment_mask) {
+ /* not aligned, return error */
+ return 0;
+ }
+
+ /* Protect against overflow (and zero len) */
+ if (end_addr_value <= start_addr_value) {
+ return 0;
+ }
+
+ /* For privileged partition execution, all secure data memory and stack
+ * is accessible
+ */
+ if (start_addr_value >= S_DATA_START &&
+ end_addr_value <= (S_DATA_START + S_DATA_SIZE)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+void tfm_spm_get_caller_client_id_handler(uint32_t *svc_args)
+{
+ uintptr_t result_ptr_value = svc_args[0];
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ const uint32_t running_partition_flags =
+ tfm_spm_partition_get_flags(running_partition_idx);
+ const struct spm_partition_runtime_data_t *curr_part_data =
+ tfm_spm_partition_get_runtime_data(running_partition_idx);
+ int res = 0;
+
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) ||
+ curr_part_data->partition_state == SPM_PARTITION_STATE_HANDLING_IRQ ||
+ curr_part_data->partition_state == SPM_PARTITION_STATE_SUSPENDED) {
+ /* This handler shouldn't be called from outside partition context.
+ * Also if the current partition is handling IRQ, the caller partition
+ * index might not be valid;
+ * Partitions are only allowed to run while S domain is locked.
+ */
+ svc_args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Make sure that the output pointer points to a memory area that is owned
+ * by the partition
+ */
+ res = tfm_spm_check_buffer_access(running_partition_idx,
+ (void *)result_ptr_value,
+ sizeof(curr_part_data->caller_client_id),
+ 2);
+ if (!res) {
+ /* Not in accessible range, return error */
+ svc_args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ *((int32_t *)result_ptr_value) = curr_part_data->caller_client_id;
+
+ /* Store return value in r0 */
+ svc_args[0] = (uint32_t)TFM_SUCCESS;
+}
+
+/* This SVC handler is called if veneer is running in thread mode */
+uint32_t tfm_spm_partition_request_svc_handler(
+ const uint32_t *svc_ctx, uint32_t excReturn)
+{
+ struct tfm_sfn_req_s *desc_ptr;
+
+ if (!(excReturn & EXC_RETURN_STACK_PROCESS)) {
+ /* Service request SVC called with MSP active.
+ * Either invalid configuration for Thread mode or SVC called
+ * from Handler mode, which is not supported.
+ * FixMe: error severity TBD
+ */
+ ERROR_MSG("Service request SVC called with MSP active!");
+ tfm_secure_api_error_handler();
+ }
+
+ desc_ptr = (struct tfm_sfn_req_s *)svc_ctx[0];
+
+ if (tfm_spm_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
+ tfm_secure_api_error_handler();
+ }
+
+ return EXC_RETURN_SECURE_FUNCTION;
+}
+
+/* This SVC handler is called, if a thread mode execution environment is to
+ * be set up, to run an unprivileged IRQ handler
+ */
+uint32_t tfm_spm_depriv_req_handler(uint32_t *svc_args, uint32_t excReturn)
+{
+ struct tfm_state_context_t *svc_ctx =
+ (struct tfm_state_context_t *)svc_args;
+
+ enum tfm_status_e res;
+
+ if (excReturn & EXC_RETURN_STACK_PROCESS) {
+ /* FixMe: error severity TBD */
+ ERROR_MSG("Partition request SVC called with PSP active!");
+ tfm_secure_api_error_handler();
+ }
+
+ res = tfm_start_partition_for_irq_handling(excReturn, svc_ctx);
+ if (res != TFM_SUCCESS) {
+ /* The partition is in an invalid state (UNINIT or CLOSED), so none of
+ * its code can be run
+ */
+ /* FixMe: For now this case is handled with TF-M panic, however it would
+ * be possible to skip the execution of the interrupt handler, and
+ * resume the execution of the interrupted code.
+ */
+ tfm_secure_api_error_handler();
+ }
+ return EXC_RETURN_SECURE_FUNCTION;
+}
+
+/* This SVC handler is called when sfn returns */
+uint32_t tfm_spm_partition_return_handler(uint32_t lr)
+{
+ enum tfm_status_e res;
+
+ if (!(lr & EXC_RETURN_STACK_PROCESS)) {
+ /* Partition return SVC called with MSP active.
+ * This should not happen!
+ */
+ ERROR_MSG("Partition return SVC called with MSP active!");
+ tfm_secure_api_error_handler();
+ }
+
+ res = tfm_return_from_partition(&lr);
+ if (res != TFM_SUCCESS) {
+ /* Unlock errors indicate ctx database corruption or unknown anomalies
+ * Halt execution
+ */
+ ERROR_MSG("Secure API error during unlock!");
+ tfm_secure_api_error_handler();
+ }
+
+ return lr;
+}
+
+/* This SVC handler is called if a deprivileged IRQ handler was executed, and
+ * the execution environment is to be set back for the privileged handler mode
+ */
+uint32_t tfm_spm_depriv_return_handler(uint32_t *irq_svc_args, uint32_t lr)
+{
+ enum tfm_status_e res;
+ struct tfm_state_context_t *irq_svc_ctx =
+ (struct tfm_state_context_t *)irq_svc_args;
+
+ if (!(lr & EXC_RETURN_STACK_PROCESS)) {
+ /* Partition request SVC called with MSP active.
+ * FixMe: error severity TBD
+ */
+ ERROR_MSG("Partition request SVC called with MSP active!");
+ tfm_secure_api_error_handler();
+ }
+
+ res = tfm_return_from_partition_irq_handling(&lr);
+ if (res != TFM_SUCCESS) {
+ /* Unlock errors indicate ctx database corruption or unknown anomalies
+ * Halt execution
+ */
+ ERROR_MSG("Secure API error during unlock!");
+ tfm_secure_api_error_handler();
+ }
+
+ irq_svc_ctx->ra = lr;
+
+ return EXC_RETURN_SECURE_HANDLER;
+}
+
+/* FIXME: get_irq_line_for_signal is also implemented in the ipc folder. */
+/**
+ * \brief Return the IRQ line number associated with a signal
+ *
+ * \param[in] partition_id The ID of the partition in which we look for the
+ * signal
+ * \param[in] signal The signal we do the query for
+ *
+ * \retval >=0 The IRQ line number associated with a signal in the partition
+ * \retval <0 error
+ */
+static IRQn_Type get_irq_line_for_signal(int32_t partition_id,
+ psa_signal_t signal)
+{
+ size_t i;
+
+ for (i = 0; i < tfm_core_irq_signals_count; ++i) {
+ if (tfm_core_irq_signals[i].partition_id == partition_id &&
+ tfm_core_irq_signals[i].signal_value == signal) {
+ return tfm_core_irq_signals[i].irq_line;
+ }
+ }
+ return (IRQn_Type) -1;
+}
+
+void tfm_spm_enable_irq_handler(uint32_t *svc_args)
+{
+ struct tfm_state_context_t *svc_ctx =
+ (struct tfm_state_context_t *)svc_args;
+ psa_signal_t irq_signal = svc_ctx->r0;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ uint32_t running_partition_id =
+ tfm_spm_partition_get_partition_id(running_partition_idx);
+ IRQn_Type irq_line;
+
+ /* Only a single signal is allowed */
+ if (!tfm_is_one_bit_set(irq_signal)) {
+ /* FixMe: error severity TBD */
+ tfm_secure_api_error_handler();
+ }
+
+ irq_line = get_irq_line_for_signal(running_partition_id, irq_signal);
+
+ if (irq_line < 0) {
+ /* FixMe: error severity TBD */
+ tfm_secure_api_error_handler();
+ }
+
+ tfm_spm_hal_enable_irq(irq_line);
+}
+
+void tfm_spm_disable_irq_handler(uint32_t *svc_args)
+{
+ struct tfm_state_context_t *svc_ctx =
+ (struct tfm_state_context_t *)svc_args;
+ psa_signal_t irq_signal = svc_ctx->r0;
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ uint32_t running_partition_id =
+ tfm_spm_partition_get_partition_id(running_partition_idx);
+ IRQn_Type irq_line;
+
+ /* Only a single signal is allowed */
+ if (!tfm_is_one_bit_set(irq_signal)) {
+ /* FixMe: error severity TBD */
+ tfm_secure_api_error_handler();
+ }
+
+ irq_line = get_irq_line_for_signal(running_partition_id, irq_signal);
+
+ if (irq_line < 0) {
+ /* FixMe: error severity TBD */
+ tfm_secure_api_error_handler();
+ }
+
+ tfm_spm_hal_disable_irq(irq_line);
+}
+
+void tfm_spm_psa_wait(uint32_t *svc_args)
+{
+ /* Look for partition that is ready for run */
+ struct tfm_state_context_t *svc_ctx =
+ (struct tfm_state_context_t *)svc_args;
+ uint32_t running_partition_idx;
+ const struct spm_partition_runtime_data_t *curr_part_data;
+
+ psa_signal_t signal_mask = svc_ctx->r0;
+ uint32_t timeout = svc_ctx->r1;
+
+ /*
+ * Timeout[30:0] are reserved for future use.
+ * SPM must ignore the value of RES.
+ */
+ timeout &= PSA_TIMEOUT_MASK;
+
+ running_partition_idx = tfm_spm_partition_get_running_partition_idx();
+ curr_part_data = tfm_spm_partition_get_runtime_data(running_partition_idx);
+
+ if (timeout == PSA_BLOCK) {
+ /* FIXME: Scheduling is not available in library model, and busy wait is
+ * also not possible as this code is running in SVC context, and it
+ * cannot be pre-empted by interrupts. So do nothing here for now
+ */
+ (void) signal_mask;
+ }
+
+ svc_ctx->r0 = curr_part_data->signal_mask;
+}
+
+void tfm_spm_psa_eoi(uint32_t *svc_args)
+{
+ struct tfm_state_context_t *svc_ctx =
+ (struct tfm_state_context_t *)svc_args;
+ psa_signal_t irq_signal = svc_ctx->r0;
+ uint32_t signal_mask;
+ uint32_t running_partition_idx;
+ uint32_t running_partition_id;
+ const struct spm_partition_runtime_data_t *curr_part_data;
+ IRQn_Type irq_line;
+
+ running_partition_idx = tfm_spm_partition_get_running_partition_idx();
+ running_partition_id =
+ tfm_spm_partition_get_partition_id(running_partition_idx);
+ curr_part_data = tfm_spm_partition_get_runtime_data(running_partition_idx);
+
+ /* Only a single signal is allowed */
+ if (!tfm_is_one_bit_set(irq_signal)) {
+ tfm_secure_api_error_handler();
+ }
+
+ irq_line = get_irq_line_for_signal(running_partition_id, irq_signal);
+
+ if (irq_line < 0) {
+ /* FixMe: error severity TBD */
+ tfm_secure_api_error_handler();
+ }
+
+ tfm_spm_hal_clear_pending_irq(irq_line);
+ tfm_spm_hal_enable_irq(irq_line);
+
+ signal_mask = curr_part_data->signal_mask & ~irq_signal;
+ tfm_spm_partition_set_signal_mask(running_partition_idx, signal_mask);
+}
+
+/*
+ * This function is called when a secure partition causes an error.
+ * In case of an error in the error handling, a non-zero value have to be
+ * returned.
+ */
+static void tfm_spm_partition_err_handler(
+ const struct spm_partition_desc_t *partition,
+ int32_t err_code)
+{
+ (void)err_code;
+
+ tfm_spm_partition_set_state(partition->static_data->partition_id,
+ SPM_PARTITION_STATE_CLOSED);
+}
+
+enum spm_err_t tfm_spm_partition_init(void)
+{
+ struct spm_partition_desc_t *part;
+ struct tfm_sfn_req_s desc;
+ int32_t args[4] = {0};
+ int32_t fail_cnt = 0;
+ uint32_t idx;
+ const struct tfm_spm_partition_platform_data_t **platform_data_p;
+
+ /* Call the init function for each partition */
+ for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) {
+ part = &g_spm_partition_db.partitions[idx];
+ platform_data_p = part->platform_data_list;
+ if (platform_data_p != NULL) {
+ while ((*platform_data_p) != NULL) {
+ if (tfm_spm_hal_configure_default_isolation(idx,
+ *platform_data_p) != TFM_PLAT_ERR_SUCCESS) {
+ fail_cnt++;
+ }
+ ++platform_data_p;
+ }
+ }
+ if (part->static_data->partition_init == NULL) {
+ tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
+ tfm_spm_partition_set_caller_partition_idx(idx,
+ SPM_INVALID_PARTITION_IDX);
+ } else {
+ int32_t res;
+
+ desc.args = args;
+ desc.ns_caller = false;
+ desc.sfn = (sfn_t)part->static_data->partition_init;
+ desc.sp_id = part->static_data->partition_id;
+ res = tfm_core_sfn_request(&desc);
+ if (res == TFM_SUCCESS) {
+ tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
+ } else {
+ tfm_spm_partition_err_handler(part, res);
+ fail_cnt++;
+ }
+ }
+ }
+
+ tfm_spm_secure_api_init_done();
+
+ if (fail_cnt == 0) {
+ return SPM_ERR_OK;
+ } else {
+ return SPM_ERR_PARTITION_NOT_AVAILABLE;
+ }
+}
+
+void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx)
+{
+ struct spm_partition_runtime_data_t *runtime_data =
+ &g_spm_partition_db.partitions[partition_idx].runtime_data;
+ struct interrupted_ctx_stack_frame_t *stack_frame =
+ (struct interrupted_ctx_stack_frame_t *)runtime_data->ctx_stack_ptr;
+
+ stack_frame->partition_state = runtime_data->partition_state;
+
+ runtime_data->ctx_stack_ptr +=
+ sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t);
+}
+
+void tfm_spm_partition_pop_interrupted_ctx(uint32_t partition_idx)
+{
+ struct spm_partition_runtime_data_t *runtime_data =
+ &g_spm_partition_db.partitions[partition_idx].runtime_data;
+ struct interrupted_ctx_stack_frame_t *stack_frame;
+
+ runtime_data->ctx_stack_ptr -=
+ sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t);
+
+ stack_frame = (struct interrupted_ctx_stack_frame_t *)
+ runtime_data->ctx_stack_ptr;
+ tfm_spm_partition_set_state(partition_idx, stack_frame->partition_state);
+ stack_frame->partition_state = 0;
+}
+
+void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx)
+{
+ struct spm_partition_runtime_data_t *runtime_data =
+ &g_spm_partition_db.partitions[partition_idx].runtime_data;
+ struct handler_ctx_stack_frame_t *stack_frame =
+ (struct handler_ctx_stack_frame_t *)
+ runtime_data->ctx_stack_ptr;
+
+ stack_frame->partition_state = runtime_data->partition_state;
+ stack_frame->caller_partition_idx = runtime_data->caller_partition_idx;
+
+ runtime_data->ctx_stack_ptr +=
+ sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);
+}
+
+void tfm_spm_partition_pop_handler_ctx(uint32_t partition_idx)
+{
+ struct spm_partition_runtime_data_t *runtime_data =
+ &g_spm_partition_db.partitions[partition_idx].runtime_data;
+ struct handler_ctx_stack_frame_t *stack_frame;
+
+ runtime_data->ctx_stack_ptr -=
+ sizeof(struct handler_ctx_stack_frame_t) / sizeof(uint32_t);
+
+ stack_frame = (struct handler_ctx_stack_frame_t *)
+ runtime_data->ctx_stack_ptr;
+
+ tfm_spm_partition_set_state(partition_idx, stack_frame->partition_state);
+ stack_frame->partition_state = 0;
+ tfm_spm_partition_set_caller_partition_idx(
+ partition_idx, stack_frame->caller_partition_idx);
+ stack_frame->caller_partition_idx = 0;
+}
+
+void tfm_spm_partition_store_context(uint32_t partition_idx,
+ uint32_t stack_ptr, uint32_t lr)
+{
+ g_spm_partition_db.partitions[partition_idx].
+ runtime_data.stack_ptr = stack_ptr;
+ g_spm_partition_db.partitions[partition_idx].
+ runtime_data.lr = lr;
+}
+
+const struct spm_partition_runtime_data_t *
+ tfm_spm_partition_get_runtime_data(uint32_t partition_idx)
+{
+ return &(g_spm_partition_db.partitions[partition_idx].runtime_data);
+}
+
+void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state)
+{
+ g_spm_partition_db.partitions[partition_idx].runtime_data.partition_state =
+ state;
+ if (state == SPM_PARTITION_STATE_RUNNING ||
+ state == SPM_PARTITION_STATE_HANDLING_IRQ) {
+ g_spm_partition_db.running_partition_idx = partition_idx;
+ }
+}
+
+void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
+ uint32_t caller_partition_idx)
+{
+ g_spm_partition_db.partitions[partition_idx].runtime_data.
+ caller_partition_idx = caller_partition_idx;
+}
+
+void tfm_spm_partition_set_signal_mask(uint32_t partition_idx,
+ uint32_t signal_mask)
+{
+ g_spm_partition_db.partitions[partition_idx].runtime_data.
+ signal_mask = signal_mask;
+}
+
+void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
+ int32_t caller_client_id)
+{
+ g_spm_partition_db.partitions[partition_idx].runtime_data.
+ caller_client_id = caller_client_id;
+}
+
+enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
+ const int32_t *args)
+{
+ struct spm_partition_runtime_data_t *runtime_data =
+ &g_spm_partition_db.partitions[partition_idx].runtime_data;
+ size_t i;
+
+ if ((args[1] < 0) || (args[3] < 0)) {
+ return SPM_ERR_INVALID_PARAMETER;
+ }
+
+ runtime_data->iovec_args.in_len = (size_t)args[1];
+ for (i = 0U; i < runtime_data->iovec_args.in_len; ++i) {
+ runtime_data->iovec_args.in_vec[i].base =
+ ((psa_invec *)args[0])[i].base;
+ runtime_data->iovec_args.in_vec[i].len = ((psa_invec *)args[0])[i].len;
+ }
+ runtime_data->iovec_args.out_len = (size_t)args[3];
+ for (i = 0U; i < runtime_data->iovec_args.out_len; ++i) {
+ runtime_data->iovec_args.out_vec[i].base =
+ ((psa_outvec *)args[2])[i].base;
+ runtime_data->iovec_args.out_vec[i].len =
+ ((psa_outvec *)args[2])[i].len;
+ }
+ runtime_data->orig_outvec = (psa_outvec *)args[2];
+
+ return SPM_ERR_OK;
+}
+
+uint32_t tfm_spm_partition_get_running_partition_idx(void)
+{
+ return g_spm_partition_db.running_partition_idx;
+}
+
+void tfm_spm_partition_cleanup_context(uint32_t partition_idx)
+{
+ struct spm_partition_desc_t *partition =
+ &(g_spm_partition_db.partitions[partition_idx]);
+ int32_t i;
+
+ partition->runtime_data.caller_partition_idx = SPM_INVALID_PARTITION_IDX;
+ partition->runtime_data.iovec_args.in_len = 0;
+ for (i = 0; i < PSA_MAX_IOVEC; ++i) {
+ partition->runtime_data.iovec_args.in_vec[i].base = 0;
+ partition->runtime_data.iovec_args.in_vec[i].len = 0;
+ }
+ partition->runtime_data.iovec_args.out_len = 0;
+ for (i = 0; i < PSA_MAX_IOVEC; ++i) {
+ partition->runtime_data.iovec_args.out_vec[i].base = 0;
+ partition->runtime_data.iovec_args.out_vec[i].len = 0;
+ }
+ partition->runtime_data.orig_outvec = 0;
+}
+
+void tfm_spm_request_handler(const struct tfm_state_context_t *svc_ctx)
+{
+ uint32_t *res_ptr = (uint32_t *)&svc_ctx->r0;
+ uint32_t running_partition_flags = 0;
+ uint32_t running_partition_idx;
+
+ /* Check permissions on request type basis */
+
+ switch (svc_ctx->r0) {
+ case TFM_SPM_REQUEST_RESET_VOTE:
+ running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ running_partition_flags = tfm_spm_partition_get_flags(
+ running_partition_idx);
+
+ /* Currently only PSA Root of Trust services are allowed to make Reset
+ * vote request
+ */
+ if ((running_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
+ *res_ptr = (uint32_t)TFM_ERROR_GENERIC;
+ }
+
+ /* FixMe: this is a placeholder for checks to be performed before
+ * allowing execution of reset
+ */
+ *res_ptr = (uint32_t)TFM_SUCCESS;
+
+ break;
+ default:
+ *res_ptr = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ }
+}
diff --git a/secure_fw/spm/model_func/tfm_core_svcalls_func.c b/secure_fw/spm/model_func/tfm_core_svcalls_func.c
new file mode 100644
index 0000000..9af7104
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_core_svcalls_func.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+
+#include "secure_utilities.h"
+#include "tfm/tfm_core_svc.h"
+#include "tfm_secure_api.h"
+#include "region_defs.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_partition_defs.h"
+#include "tfm_api.h"
+#include "tfm_internal.h"
+#include "tfm_memory_utils.h"
+#include "tfm_arch.h"
+#include "tfm_peripherals_def.h"
+#include "tfm_irq_list.h"
+
+#ifdef PLATFORM_SVC_HANDLERS
+extern int32_t platform_svc_handlers(tfm_svc_number_t svc_num,
+ uint32_t *svc_args, uint32_t lr);
+#endif
+
+/* Include the definitions of the privileged IRQ handlers in case of library
+ * model
+ */
+#include "tfm_secure_irq_handlers.inc"
+
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t lr, uint32_t *msp)
+{
+ uint8_t svc_number = 0;
+ /*
+ * Stack contains:
+ * r0, r1, r2, r3, r12, r14 (lr), the return address and xPSR
+ * First argument (r0) is svc_args[0]
+ */
+ if (is_return_secure_stack(lr)) {
+ /* SV called directly from secure context. Check instruction for
+ * svc_number
+ */
+ svc_number = ((uint8_t *)svc_args[6])[-2];
+ } else {
+ /* Secure SV executing with NS return.
+ * NS cannot directly trigger S SVC so this should not happen. This is
+ * an unrecoverable error.
+ */
+ tfm_core_panic();
+ }
+ switch (svc_number) {
+ case TFM_SVC_SFN_REQUEST:
+ lr = tfm_spm_partition_request_svc_handler(svc_args, lr);
+ break;
+ case TFM_SVC_SFN_RETURN:
+ lr = tfm_spm_partition_return_handler(lr);
+ break;
+ case TFM_SVC_VALIDATE_SECURE_CALLER:
+ tfm_spm_validate_secure_caller_handler(svc_args);
+ break;
+ case TFM_SVC_GET_CALLER_CLIENT_ID:
+ tfm_spm_get_caller_client_id_handler(svc_args);
+ break;
+ case TFM_SVC_SPM_REQUEST:
+ tfm_spm_request_handler((struct tfm_state_context_t *)svc_args);
+ break;
+ case TFM_SVC_DEPRIV_REQ:
+ lr = tfm_spm_depriv_req_handler(svc_args, lr);
+ break;
+ case TFM_SVC_DEPRIV_RET:
+ lr = tfm_spm_depriv_return_handler(msp, lr);
+ break;
+ case TFM_SVC_PSA_WAIT:
+ tfm_spm_psa_wait(svc_args);
+ break;
+ case TFM_SVC_PSA_EOI:
+ tfm_spm_psa_eoi(svc_args);
+ break;
+ case TFM_SVC_ENABLE_IRQ:
+ tfm_spm_enable_irq_handler(svc_args);
+ break;
+ case TFM_SVC_DISABLE_IRQ:
+ tfm_spm_disable_irq_handler(svc_args);
+ break;
+ case TFM_SVC_GET_BOOT_DATA:
+ tfm_core_get_boot_data_handler(svc_args);
+ break;
+ default:
+#ifdef PLATFORM_SVC_HANDLERS
+ svc_args[0] = platform_svc_handlers(svc_num, svc_args, lr);
+#endif
+ break;
+ }
+
+ return lr;
+}
+
+void tfm_access_violation_handler(void)
+{
+ while (1) {
+ ;
+ }
+}
diff --git a/secure_fw/spm/model_func/tfm_nspm_func.c b/secure_fw/spm/model_func/tfm_nspm_func.c
new file mode 100644
index 0000000..83bcce6
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_nspm_func.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "cmsis_compiler.h"
+#include "platform/include/tfm_spm_hal.h"
+#include "tfm_arch.h"
+#include "tfm_api.h"
+#include "tfm_internal.h"
+#include "tfm_nspm.h"
+
+#ifndef TFM_MAX_NS_THREAD_COUNT
+#define TFM_MAX_NS_THREAD_COUNT 8
+#endif
+#define INVALID_CLIENT_ID 0
+
+#define DEFAULT_NS_CLIENT_ID ((int32_t)-1)
+
+#define INVALID_NS_CLIENT_IDX (-1)
+#define DEFAULT_NS_CLIENT_IDX 0
+
+typedef uint32_t TZ_ModuleId_t;
+typedef uint32_t TZ_MemoryId_t;
+
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+static struct ns_client_list_t {
+ int32_t ns_client_id;
+ int32_t next_free_index;
+} NsClientIdList[TFM_MAX_NS_THREAD_COUNT];
+
+static int32_t free_index = 0U;
+static int32_t active_ns_client_idx = INVALID_NS_CLIENT_IDX;
+
+static int get_next_ns_client_id()
+{
+ static int32_t next_ns_client_id = DEFAULT_NS_CLIENT_ID;
+
+ if (next_ns_client_id > 0) {
+ next_ns_client_id = DEFAULT_NS_CLIENT_ID;
+ }
+ return next_ns_client_id--;
+}
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+
+void tfm_nspm_configure_clients(void)
+{
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ int32_t i;
+
+ /* Default to one NS client */
+ free_index = 1;
+ NsClientIdList[0].ns_client_id = get_next_ns_client_id();
+ for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
+ NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
+ }
+ active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+}
+
+int32_t tfm_nspm_get_current_client_id(void)
+{
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ if (active_ns_client_idx == INVALID_NS_CLIENT_IDX) {
+ return 0;
+ } else {
+ return NsClientIdList[active_ns_client_idx].ns_client_id;
+ }
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ return DEFAULT_NS_CLIENT_ID;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+}
+
+/*
+ * TF-M implementation of the CMSIS TZ RTOS thread context management API
+ * Currently the context management only contains the NS ID identification
+ */
+
+/// Initialize secure context memory system
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_InitContextSystem_S(void)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ int32_t i;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ /* NS RTOS supports TZ context management, override defaults */
+ for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
+ NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
+ NsClientIdList[i].next_free_index = i + 1;
+ }
+
+ /* Terminate list */
+ NsClientIdList[i - 1].next_free_index = INVALID_NS_CLIENT_IDX;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ /* Success */
+ return 1U;
+}
+
+/// Allocate context memory for calling secure software modules in TrustZone
+/// \param[in] module identifies software modules called from non-secure mode
+/// \return value != 0 id TrustZone memory slot identifier
+/// \return value 0 no memory available or internal error
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module)
+{
+ TZ_MemoryId_t tz_id = 1;
+ (void) module; /* Currently unused */
+
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ if (free_index < 0) {
+ /* No more free slots */
+ return 0U;
+ }
+
+ /* TZ_MemoryId_t must be a positive integer */
+ tz_id = (TZ_MemoryId_t)free_index + 1;
+ NsClientIdList[free_index].ns_client_id = get_next_ns_client_id();
+ free_index = NsClientIdList[free_index].next_free_index;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return tz_id;
+}
+
+/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ uint32_t index;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
+ /* Invalid TZ_MemoryId_t */
+ return 0U;
+ }
+
+ index = id - 1;
+
+ if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
+ /* Non-existent client */
+ return 0U;
+ }
+
+ if (active_ns_client_idx == index) {
+ active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
+ }
+ NsClientIdList[index].ns_client_id = INVALID_CLIENT_ID;
+ NsClientIdList[index].next_free_index = free_index;
+
+ free_index = index;
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ (void)id;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#else /* CONFIG_TFM_ENABLE_CTX_MGMT */
+ (void)id;
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return 1U; // Success
+}
+
+/// Load secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_LoadContext_S (TZ_MemoryId_t id)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ uint32_t index;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
+ /* Invalid TZ_MemoryId_t */
+ return 0U;
+ }
+
+ index = id - 1;
+
+ if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
+ /* Non-existent client */
+ return 0U;
+ }
+
+ active_ns_client_idx = index;
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ (void)id;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#else /* CONFIG_TFM_ENABLE_CTX_MGMT */
+ (void)id;
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return 1U; // Success
+}
+
+/// Store secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_StoreContext_S (TZ_MemoryId_t id)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ uint32_t index;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ /* id corresponds to context being swapped out on NS side */
+ if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
+ /* Invalid TZ_MemoryId_t */
+ return 0U;
+ }
+
+ index = id - 1;
+
+ if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
+ /* Non-existent client */
+ return 0U;
+ }
+
+ if (active_ns_client_idx != index) {
+ return 0U;
+ }
+
+ active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ (void)id;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#else /* CONFIG_TFM_ENABLE_CTX_MGMT */
+ (void)id;
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return 1U; // Success
+}
+
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+__tfm_nspm_secure_gateway_attributes__
+enum tfm_status_e tfm_register_client_id (int32_t ns_client_id)
+{
+ int current_client_id;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return TFM_ERROR_NS_THREAD_MODE_CALL;
+ }
+
+ if (ns_client_id >= 0) {
+ /* The client ID is invalid */
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ if (active_ns_client_idx < 0) {
+ /* No client is active */
+ return TFM_ERROR_GENERIC;
+ }
+
+ current_client_id = NsClientIdList[active_ns_client_idx].ns_client_id;
+ if (current_client_id >= 0 ) {
+ /* The client ID is invalid */
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ NsClientIdList[active_ns_client_idx].ns_client_id = ns_client_id;
+
+ return TFM_SUCCESS;
+}
+#endif
+
+void configure_ns_code(void)
+{
+ /* SCB_NS.VTOR points to the Non-secure vector table base address */
+ SCB_NS->VTOR = tfm_spm_hal_get_ns_VTOR();
+
+ /* Setups Main stack pointer of the non-secure code */
+ uint32_t ns_msp = tfm_spm_hal_get_ns_MSP();
+
+ __TZ_set_MSP_NS(ns_msp);
+
+ /* Get the address of non-secure code entry point to jump there */
+ uint32_t entry_ptr = tfm_spm_hal_get_ns_entry_point();
+
+ /* Clears LSB of the function address to indicate the function-call
+ * will perform the switch from secure to non-secure
+ */
+ ns_entry = (nsfptr_t) cmse_nsfptr_create(entry_ptr);
+}
diff --git a/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc
new file mode 100644
index 0000000..45418a2
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#include "secure_fw/partitions/secure_storage/psa_manifest/tfm_secure_storage.h"
+#include "secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h"
+#include "secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h"
+#include "secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h"
+#include "secure_fw/partitions/platform/psa_manifest/tfm_platform.h"
+#include "secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h"
+#include "test/test_services/tfm_core_test/psa_manifest/tfm_test_core.h"
+#include "test/test_services/tfm_core_test_2/psa_manifest/tfm_test_core_2.h"
+#include "test/test_services/tfm_secure_client_service/psa_manifest/tfm_test_client_service.h"
+#include "test/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_partition.h"
+#include "test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_partition.h"
+#include "test/test_services/tfm_irq_test_service_1/psa_manifest/tfm_irq_test_service_1.h"
+#include "test/test_services/tfm_sst_test_service/psa_manifest/tfm_sst_test_service.h"
+#include "test/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h"
+#include "test/test_services/tfm_multi_core_test/psa_manifest/tfm_multi_core_test.h"
+#include "psa_manifest/pid.h"
+
+/* Definitions of the signals of the IRQs */
+const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = {
+#ifdef TFM_ENABLE_IRQ_TEST
+ { TFM_IRQ_TEST_1, SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ, TFM_TIMER0_IRQ, 64 },
+#endif /* TFM_ENABLE_IRQ_TEST */
+ {0, 0, (IRQn_Type) 0, 0} /* add dummy element to avoid non-standard empty array */
+};
+
+const size_t tfm_core_irq_signals_count = (sizeof(tfm_core_irq_signals) /
+ sizeof(*tfm_core_irq_signals)) - 1; /* adjust for the dummy element */
+
+extern void priv_irq_handler_main(uint32_t partition_id,
+ uint32_t unpriv_handler,
+ uint32_t irq_signal,
+ uint32_t irq_line);
+
+/* Forward declarations of unpriv IRQ handlers*/
+#ifdef TFM_ENABLE_IRQ_TEST
+extern void SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr(void);
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+
+/* Definitions of privileged IRQ handlers */
+#ifdef TFM_ENABLE_IRQ_TEST
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ priv_irq_handler_main(TFM_IRQ_TEST_1,
+ (uint32_t)SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr,
+ SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ,
+ TFM_TIMER0_IRQ);
+}
+
+#endif /* TFM_ENABLE_IRQ_TEST */
+
diff --git a/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc.template b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc.template
new file mode 100644
index 0000000..9db5d64
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc.template
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+{{utilities.donotedit_warning}}
+
+{% for header in utilities.manifest_header_list %}
+#include "{{header}}"
+{% endfor %}
+#include "psa_manifest/pid.h"
+{% macro _irq_record(partition_name, signal, line, priority) -%}
+{ {{ partition_name }}, {{ signal }}, {{ line }}, {{ priority }} },
+{%- endmacro %}
+
+/* Definitions of the signals of the IRQs */
+const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = {
+{% for manifest in manifests %}
+ {% if manifest.manifest.irqs %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% for handler in manifest.manifest.irqs %}
+ {% set irq_data = namespace() %}
+ {% if handler.source %}
+ {% set irq_data.line = handler.source %}
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+ {% if handler.tfm_irq_priority %}
+ {% set irq_data.priority = handler.tfm_irq_priority %}
+ {% else %}
+ {% set irq_data.priority = "TFM_DEFAULT_SECURE_IRQ_PRIOTITY" %}
+ {% endif %}
+ {{ _irq_record(manifest.manifest.name, handler.signal, irq_data.line, irq_data.priority) }}
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+ {% endif %}
+{% endfor %}
+ {0, 0, (IRQn_Type) 0, 0} /* add dummy element to avoid non-standard empty array */
+};
+
+const size_t tfm_core_irq_signals_count = (sizeof(tfm_core_irq_signals) /
+ sizeof(*tfm_core_irq_signals)) - 1; /* adjust for the dummy element */
+
+extern void priv_irq_handler_main(uint32_t partition_id,
+ uint32_t unpriv_handler,
+ uint32_t irq_signal,
+ uint32_t irq_line);
+
+/* Forward declarations of unpriv IRQ handlers*/
+{% for manifest in manifests %}
+ {% if manifest.manifest.irqs %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% for handler in manifest.manifest.irqs %}
+extern void {{handler.signal}}_isr(void);
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
+
+/* Definitions of privileged IRQ handlers */
+{% for manifest in manifests %}
+ {% if manifest.manifest.irqs %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% for handler in manifest.manifest.irqs %}
+ {% if handler.source is number %}
+void irq_{{handler.source}}_Handler(void)
+ {% elif handler.source %}
+void {{handler.source}}_Handler(void)
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+{
+ {% if handler.source %}
+ priv_irq_handler_main({{manifest.manifest.name}},
+ (uint32_t){{handler.signal}}_isr,
+ {{handler.signal}},
+ {{handler.source}});
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+}
+
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
diff --git a/secure_fw/spm/model_func/tfm_spm_db_func.inc b/secure_fw/spm/model_func/tfm_spm_db_func.inc
new file mode 100644
index 0000000..21a76ca
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_spm_db_func.inc
@@ -0,0 +1,954 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#ifndef __TFM_SPM_DB_FUNC_INC__
+#define __TFM_SPM_DB_FUNC_INC__
+
+#include "tfm/spm_api.h"
+#include "psa_manifest/sid.h"
+
+/**************************************************************************/
+/** IRQ count per partition */
+/**************************************************************************/
+#ifdef TFM_PARTITION_SECURE_STORAGE
+#define TFM_PARTITION_TFM_SP_STORAGE_IRQ_COUNT 0
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+#define TFM_PARTITION_TFM_SP_ITS_IRQ_COUNT 0
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+#define TFM_PARTITION_TFM_SP_AUDIT_LOG_IRQ_COUNT 0
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+#define TFM_PARTITION_TFM_SP_CRYPTO_IRQ_COUNT 0
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+#define TFM_PARTITION_TFM_SP_PLATFORM_IRQ_COUNT 0
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+#define TFM_PARTITION_TFM_SP_INITIAL_ATTESTATION_IRQ_COUNT 0
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+#define TFM_PARTITION_TFM_SP_CORE_TEST_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+#define TFM_PARTITION_TFM_SP_CORE_TEST_2_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+#define TFM_PARTITION_TFM_SP_SECURE_TEST_PARTITION_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+#define TFM_PARTITION_TFM_SP_IPC_SERVICE_TEST_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+#define TFM_PARTITION_TFM_SP_IPC_CLIENT_TEST_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+#define TFM_PARTITION_TFM_IRQ_TEST_1_IRQ_COUNT 1
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+#define TFM_PARTITION_TFM_SP_SST_TEST_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+#define TFM_PARTITION_TFM_SP_SECURE_CLIENT_2_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+#define TFM_PARTITION_TFM_SP_MULTI_CORE_TEST_IRQ_COUNT 0
+#endif /* TFM_MULTI_CORE_TEST */
+
+/**************************************************************************/
+/** Declarations of partition init functions */
+/**************************************************************************/
+#ifdef TFM_PARTITION_SECURE_STORAGE
+extern void tfm_sst_req_mngr_init(void);
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+extern void tfm_its_req_mngr_init(void);
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+extern void audit_core_init(void);
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+extern void tfm_crypto_init(void);
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+extern void platform_sp_init(void);
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+extern void attest_partition_init(void);
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+extern void core_test_init(void);
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+extern void core_test_2_init(void);
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+extern void tfm_secure_client_service_init(void);
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+extern void ipc_service_test_main(void);
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+extern void ipc_client_test_main(void);
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+extern void tfm_irq_test_1_init(void);
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+extern void tfm_sst_test_init(void);
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+extern void tfm_secure_client_2_init(void);
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+extern void multi_core_test_main(void);
+#endif /* TFM_MULTI_CORE_TEST */
+
+/**************************************************************************/
+/** Context stacks for IRQ handling */
+/**************************************************************************/
+/* The max size of the context stack can be calculated as a function of the IRQ
+ * count of the secure partition:
+ *
+ * max_stack_size = intr_ctx_size + (IRQ_CNT * (intr_ctx_size + hndl_ctx_size))
+ *
+ * where:
+ * intr_ctx: Frame pushed when the partition is interrupted
+ * hndl_ctx: Frame pushed when the partition is handling an interrupt
+ */
+static uint32_t ns_interrupt_ctx_stack[
+ sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t)];
+
+static uint32_t tfm_core_interrupt_ctx_stack[
+ sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t)];
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+static uint32_t ctx_stack_TFM_SP_STORAGE[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_STORAGE_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+static uint32_t ctx_stack_TFM_SP_ITS[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_ITS_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+static uint32_t ctx_stack_TFM_SP_AUDIT_LOG[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_AUDIT_LOG_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+static uint32_t ctx_stack_TFM_SP_CRYPTO[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_CRYPTO_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+static uint32_t ctx_stack_TFM_SP_PLATFORM[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_PLATFORM_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+static uint32_t ctx_stack_TFM_SP_INITIAL_ATTESTATION[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_INITIAL_ATTESTATION_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+static uint32_t ctx_stack_TFM_SP_CORE_TEST[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_CORE_TEST_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+static uint32_t ctx_stack_TFM_SP_CORE_TEST_2[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_CORE_TEST_2_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+static uint32_t ctx_stack_TFM_SP_SECURE_TEST_PARTITION[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_SECURE_TEST_PARTITION_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+static uint32_t ctx_stack_TFM_SP_IPC_SERVICE_TEST[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_IPC_SERVICE_TEST_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+static uint32_t ctx_stack_TFM_SP_IPC_CLIENT_TEST[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_IPC_CLIENT_TEST_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+static uint32_t ctx_stack_TFM_IRQ_TEST_1[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_IRQ_TEST_1_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+static uint32_t ctx_stack_TFM_SP_SST_TEST[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_SST_TEST_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+static uint32_t ctx_stack_TFM_SP_SECURE_CLIENT_2[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_SECURE_CLIENT_2_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+static uint32_t ctx_stack_TFM_SP_MULTI_CORE_TEST[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_MULTI_CORE_TEST_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_MULTI_CORE_TEST */
+
+uint32_t *ctx_stack_list[] =
+{
+ ns_interrupt_ctx_stack,
+ tfm_core_interrupt_ctx_stack,
+#ifdef TFM_PARTITION_SECURE_STORAGE
+ ctx_stack_TFM_SP_STORAGE,
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+ ctx_stack_TFM_SP_ITS,
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+#ifdef TFM_PARTITION_AUDIT_LOG
+ ctx_stack_TFM_SP_AUDIT_LOG,
+#endif /* TFM_PARTITION_AUDIT_LOG */
+#ifdef TFM_PARTITION_CRYPTO
+ ctx_stack_TFM_SP_CRYPTO,
+#endif /* TFM_PARTITION_CRYPTO */
+#ifdef TFM_PARTITION_PLATFORM
+ ctx_stack_TFM_SP_PLATFORM,
+#endif /* TFM_PARTITION_PLATFORM */
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+ ctx_stack_TFM_SP_INITIAL_ATTESTATION,
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+#ifdef TFM_PARTITION_TEST_CORE
+ ctx_stack_TFM_SP_CORE_TEST,
+#endif /* TFM_PARTITION_TEST_CORE */
+#ifdef TFM_PARTITION_TEST_CORE
+ ctx_stack_TFM_SP_CORE_TEST_2,
+#endif /* TFM_PARTITION_TEST_CORE */
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ ctx_stack_TFM_SP_SECURE_TEST_PARTITION,
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ ctx_stack_TFM_SP_IPC_SERVICE_TEST,
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ ctx_stack_TFM_SP_IPC_CLIENT_TEST,
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+#ifdef TFM_ENABLE_IRQ_TEST
+ ctx_stack_TFM_IRQ_TEST_1,
+#endif /* TFM_ENABLE_IRQ_TEST */
+#ifdef TFM_PARTITION_TEST_SST
+ ctx_stack_TFM_SP_SST_TEST,
+#endif /* TFM_PARTITION_TEST_SST */
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ ctx_stack_TFM_SP_SECURE_CLIENT_2,
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_MULTI_CORE_TEST
+ ctx_stack_TFM_SP_MULTI_CORE_TEST,
+#endif /* TFM_MULTI_CORE_TEST */
+};
+
+/**************************************************************************/
+/** Dependencies array for Secure Partition */
+/**************************************************************************/
+#ifdef TFM_PARTITION_SECURE_STORAGE
+static int32_t dependencies_TFM_SP_STORAGE[] =
+{
+ TFM_CRYPTO_SID,
+ TFM_ITS_SET_SID,
+ TFM_ITS_GET_SID,
+ TFM_ITS_GET_INFO_SID,
+ TFM_ITS_REMOVE_SID,
+ TFM_SP_PLATFORM_NV_COUNTER_SID,
+};
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_CRYPTO
+static int32_t dependencies_TFM_SP_CRYPTO[] =
+{
+ TFM_ITS_SET_SID,
+ TFM_ITS_GET_SID,
+ TFM_ITS_GET_INFO_SID,
+ TFM_ITS_REMOVE_SID,
+};
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+static int32_t dependencies_TFM_SP_INITIAL_ATTESTATION[] =
+{
+ TFM_CRYPTO_SID,
+};
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+static int32_t dependencies_TFM_SP_CORE_TEST[] =
+{
+ SPM_CORE_TEST_2_INVERT_SID,
+ SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID,
+ SPM_CORE_TEST_2_SLAVE_SERVICE_SID,
+};
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+static int32_t dependencies_TFM_SP_SECURE_TEST_PARTITION[] =
+{
+ TFM_SECURE_CLIENT_2_SID,
+ TFM_CRYPTO_SID,
+ TFM_SST_SET_SID,
+ TFM_SST_GET_SID,
+ TFM_SST_GET_INFO_SID,
+ TFM_SST_REMOVE_SID,
+ TFM_SST_GET_SUPPORT_SID,
+ TFM_ITS_SET_SID,
+ TFM_ITS_GET_SID,
+ TFM_ITS_GET_INFO_SID,
+ TFM_ITS_REMOVE_SID,
+ TFM_ATTEST_GET_TOKEN_SID,
+ TFM_ATTEST_GET_TOKEN_SIZE_SID,
+ TFM_ATTEST_GET_PUBLIC_KEY_SID,
+ TFM_SST_TEST_PREPARE_SID,
+ TFM_SP_PLATFORM_SYSTEM_RESET_SID,
+ TFM_SP_PLATFORM_IOCTL_SID,
+};
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+static int32_t dependencies_TFM_SP_IPC_CLIENT_TEST[] =
+{
+ IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID,
+ IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID,
+ IPC_SERVICE_TEST_BASIC_SID,
+ IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID,
+};
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_SST
+static int32_t dependencies_TFM_SP_SST_TEST[] =
+{
+ TFM_CRYPTO_SID,
+ TFM_ITS_GET_SID,
+ TFM_ITS_REMOVE_SID,
+};
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+static int32_t dependencies_TFM_SP_SECURE_CLIENT_2[] =
+{
+ TFM_ITS_GET_SID,
+ TFM_CRYPTO_SID,
+};
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+/**************************************************************************/
+/** The static data of the partition list */
+/**************************************************************************/
+const struct spm_partition_static_data_t static_data_list[] =
+{
+ {
+ .partition_id = TFM_SP_NON_SECURE_ID,
+ .partition_flags = 0,
+ },
+
+ {
+ .partition_id = TFM_SP_CORE_ID,
+ .partition_flags = SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_PSA_ROT,
+ },
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+ {
+ .partition_id = TFM_SP_STORAGE,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_sst_req_mngr_init,
+ .dependencies_num = 6,
+ .p_dependencies = dependencies_TFM_SP_STORAGE,
+ },
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+ {
+ .partition_id = TFM_SP_ITS,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_its_req_mngr_init,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+ {
+ .partition_id = TFM_SP_AUDIT_LOG,
+ .partition_flags = 0
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = audit_core_init,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+ {
+ .partition_id = TFM_SP_CRYPTO,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_crypto_init,
+ .dependencies_num = 4,
+ .p_dependencies = dependencies_TFM_SP_CRYPTO,
+ },
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+ {
+ .partition_id = TFM_SP_PLATFORM,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = platform_sp_init,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+ {
+ .partition_id = TFM_SP_INITIAL_ATTESTATION,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = attest_partition_init,
+ .dependencies_num = 1,
+ .p_dependencies = dependencies_TFM_SP_INITIAL_ATTESTATION,
+ },
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+ {
+ .partition_id = TFM_SP_CORE_TEST,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = core_test_init,
+ .dependencies_num = 3,
+ .p_dependencies = dependencies_TFM_SP_CORE_TEST,
+ },
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+ {
+ .partition_id = TFM_SP_CORE_TEST_2,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = core_test_2_init,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ {
+ .partition_id = TFM_SP_SECURE_TEST_PARTITION,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_secure_client_service_init,
+ .dependencies_num = 17,
+ .p_dependencies = dependencies_TFM_SP_SECURE_TEST_PARTITION,
+ },
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ {
+ .partition_id = TFM_SP_IPC_SERVICE_TEST,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(HIGH),
+ .partition_init = ipc_service_test_main,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ {
+ .partition_id = TFM_SP_IPC_CLIENT_TEST,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = ipc_client_test_main,
+ .dependencies_num = 4,
+ .p_dependencies = dependencies_TFM_SP_IPC_CLIENT_TEST,
+ },
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+ {
+ .partition_id = TFM_IRQ_TEST_1,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_irq_test_1_init,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+ {
+ .partition_id = TFM_SP_SST_TEST,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_sst_test_init,
+ .dependencies_num = 3,
+ .p_dependencies = dependencies_TFM_SP_SST_TEST,
+ },
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ {
+ .partition_id = TFM_SP_SECURE_CLIENT_2,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_secure_client_2_init,
+ .dependencies_num = 2,
+ .p_dependencies = dependencies_TFM_SP_SECURE_CLIENT_2,
+ },
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+ {
+ .partition_id = TFM_SP_MULTI_CORE_TEST,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = multi_core_test_main,
+ .dependencies_num = 0,
+ .p_dependencies = NULL,
+ },
+#endif /* TFM_MULTI_CORE_TEST */
+
+};
+
+/**************************************************************************/
+/** The platform data of the partition list */
+/**************************************************************************/
+#ifdef TFM_PARTITION_AUDIT_LOG
+const struct tfm_spm_partition_platform_data_t *
+ platform_data_list_TFM_SP_AUDIT_LOG[] =
+{
+#ifdef AUDIT_UART_REDIRECTION
+ TFM_PERIPHERAL_UART1,
+#endif /* AUDIT_UART_REDIRECTION */
+ NULL
+};
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_TEST_CORE
+const struct tfm_spm_partition_platform_data_t *
+ platform_data_list_TFM_SP_CORE_TEST[] =
+{
+ TFM_PERIPHERAL_FPGA_IO,
+ NULL
+};
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+const struct tfm_spm_partition_platform_data_t *
+ platform_data_list_TFM_SP_SECURE_TEST_PARTITION[] =
+{
+ TFM_PERIPHERAL_STD_UART,
+ NULL
+};
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+const struct tfm_spm_partition_platform_data_t *
+ platform_data_list_TFM_IRQ_TEST_1[] =
+{
+ TFM_PERIPHERAL_TIMER0,
+ NULL
+};
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+const struct tfm_spm_partition_platform_data_t **platform_data_list_list[] =
+{
+ NULL,
+ NULL,
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+ NULL,
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+ NULL,
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+ platform_data_list_TFM_SP_AUDIT_LOG,
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+ NULL,
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+ NULL,
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+ NULL,
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+ platform_data_list_TFM_SP_CORE_TEST,
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+ NULL,
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ platform_data_list_TFM_SP_SECURE_TEST_PARTITION,
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ NULL,
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ NULL,
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+ platform_data_list_TFM_IRQ_TEST_1,
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+ NULL,
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ NULL,
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+ NULL,
+#endif /* TFM_MULTI_CORE_TEST */
+
+};
+
+/**************************************************************************/
+/** The partition list for the DB */
+/**************************************************************************/
+static struct spm_partition_desc_t partition_list [] =
+{
+ {{0}}, /* placeholder for Non-secure internal partition */
+ {{0}}, /* placeholder for TF-M Core internal partition */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_STORAGE */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_SECURE_STORAGE
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_ITS */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_AUDIT_LOG */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_AUDIT_LOG
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_CRYPTO */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_CRYPTO
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_CRYPTO */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_PLATFORM */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_PLATFORM
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_PLATFORM */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_INITIAL_ATTESTATION */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_CORE_TEST */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_CORE
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_CORE */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_CORE_TEST_2 */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_CORE
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_CORE */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_SECURE_TEST_PARTITION */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_IPC_SERVICE_TEST */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_IPC_CLIENT_TEST */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_IRQ_TEST_1 */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_ENABLE_IRQ_TEST
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_SST_TEST */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_SST
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_SST */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_SECURE_CLIENT_2 */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for TFM_SP_MULTI_CORE_TEST */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_MULTI_CORE_TEST
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_MULTI_CORE_TEST */
+
+};
+
+struct spm_partition_db_t g_spm_partition_db = {
+ .is_init = 0,
+ .partition_count = sizeof(partition_list) / sizeof(partition_list[0]),
+ .running_partition_idx = 0,
+ .partitions = partition_list,
+};
+
+#endif /* __TFM_SPM_DB_FUNC_INC__ */
diff --git a/secure_fw/spm/model_func/tfm_spm_db_func.inc.template b/secure_fw/spm/model_func/tfm_spm_db_func.inc.template
new file mode 100644
index 0000000..55bcce5
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_spm_db_func.inc.template
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+{{utilities.donotedit_warning}}
+
+#ifndef __TFM_SPM_DB_FUNC_INC__
+#define __TFM_SPM_DB_FUNC_INC__
+
+#include "tfm/spm_api.h"
+#include "psa_manifest/sid.h"
+
+{# Produce a build error if heap_size is presented in the manifest, because of the dynamic memory allocation is not supported now. #}
+{% for manifest in manifests %}
+ {% if manifest.manifest.heap_size %}
+#error "Please do not add 'heap_size' for partition '{{manifest.manifest.name}}', the dynamic memory allocation is not supported now!"
+ {% endif %}
+{% endfor %}
+/**************************************************************************/
+/** IRQ count per partition */
+/**************************************************************************/
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% if manifest.manifest.irqs %}
+#define TFM_PARTITION_{{manifest.manifest.name}}_IRQ_COUNT {{manifest.manifest.irqs | length() }}
+ {% else %}
+#define TFM_PARTITION_{{manifest.manifest.name}}_IRQ_COUNT 0
+ {% endif %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+/**************************************************************************/
+/** Declarations of partition init functions */
+/**************************************************************************/
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+extern void {{manifest.manifest.entry_point}}(void);
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+/**************************************************************************/
+/** Context stacks for IRQ handling */
+/**************************************************************************/
+/* The max size of the context stack can be calculated as a function of the IRQ
+ * count of the secure partition:
+ *
+ * max_stack_size = intr_ctx_size + (IRQ_CNT * (intr_ctx_size + hndl_ctx_size))
+ *
+ * where:
+ * intr_ctx: Frame pushed when the partition is interrupted
+ * hndl_ctx: Frame pushed when the partition is handling an interrupt
+ */
+static uint32_t ns_interrupt_ctx_stack[
+ sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t)];
+
+static uint32_t tfm_core_interrupt_ctx_stack[
+ sizeof(struct interrupted_ctx_stack_frame_t) / sizeof(uint32_t)];
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+static uint32_t ctx_stack_{{manifest.manifest.name}}[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_{{manifest.manifest.name}}_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+uint32_t *ctx_stack_list[] =
+{
+ ns_interrupt_ctx_stack,
+ tfm_core_interrupt_ctx_stack,
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ ctx_stack_{{manifest.manifest.name}},
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+{% endfor %}
+};
+
+/**************************************************************************/
+/** Dependencies array for Secure Partition */
+/**************************************************************************/
+{% for manifest in manifests %}
+ {% if manifest.manifest.dependencies %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+static int32_t dependencies_{{manifest.manifest.name}}[] =
+{
+ {% for dependence in manifest.manifest.dependencies %}
+ {% for service in manifest.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 manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
+/**************************************************************************/
+/** The static data of the partition list */
+/**************************************************************************/
+const struct spm_partition_static_data_t static_data_list[] =
+{
+ {
+ .partition_id = TFM_SP_NON_SECURE_ID,
+ .partition_flags = 0,
+ },
+
+ {
+ .partition_id = TFM_SP_CORE_ID,
+ .partition_flags = SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_PSA_ROT,
+ },
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {{'{'}}
+ .partition_id = {{manifest.manifest.name}},
+ {% if manifest.attr.tfm_partition_ipc %}
+ .partition_flags = SPM_PART_FLAG_IPC
+ {% else %}
+ .partition_flags = 0
+ {% endif %}
+ {% if manifest.manifest.type == "APPLICATION-ROT" %}
+ | SPM_PART_FLAG_APP_ROT
+ {% elif manifest.manifest.type == "PSA-ROT" %}
+ | SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT
+ {% else %}
+#error "Unsupported type '{{manifest.manifest.type}}' for partition '{{manifest.manifest.name}}'!"
+ {% endif %}
+ ,
+ .partition_priority = TFM_PRIORITY({{manifest.manifest.priority}}),
+ .partition_init = {{manifest.manifest.entry_point}},
+ .dependencies_num = {{manifest.manifest.dependencies | length()}},
+ {% if manifest.manifest.dependencies %}
+ .p_dependencies = dependencies_{{manifest.manifest.name}},
+ {% else %}
+ .p_dependencies = NULL,
+ {% endif %}
+ {{'},'}}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+};
+
+/**************************************************************************/
+/** The platform data of the partition list */
+/**************************************************************************/
+{% for manifest in manifests %}
+ {% if manifest.manifest.mmio_regions %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+const struct tfm_spm_partition_platform_data_t *
+ platform_data_list_{{manifest.manifest.name}}[] =
+{
+ {% for region in manifest.manifest.mmio_regions %}
+ {% if region.conditional %}
+#ifdef {{region.conditional}}
+ {% endif %}
+ {{region.name}},
+ {% if region.conditional %}
+#endif /* {{region.conditional}} */
+ {% endif %}
+ {% endfor %}
+ NULL
+};
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
+const struct tfm_spm_partition_platform_data_t **platform_data_list_list[] =
+{
+ NULL,
+ NULL,
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% if manifest.manifest.mmio_regions %}
+ platform_data_list_{{manifest.manifest.name}},
+ {% else %}{# if manifest.manifest.mmio_regions #}
+ NULL,
+ {% endif %}{# if manifest.manifest.mmio_regions #}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+};
+
+/**************************************************************************/
+/** The partition list for the DB */
+/**************************************************************************/
+static struct spm_partition_desc_t partition_list [] =
+{
+ {{'{{0}}'}}, /* placeholder for Non-secure internal partition */
+ {{'{{0}}'}}, /* placeholder for TF-M Core internal partition */
+
+{% for manifest in manifests %}
+ /* -----------------------------------------------------------------------*/
+ /* - Partition DB record for {{manifest.manifest.name}} */
+ /* -----------------------------------------------------------------------*/
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {{'{'}}
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ {{'},'}}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+};
+
+struct spm_partition_db_t g_spm_partition_db = {
+ .is_init = 0,
+ .partition_count = sizeof(partition_list) / sizeof(partition_list[0]),
+ .running_partition_idx = 0,
+ .partitions = partition_list,
+};
+
+#endif /* __TFM_SPM_DB_FUNC_INC__ */
diff --git a/secure_fw/spm/model_func/tfm_veneers.c b/secure_fw/spm/model_func/tfm_veneers.c
new file mode 100644
index 0000000..0da2ca9
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_veneers.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#include "tfm_secure_api.h"
+#include "tfm/spm_partition_defs.h"
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+/******** TFM_SP_STORAGE ********/
+psa_status_t tfm_sst_set_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_get_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_get_info_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_get_support_req(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+/******** TFM_SP_ITS ********/
+psa_status_t tfm_its_set_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_get_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_get_info_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+/******** TFM_SP_AUDIT_LOG ********/
+psa_status_t audit_core_retrieve_record(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_add_record(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_get_info(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_get_record_info(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_delete_record(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+/******** TFM_SP_CRYPTO ********/
+psa_status_t tfm_crypto_get_key_attributes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_open_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_close_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_reset_key_attributes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_import_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_destroy_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_export_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_export_public_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_copy_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_compute(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_compare(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_verify(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_clone(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_compute(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_sign_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_sign_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_encrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_decrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_generate_iv(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_set_iv(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_encrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_decrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_encrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_decrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_generate_nonce(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_set_nonce(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_set_lengths(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_update_ad(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_verify(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_sign_hash(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_verify_hash(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_asymmetric_encrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_asymmetric_decrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_get_capacity(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_set_capacity(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_input_bytes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_input_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_key_agreement(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_output_bytes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_output_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_raw_key_agreement(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_generate_random(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_generate_key(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+/******** TFM_SP_PLATFORM ********/
+psa_status_t platform_sp_system_reset(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_ioctl(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_nv_counter_read(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_nv_counter_increment(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+/******** TFM_SP_INITIAL_ATTESTATION ********/
+psa_status_t initial_attest_get_token(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t initial_attest_get_token_size(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t initial_attest_get_public_key(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST ********/
+psa_status_t spm_core_test_sfn(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_sfn_init_success(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_sfn_direct_recursion(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST_2 ********/
+psa_status_t spm_core_test_2_slave_service(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_sfn_invert(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_check_caller_client_id(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_get_every_second_byte(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_prepare_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_execute_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_TEST_PARTITION ********/
+psa_status_t tfm_secure_client_service_sfn_run_tests(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+/******** TFM_IRQ_TEST_1 ********/
+psa_status_t spm_irq_test_1_prepare_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_irq_test_1_execute_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+/******** TFM_SP_SST_TEST ********/
+psa_status_t tfm_sst_test_prepare(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_CLIENT_2 ********/
+psa_status_t tfm_secure_client_2_call(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+/******** TFM_SP_MULTI_CORE_TEST ********/
+#endif /* TFM_MULTI_CORE_TEST */
+
+
+#define TFM_VENEER_FUNCTION(partition_name, sfn_name) \
+ __tfm_secure_gateway_attributes__ \
+ psa_status_t tfm_##sfn_name##_veneer(psa_invec *in_vec, \
+ size_t in_len, \
+ psa_outvec *out_vec, \
+ size_t out_len) \
+ { \
+ bool is_ns = tfm_core_is_ns_client(); \
+ \
+ TFM_CORE_IOVEC_SFN_REQUEST(partition_name, \
+ is_ns, \
+ (void *) sfn_name, \
+ in_vec, in_len, out_vec, out_len); \
+ }
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+/******** TFM_SP_STORAGE ********/
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_set_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_info_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_remove_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_support_req)
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+/******** TFM_SP_ITS ********/
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_set_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_info_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_remove_req)
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+/******** TFM_SP_AUDIT_LOG ********/
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_retrieve_record)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_add_record)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_get_info)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_get_record_info)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_delete_record)
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+/******** TFM_SP_CRYPTO ********/
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_get_key_attributes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_open_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_close_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_reset_key_attributes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_import_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_destroy_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_public_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_copy_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_compute)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_compare)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_verify)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_clone)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_compute)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_sign_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_sign_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_generate_iv)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_set_iv)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_decrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_decrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_generate_nonce)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_set_nonce)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_set_lengths)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_update_ad)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_verify)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_sign_hash)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_verify_hash)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_asymmetric_encrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_asymmetric_decrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_get_capacity)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_set_capacity)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_input_bytes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_input_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_key_agreement)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_output_bytes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_output_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_raw_key_agreement)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_generate_random)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_generate_key)
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+/******** TFM_SP_PLATFORM ********/
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_system_reset)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_ioctl)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_nv_counter_read)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_nv_counter_increment)
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+/******** TFM_SP_INITIAL_ATTESTATION ********/
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_token)
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_token_size)
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_public_key)
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST ********/
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, spm_core_test_sfn)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, spm_core_test_sfn_init_success)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, spm_core_test_sfn_direct_recursion)
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST_2 ********/
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_slave_service)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_sfn_invert)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_check_caller_client_id)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_get_every_second_byte)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_prepare_test_scenario)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_execute_test_scenario)
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_TEST_PARTITION ********/
+TFM_VENEER_FUNCTION(TFM_SP_SECURE_TEST_PARTITION, tfm_secure_client_service_sfn_run_tests)
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+/******** TFM_IRQ_TEST_1 ********/
+TFM_VENEER_FUNCTION(TFM_IRQ_TEST_1, spm_irq_test_1_prepare_test_scenario)
+TFM_VENEER_FUNCTION(TFM_IRQ_TEST_1, spm_irq_test_1_execute_test_scenario)
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+/******** TFM_SP_SST_TEST ********/
+TFM_VENEER_FUNCTION(TFM_SP_SST_TEST, tfm_sst_test_prepare)
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_CLIENT_2 ********/
+TFM_VENEER_FUNCTION(TFM_SP_SECURE_CLIENT_2, tfm_secure_client_2_call)
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+/******** TFM_SP_MULTI_CORE_TEST ********/
+#endif /* TFM_MULTI_CORE_TEST */
+
diff --git a/secure_fw/spm/model_func/tfm_veneers.c.template b/secure_fw/spm/model_func/tfm_veneers.c.template
new file mode 100644
index 0000000..f6b482e
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_veneers.c.template
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+{{utilities.donotedit_warning}}
+
+#include "tfm_secure_api.h"
+#include "tfm/spm_partition_defs.h"
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+/******** {{manifest.manifest.name}} ********/
+ {% for sec_func in manifest.manifest.secure_functions %}
+psa_status_t {{sec_func.signal.lower()}}(psa_invec *, size_t, psa_outvec *, size_t);
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+
+#define TFM_VENEER_FUNCTION(partition_name, sfn_name) \
+ __tfm_secure_gateway_attributes__ \
+ psa_status_t tfm_##sfn_name##_veneer(psa_invec *in_vec, \
+ size_t in_len, \
+ psa_outvec *out_vec, \
+ size_t out_len) \
+ { \
+ bool is_ns = tfm_core_is_ns_client(); \
+ \
+ TFM_CORE_IOVEC_SFN_REQUEST(partition_name, \
+ is_ns, \
+ (void *) sfn_name, \
+ in_vec, in_len, out_vec, out_len); \
+ }
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+/******** {{manifest.manifest.name}} ********/
+ {% for sec_func in manifest.manifest.secure_functions %}
+TFM_VENEER_FUNCTION({{manifest.manifest.name}}, {{sec_func.signal.lower()}})
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}