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 &REGION_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)&REGION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
+    partition_psplim =
+        (uint32_t)&REGION_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 = &REGION_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 %}