SPM: Restructure SPM folder
- Change model_ipc to cmsis_psa, and move arch into it.
- Change model_func to cmsis_func, and move arch related operations to
arch.c file.
- Remove tfm_spm_services.c, and move related function into cmsis_psa
and cmsis_func.
- Move tfm_arch.h and tfm_arch_v8m.h into spm/include, so this header
could be shared by cmsis_psa and cmsis_func.
Change-Id: I120395a6f613cb151c144c344a9394efdfb2b67d
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/secure_fw/spm/cmsis_func/CMakeLists.inc b/secure_fw/spm/cmsis_func/CMakeLists.inc
new file mode 100644
index 0000000..b9235f0
--- /dev/null
+++ b/secure_fw/spm/cmsis_func/CMakeLists.inc
@@ -0,0 +1,59 @@
+#-------------------------------------------------------------------------------
+# 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_INIT_DIR "${SFW_SPM_DIR}/common/init")
+set(SFW_SPM_RUNTIME_DIR "${SFW_SPM_DIR}/common/runtime")
+
+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}/tfm_secure_api.c"
+ "${SFW_FUNC_SPM_DIR}/spm_func.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_nspm_func.c"
+ "${SFW_SPM_RUNTIME_DIR}/utilities.c"
+ "${SFW_SPM_RUNTIME_DIR}/tfm_core_mem_check.c"
+ "${SFW_SPM_RUNTIME_DIR}/tfm_core_utils.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_veneers.c"
+ "${SFW_FUNC_SPM_DIR}/arch.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}/bl2/include ABSOLUTE)
diff --git a/secure_fw/spm/cmsis_func/arch.c b/secure_fw/spm/cmsis_func/arch.c
new file mode 100644
index 0000000..d142e84
--- /dev/null
+++ b/secure_fw/spm/cmsis_func/arch.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_secure_api.h"
+#include "tfm_internal.h"
+#include "tfm/tfm_spm_services.h"
+
+nsfptr_t ns_entry;
+
+void jump_to_ns_code(void)
+{
+ /* Calls the non-secure Reset_Handler to jump to the non-secure binary */
+ ns_entry();
+}
+
+__attribute__((naked))
+int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id)
+{
+ __ASM volatile(
+ "SVC %0\n"
+ "BX LR\n"
+ : : "I" (TFM_SVC_GET_CALLER_CLIENT_ID));
+}
+
+__attribute__((naked))
+int32_t tfm_spm_request(void)
+{
+ __ASM volatile(
+ "SVC %0\n"
+ "BX lr\n"
+ : : "I" (TFM_SVC_SPM_REQUEST));
+}
+
+__attribute__((naked))
+int32_t tfm_spm_request_reset_vote(void)
+{
+ __ASM volatile(
+ "MOVS R0, %0\n"
+ "B tfm_spm_request\n"
+ : : "I" (TFM_SPM_REQUEST_RESET_VOTE));
+}
+
+__attribute__((naked))
+void tfm_enable_irq(psa_signal_t irq_signal)
+{
+ __ASM("SVC %0\n"
+ "BX LR\n"
+ : : "I" (TFM_SVC_ENABLE_IRQ));
+}
+
+__attribute__((naked))
+void tfm_disable_irq(psa_signal_t irq_signal)
+{
+ __ASM("SVC %0\n"
+ "BX LR\n"
+ : : "I" (TFM_SVC_DISABLE_IRQ));
+}
+
+__attribute__((naked))
+static psa_signal_t psa_wait_internal(psa_signal_t signal_mask,
+ uint32_t timeout)
+{
+ __ASM("SVC %0\n"
+ "BX LR\n"
+ : : "I" (TFM_SVC_PSA_WAIT));
+}
+
+psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
+{
+ /* FIXME: By using the 'WFI' instruction this function blocks until an
+ * interrupt happens. It is necessary to do this here as tfm_core_psa_wait
+ * runs with the priority of the SVC, so it cannot be interrupted, so
+ * waiting in it for the required interrupt to happen is not an option.
+ */
+ psa_signal_t actual_signal_mask;
+
+ while (1) {
+ actual_signal_mask = psa_wait_internal(signal_mask, timeout);
+ if ((actual_signal_mask & signal_mask) != 0) {
+ return actual_signal_mask;
+ }
+ __WFI();
+ }
+}
+
+__attribute__((naked))
+void psa_eoi(psa_signal_t irq_signal)
+{
+ __ASM("SVC %0\n"
+ "BX LR\n"
+ : : "I" (TFM_SVC_PSA_EOI));
+}
+
+#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
+__attribute__((section("SFN"), naked))
+int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr)
+{
+ __ASM volatile(
+ "PUSH {r4-r12, lr} \n"
+ "SVC %[SVC_REQ] \n"
+ "MOV r4, #0 \n"
+ "MOV r5, r4 \n"
+ "MOV r6, r4 \n"
+ "MOV r7, r4 \n"
+ "MOV r8, r4 \n"
+ "MOV r9, r4 \n"
+ "MOV r10, r4 \n"
+ "MOV r11, r4 \n"
+ "BLX lr \n"
+ "SVC %[SVC_RET] \n"
+ "POP {r4-r12, pc} \n"
+ : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST),
+ [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
+ );
+}
+
+__attribute__((section("SFN"), naked))
+void priv_irq_handler_main(uint32_t partition_id, uint32_t unpriv_handler,
+ uint32_t irq_signal, uint32_t irq_line)
+{
+ __ASM(
+ /* Save the callee saved registers*/
+ "PUSH {r4-r12, lr} \n"
+ /* Request SVC to configure environment for the unpriv IRQ handler */
+ "SVC %[SVC_REQ] \n"
+ /* clear the callee saved registers to prevent information leak */
+ "MOV r4, #0 \n"
+ "MOV r5, r4 \n"
+ "MOV r6, r4 \n"
+ "MOV r7, r4 \n"
+ "MOV r8, r4 \n"
+ "MOV r9, r4 \n"
+ "MOV r10, r4 \n"
+ "MOV r11, r4 \n"
+ /* Branch to the unprivileged handler */
+ "BLX lr \n"
+ /* Request SVC to reconfigure the environment of the interrupted
+ * partition
+ */
+ "SVC %[SVC_RET] \n"
+ /* restore callee saved registers and return */
+ "POP {r4-r12, pc} \n"
+ : : [SVC_REQ] "I" (TFM_SVC_DEPRIV_REQ)
+ , [SVC_RET] "I" (TFM_SVC_DEPRIV_RET)
+ );
+}
+#elif defined(__ARM_ARCH_8M_BASE__)
+__attribute__((section("SFN"), naked))
+int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr)
+{
+ __ASM volatile(
+ "PUSH {lr} \n"
+ "PUSH {r4-r7} \n"
+ "MOV r4, r8 \n"
+ "MOV r5, r9 \n"
+ "MOV r6, r10 \n"
+ "MOV r7, r11 \n"
+ "PUSH {r4-r7} \n"
+ "MOV r4, r12 \n"
+ "PUSH {r4} \n"
+ "SVC %[SVC_REQ] \n"
+ "MOVS r4, #0 \n"
+ "MOV r5, r4 \n"
+ "MOV r6, r4 \n"
+ "MOV r7, r4 \n"
+ "MOV r8, r4 \n"
+ "MOV r9, r4 \n"
+ "MOV r10, r4 \n"
+ "MOV r11, r4 \n"
+ "BLX lr \n"
+ "SVC %[SVC_RET] \n"
+ "POP {r4} \n"
+ "MOV r12, r4 \n"
+ "POP {r4-r7} \n"
+ "MOV r8, r4 \n"
+ "MOV r9, r5 \n"
+ "MOV r10, r6 \n"
+ "MOV r11, r7 \n"
+ "POP {r4-r7} \n"
+ "POP {pc} \n"
+ : : [SVC_REQ] "I" (TFM_SVC_SFN_REQUEST),
+ [SVC_RET] "I" (TFM_SVC_SFN_RETURN)
+ );
+}
+
+__attribute__((section("SFN"), naked))
+void priv_irq_handler_main(uint32_t partition_id, uint32_t unpriv_handler,
+ uint32_t irq_signal, uint32_t irq_line)
+{
+ __ASM(
+ /* Save the callee saved registers*/
+ "PUSH {r4-r7, lr} \n"
+ "MOV r4, r8 \n"
+ "MOV r5, r9 \n"
+ "MOV r6, r10 \n"
+ "MOV r7, r11 \n"
+ "PUSH {r4-r7} \n"
+ "MOV r4, r12 \n"
+ "PUSH {r4} \n"
+ /* Request SVC to configure environment for the unpriv IRQ handler */
+ "SVC %[SVC_REQ] \n"
+ /* clear the callee saved registers to prevent information leak */
+ "MOVS r4, #0 \n"
+ "MOV r5, r4 \n"
+ "MOV r6, r4 \n"
+ "MOV r7, r4 \n"
+ "MOV r8, r4 \n"
+ "MOV r9, r4 \n"
+ "MOV r10, r4 \n"
+ "MOV r11, r4 \n"
+ /* Branch to the unprivileged handler */
+ "BLX lr \n"
+ /* Request SVC to reconfigure the environment of the interrupted
+ * partition
+ */
+ "SVC %[SVC_RET] \n"
+ /* restore callee saved registers and return */
+ "POP {r4} \n"
+ "MOV r12, r4 \n"
+ "POP {r4-r7} \n"
+ "MOV r8, r4 \n"
+ "MOV r9, r5 \n"
+ "MOV r10, r6 \n"
+ "MOV r11, r7 \n"
+ "POP {r4-r7, pc} \n"
+ : : [SVC_REQ] "I" (TFM_SVC_DEPRIV_REQ)
+ , [SVC_RET] "I" (TFM_SVC_DEPRIV_RET)
+ );
+}
+#endif
+
+#if defined(__ARM_ARCH_8_1M_MAIN__) || \
+ defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
+void tfm_arch_prioritize_secure_exception(void)
+{
+ uint32_t VECTKEY;
+ SCB_Type *scb = SCB;
+ uint32_t AIRCR;
+
+ /* Set PRIS flag in AIRCR */
+ AIRCR = scb->AIRCR;
+ VECTKEY = (~AIRCR & SCB_AIRCR_VECTKEYSTAT_Msk);
+ scb->AIRCR = SCB_AIRCR_PRIS_Msk |
+ VECTKEY |
+ (AIRCR & ~SCB_AIRCR_VECTKEY_Msk);
+}
+#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
+ defined(__ARM_ARCH_7EM__)
+void tfm_arch_prioritize_secure_exception(void)
+{
+}
+#endif
+
+#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
+__attribute__((naked)) void SVC_Handler(void)
+{
+ __ASM volatile(
+ "MRS r2, MSP \n"
+ /* Check store SP in thread mode to r0 */
+ "TST lr, #4 \n"
+ "ITE EQ \n"
+ "MOVEQ r0, r2 \n"
+ "MRSNE r0, PSP \n"
+ "MOV r1, lr \n"
+ "BL tfm_core_svc_handler \n"
+ "BX r0 \n"
+ );
+}
+#elif defined(__ARM_ARCH_8M_BASE__)
+__attribute__((naked)) void SVC_Handler(void)
+{
+ __ASM volatile(
+ "MRS r2, MSP \n"
+ "MOVS r1, #4 \n"
+ "MOV r3, lr \n"
+ "MOV r0, r2 \n"
+ "TST r1, r3 \n"
+ "BEQ handler \n"
+ /* If SVC was made from thread mode, overwrite r0 with PSP */
+ "MRS r0, PSP \n"
+ "handler: \n"
+ "MOV r1, lr \n"
+ "BL tfm_core_svc_handler \n"
+ "BX r0 \n"
+ );
+}
+#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
+ defined(__ARM_ARCH_7EM__)
+__attribute__((naked)) void SVC_Handler(void)
+{
+ __ASM volatile(
+ "MOVS r0, #4 \n" /* Check store SP in thread mode to r0 */
+ "MOV r1, lr \n"
+ "TST r0, r1 \n"
+ "BEQ handler \n"
+ "MRS r0, PSP \n" /* Coming from thread mode */
+ "B sp_stored \n"
+ "handler: \n"
+ "BX lr \n" /* Coming from handler mode */
+ "sp_stored: \n"
+ "MOV r1, lr \n"
+ "BL tfm_core_svc_handler \n"
+ "BX r0 \n"
+ );
+}
+#endif
diff --git a/secure_fw/spm/cmsis_func/spm_func.c b/secure_fw/spm/cmsis_func/spm_func.c
new file mode 100644
index 0000000..9cfd1a8
--- /dev/null
+++ b/secure_fw/spm/cmsis_func/spm_func.c
@@ -0,0 +1,1377 @@
+/*
+ * 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 "tfm_api.h"
+#include "tfm_arch.h"
+#include "tfm_irq_list.h"
+#include "psa/service.h"
+#include "tfm_core_mem_check.h"
+#include "tfm_peripherals_def.h"
+#include "tfm_secure_api.h"
+#include "tfm_spm_hal.h"
+#include "spm_api.h"
+#include "spm_db.h"
+#include "region_defs.h"
+#include "region.h"
+#include "tfm/tfm_spm_services.h"
+#include "tfm_spm_db_func.inc"
+
+#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
+ */
+static int32_t tfm_secure_lock;
+static int32_t tfm_secure_api_initializing = 1;
+
+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];
+}
+
+/**
+ * \brief Returns the index of the partition with the given partition ID.
+ *
+ * \param[in] partition_id Partition id
+ *
+ * \return the partition idx if partition_id is valid,
+ * \ref SPM_INVALID_PARTITION_IDX othervise
+ */
+static uint32_t get_partition_idx(uint32_t partition_id)
+{
+ uint32_t i;
+
+ if (partition_id == INVALID_PARTITION_ID) {
+ return SPM_INVALID_PARTITION_IDX;
+ }
+
+ for (i = 0; i < g_spm_partition_db.partition_count; ++i) {
+ if (g_spm_partition_db.partitions[i].static_data->partition_id ==
+ partition_id) {
+ return i;
+ }
+ }
+ return SPM_INVALID_PARTITION_IDX;
+}
+
+/**
+ * \brief Get the flags associated with a partition
+ *
+ * \param[in] partition_idx Partition index
+ *
+ * \return Flags associated with the partition
+ *
+ * \note This function doesn't check if partition_idx is valid.
+ */
+static uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx)
+{
+ return g_spm_partition_db.partitions[partition_idx].static_data->
+ partition_flags;
+}
+
+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;
+}
+
+uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx)
+{
+ return g_spm_partition_db.partitions[partition_idx].static_data->
+ partition_id;
+}
+
+uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags)
+{
+ if (partition_flags & SPM_PART_FLAG_PSA_ROT) {
+ return TFM_PARTITION_PRIVILEGED_MODE;
+ } else {
+ return TFM_PARTITION_UNPRIVILEGED_MODE;
+ }
+}
+
+bool tfm_is_partition_privileged(uint32_t partition_idx)
+{
+ uint32_t flags = tfm_spm_partition_get_flags(partition_idx);
+
+ return tfm_spm_partition_get_privileged_mode(flags) ==
+ TFM_PARTITION_PRIVILEGED_MODE;
+}
+
+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;
+}
+
+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;
+ }
+}
+
+enum spm_err_t tfm_spm_db_init(void)
+{
+ uint32_t i;
+
+ /* This function initialises partition db */
+
+ /* For the non secure Execution environment */
+ tfm_nspm_configure_clients();
+
+ for (i = 0; i < g_spm_partition_db.partition_count; i++) {
+ g_spm_partition_db.partitions[i].runtime_data.partition_state =
+ SPM_PARTITION_STATE_UNINIT;
+ g_spm_partition_db.partitions[i].runtime_data.caller_partition_idx =
+ SPM_INVALID_PARTITION_IDX;
+ g_spm_partition_db.partitions[i].runtime_data.caller_client_id =
+ TFM_INVALID_CLIENT_ID;
+ g_spm_partition_db.partitions[i].runtime_data.ctx_stack_ptr =
+ ctx_stack_list[i];
+ g_spm_partition_db.partitions[i].static_data = &static_data_list[i];
+ g_spm_partition_db.partitions[i].platform_data_list =
+ platform_data_list_list[i];
+ }
+ g_spm_partition_db.is_init = 1;
+
+ return SPM_ERR_OK;
+}
diff --git a/secure_fw/spm/cmsis_func/tfm_core_svcalls_func.c b/secure_fw/spm/cmsis_func/tfm_core_svcalls_func.c
new file mode 100644
index 0000000..c1b21f6
--- /dev/null
+++ b/secure_fw/spm/cmsis_func/tfm_core_svcalls_func.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+
+#include "tfm/tfm_core_svc.h"
+#include "tfm_secure_api.h"
+#include "region_defs.h"
+#include "spm_api.h"
+#include "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_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/cmsis_func/tfm_nspm_func.c b/secure_fw/spm/cmsis_func/tfm_nspm_func.c
new file mode 100644
index 0000000..bc36c15
--- /dev/null
+++ b/secure_fw/spm/cmsis_func/tfm_nspm_func.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "cmsis_compiler.h"
+#include "spm_api.h"
+#include "tfm_spm_hal.h"
+#include "tfm_arch.h"
+#include "tfm_api.h"
+#include "tfm_internal.h"
+#include "tfm_nspm.h"
+#include "ext/tz_context.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
+
+#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/cmsis_func/tfm_secure_api.c b/secure_fw/spm/cmsis_func/tfm_secure_api.c
new file mode 100644
index 0000000..d4fe179
--- /dev/null
+++ b/secure_fw/spm/cmsis_func/tfm_secure_api.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "spm_api.h"
+#include "tfm_secure_api.h"
+
+void tfm_secure_api_error_handler(void)
+{
+ ERROR_MSG("Security violation when calling secure API");
+ tfm_core_panic();
+}
+
+int32_t tfm_core_partition_request(uint32_t id, bool is_ns, void *fn,
+ int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
+{
+ int32_t args[4] = {arg1, arg2, arg3, arg4};
+ struct tfm_sfn_req_s desc, *desc_ptr = &desc;
+
+ desc.sp_id = id;
+ desc.sfn = (sfn_t) fn;
+ desc.args = args;
+ desc.ns_caller = is_ns;
+
+ if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
+ /* The veneer of a secure service had been called from Handler mode.
+ * This violates TF-M's programming model, and is considered an
+ * unrecoverable error.
+ */
+ tfm_core_panic();
+ } else {
+ if (desc.ns_caller) {
+ return tfm_core_sfn_request(desc_ptr);
+ } else {
+ return tfm_spm_sfn_request_thread_mode(desc_ptr);
+ }
+ }
+ return TFM_ERROR_GENERIC;
+}
diff --git a/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc b/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc
new file mode 100644
index 0000000..8c35661
--- /dev/null
+++ b/secure_fw/spm/cmsis_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/protected_storage/psa_manifest/tfm_protected_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_ps_test_service/psa_manifest/tfm_ps_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/cmsis_func/tfm_secure_irq_handlers.inc.template b/secure_fw/spm/cmsis_func/tfm_secure_irq_handlers.inc.template
new file mode 100644
index 0000000..9db5d64
--- /dev/null
+++ b/secure_fw/spm/cmsis_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/cmsis_func/tfm_spm_db_func.inc b/secure_fw/spm/cmsis_func/tfm_spm_db_func.inc
new file mode 100644
index 0000000..54f2ddb
--- /dev/null
+++ b/secure_fw/spm/cmsis_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 "spm_api.h"
+#include "psa_manifest/sid.h"
+
+/**************************************************************************/
+/** IRQ count per partition */
+/**************************************************************************/
+#ifdef TFM_PARTITION_PROTECTED_STORAGE
+#define TFM_PARTITION_TFM_SP_PS_IRQ_COUNT 0
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+#define TFM_PARTITION_TFM_SP_PS_TEST_IRQ_COUNT 0
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PROTECTED_STORAGE
+extern void tfm_ps_req_mngr_init(void);
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+extern void tfm_ps_test_init(void);
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PROTECTED_STORAGE
+static uint32_t ctx_stack_TFM_SP_PS[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_PS_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+static uint32_t ctx_stack_TFM_SP_PS_TEST[
+ (sizeof(struct interrupted_ctx_stack_frame_t) +
+ (TFM_PARTITION_TFM_SP_PS_TEST_IRQ_COUNT) * (
+ sizeof(struct interrupted_ctx_stack_frame_t) +
+ sizeof(struct handler_ctx_stack_frame_t)
+ )) / sizeof(uint32_t)];
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PROTECTED_STORAGE
+ ctx_stack_TFM_SP_PS,
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+ ctx_stack_TFM_SP_PS_TEST,
+#endif /* TFM_PARTITION_TEST_PS */
+#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_PROTECTED_STORAGE
+static int32_t dependencies_TFM_SP_PS[] =
+{
+ 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_PROTECTED_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_PS_SET_SID,
+ TFM_PS_GET_SID,
+ TFM_PS_GET_INFO_SID,
+ TFM_PS_REMOVE_SID,
+ TFM_PS_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_PS_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_PS
+static int32_t dependencies_TFM_SP_PS_TEST[] =
+{
+ TFM_CRYPTO_SID,
+ TFM_ITS_GET_SID,
+ TFM_ITS_REMOVE_SID,
+};
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PROTECTED_STORAGE
+ {
+ .partition_id = TFM_SP_PS,
+ .partition_flags = SPM_PART_FLAG_IPC
+ | SPM_PART_FLAG_APP_ROT
+ ,
+ .partition_priority = TFM_PRIORITY(NORMAL),
+ .partition_init = tfm_ps_req_mngr_init,
+ .dependencies_num = 6,
+ .p_dependencies = dependencies_TFM_SP_PS,
+ },
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+ {
+ .partition_id = TFM_SP_PS_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_ps_test_init,
+ .dependencies_num = 3,
+ .p_dependencies = dependencies_TFM_SP_PS_TEST,
+ },
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PROTECTED_STORAGE
+ NULL,
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+ NULL,
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PS */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_PROTECTED_STORAGE
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_PROTECTED_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_PS_TEST */
+ /* -----------------------------------------------------------------------*/
+#ifdef TFM_PARTITION_TEST_PS
+ {
+ /* Runtime data */
+ .runtime_data = {0},
+ .static_data = NULL,
+ .platform_data_list = NULL,
+ },
+#endif /* TFM_PARTITION_TEST_PS */
+
+ /* -----------------------------------------------------------------------*/
+ /* - 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/cmsis_func/tfm_spm_db_func.inc.template b/secure_fw/spm/cmsis_func/tfm_spm_db_func.inc.template
new file mode 100644
index 0000000..8f424b8
--- /dev/null
+++ b/secure_fw/spm/cmsis_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 "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/cmsis_func/tfm_veneers.c b/secure_fw/spm/cmsis_func/tfm_veneers.c
new file mode 100644
index 0000000..b58fca5
--- /dev/null
+++ b/secure_fw/spm/cmsis_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 "spm_partition_defs.h"
+
+#ifdef TFM_PARTITION_PROTECTED_STORAGE
+/******** TFM_SP_PS ********/
+psa_status_t tfm_ps_set_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_ps_get_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_ps_get_info_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_ps_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_ps_get_support_req(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+/******** TFM_SP_PS_TEST ********/
+psa_status_t tfm_ps_test_prepare(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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_PROTECTED_STORAGE
+/******** TFM_SP_PS ********/
+TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_set_req)
+TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_get_req)
+TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_get_info_req)
+TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_remove_req)
+TFM_VENEER_FUNCTION(TFM_SP_PS, tfm_ps_get_support_req)
+#endif /* TFM_PARTITION_PROTECTED_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_PS
+/******** TFM_SP_PS_TEST ********/
+TFM_VENEER_FUNCTION(TFM_SP_PS_TEST, tfm_ps_test_prepare)
+#endif /* TFM_PARTITION_TEST_PS */
+
+#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/cmsis_func/tfm_veneers.c.template b/secure_fw/spm/cmsis_func/tfm_veneers.c.template
new file mode 100644
index 0000000..b518164
--- /dev/null
+++ b/secure_fw/spm/cmsis_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 "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 %}