Build: Follow the 'source_structure.rst'
This is the first patch to follow the first commit of source structure
document. The items under the 'secure_fw' folder are re-organized:
- Create/Move some folders/files to follow document.
- Rename some folders to foll, for example, 'secure_fw/services' to
'secure_fw/partitions'.
- Update affected files to make it work.
This is a big change, to make the structure meet the basic shape of
the structure document defined, and make it easier to be understood
for users. Staging changes are not applicable so they are combined
into one - and because it is not the final shape yet, so:
- Upcoming updates on the 'secure_fw' folder would follow up soon.
- Fine-tune about the 'source_structure.rst' would come, too.
Change-Id: I5c11175e0a4579cd9b42d3e3519dbffb87334d0b
Signed-off-by: Ken Liu <ken.liu@arm.com>
diff --git a/secure_fw/spm/CMakeLists.inc b/secure_fw/spm/CMakeLists.inc
deleted file mode 100644
index cb458d5..0000000
--- a/secure_fw/spm/CMakeLists.inc
+++ /dev/null
@@ -1,65 +0,0 @@
-#-------------------------------------------------------------------------------
-# Copyright (c) 2017-2020, Arm Limited. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-3-Clause
-#
-#-------------------------------------------------------------------------------
-
-#Definitions to compile the "spm" module.
-#This file assumes it will be included from a project specific cmakefile, and
-#will not create a library or executable.
-#Inputs:
-# TFM_ROOT_DIR - root directory of the TF-M repository.
-#
-#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.
-
-#Get the current directory where this file is located.
-set(SS_SPM_DIR ${CMAKE_CURRENT_LIST_DIR})
-if(NOT DEFINED TFM_ROOT_DIR)
- message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.")
-endif()
-
-set (SS_SPM_C_SRC "${SS_SPM_DIR}/spm_api.c")
-
-if(TFM_PSA_API)
- list(APPEND SS_SPM_C_SRC "${SS_SPM_DIR}/spm_ipc.c"
- "${SS_SPM_DIR}/spm_psa_client_call.c")
-else()
- list(APPEND SS_SPM_C_SRC "${SS_SPM_DIR}/spm_func.c")
-endif()
-
-#Append all our source files to global lists.
-list(APPEND ALL_SRC_C ${SS_SPM_C_SRC})
-unset(SS_SPM_C_SRC)
-
-#Setting include directories
-embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
-embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
-embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE)
-embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/include ABSOLUTE)
-
-set(BUILD_CMSIS_CORE Off)
-set(BUILD_RETARGET Off)
-set(BUILD_NATIVE_DRIVERS Off)
-set(BUILD_STARTUP Off)
-set(BUILD_TARGET_CFG Off)
-set(BUILD_TARGET_HARDWARE_KEYS Off)
-set(BUILD_TARGET_NV_COUNTERS Off)
-set(BUILD_CMSIS_DRIVERS Off)
-set(BUILD_TIME Off)
-set(BUILD_UART_STDOUT Off)
-set(BUILD_FLASH Off)
-set(BUILD_PLAT_TEST Off)
-if(NOT DEFINED PLATFORM_CMAKE_FILE)
- message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.")
-elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE})
- message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.")
-else()
- include(${PLATFORM_CMAKE_FILE})
-endif()
-
diff --git a/secure_fw/spm/arch/CMakeLists.inc b/secure_fw/spm/arch/CMakeLists.inc
new file mode 100644
index 0000000..01ab370
--- /dev/null
+++ b/secure_fw/spm/arch/CMakeLists.inc
@@ -0,0 +1,60 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the "arch" module.
+#This file assumes it will be included from a project specific cmakefile, and
+#will not create a library or executable.
+#Inputs:
+# TFM_ROOT_DIR - directory where TF-M soure code is located.
+#
+#Outputs:
+# Will modify include directories to make the source compile.
+# ALL_SRC_C_S: 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_S: 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.
+
+#Get the current directory where this file is located.
+set(TFM_ARCH_DIR ${CMAKE_CURRENT_LIST_DIR})
+if(NOT DEFINED TFM_ROOT_DIR)
+ message(FATAL_ERROR
+ "Please set TFM_ROOT_DIR before including this file.")
+endif()
+
+if (NOT DEFINED ARM_CPU_ARCHITECTURE)
+ message(FATAL_ERROR "Incomplete build configuration: architecture is not specified.")
+elseif (${ARM_CPU_ARCHITECTURE} STREQUAL "ARMv8.1-M.MAIN")
+ set(TFM_ARCH_C_SRC "${TFM_ARCH_DIR}/tfm_arch_v8m_main.c")
+elseif (${ARM_CPU_ARCHITECTURE} STREQUAL "ARMv8-M.MAIN")
+ set(TFM_ARCH_C_SRC "${TFM_ARCH_DIR}/tfm_arch_v8m_main.c")
+elseif (${ARM_CPU_ARCHITECTURE} STREQUAL "ARMv8-M.BASE")
+ set(TFM_ARCH_C_SRC "${TFM_ARCH_DIR}/tfm_arch_v8m_base.c")
+elseif (${ARM_CPU_ARCHITECTURE} STREQUAL "ARMv7-M" OR
+ ${ARM_CPU_ARCHITECTURE} STREQUAL "ARMv6-M" OR
+ ${ARM_CPU_ARCHITECTURE} STREQUAL "ARMv6S-M")
+ if (NOT DEFINED TFM_MULTI_CORE_TOPOLOGY OR NOT TFM_MULTI_CORE_TOPOLOGY)
+ message(FATAL_ERROR "Armv6-M/Armv7-M can only support multi-core TF-M.")
+ endif()
+
+ set(TFM_ARCH_C_SRC "${TFM_ARCH_DIR}/tfm_arch_v6m_v7m.c")
+else ()
+ message(FATAL_ERROR "Unsupported architecture.")
+endif()
+
+list(APPEND TFM_ARCH_C_SRC "${TFM_ARCH_DIR}/tfm_arch.c")
+
+#Append all our source files to global secure source code lists.
+list(APPEND ALL_SRC_C_S ${TFM_ARCH_C_SRC})
+unset(TFM_ARCH_C_SRC)
+
+#Setting include directories
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/platform/ext/cmsis ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ARCH_DIR}/include ABSOLUTE)
diff --git a/secure_fw/spm/arch/include/tfm_arch.h b/secure_fw/spm/arch/include/tfm_arch.h
new file mode 100644
index 0000000..929a870
--- /dev/null
+++ b/secure_fw/spm/arch/include/tfm_arch.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_ARCH_H__
+#define __TFM_ARCH_H__
+
+/* This header file collects the architecture related operations. */
+
+#include <stddef.h>
+#include <inttypes.h>
+#include "tfm_hal_device_header.h"
+#include "cmsis_compiler.h"
+
+#if defined(__ARM_ARCH_8_1M_MAIN__) || \
+ defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__)
+#include "tfm_arch_v8m.h"
+#elif defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_7M__) || \
+ defined(__ARM_ARCH_7EM__)
+#include "tfm_arch_v6m_v7m.h"
+#else
+#error "Unsupported ARM Architecture."
+#endif
+
+#define XPSR_T32 0x01000000
+
+/* General core state context */
+struct tfm_state_context_t {
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r12;
+ uint32_t lr;
+ uint32_t ra;
+ uint32_t xpsr;
+};
+
+#define TFM_STATE_RET_VAL(ctx) (((struct tfm_state_context_t *)((ctx)->sp))->r0)
+
+__attribute__ ((always_inline))
+__STATIC_INLINE void tfm_arch_trigger_pendsv(void)
+{
+ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+}
+
+/**
+ * \brief Get Link Register
+ * \details Returns the value of the Link Register (LR)
+ * \return LR value
+ */
+__attribute__ ((always_inline)) __STATIC_INLINE uint32_t __get_LR(void)
+{
+ register uint32_t result;
+
+ __ASM volatile ("MOV %0, LR\n" : "=r" (result));
+ return result;
+}
+
+__attribute__ ((always_inline))
+__STATIC_INLINE uint32_t __get_active_exc_num(void)
+{
+ IPSR_Type IPSR;
+
+ /* if non-zero, exception is active. NOT banked S/NS */
+ IPSR.w = __get_IPSR();
+ return IPSR.b.ISR;
+}
+
+__attribute__ ((always_inline))
+__STATIC_INLINE void __set_CONTROL_SPSEL(uint32_t SPSEL)
+{
+ CONTROL_Type ctrl;
+
+ ctrl.w = __get_CONTROL();
+ ctrl.b.SPSEL = SPSEL;
+ __set_CONTROL(ctrl.w);
+ __ISB();
+}
+
+/*
+ * Initialize CPU architecture specific thread context extension
+ */
+void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
+ uint32_t sp, uint32_t sp_limit);
+
+/*
+ * Prioritize Secure exceptions
+ */
+void tfm_arch_prioritize_secure_exception(void);
+
+/*
+ * Clear float point status.
+ */
+void tfm_arch_clear_fp_status(void);
+
+void tfm_arch_init_context(struct tfm_arch_ctx_t *p_actx,
+ void *param, uintptr_t pfn,
+ uintptr_t stk_btm, uintptr_t stk_top);
+#endif
diff --git a/secure_fw/spm/arch/include/tfm_arch_v6m_v7m.h b/secure_fw/spm/arch/include/tfm_arch_v6m_v7m.h
new file mode 100644
index 0000000..380df16
--- /dev/null
+++ b/secure_fw/spm/arch/include/tfm_arch_v6m_v7m.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_ARCH_V6M_V7M_H__
+#define __TFM_ARCH_V6M_V7M_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "cmsis_compiler.h"
+
+#if !TFM_MULTI_CORE_TOPOLOGY
+#error "Armv6-M/Armv7-M can only support multi-core TF-M now."
+#endif
+
+#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
+#define EXC_RETURN_FPU_FRAME_BASIC (1 << 4)
+#endif
+
+/* Initial EXC_RETURN value in LR when a thread is loaded at the first time */
+#define EXC_RETURN_THREAD_S_PSP 0xFFFFFFFD
+
+struct tfm_arch_ctx_t {
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t sp;
+ uint32_t lr;
+};
+
+/**
+ * \brief Check whether Secure or Non-secure stack is used to restore stack
+ * frame on exception return.
+ *
+ * \param[in] lr LR register containing the EXC_RETURN value.
+ *
+ * \retval true Always return to Secure stack on secure core in
+ * multi-core topology.
+ */
+__STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
+{
+ (void)lr;
+
+ return true;
+}
+
+#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
+/**
+ * \brief Check whether the stack frame for this exception has space allocated
+ * for Floating Point(FP) state information.
+ *
+ * \param[in] lr LR register containing the EXC_RETURN value.
+ *
+ * \retval true The stack allocates space for FP information
+ * \retval false The stack doesn't allocate space for FP information
+ */
+__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
+{
+ return (lr & EXC_RETURN_FPU_FRAME_BASIC) ? false : true;
+}
+#elif defined(__ARM_ARCH_6M__)
+/**
+ * \brief Check whether the stack frame for this exception has space allocated
+ * for Floating Point(FP) state information.
+ *
+ * \param[in] lr LR register containing the EXC_RETURN value.
+ *
+ * \retval false The stack doesn't allocate space for FP information
+ */
+__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
+{
+ (void)lr;
+
+ return false;
+}
+#endif
+
+/**
+ * \brief Set PSP limit value.
+ *
+ * \param[in] psplim PSP limit value to be written.
+ */
+__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
+{
+ /*
+ * Defined as an empty function now.
+ * The PSP limit value can be used in more strict memory check.
+ */
+ (void)psplim;
+}
+
+/**
+ * \brief Update architecture context value into hardware
+ *
+ * \param[in] p_actx Pointer of context data
+ */
+__STATIC_INLINE void tfm_arch_update_ctx(struct tfm_arch_ctx_t *p_actx)
+{
+ __set_PSP(p_actx->sp);
+}
+
+/**
+ * \brief Set MSP limit value.
+ *
+ * \param[in] msplim MSP limit value to be written.
+ */
+__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
+{
+ /*
+ * Defined as an empty function now.
+ * The MSP limit value can be used in more strict memory check.
+ */
+ (void)msplim;
+}
+
+#endif
diff --git a/secure_fw/spm/arch/include/tfm_arch_v8m.h b/secure_fw/spm/arch/include/tfm_arch_v8m.h
new file mode 100644
index 0000000..94a2e4f
--- /dev/null
+++ b/secure_fw/spm/arch/include/tfm_arch_v8m.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_ARCH_V8M_H__
+#define __TFM_ARCH_V8M_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "cmsis_compiler.h"
+
+#define EXC_RETURN_INDICATOR (0xFF << 24)
+#define EXC_RETURN_RES1 (0x1FFFF << 7)
+#define EXC_RETURN_SECURE_STACK (1 << 6)
+#define EXC_RETURN_STACK_RULE (1 << 5)
+#define EXC_RETURN_FPU_FRAME_BASIC (1 << 4)
+#define EXC_RETURN_MODE_THREAD (1 << 3)
+#define EXC_RETURN_STACK_PROCESS (1 << 2)
+#define EXC_RETURN_RES0 (0 << 1)
+#define EXC_RETURN_EXC_SECURE (1)
+
+/* Initial EXC_RETURN value in LR when a thread is loaded at the first time */
+#define EXC_RETURN_THREAD_S_PSP \
+ EXC_RETURN_INDICATOR | EXC_RETURN_RES1 | \
+ EXC_RETURN_SECURE_STACK | EXC_RETURN_STACK_RULE | \
+ EXC_RETURN_FPU_FRAME_BASIC | EXC_RETURN_MODE_THREAD | \
+ EXC_RETURN_STACK_PROCESS | EXC_RETURN_RES0 | \
+ EXC_RETURN_EXC_SECURE
+
+#if defined(__ARM_ARCH_8_1M_MAIN__) || defined(__ARM_ARCH_8M_MAIN__)
+struct tfm_arch_ctx_t {
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t sp;
+ uint32_t sp_limit;
+ uint32_t dummy;
+ uint32_t lr;
+};
+#elif defined(__ARM_ARCH_8M_BASE__)
+struct tfm_arch_ctx_t {
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r11;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t r7;
+ uint32_t sp;
+ uint32_t sp_limit;
+ uint32_t dummy;
+ uint32_t lr;
+};
+#endif
+
+/* Disable NS exceptions by setting NS PRIMASK to 1 */
+#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
+/* Enable NS exceptions by setting NS PRIMASK to 0 */
+#define TFM_NS_EXC_ENABLE() __TZ_set_PRIMASK_NS(0)
+
+/**
+ * \brief Check whether Secure or Non-secure stack is used to restore stack
+ * frame on exception return.
+ *
+ * \param[in] lr LR register containing the EXC_RETURN value.
+ *
+ * \retval true Secure stack is used to restore stack frame on
+ * exception return.
+ * \retval false Non-secure stack is used to restore stack frame on
+ * exception return.
+ */
+__STATIC_INLINE bool is_return_secure_stack(uint32_t lr)
+{
+ return (lr & EXC_RETURN_SECURE_STACK);
+}
+
+/**
+ * \brief Check whether the stack frame for this exception has space allocated
+ * for Floating Point(FP) state information.
+ *
+ * \param[in] lr LR register containing the EXC_RETURN value.
+ *
+ * \retval true The stack allocates space for FP information
+ * \retval false The stack doesn't allocate space for FP information
+ */
+__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
+{
+ return (lr & EXC_RETURN_FPU_FRAME_BASIC) ? false : true;
+}
+
+/**
+ * \brief Set PSPLIM register.
+ *
+ * \param[in] psplim Register value to be written into PSPLIM.
+ */
+__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
+{
+ __set_PSPLIM(psplim);
+}
+
+/**
+ * \brief Update architecture context value into hardware
+ *
+ * \param[in] p_actx Pointer of context data
+ */
+__STATIC_INLINE void tfm_arch_update_ctx(struct tfm_arch_ctx_t *p_actx)
+{
+ __set_PSP(p_actx->sp);
+ __set_PSPLIM(p_actx->sp_limit);
+}
+
+/**
+ * \brief Set MSPLIM register.
+ *
+ * \param[in] msplim Register value to be written into MSPLIM.
+ */
+__STATIC_INLINE void tfm_arch_set_msplim(uint32_t msplim)
+{
+ __set_MSPLIM(msplim);
+}
+
+#endif
diff --git a/secure_fw/spm/arch/tfm_arch.c b/secure_fw/spm/arch/tfm_arch.c
new file mode 100644
index 0000000..54df423
--- /dev/null
+++ b/secure_fw/spm/arch/tfm_arch.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_arch.h"
+#include "tfm_core_utils.h"
+
+#ifdef TFM_PSA_API
+static void tfm_arch_init_state_ctx(struct tfm_state_context_t *p_stat_ctx,
+ void *param, uintptr_t pfn)
+{
+ p_stat_ctx->r0 = (uint32_t)param;
+ p_stat_ctx->ra = (uint32_t)pfn;
+ /*
+ * Prevent thread exits:
+ * Only T32 is supported, so bit[0] must be 1. Clear the bit[0] of LR to
+ * trigger a fault.
+ */
+ p_stat_ctx->lr = ((uint32_t)pfn) & (~1UL);
+ p_stat_ctx->xpsr = XPSR_T32;
+}
+
+void tfm_arch_init_context(struct tfm_arch_ctx_t *p_actx,
+ void *param, uintptr_t pfn,
+ uintptr_t stk_btm, uintptr_t stk_top)
+{
+ /*
+ * For security consideration, set unused registers into ZERO;
+ * and only necessary registers are set here.
+ */
+ struct tfm_state_context_t *p_stat_ctx =
+ (struct tfm_state_context_t *)stk_top;
+
+ /*
+ * Shift back SP to leave space for holding base context
+ * since thread is kicked off through exception return.
+ */
+ p_stat_ctx--;
+
+ /* State context is considerate at thread start.*/
+ tfm_core_util_memset(p_stat_ctx, 0, sizeof(*p_stat_ctx));
+ tfm_arch_init_state_ctx(p_stat_ctx, param, pfn);
+
+ /* Initialize architecture context */
+ tfm_core_util_memset(p_actx, 0, sizeof(*p_actx));
+ tfm_arch_init_actx(p_actx, (uint32_t)p_stat_ctx, (uint32_t)stk_btm);
+}
+
+#endif /* TFM_PSA_API */
diff --git a/secure_fw/spm/arch/tfm_arch_v6m_v7m.c b/secure_fw/spm/arch/tfm_arch_v6m_v7m.c
new file mode 100644
index 0000000..34debc6
--- /dev/null
+++ b/secure_fw/spm/arch/tfm_arch_v6m_v7m.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include "tfm_hal_device_header.h"
+#include "tfm_arch.h"
+
+#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && \
+ !defined(__ARM_ARCH_7EM__)
+#error "Unsupported ARM Architecture."
+#endif
+
+extern uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr);
+
+/*
+ * Stack status at PendSV entry:
+ *
+ * [ R0 - R3 ]<- PSP
+ * [ R12 ]
+ * [ LR_of_RA ]
+ * MSP->[ ........ ] [ RA ]
+ * [ ........ ] [ XPSR ]
+ * [ ........ ]
+ * [ ........ ]
+ *
+ * Stack status before calling tfm_pendsv_do_schedule():
+ *
+ * MSP->[ R8 - R9 ]
+ * [ R4 - R7 ]
+ * [ PSP ]--->[ R0 - R3 ]
+ * [ LR ] [ R12 ]
+ * [ ........ ] [ LR_of_RA ]
+ * [ ........ ] [ RA ]
+ * [ XPSR ]
+ * [ ........ ]
+ * [ ........ ]
+ *
+ * tfm_pendsv_do_schedule() updates stacked context into current thread and
+ * replace stacked context with context of next thread.
+ *
+ * Scheduler does not support handler mode thread so take PSP as thread SP.
+ */
+#if defined(__ICCARM__)
+extern void tfm_pendsv_do_schedule(void);
+#pragma required = tfm_pendsv_do_schedule
+#endif
+
+__attribute__((naked)) void PendSV_Handler(void)
+{
+ __ASM volatile(
+ "MRS r0, psp \n"
+ "PUSH {r0, 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 r0, sp \n"
+ "BL tfm_pendsv_do_schedule \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 {r0, r1} \n"
+ "MOV lr, r1 \n"
+ "MSR psp, r0 \n"
+ "BX lr \n"
+ );
+}
+
+void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
+ uint32_t sp, uint32_t sp_limit)
+{
+ (void)sp_limit;
+
+ p_actx->sp = sp;
+ p_actx->lr = EXC_RETURN_THREAD_S_PSP;
+}
+
+#if defined(__ICCARM__)
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
+#pragma required = tfm_core_svc_handler
+#endif
+
+__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"
+ );
+}
+
+/**
+ * \brief Overwrites default Hard fault handler.
+ */
+#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
+void HardFault_Handler(void)
+{
+ /* HFSR can be read to provide further information of cause of HardFault */
+ __ASM volatile("b .");
+}
+#elif defined(__ARM_ARCH_6M__)
+void HardFault_Handler(void)
+{
+ /* In a baseline implementation there is no way, to find out whether this is
+ * a hard fault triggered directly, or another fault that has been
+ * escalated.
+ */
+ __ASM volatile("b .");
+}
+#endif
+
+/* Reserved for future usage */
+__attribute__((naked)) void MemManage_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+__attribute__((naked)) void BusFault_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+__attribute__((naked)) void UsageFault_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+void tfm_arch_prioritize_secure_exception(void)
+{
+}
+
+/* There is no FPCA in v6m */
+#ifndef __ARM_ARCH_6M__
+__attribute__((naked, noinline)) void tfm_arch_clear_fp_status(void)
+{
+ __ASM volatile(
+ ".syntax unified \n"
+ "mrs r0, control \n"
+ "bics r0, r0, #4 \n"
+ "msr control, r0 \n"
+ "isb \n"
+ "bx lr \n"
+ );
+}
+#else
+void tfm_arch_clear_fp_status(void)
+{
+}
+#endif
diff --git a/secure_fw/spm/arch/tfm_arch_v8m_base.c b/secure_fw/spm/arch/tfm_arch_v8m_base.c
new file mode 100644
index 0000000..00c4fca
--- /dev/null
+++ b/secure_fw/spm/arch/tfm_arch_v8m_base.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include "tfm_hal_device_header.h"
+#include "secure_utilities.h"
+#include "tfm_arch.h"
+#include "tfm_secure_api.h"
+#include "tfm/spm_api.h"
+#include "tfm/tfm_core_svc.h"
+
+#if !defined(__ARM_ARCH_8M_BASE__)
+#error "Unsupported ARM Architecture."
+#endif
+
+#ifdef TFM_PSA_API
+/*
+ * Stack status at PendSV entry:
+ *
+ * [ R0 - R3 ]<- PSP
+ * [ R12 ]
+ * [ LR_of_RA ]
+ * MSP->[ ........ ] [ RA ]
+ * [ ........ ] [ XPSR ]
+ * [ ........ ]
+ * [ ........ ]
+ *
+ * Stack status before calling pendsv_do_schedule():
+ *
+ * MSP->[ R4 - R11 ]
+ * [ PSP ]--->[ R0 - R3 ]
+ * [ PSP Limit] [ R12 ]
+ * [ R2(dummy)] [ LR_of_RA ]
+ * [ LR ] [ RA ]
+ * [ ........ ] [ XPSR ]
+ * [ ........ ] [ ........ ]
+ * [ ........ ]
+ *
+ * tfm_pendsv_do_schedule() updates stacked context into current thread and
+ * replace stacked context with context of next thread.
+ *
+ * Scheduler does not support handler mode thread so take PSP/PSP_LIMIT as
+ * thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
+ * aligned.
+ */
+#if defined(__ICCARM__)
+#pragma required = tfm_pendsv_do_schedule
+#endif
+
+__attribute__((naked)) void PendSV_Handler(void)
+{
+ __ASM volatile(
+ "mrs r0, psp \n"
+ "mrs r1, psplim \n"
+ "push {r0, r1, r2, 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 r0, sp \n"
+ "bl tfm_pendsv_do_schedule \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 {r0-r3} \n"
+ "mov lr, r3 \n"
+ "msr psp, r0 \n"
+ "msr psplim, r1 \n"
+ "bx lr \n"
+ );
+}
+
+void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
+ uint32_t sp, uint32_t sp_limit)
+{
+ p_actx->sp = sp;
+ p_actx->sp_limit = sp_limit;
+ p_actx->lr = EXC_RETURN_THREAD_S_PSP;
+}
+#else
+__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
+
+/**
+ * \brief Overwrites default Hard fault handler.
+ *
+ * In case of a baseline implementation fault conditions that would generate a
+ * SecureFault in a mainline implementation instead generate a Secure HardFault.
+ */
+void HardFault_Handler(void)
+{
+ /* In a baseline implementation there is no way, to find out whether this is
+ * a hard fault triggered directly, or another fault that has been
+ * escalated.
+ */
+ while (1) {
+ ;
+ }
+}
+
+#if defined(__ICCARM__)
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
+#pragma required = tfm_core_svc_handler
+#endif
+
+__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"
+ );
+}
+
+/* Reserved for future usage */
+__attribute__((naked)) void MemManage_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+__attribute__((naked)) void BusFault_Handler(void)
+{
+ __ASM volatile("b .");
+}
+__attribute__((naked)) void UsageFault_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+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);
+}
+
+/* There is no FPCA in baseline. */
+void tfm_arch_clear_fp_status(void)
+{
+}
diff --git a/secure_fw/spm/arch/tfm_arch_v8m_main.c b/secure_fw/spm/arch/tfm_arch_v8m_main.c
new file mode 100644
index 0000000..f975a66
--- /dev/null
+++ b/secure_fw/spm/arch/tfm_arch_v8m_main.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include "tfm_hal_device_header.h"
+#include "region_defs.h"
+#include "secure_utilities.h"
+#include "tfm_arch.h"
+#include "tfm_memory_utils.h"
+#include "tfm_core_utils.h"
+#include "tfm_secure_api.h"
+#include "tfm/spm_api.h"
+#include "tfm/tfm_core_svc.h"
+
+#if !defined(__ARM_ARCH_8M_MAIN__) && !defined(__ARM_ARCH_8_1M_MAIN__)
+#error "Unsupported ARM Architecture."
+#endif
+
+struct tfm_fault_context_s {
+ uint32_t R0;
+ uint32_t R1;
+ uint32_t R2;
+ uint32_t R3;
+ uint32_t R12;
+ uint32_t LR;
+ uint32_t ReturnAddress;
+ uint32_t RETPSR;
+} tfm_fault_context;
+
+#ifdef TFM_PSA_API
+/*
+ * Stack status at PendSV entry:
+ *
+ * [ R0 - R3 ]<- PSP
+ * [ R12 ]
+ * [ LR_of_RA ]
+ * MSP->[ ........ ] [ RA ]
+ * [ ........ ] [ XPSR ]
+ * [ ........ ]
+ * [ ........ ]
+ *
+ * Stack status before calling pendsv_do_schedule():
+ *
+ * MSP->[ R4 - R11 ]
+ * [ PSP ]--->[ R0 - R3 ]
+ * [ PSP Limit] [ R12 ]
+ * [ R2(dummy)] [ LR_of_RA ]
+ * [ LR ] [ RA ]
+ * [ ........ ] [ XPSR ]
+ * [ ........ ] [ ........ ]
+ * [ ........ ]
+ *
+ * tfm_pendsv_do_schedule() updates stacked context into current thread and
+ * replace stacked context with context of next thread.
+ *
+ * Scheduler does not support handler mode thread so take PSP/PSP_LIMIT as
+ * thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
+ * aligned.
+ */
+#if defined(__ICCARM__)
+#pragma required = tfm_pendsv_do_schedule
+#endif
+
+__attribute__((naked)) void PendSV_Handler(void)
+{
+ __ASM volatile(
+ "mrs r0, psp \n"
+ "mrs r1, psplim \n"
+ "push {r0, r1, r2, lr} \n"
+ "push {r4-r11} \n"
+ "mov r0, sp \n"
+ "bl tfm_pendsv_do_schedule \n"
+ "pop {r4-r11} \n"
+ "pop {r0, r1, r2, lr} \n"
+ "msr psp, r0 \n"
+ "msr psplim, r1 \n"
+ "bx lr \n"
+ );
+}
+
+void tfm_arch_init_actx(struct tfm_arch_ctx_t *p_actx,
+ uint32_t sp, uint32_t sp_limit)
+{
+ p_actx->sp = sp;
+ p_actx->sp_limit = sp_limit;
+ p_actx->lr = EXC_RETURN_THREAD_S_PSP;
+}
+#else
+__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)
+ );
+}
+#endif
+
+/**
+ * \brief Overwrites default Secure fault handler.
+ */
+void SecureFault_Handler(void)
+{
+ /* figure out context from which we landed in fault handler */
+ uint32_t lr = __get_LR();
+ uint32_t sp;
+
+ if (lr & EXC_RETURN_SECURE_STACK) {
+ if (lr & EXC_RETURN_STACK_PROCESS) {
+ sp = __get_PSP();
+ } else {
+ sp = __get_MSP();
+ }
+ } else {
+ if (lr & EXC_RETURN_STACK_PROCESS) {
+ sp = __TZ_get_PSP_NS();
+ } else {
+ sp = __TZ_get_MSP_NS();
+ }
+ }
+
+ /* Only save the context if sp is valid */
+ if ((sp >= S_DATA_START &&
+ sp <= (S_DATA_LIMIT - sizeof(tfm_fault_context)) + 1) ||
+ (sp >= NS_DATA_START &&
+ sp <= (NS_DATA_LIMIT - sizeof(tfm_fault_context)) + 1)) {
+ tfm_core_util_memcpy(&tfm_fault_context,
+ (const void *)sp,
+ sizeof(tfm_fault_context));
+ }
+
+ ERROR_MSG("Oops... Secure fault!!! You're not going anywhere!");
+ while (1) {
+ ;
+ }
+}
+
+#if defined(__ICCARM__)
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
+#pragma required = tfm_core_svc_handler
+#endif
+
+__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"
+ );
+}
+
+/* Reserved for future usage */
+__attribute__((naked)) void MemManage_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+__attribute__((naked)) void BusFault_Handler(void)
+{
+ __ASM volatile("b .");
+}
+__attribute__((naked)) void UsageFault_Handler(void)
+{
+ __ASM volatile("b .");
+}
+
+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);
+}
+
+__attribute__((naked, noinline)) void tfm_arch_clear_fp_status(void)
+{
+ __ASM volatile(
+ "mrs r0, control \n"
+ "bics r0, r0, #4 \n"
+ "msr control, r0 \n"
+ "isb \n"
+ "bx lr \n"
+ );
+}
diff --git a/secure_fw/spm/dir_spm.dox b/secure_fw/spm/dir_spm.dox
deleted file mode 100644
index 92c8a27..0000000
--- a/secure_fw/spm/dir_spm.dox
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-//This file holds description for the current directory. This documentation
-//will be included in the Doxygen output.
-
-/*!
-\dir
-\brief Source code for the Secure Partition Manager.
-\details This directory holds the source code of the "TF-M SPM" module.
-
-*/
\ No newline at end of file
diff --git a/secure_fw/spm/include/secure_utilities.h b/secure_fw/spm/include/secure_utilities.h
new file mode 100644
index 0000000..83dc402
--- /dev/null
+++ b/secure_fw/spm/include/secure_utilities.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __SECURE_UTILITIES_H__
+#define __SECURE_UTILITIES_H__
+
+#include <stdbool.h>
+#include "tfm_hal_device_header.h"
+#include "cmsis_compiler.h"
+
+#define EXC_NUM_THREAD_MODE (0)
+#define EXC_NUM_SVCALL (11)
+#define EXC_NUM_PENDSV (14)
+#define EXC_NUM_SYSTICK (15)
+
+#define ERROR_MSG(msg)
+
+bool tfm_is_one_bit_set(uint32_t n);
+
+#endif /* __SECURE_UTILITIES_H__ */
diff --git a/secure_fw/spm/include/tfm_core.h b/secure_fw/spm/include/tfm_core.h
new file mode 100644
index 0000000..8f1c663
--- /dev/null
+++ b/secure_fw/spm/include/tfm_core.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CORE_H__
+#define __TFM_CORE_H__
+
+#include <arm_cmse.h>
+#include "secure_utilities.h"
+
+#endif /* __TFM_CORE_H__ */
diff --git a/secure_fw/spm/include/tfm_core_mem_check.h b/secure_fw/spm/include/tfm_core_mem_check.h
new file mode 100644
index 0000000..6a40563
--- /dev/null
+++ b/secure_fw/spm/include/tfm_core_mem_check.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CORE_MEM_CHECK_H__
+#define __TFM_CORE_MEM_CHECK_H__
+
+#include "tfm_api.h"
+
+/**
+ * \brief Check whether the current partition has read access to a memory range
+ *
+ * This function assumes, that the current MPU configuration is set for the
+ * partition to be checked.
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] ns_caller Whether the current partition is non-secure
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
+ *
+ * \return TFM_SUCCESS if the partition has access to the memory range,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s,
+ bool ns_caller,
+ uint32_t privileged);
+
+/**
+ * \brief Check whether the current partition has write access to a memory range
+ *
+ * This function assumes, that the current MPU configuration is set for the
+ * partition to be checked.
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] ns_caller Whether the current partition is non-secure
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
+ *
+ * \return TFM_SUCCESS if the partition has access to the memory range,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+enum tfm_status_e tfm_core_has_write_access_to_region(const void *p, size_t s,
+ bool ns_caller,
+ uint32_t privileged);
+
+#endif /* __TFM_CORE_MEM_CHECK_H__ */
diff --git a/secure_fw/spm/include/tfm_core_topology.h b/secure_fw/spm/include/tfm_core_topology.h
new file mode 100644
index 0000000..4f31d99
--- /dev/null
+++ b/secure_fw/spm/include/tfm_core_topology.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _TFM_CORE_TOPOLOGY_H_
+#define _TFM_CORE_TOPOLOGY_H_
+
+#include "tfm_hal_device_header.h"
+#include "cmsis_compiler.h"
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+__STATIC_INLINE void tfm_core_topology_set_pendsv_priority(void)
+{
+ NVIC_SetPriority(PendSV_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+}
+#else
+__STATIC_INLINE void tfm_core_topology_set_pendsv_priority(void)
+{
+ /*
+ * Set secure PendSV priority to the lowest in SECURE state.
+ *
+ * IMPORTANT NOTE:
+ *
+ * Although the priority of the secure PendSV must be the lowest possible
+ * among other interrupts in the Secure state, it must be ensured that
+ * PendSV is not preempted nor masked by Non-Secure interrupts to ensure
+ * the integrity of the Secure operation.
+ * When AIRCR.PRIS is set, the Non-Secure execution can act on
+ * FAULTMASK_NS, PRIMASK_NS or BASEPRI_NS register to boost its priority
+ * number up to the value 0x80.
+ * For this reason, set the priority of the PendSV interrupt to the next
+ * priority level configurable on the platform, just below 0x80.
+ */
+ NVIC_SetPriority(PendSV_IRQn, (1 << (__NVIC_PRIO_BITS - 1)) - 1);
+}
+#endif /* TFM_MULTI_CORE_TOPOLOGY */
+
+#endif
diff --git a/secure_fw/spm/include/tfm_core_trustzone.h b/secure_fw/spm/include/tfm_core_trustzone.h
new file mode 100644
index 0000000..061235e
--- /dev/null
+++ b/secure_fw/spm/include/tfm_core_trustzone.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CORE_TRUSTZONE_H__
+#define __TFM_CORE_TRUSTZONE_H__
+
+/* This file holds specification or design defined TrustZone settings. */
+
+/*
+ * The non-secure entry stack guard words. To avoid fuzzing jump to
+ * FNC_RETURN in NSPE, the non-secure entry address is stacked into
+ * bottom (high end address) of secure stack. This would lead the
+ * fuzzing jump of FNC_RETURN to the non-secure entry. Define a size
+ * here for code reference.
+ */
+#define TFM_VENEER_STACK_GUARD_SIZE 8
+
+/*
+ * The numbers in 32bit words while basic FP involved in preempted context:
+ * S0 - S15, FPSCR, Reserved
+ */
+#define TFM_BASIC_FP_CONTEXT_WORDS 18
+
+/*
+ * The numbers in 32bit words while addtional FP involved in preempted context:
+ * S16 - S31
+ */
+#define TFM_ADDTIONAL_FP_CONTEXT_WORDS 16
+
+/*
+ * SG sets LR[0] to ZERO indicates a non-secure to secure transition.
+ * Make sure to apply this mask on a 'LR' just after 'SG' (in veneer).
+ */
+#define TFM_VENEER_LR_BIT0_MASK 1
+
+#endif /* __TFM_CORE_TRUSTZONE_H__ */
diff --git a/secure_fw/spm/include/tfm_core_utils.h b/secure_fw/spm/include/tfm_core_utils.h
new file mode 100644
index 0000000..680deec
--- /dev/null
+++ b/secure_fw/spm/include/tfm_core_utils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CORE_UTILS_H__
+#define __TFM_CORE_UTILS_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+/**
+ * \brief Memory copy function for TF-M core
+ *
+ * \param[out] dest Destination address of memory
+ * \param[in] src Source address of memory
+ * \param[in] n Number of bytes to copy
+ *
+ * \retval Destination address of memory
+ * \note The function is used for copying same-sized object
+ * only.
+ */
+void *tfm_core_util_memcpy(void *dest, const void *src, size_t n);
+
+/**
+ * \brief Memory set function for TF-M core
+ *
+ * \param[out] s Destination address of memory
+ * \param[in] c Value to be written to memory
+ * \param[in] n Number of bytes to be wirtten
+ *
+ * \retval Destination address of memory
+ */
+void *tfm_core_util_memset(void *s, int c, size_t n);
+
+#endif /* __TFM_CORE_UTILS_H__ */
diff --git a/secure_fw/spm/include/tfm_internal.h b/secure_fw/spm/include/tfm_internal.h
new file mode 100644
index 0000000..119f53f
--- /dev/null
+++ b/secure_fw/spm/include/tfm_internal.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_INTERNAL_H__
+#define __TFM_INTERNAL_H__
+
+#include "secure_utilities.h"
+#include "tfm_arch.h"
+
+#ifndef TFM_PSA_API
+/*
+ * This function pointer is meant to only hold non secure function pointers.
+ * It will be turned into a non-secure one (LSB cleared) before being called
+ * whatever happens anyway (unless cast to another function pointer type).
+ * Registers will be cleared before branching so that no information leaks
+ * from secure to non-secure world.
+ */
+typedef void (*nsfptr_t) (void) __attribute__((cmse_nonsecure_call));
+
+extern nsfptr_t ns_entry;
+
+/**
+ * \brief Jumps to non-secure code.
+ */
+void jump_to_ns_code(void);
+#else /* !defined(TFM_PSA_API) */
+
+/**
+ * \brief Move to handler mode by a SVC for specific purpose
+ */
+void tfm_core_handler_mode(void);
+#endif /* !defined(TFM_PSA_API) */
+
+/**
+ * \brief Retrieve secure partition related data from shared memory area, which
+ * stores shared data between bootloader and runtime firmware.
+ *
+ * \param[in] args Pointer to stack frame, which carries input parameters.
+ */
+void tfm_core_get_boot_data_handler(uint32_t args[]);
+
+/**
+ * \brief Validate the content of shared memory area, which stores the shared
+ * data between bootloader and runtime firmware.
+ */
+void tfm_core_validate_boot_data(void);
+
+#endif /* __TFM_INTERNAL_H__ */
diff --git a/secure_fw/spm/include/tfm_irq_list.h b/secure_fw/spm/include/tfm_irq_list.h
new file mode 100644
index 0000000..fbad8f4
--- /dev/null
+++ b/secure_fw/spm/include/tfm_irq_list.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_IRQ_LIST_H__
+#define __TFM_IRQ_LIST_H__
+
+#include "psa/service.h"
+
+#define TFM_DEFAULT_SECURE_IRQ_PRIOTITY 128
+
+struct tfm_core_irq_signal_data_t {
+ int32_t partition_id;
+ psa_signal_t signal_value;
+ IRQn_Type irq_line;
+ uint32_t irq_priority;
+};
+
+extern const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[];
+extern const size_t tfm_core_irq_signals_count;
+
+#endif /* __TFM_IRQ_LIST_H__ */
diff --git a/secure_fw/spm/include/tfm_memory_utils.h b/secure_fw/spm/include/tfm_memory_utils.h
new file mode 100644
index 0000000..150e3cc
--- /dev/null
+++ b/secure_fw/spm/include/tfm_memory_utils.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_MEMORY_UTILS_H__
+#define __TFM_MEMORY_UTILS_H__
+
+#include <string.h>
+#include "cmsis_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* FIXME: The following functions are wrappers around standard C library
+ * functions: memcpy, memcmp, memset
+ * In long term standard C library might be removed from TF-M project or
+ * replaced with a secure implementation due to security concerns.
+ */
+__attribute__ ((always_inline)) __STATIC_INLINE
+void *tfm_memcpy(void *dest, const void *src, size_t num)
+{
+ return (memcpy(dest, src, num));
+}
+
+__attribute__ ((always_inline)) __STATIC_INLINE
+int tfm_memcmp(const void *ptr1, const void *ptr2, size_t num)
+{
+ return (memcmp(ptr1, ptr2, num));
+}
+
+__attribute__ ((always_inline)) __STATIC_INLINE
+void *tfm_memset(void *ptr, int value, size_t num)
+{
+ return (memset(ptr, value, num));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_MEMORY_UTILS_H__ */
diff --git a/secure_fw/spm/include/tfm_nspm.h b/secure_fw/spm/include/tfm_nspm.h
new file mode 100644
index 0000000..3c3e276
--- /dev/null
+++ b/secure_fw/spm/include/tfm_nspm.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_NSPM_H__
+#define __TFM_NSPM_H__
+
+#include <stdint.h>
+
+#if defined(__GNUC__) && !defined(TFM_MULTI_CORE_TOPOLOGY)
+/*
+ * The macro cmse_nsfptr_create defined in the gcc library uses the non-standard
+ * gcc C lanuage extension 'typeof'. TF-M is built with '-std=c99' so typeof
+ * cannot be used in the code. As a workaround cmse_nsfptr_create is redefined
+ * here to use only standard language elements.
+ */
+#undef cmse_nsfptr_create
+#define cmse_nsfptr_create(p) ((intptr_t) (p) & ~1)
+
+/*!
+ * \def __tfm_nspm_secure_gateway_attributes__
+ *
+ * \brief Attributes for secure gateway functions for NSPM
+ */
+#ifndef __ARMCC_VERSION
+/*
+ * GNUARM requires noclone attribute to protect gateway function symbol from
+ * being renamed and cloned
+ */
+#define __tfm_nspm_secure_gateway_attributes__ \
+ __attribute__((cmse_nonsecure_entry, noclone))
+#else
+#define __tfm_nspm_secure_gateway_attributes__ \
+ __attribute__((cmse_nonsecure_entry))
+#endif /* !__ARMCC_VERSION */
+#endif /* __GNUC__ && !TFM_MULTI_CORE_TOPOLOGY */
+
+#ifndef TFM_PSA_API
+/**
+ * \brief initialise the NS context database
+ */
+void tfm_nspm_configure_clients(void);
+#endif
+
+/**
+ * \brief Get the client ID of the current NS client
+ *
+ * \return The client id of the current NS client. 0 (invalid client id) is
+ * returned in case of error.
+ */
+int32_t tfm_nspm_get_current_client_id(void);
+
+#ifdef TFM_PSA_API
+/**
+ * \brief NSPM thread main entry function
+ *
+ * Note: This function should not return back.
+ */
+void tfm_nspm_thread_entry(void);
+#endif
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+/* Unnecessary to configure Non-secure side code */
+#define configure_ns_code() do {} while (0)
+#else
+/*
+ * \brief Configure Non-secure code, such as vector table, MSP and entry point.
+ */
+void configure_ns_code(void);
+#endif
+
+#endif /* __TFM_NSPM_H__ */
diff --git a/secure_fw/spm/include/tfm_platform_core_api.h b/secure_fw/spm/include/tfm_platform_core_api.h
new file mode 100644
index 0000000..0f0d759
--- /dev/null
+++ b/secure_fw/spm/include/tfm_platform_core_api.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_PLATFORM_CORE_API_H__
+#define __TFM_PLATFORM_CORE_API_H__
+
+#include <stdbool.h>
+
+/**
+ * \brief Should be called in case of access violation.
+ *
+ * There might be platform specific means, by which it is possible on a
+ * subsystem to detect access violation. For example a platform can have a
+ * Peripheral Protection Controller, to detect unauthorised accesses to
+ * peripheral registers. Setting up the protection, and handling the violation
+ * is implemented in platform specific code. However TF-M should be able to
+ * decide how to proceed if a violation happens. So to notify TF-M, platform
+ * code have to call this function, if a violation happens.
+ */
+void tfm_access_violation_handler(void);
+
+/**
+ * \brief Return whether a secure partition is privileged.
+ *
+ * \param[in] partition_idx The index of the partition in the partition_db.
+ *
+ * \return True if the partition is privileged, false otherwise.
+ */
+bool tfm_is_partition_privileged(uint32_t partition_idx);
+
+#endif /* __TFM_PLATFORM_CORE_API_H__ */
diff --git a/secure_fw/spm/include/tfm_secure_api.h b/secure_fw/spm/include/tfm_secure_api.h
new file mode 100644
index 0000000..2112ce9
--- /dev/null
+++ b/secure_fw/spm/include/tfm_secure_api.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SECURE_API_H__
+#define __TFM_SECURE_API_H__
+
+#ifndef TFM_MULTI_CORE_TOPOLOGY
+#include <arm_cmse.h>
+#endif
+#include "tfm_arch.h"
+#include "tfm/tfm_core_svc.h"
+#include "tfm_core.h"
+#include "tfm_api.h"
+#include "tfm_utils.h"
+#include "bl2/include/tfm_boot_status.h"
+#include "psa/service.h"
+
+#ifndef TFM_MULTI_CORE_TOPOLOGY
+/*!
+ * \def __tfm_secure_gateway_attributes__
+ *
+ * \brief Attributes for secure gateway functions
+ */
+#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
+/*
+ * GNUARM requires noclone attribute to protect gateway function symbol from
+ * being renamed and cloned
+ */
+#define __tfm_secure_gateway_attributes__ \
+ __attribute__((cmse_nonsecure_entry, noclone, section("SFN")))
+#else
+#define __tfm_secure_gateway_attributes__ \
+ __attribute__((cmse_nonsecure_entry, section("SFN")))
+#endif /* __GNUC__ && !__ARMCC_VERSION */
+
+/*!
+ * \def __tfm_psa_secure_gateway_attributes__
+ *
+ * \brief Attributes for psa api secure gateway functions
+ */
+#if defined(__GNUC__) && !defined(__ARMCC_VERSION)
+/*
+ * GNUARM requires noclone attribute to protect gateway function symbol from
+ * being renamed and cloned
+ */
+#define __tfm_psa_secure_gateway_attributes__ \
+ __attribute__((cmse_nonsecure_entry, noclone, naked, section("SFN")))
+#else
+#define __tfm_psa_secure_gateway_attributes__ \
+ __attribute__((cmse_nonsecure_entry, naked, section("SFN")))
+#endif /* __GNUC__ && !__ARMCC_VERSION */
+#endif /* TFM_MULTI_CORE_TOPOLOGY */
+
+/* Hide specific errors if not debugging */
+#ifdef TFM_CORE_DEBUG
+#define TFM_ERROR_STATUS(status) (status)
+#else
+#define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
+#endif
+
+#ifndef TFM_LVL
+#error TFM_LVL is not defined!
+#endif
+
+extern void tfm_secure_api_error_handler(void);
+
+typedef int32_t(*sfn_t)(int32_t, int32_t, int32_t, int32_t);
+
+struct tfm_sfn_req_s {
+ uint32_t sp_id;
+ sfn_t sfn;
+ int32_t *args;
+ uint32_t caller_part_idx;
+ bool ns_caller;
+};
+
+enum tfm_memory_access_e {
+ TFM_MEMORY_ACCESS_RO = 1,
+ TFM_MEMORY_ACCESS_RW = 2,
+};
+
+extern int32_t tfm_core_validate_secure_caller(void);
+
+extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
+
+extern int32_t tfm_core_get_boot_data(uint8_t major_type,
+ struct tfm_boot_data *boot_data,
+ uint32_t len);
+
+int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr);
+
+int32_t tfm_spm_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
+
+/**
+ * \brief Check whether a memory range is inside a memory region.
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] region_start The start address of the region, which should
+ * contain the range
+ * \param[in] region_limit The end address of the region, which should contain
+ * the range
+ *
+ * \return TFM_SUCCESS if the region contains the range,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+enum tfm_status_e check_address_range(const void *p, size_t s,
+ uintptr_t region_start,
+ uintptr_t region_limit);
+
+void tfm_enable_irq(psa_signal_t irq_signal);
+void tfm_disable_irq(psa_signal_t irq_signal);
+
+#ifdef TFM_PSA_API
+/* The following macros are only valid if secure services can be called
+ * using veneer functions. This is not the case if IPC messaging is enabled
+ */
+#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \
+ do { \
+ ERROR_MSG("Invalid TF-M configuration detected"); \
+ tfm_secure_api_error_handler(); \
+ /* This point never reached */ \
+ return (int32_t)TFM_ERROR_GENERIC; \
+ } while (0)
+#else
+#define TFM_CORE_IOVEC_SFN_REQUEST(id, is_ns, fn, a, b, c, d) \
+ return tfm_core_partition_request(id, is_ns, fn, \
+ (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
+
+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);
+
+__attribute__ ((always_inline)) __STATIC_INLINE
+bool tfm_core_is_ns_client(void)
+{
+ /*
+ * This preprocessor condition checks if a version of GCC smaller than
+ * 7.3.1 is being used to compile the code.
+ * These versions are affected by a bug on the cmse_nonsecure_caller
+ * intrinsic which returns incorrect results.
+ * Please check Bug 85203 on GCC Bugzilla for more information.
+ */
+#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && \
+ (__GNUC__ < 7 || \
+ (__GNUC__ == 7 && (__GNUC_MINOR__ < 3 || \
+ (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ < 1))))
+ /*
+ * Use the fact that, if called from Non-Secure, the LSB of the return
+ * address is set to 0.
+ */
+ return !(
+ (uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0U))
+ & 0x1);
+#else
+ /*
+ * Convert the result of cmse_nonsecure_caller from an int to a bool
+ * to prevent using an int in the tfm_sfn_req_s structure.
+ */
+ return (cmse_nonsecure_caller() != 0) ? true : false;
+#endif /* Check for GCC compiler version smaller than 7.3.1 */
+}
+#endif
+
+#endif /* __TFM_SECURE_API_H__ */
diff --git a/secure_fw/spm/include/tfm_utils.h b/secure_fw/spm/include/tfm_utils.h
new file mode 100644
index 0000000..4354eda
--- /dev/null
+++ b/secure_fw/spm/include/tfm_utils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_UTILS_H__
+#define __TFM_UTILS_H__
+
+#include <stdio.h>
+
+/*
+ * CPU spin here.
+ * Note: this function is used to handle PROGRAMMER ERROR.
+ */
+void tfm_core_panic(void);
+
+/* Core assert and spin */
+#ifndef NDEBUG
+#define TFM_CORE_ASSERT(cond) \
+ do { \
+ if (!(cond)) { \
+ while (1) \
+ ; \
+ } \
+ } while (0)
+#else
+#define TFM_CORE_ASSERT(cond)
+#endif
+
+/* Get container structure start address from member */
+#define TFM_GET_CONTAINER_PTR(ptr, type, member) \
+ (type *)((unsigned long)(ptr) - offsetof(type, member))
+
+#endif /* __TFM_UTILS_H__ */
diff --git a/secure_fw/spm/include/tfm_version.h b/secure_fw/spm/include/tfm_version.h
new file mode 100644
index 0000000..461ba97
--- /dev/null
+++ b/secure_fw/spm/include/tfm_version.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_VERSION_H__
+#define __TFM_VERSION_H__
+
+/*
+ * Defines for TFM version.
+ */
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 0
+#define VERSION_STRING ""
+
+#endif /* __TFM_VERSION_H__ */
diff --git a/secure_fw/spm/init/tfm_boot_data.c b/secure_fw/spm/init/tfm_boot_data.c
new file mode 100644
index 0000000..2dfbbc4
--- /dev/null
+++ b/secure_fw/spm/init/tfm_boot_data.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "bl2/include/tfm_boot_status.h"
+#include "region_defs.h"
+#include "tfm_memory_utils.h"
+#include "tfm_internal.h"
+#include "tfm_api.h"
+#include "tfm_core_utils.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_partition_defs.h"
+#ifdef TFM_PSA_API
+#include "tfm_internal_defines.h"
+#include "tfm_utils.h"
+#include "psa/service.h"
+#include "tfm_thread.h"
+#include "tfm_wait.h"
+#include "tfm_message_queue.h"
+#include "tfm_spm_hal.h"
+#include "tfm/spm_db.h"
+#endif
+
+/*!
+ * \def BOOT_DATA_VALID
+ *
+ * \brief Indicates that shared data between bootloader and runtime firmware was
+ * passed the sanity check with success.
+ */
+#define BOOT_DATA_VALID (1u)
+
+/*!
+ * \def BOOT_DATA_INVALID
+ *
+ * \brief Indicates that shared data between bootloader and runtime firmware was
+ * failed on sanity check.
+ */
+#define BOOT_DATA_INVALID (0u)
+
+/*!
+ * \var is_boot_data_valid
+ *
+ * \brief Indicates the status of shared data between bootloader and runtime
+ * firmware
+ */
+static uint32_t is_boot_data_valid = BOOT_DATA_INVALID;
+
+/*!
+ * \struct boot_data_access_policy
+ *
+ * \brief Defines the access policy of secure partitions to data items in shared
+ * data area (between bootloader and runtime firmware).
+ */
+struct boot_data_access_policy {
+ uint32_t partition_id;
+ uint32_t major_type;
+};
+
+/*!
+ * \var access_policy_table
+ *
+ * \brief Contains the partition_id and major_type assignments. This describes
+ * which secure partition is allowed to access which data item
+ * (identified by major_type).
+ */
+static const struct boot_data_access_policy access_policy_table[] = {
+ {TFM_SP_INITIAL_ATTESTATION, TLV_MAJOR_IAS},
+};
+
+/*!
+ * \brief Verify the access right of the active secure partition to the
+ * specified data type in the shared data area.
+ *
+ * \param[in] major_type Data type identifier.
+ *
+ * \return Returns 0 in case of success, otherwise -1.
+ */
+static int32_t tfm_core_check_boot_data_access_policy(uint8_t major_type)
+{
+ uint32_t partition_id;
+ uint32_t i;
+ int32_t rc = -1;
+ const uint32_t array_size =
+ sizeof(access_policy_table) / sizeof(access_policy_table[0]);
+
+#ifndef TFM_PSA_API
+ uint32_t partition_idx = tfm_spm_partition_get_running_partition_idx();
+
+ partition_id = tfm_spm_partition_get_partition_id(partition_idx);
+#else
+ partition_id = tfm_spm_partition_get_running_partition_id();
+#endif
+
+ for (i = 0; i < array_size; ++i) {
+ if (partition_id == access_policy_table[i].partition_id) {
+ if (major_type == access_policy_table[i].major_type) {
+ rc = 0;
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/* Compile time check to verify that shared data region is not overlapping with
+ * non-secure data area.
+ */
+#if ((BOOT_TFM_SHARED_DATA_BASE >= NS_DATA_START && \
+ BOOT_TFM_SHARED_DATA_BASE <= NS_DATA_LIMIT) || \
+ (BOOT_TFM_SHARED_DATA_LIMIT >= NS_DATA_START && \
+ BOOT_TFM_SHARED_DATA_LIMIT <= NS_DATA_LIMIT))
+#error "Shared data area and non-secure data area is overlapping"
+#endif
+
+void tfm_core_validate_boot_data(void)
+{
+#ifdef BOOT_DATA_AVAILABLE
+ struct tfm_boot_data *boot_data;
+
+ boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
+
+ if (boot_data->header.tlv_magic == SHARED_DATA_TLV_INFO_MAGIC) {
+ is_boot_data_valid = BOOT_DATA_VALID;
+ }
+#else
+ is_boot_data_valid = BOOT_DATA_VALID;
+#endif /* BOOT_DATA_AVAILABLE */
+}
+
+void tfm_core_get_boot_data_handler(uint32_t args[])
+{
+ uint8_t tlv_major = (uint8_t)args[0];
+ uint8_t *buf_start = (uint8_t *)args[1];
+ uint16_t buf_size = (uint16_t)args[2];
+ struct tfm_boot_data *boot_data;
+#ifdef BOOT_DATA_AVAILABLE
+ uint8_t *ptr;
+ struct shared_data_tlv_entry tlv_entry;
+ uintptr_t tlv_end, offset;
+#endif /* BOOT_DATA_AVAILABLE */
+#ifndef TFM_PSA_API
+ uint32_t running_partition_idx =
+ tfm_spm_partition_get_running_partition_idx();
+ uint32_t res;
+#else
+ struct spm_partition_desc_t *partition = NULL;
+ uint32_t privileged;
+#endif
+
+#ifndef TFM_PSA_API
+ /*
+ * Make sure that the output pointer points to a memory area that is owned
+ * by the partition. And check 4 bytes alignment.
+ */
+ res = tfm_spm_check_buffer_access(running_partition_idx,
+ (void *)buf_start,
+ buf_size,
+ 2);
+ if (!res) {
+ /* Not in accessible range, return error */
+ args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+#else
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_core_panic();
+ }
+ privileged =
+ tfm_spm_partition_get_privileged_mode(partition->static_data->
+ partition_flags);
+
+ if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW,
+ privileged) != IPC_SUCCESS) {
+ /* Not in accessible range, return error */
+ args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+#endif
+
+ if (is_boot_data_valid != BOOT_DATA_VALID) {
+ args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Check whether caller has access right to given tlv_major_type */
+ if (tfm_core_check_boot_data_access_policy(tlv_major)) {
+ args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+#ifdef BOOT_DATA_AVAILABLE
+ /* Get the boundaries of TLV section */
+ boot_data = (struct tfm_boot_data *)BOOT_TFM_SHARED_DATA_BASE;
+ tlv_end = BOOT_TFM_SHARED_DATA_BASE + boot_data->header.tlv_tot_len;
+ offset = BOOT_TFM_SHARED_DATA_BASE + SHARED_DATA_HEADER_SIZE;
+#endif /* BOOT_DATA_AVAILABLE */
+
+ /* Add header to output buffer as well */
+ if (buf_size < SHARED_DATA_HEADER_SIZE) {
+ args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ } else {
+ boot_data = (struct tfm_boot_data *)buf_start;
+ boot_data->header.tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
+ boot_data->header.tlv_tot_len = SHARED_DATA_HEADER_SIZE;
+ }
+
+#ifdef BOOT_DATA_AVAILABLE
+ ptr = boot_data->data;
+ /* Iterates over the TLV section and copy TLVs with requested major
+ * type to the provided buffer.
+ */
+ for (; offset < tlv_end; offset += tlv_entry.tlv_len) {
+ /* Create local copy to avoid unaligned access */
+ (void)tfm_core_util_memcpy(&tlv_entry,
+ (const void *)offset,
+ SHARED_DATA_ENTRY_HEADER_SIZE);
+ if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
+ /* Check buffer overflow */
+ if (((ptr - buf_start) + tlv_entry.tlv_len) > buf_size) {
+ args[0] = (uint32_t)TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ (void)tfm_core_util_memcpy(ptr, (const void *)offset,
+ tlv_entry.tlv_len);
+
+ ptr += tlv_entry.tlv_len;
+ boot_data->header.tlv_tot_len += tlv_entry.tlv_len;
+ }
+ }
+#endif /* BOOT_DATA_AVAILABLE */
+
+ args[0] = (uint32_t)TFM_SUCCESS;
+ return;
+}
diff --git a/secure_fw/spm/init/tfm_core.c b/secure_fw/spm/init/tfm_core.c
new file mode 100644
index 0000000..e1f0c14
--- /dev/null
+++ b/secure_fw/spm/init/tfm_core.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "region.h"
+#include "tfm_core_topology.h"
+#include "tfm_internal.h"
+#include "tfm_irq_list.h"
+#include "tfm_nspm.h"
+#include "tfm_spm_hal.h"
+#include "tfm_version.h"
+#include "log/tfm_log.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_db.h"
+
+/*
+ * Avoids the semihosting issue
+ * FixMe: describe 'semihosting issue'
+ */
+#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
+__asm(" .global __ARM_use_no_argv\n");
+#endif
+
+#ifndef TFM_LVL
+#error TFM_LVL is not defined!
+#endif
+
+#ifdef TFM_PSA_API
+#if (TFM_LVL != 1) && (TFM_LVL != 2)
+#error Only TFM_LVL 1 and 2 are supported for IPC model!
+#endif
+#else
+#if (TFM_LVL != 1)
+#error Only TFM_LVL 1 is supported for library model!
+#endif
+#endif
+
+REGION_DECLARE(Image$$, ARM_LIB_STACK_MSP, $$ZI$$Base);
+
+static int32_t tfm_core_init(void)
+{
+ size_t i;
+ enum tfm_plat_err_t plat_err = TFM_PLAT_ERR_SYSTEM_ERR;
+ enum irq_target_state_t irq_target_state = TFM_IRQ_TARGET_STATE_SECURE;
+
+ /* Enables fault handlers */
+ plat_err = tfm_spm_hal_enable_fault_handlers();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ /* Configures the system reset request properties */
+ plat_err = tfm_spm_hal_system_reset_cfg();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ /* Configures debug authentication */
+ plat_err = tfm_spm_hal_init_debug();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ /*
+ * Access to any peripheral should be performed after programming
+ * the necessary security components such as PPC/SAU.
+ */
+ plat_err = tfm_spm_hal_init_isolation_hw();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ /* Performs platform specific initialization */
+ plat_err = tfm_spm_hal_post_init();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ LOG_MSG("\033[1;34m[Sec Thread] Secure image initializing!\033[0m\r\n");
+
+#ifdef TFM_CORE_DEBUG
+ LOG_MSG("TF-M isolation level is: %d\r\n", TFM_LVL);
+#endif
+
+ tfm_core_validate_boot_data();
+
+ configure_ns_code();
+
+ /* Configures all interrupts to retarget NS state, except for
+ * secure peripherals
+ */
+ plat_err = tfm_spm_hal_nvic_interrupt_target_state_cfg();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ for (i = 0; i < tfm_core_irq_signals_count; ++i) {
+ plat_err = tfm_spm_hal_set_secure_irq_priority(
+ tfm_core_irq_signals[i].irq_line,
+ tfm_core_irq_signals[i].irq_priority);
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+ irq_target_state = tfm_spm_hal_set_irq_target_state(
+ tfm_core_irq_signals[i].irq_line,
+ TFM_IRQ_TARGET_STATE_SECURE);
+ if (irq_target_state != TFM_IRQ_TARGET_STATE_SECURE) {
+ return TFM_ERROR_GENERIC;
+ }
+ }
+
+ /* Enable secure peripherals interrupts */
+ plat_err = tfm_spm_hal_nvic_interrupt_enable();
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ return TFM_SUCCESS;
+}
+
+static int32_t tfm_core_set_secure_exception_priorities(void)
+{
+ enum tfm_plat_err_t plat_err = TFM_PLAT_ERR_SYSTEM_ERR;
+
+ tfm_arch_prioritize_secure_exception();
+
+ /* Explicitly set Secure SVC priority to highest */
+ plat_err = tfm_spm_hal_set_secure_irq_priority(SVCall_IRQn, 0);
+ if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ tfm_core_topology_set_pendsv_priority();
+
+ return TFM_SUCCESS;
+}
+
+int main(void)
+{
+ /* set Main Stack Pointer limit */
+ tfm_arch_set_msplim((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK_MSP,
+ $$ZI$$Base));
+
+ if (tfm_core_init() != TFM_SUCCESS) {
+ tfm_core_panic();
+ }
+ /* Print the TF-M version */
+ LOG_MSG("\033[1;34mBooting TFM v%d.%d %s\033[0m\r\n",
+ VERSION_MAJOR, VERSION_MINOR, VERSION_STRING);
+
+ if (tfm_spm_db_init() != SPM_ERR_OK) {
+ tfm_core_panic();
+ }
+
+#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+ if (tfm_spm_hal_setup_isolation_hw() != TFM_PLAT_ERR_SUCCESS) {
+ tfm_core_panic();
+ }
+#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
+
+#ifndef TFM_PSA_API
+ tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_RUNNING);
+
+ REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base)[];
+ uint32_t psp_stack_bottom =
+ (uint32_t)REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
+
+ tfm_arch_set_psplim(psp_stack_bottom);
+
+ if (tfm_spm_partition_init() != SPM_ERR_OK) {
+ /* Certain systems might refuse to boot altogether if partitions fail
+ * to initialize. This is a placeholder for such an error handler
+ */
+ }
+
+ /*
+ * Prioritise secure exceptions to avoid NS being able to pre-empt
+ * secure SVC or SecureFault. Do it before PSA API initialization.
+ */
+ if (tfm_core_set_secure_exception_priorities() != TFM_SUCCESS) {
+ tfm_core_panic();
+ }
+
+ /* We close the TFM_SP_CORE_ID partition, because its only purpose is
+ * to be able to pass the state checks for the tests started from secure.
+ */
+ tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_CLOSED);
+ tfm_spm_partition_set_state(TFM_SP_NON_SECURE_ID,
+ SPM_PARTITION_STATE_RUNNING);
+
+#ifdef TFM_CORE_DEBUG
+ /* Jumps to non-secure code */
+ LOG_MSG("\033[1;34mJumping to non-secure code...\033[0m\r\n");
+#endif
+
+ jump_to_ns_code();
+#else /* !defined(TFM_PSA_API) */
+ /*
+ * Prioritise secure exceptions to avoid NS being able to pre-empt
+ * secure SVC or SecureFault. Do it before PSA API initialization.
+ */
+ if (tfm_core_set_secure_exception_priorities() != TFM_SUCCESS) {
+ tfm_core_panic();
+ }
+
+ /* Move to handler mode for further SPM initialization. */
+ tfm_core_handler_mode();
+#endif /* !defined(TFM_PSA_API) */
+}
diff --git a/secure_fw/spm/model_func/CMakeLists.inc b/secure_fw/spm/model_func/CMakeLists.inc
new file mode 100644
index 0000000..154417c
--- /dev/null
+++ b/secure_fw/spm/model_func/CMakeLists.inc
@@ -0,0 +1,60 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#This file assumes it will be included from a project specific cmakefile.
+#
+#Inputs:
+# TFM_ROOT_DIR - directory where secure FW sourec is located.
+#
+#Outputs:
+# Will modify include directories to make the source compile.
+# ALL_SRC_C: C source files to be compiled will be added to this list.
+# This shall be added to your add_executable or add_library command.
+# ALL_SRC_CXX: C++ source files to be compiled will be added to this list.
+# This shall be added to your add_executable or add_library command.
+# ALL_SRC_ASM: assembly source files to be compiled will be added to this
+# list. This shall be added to your add_executable or add_library
+# command.
+# Include directories will be modified by using the include_directories()
+# commands as needed.
+
+if(NOT DEFINED TFM_ROOT_DIR)
+ message(FATAL_ERROR
+ "Please set TFM_ROOT_DIR before including this file.")
+endif()
+
+#Get the current directory where this file is located.
+set(SFW_FUNC_SPM_DIR ${CMAKE_CURRENT_LIST_DIR})
+set(SFW_SPM_DIR "${SFW_FUNC_SPM_DIR}/..")
+set(SFW_SPM_ARCH_DIR "${SFW_SPM_DIR}/arch")
+set(SFW_SPM_INIT_DIR "${SFW_SPM_DIR}/init")
+
+set (SFW_FUNC_SPM_SRC
+ "${SFW_SPM_INIT_DIR}/tfm_boot_data.c"
+ "${SFW_SPM_INIT_DIR}/tfm_core.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_core_svcalls_func.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_secure_api.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_spm_services.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/spm_api.c"
+ "${SFW_FUNC_SPM_DIR}/spm_func.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_nspm_func.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_utils.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_core_mem_check.c"
+ "${SFW_FUNC_SPM_DIR}/../runtime/tfm_core_utils.c"
+ "${SFW_FUNC_SPM_DIR}/tfm_veneers.c"
+ )
+
+#Append all our source files to global lists.
+list(APPEND ALL_SRC_C ${SFW_FUNC_SPM_SRC})
+unset(SFW_FUNC_SPM_SRC)
+
+#Setting include directories
+embedded_include_directories(PATH ${SFW_FUNC_SPM_DIR} ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm/arch/include ABSOLUTE)
diff --git a/secure_fw/spm/spm_func.c b/secure_fw/spm/model_func/spm_func.c
similarity index 99%
rename from secure_fw/spm/spm_func.c
rename to secure_fw/spm/model_func/spm_func.c
index 696fdcf..cd88329 100644
--- a/secure_fw/spm/spm_func.c
+++ b/secure_fw/spm/model_func/spm_func.c
@@ -17,11 +17,11 @@
#include "tfm_core_mem_check.h"
#include "tfm_secure_api.h"
#include "tfm_spm_hal.h"
-#include "spm_api.h"
-#include "spm_db.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_db.h"
#include "region_defs.h"
#include "region.h"
-#include "tfm_spm_services_api.h"
+#include "tfm/tfm_spm_services_api.h"
#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
#define EXC_RETURN_SECURE_HANDLER 0xFFFFFFF1
diff --git a/secure_fw/spm/model_func/tfm_core_svcalls_func.c b/secure_fw/spm/model_func/tfm_core_svcalls_func.c
new file mode 100644
index 0000000..9af7104
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_core_svcalls_func.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+
+#include "secure_utilities.h"
+#include "tfm/tfm_core_svc.h"
+#include "tfm_secure_api.h"
+#include "region_defs.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_partition_defs.h"
+#include "tfm_api.h"
+#include "tfm_internal.h"
+#include "tfm_memory_utils.h"
+#include "tfm_arch.h"
+#include "tfm_peripherals_def.h"
+#include "tfm_irq_list.h"
+
+#ifdef PLATFORM_SVC_HANDLERS
+extern int32_t platform_svc_handlers(tfm_svc_number_t svc_num,
+ uint32_t *svc_args, uint32_t lr);
+#endif
+
+/* Include the definitions of the privileged IRQ handlers in case of library
+ * model
+ */
+#include "tfm_secure_irq_handlers.inc"
+
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t lr, uint32_t *msp)
+{
+ uint8_t svc_number = 0;
+ /*
+ * Stack contains:
+ * r0, r1, r2, r3, r12, r14 (lr), the return address and xPSR
+ * First argument (r0) is svc_args[0]
+ */
+ if (is_return_secure_stack(lr)) {
+ /* SV called directly from secure context. Check instruction for
+ * svc_number
+ */
+ svc_number = ((uint8_t *)svc_args[6])[-2];
+ } else {
+ /* Secure SV executing with NS return.
+ * NS cannot directly trigger S SVC so this should not happen. This is
+ * an unrecoverable error.
+ */
+ tfm_core_panic();
+ }
+ switch (svc_number) {
+ case TFM_SVC_SFN_REQUEST:
+ lr = tfm_spm_partition_request_svc_handler(svc_args, lr);
+ break;
+ case TFM_SVC_SFN_RETURN:
+ lr = tfm_spm_partition_return_handler(lr);
+ break;
+ case TFM_SVC_VALIDATE_SECURE_CALLER:
+ tfm_spm_validate_secure_caller_handler(svc_args);
+ break;
+ case TFM_SVC_GET_CALLER_CLIENT_ID:
+ tfm_spm_get_caller_client_id_handler(svc_args);
+ break;
+ case TFM_SVC_SPM_REQUEST:
+ tfm_spm_request_handler((struct tfm_state_context_t *)svc_args);
+ break;
+ case TFM_SVC_DEPRIV_REQ:
+ lr = tfm_spm_depriv_req_handler(svc_args, lr);
+ break;
+ case TFM_SVC_DEPRIV_RET:
+ lr = tfm_spm_depriv_return_handler(msp, lr);
+ break;
+ case TFM_SVC_PSA_WAIT:
+ tfm_spm_psa_wait(svc_args);
+ break;
+ case TFM_SVC_PSA_EOI:
+ tfm_spm_psa_eoi(svc_args);
+ break;
+ case TFM_SVC_ENABLE_IRQ:
+ tfm_spm_enable_irq_handler(svc_args);
+ break;
+ case TFM_SVC_DISABLE_IRQ:
+ tfm_spm_disable_irq_handler(svc_args);
+ break;
+ case TFM_SVC_GET_BOOT_DATA:
+ tfm_core_get_boot_data_handler(svc_args);
+ break;
+ default:
+#ifdef PLATFORM_SVC_HANDLERS
+ svc_args[0] = platform_svc_handlers(svc_num, svc_args, lr);
+#endif
+ break;
+ }
+
+ return lr;
+}
+
+void tfm_access_violation_handler(void)
+{
+ while (1) {
+ ;
+ }
+}
diff --git a/secure_fw/spm/model_func/tfm_nspm_func.c b/secure_fw/spm/model_func/tfm_nspm_func.c
new file mode 100644
index 0000000..83bcce6
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_nspm_func.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "cmsis_compiler.h"
+#include "platform/include/tfm_spm_hal.h"
+#include "tfm_arch.h"
+#include "tfm_api.h"
+#include "tfm_internal.h"
+#include "tfm_nspm.h"
+
+#ifndef TFM_MAX_NS_THREAD_COUNT
+#define TFM_MAX_NS_THREAD_COUNT 8
+#endif
+#define INVALID_CLIENT_ID 0
+
+#define DEFAULT_NS_CLIENT_ID ((int32_t)-1)
+
+#define INVALID_NS_CLIENT_IDX (-1)
+#define DEFAULT_NS_CLIENT_IDX 0
+
+typedef uint32_t TZ_ModuleId_t;
+typedef uint32_t TZ_MemoryId_t;
+
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+static struct ns_client_list_t {
+ int32_t ns_client_id;
+ int32_t next_free_index;
+} NsClientIdList[TFM_MAX_NS_THREAD_COUNT];
+
+static int32_t free_index = 0U;
+static int32_t active_ns_client_idx = INVALID_NS_CLIENT_IDX;
+
+static int get_next_ns_client_id()
+{
+ static int32_t next_ns_client_id = DEFAULT_NS_CLIENT_ID;
+
+ if (next_ns_client_id > 0) {
+ next_ns_client_id = DEFAULT_NS_CLIENT_ID;
+ }
+ return next_ns_client_id--;
+}
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+
+void tfm_nspm_configure_clients(void)
+{
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ int32_t i;
+
+ /* Default to one NS client */
+ free_index = 1;
+ NsClientIdList[0].ns_client_id = get_next_ns_client_id();
+ for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
+ NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
+ }
+ active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+}
+
+int32_t tfm_nspm_get_current_client_id(void)
+{
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ if (active_ns_client_idx == INVALID_NS_CLIENT_IDX) {
+ return 0;
+ } else {
+ return NsClientIdList[active_ns_client_idx].ns_client_id;
+ }
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ return DEFAULT_NS_CLIENT_ID;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+}
+
+/*
+ * TF-M implementation of the CMSIS TZ RTOS thread context management API
+ * Currently the context management only contains the NS ID identification
+ */
+
+/// Initialize secure context memory system
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_InitContextSystem_S(void)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ int32_t i;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ /* NS RTOS supports TZ context management, override defaults */
+ for (i = 1; i < TFM_MAX_NS_THREAD_COUNT; ++i) {
+ NsClientIdList[i].ns_client_id = INVALID_CLIENT_ID;
+ NsClientIdList[i].next_free_index = i + 1;
+ }
+
+ /* Terminate list */
+ NsClientIdList[i - 1].next_free_index = INVALID_NS_CLIENT_IDX;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ /* Success */
+ return 1U;
+}
+
+/// Allocate context memory for calling secure software modules in TrustZone
+/// \param[in] module identifies software modules called from non-secure mode
+/// \return value != 0 id TrustZone memory slot identifier
+/// \return value 0 no memory available or internal error
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+TZ_MemoryId_t TZ_AllocModuleContext_S (TZ_ModuleId_t module)
+{
+ TZ_MemoryId_t tz_id = 1;
+ (void) module; /* Currently unused */
+
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ if (free_index < 0) {
+ /* No more free slots */
+ return 0U;
+ }
+
+ /* TZ_MemoryId_t must be a positive integer */
+ tz_id = (TZ_MemoryId_t)free_index + 1;
+ NsClientIdList[free_index].ns_client_id = get_next_ns_client_id();
+ free_index = NsClientIdList[free_index].next_free_index;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return tz_id;
+}
+
+/// Free context memory that was previously allocated with \ref TZ_AllocModuleContext_S
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_FreeModuleContext_S (TZ_MemoryId_t id)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ uint32_t index;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
+ /* Invalid TZ_MemoryId_t */
+ return 0U;
+ }
+
+ index = id - 1;
+
+ if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
+ /* Non-existent client */
+ return 0U;
+ }
+
+ if (active_ns_client_idx == index) {
+ active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
+ }
+ NsClientIdList[index].ns_client_id = INVALID_CLIENT_ID;
+ NsClientIdList[index].next_free_index = free_index;
+
+ free_index = index;
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ (void)id;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#else /* CONFIG_TFM_ENABLE_CTX_MGMT */
+ (void)id;
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return 1U; // Success
+}
+
+/// Load secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_LoadContext_S (TZ_MemoryId_t id)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ uint32_t index;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
+ /* Invalid TZ_MemoryId_t */
+ return 0U;
+ }
+
+ index = id - 1;
+
+ if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
+ /* Non-existent client */
+ return 0U;
+ }
+
+ active_ns_client_idx = index;
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ (void)id;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#else /* CONFIG_TFM_ENABLE_CTX_MGMT */
+ (void)id;
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return 1U; // Success
+}
+
+/// Store secure context (called on RTOS thread context switch)
+/// \param[in] id TrustZone memory slot identifier
+/// \return execution status (1: success, 0: error)
+/* This veneer is TF-M internal, not a secure service */
+__tfm_nspm_secure_gateway_attributes__
+uint32_t TZ_StoreContext_S (TZ_MemoryId_t id)
+{
+#ifdef CONFIG_TFM_ENABLE_CTX_MGMT
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+ uint32_t index;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return 0U;
+ }
+
+ /* id corresponds to context being swapped out on NS side */
+ if ((id == 0U) || (id > TFM_MAX_NS_THREAD_COUNT)) {
+ /* Invalid TZ_MemoryId_t */
+ return 0U;
+ }
+
+ index = id - 1;
+
+ if (NsClientIdList[index].ns_client_id == INVALID_CLIENT_ID) {
+ /* Non-existent client */
+ return 0U;
+ }
+
+ if (active_ns_client_idx != index) {
+ return 0U;
+ }
+
+ active_ns_client_idx = DEFAULT_NS_CLIENT_IDX;
+#else /* TFM_NS_CLIENT_IDENTIFICATION */
+ (void)id;
+#endif /* TFM_NS_CLIENT_IDENTIFICATION */
+#else /* CONFIG_TFM_ENABLE_CTX_MGMT */
+ (void)id;
+#endif /* CONFIG_TFM_ENABLE_CTX_MGMT */
+
+ return 1U; // Success
+}
+
+#ifdef TFM_NS_CLIENT_IDENTIFICATION
+__tfm_nspm_secure_gateway_attributes__
+enum tfm_status_e tfm_register_client_id (int32_t ns_client_id)
+{
+ int current_client_id;
+
+ if (__get_active_exc_num() == EXC_NUM_THREAD_MODE) {
+ /* This veneer should only be called by NS RTOS in handler mode */
+ return TFM_ERROR_NS_THREAD_MODE_CALL;
+ }
+
+ if (ns_client_id >= 0) {
+ /* The client ID is invalid */
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ if (active_ns_client_idx < 0) {
+ /* No client is active */
+ return TFM_ERROR_GENERIC;
+ }
+
+ current_client_id = NsClientIdList[active_ns_client_idx].ns_client_id;
+ if (current_client_id >= 0 ) {
+ /* The client ID is invalid */
+ return TFM_ERROR_INVALID_PARAMETER;
+ }
+
+ NsClientIdList[active_ns_client_idx].ns_client_id = ns_client_id;
+
+ return TFM_SUCCESS;
+}
+#endif
+
+void configure_ns_code(void)
+{
+ /* SCB_NS.VTOR points to the Non-secure vector table base address */
+ SCB_NS->VTOR = tfm_spm_hal_get_ns_VTOR();
+
+ /* Setups Main stack pointer of the non-secure code */
+ uint32_t ns_msp = tfm_spm_hal_get_ns_MSP();
+
+ __TZ_set_MSP_NS(ns_msp);
+
+ /* Get the address of non-secure code entry point to jump there */
+ uint32_t entry_ptr = tfm_spm_hal_get_ns_entry_point();
+
+ /* Clears LSB of the function address to indicate the function-call
+ * will perform the switch from secure to non-secure
+ */
+ ns_entry = (nsfptr_t) cmse_nsfptr_create(entry_ptr);
+}
diff --git a/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc
new file mode 100644
index 0000000..45418a2
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#include "secure_fw/partitions/secure_storage/psa_manifest/tfm_secure_storage.h"
+#include "secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h"
+#include "secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h"
+#include "secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h"
+#include "secure_fw/partitions/platform/psa_manifest/tfm_platform.h"
+#include "secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h"
+#include "test/test_services/tfm_core_test/psa_manifest/tfm_test_core.h"
+#include "test/test_services/tfm_core_test_2/psa_manifest/tfm_test_core_2.h"
+#include "test/test_services/tfm_secure_client_service/psa_manifest/tfm_test_client_service.h"
+#include "test/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_partition.h"
+#include "test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_partition.h"
+#include "test/test_services/tfm_irq_test_service_1/psa_manifest/tfm_irq_test_service_1.h"
+#include "test/test_services/tfm_sst_test_service/psa_manifest/tfm_sst_test_service.h"
+#include "test/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h"
+#include "test/test_services/tfm_multi_core_test/psa_manifest/tfm_multi_core_test.h"
+#include "psa_manifest/pid.h"
+
+/* Definitions of the signals of the IRQs */
+const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = {
+#ifdef TFM_ENABLE_IRQ_TEST
+ { TFM_IRQ_TEST_1, SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ, TFM_TIMER0_IRQ, 64 },
+#endif /* TFM_ENABLE_IRQ_TEST */
+ {0, 0, (IRQn_Type) 0, 0} /* add dummy element to avoid non-standard empty array */
+};
+
+const size_t tfm_core_irq_signals_count = (sizeof(tfm_core_irq_signals) /
+ sizeof(*tfm_core_irq_signals)) - 1; /* adjust for the dummy element */
+
+extern void priv_irq_handler_main(uint32_t partition_id,
+ uint32_t unpriv_handler,
+ uint32_t irq_signal,
+ uint32_t irq_line);
+
+/* Forward declarations of unpriv IRQ handlers*/
+#ifdef TFM_ENABLE_IRQ_TEST
+extern void SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr(void);
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+
+/* Definitions of privileged IRQ handlers */
+#ifdef TFM_ENABLE_IRQ_TEST
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ priv_irq_handler_main(TFM_IRQ_TEST_1,
+ (uint32_t)SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ_isr,
+ SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ,
+ TFM_TIMER0_IRQ);
+}
+
+#endif /* TFM_ENABLE_IRQ_TEST */
+
diff --git a/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc.template b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc.template
new file mode 100644
index 0000000..9db5d64
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_secure_irq_handlers.inc.template
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+{{utilities.donotedit_warning}}
+
+{% for header in utilities.manifest_header_list %}
+#include "{{header}}"
+{% endfor %}
+#include "psa_manifest/pid.h"
+{% macro _irq_record(partition_name, signal, line, priority) -%}
+{ {{ partition_name }}, {{ signal }}, {{ line }}, {{ priority }} },
+{%- endmacro %}
+
+/* Definitions of the signals of the IRQs */
+const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[] = {
+{% for manifest in manifests %}
+ {% if manifest.manifest.irqs %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% for handler in manifest.manifest.irqs %}
+ {% set irq_data = namespace() %}
+ {% if handler.source %}
+ {% set irq_data.line = handler.source %}
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+ {% if handler.tfm_irq_priority %}
+ {% set irq_data.priority = handler.tfm_irq_priority %}
+ {% else %}
+ {% set irq_data.priority = "TFM_DEFAULT_SECURE_IRQ_PRIOTITY" %}
+ {% endif %}
+ {{ _irq_record(manifest.manifest.name, handler.signal, irq_data.line, irq_data.priority) }}
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+ {% endif %}
+{% endfor %}
+ {0, 0, (IRQn_Type) 0, 0} /* add dummy element to avoid non-standard empty array */
+};
+
+const size_t tfm_core_irq_signals_count = (sizeof(tfm_core_irq_signals) /
+ sizeof(*tfm_core_irq_signals)) - 1; /* adjust for the dummy element */
+
+extern void priv_irq_handler_main(uint32_t partition_id,
+ uint32_t unpriv_handler,
+ uint32_t irq_signal,
+ uint32_t irq_line);
+
+/* Forward declarations of unpriv IRQ handlers*/
+{% for manifest in manifests %}
+ {% if manifest.manifest.irqs %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% for handler in manifest.manifest.irqs %}
+extern void {{handler.signal}}_isr(void);
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
+
+/* Definitions of privileged IRQ handlers */
+{% for manifest in manifests %}
+ {% if manifest.manifest.irqs %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+ {% for handler in manifest.manifest.irqs %}
+ {% if handler.source is number %}
+void irq_{{handler.source}}_Handler(void)
+ {% elif handler.source %}
+void {{handler.source}}_Handler(void)
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+{
+ {% if handler.source %}
+ priv_irq_handler_main({{manifest.manifest.name}},
+ (uint32_t){{handler.signal}}_isr,
+ {{handler.signal}},
+ {{handler.source}});
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+}
+
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
diff --git a/secure_fw/spm/tfm_spm_db_func.inc b/secure_fw/spm/model_func/tfm_spm_db_func.inc
similarity index 99%
rename from secure_fw/spm/tfm_spm_db_func.inc
rename to secure_fw/spm/model_func/tfm_spm_db_func.inc
index 7a99476..21a76ca 100644
--- a/secure_fw/spm/tfm_spm_db_func.inc
+++ b/secure_fw/spm/model_func/tfm_spm_db_func.inc
@@ -10,7 +10,7 @@
#ifndef __TFM_SPM_DB_FUNC_INC__
#define __TFM_SPM_DB_FUNC_INC__
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "psa_manifest/sid.h"
/**************************************************************************/
diff --git a/secure_fw/spm/tfm_spm_db_func.inc.template b/secure_fw/spm/model_func/tfm_spm_db_func.inc.template
similarity index 99%
rename from secure_fw/spm/tfm_spm_db_func.inc.template
rename to secure_fw/spm/model_func/tfm_spm_db_func.inc.template
index 8f424b8..55bcce5 100644
--- a/secure_fw/spm/tfm_spm_db_func.inc.template
+++ b/secure_fw/spm/model_func/tfm_spm_db_func.inc.template
@@ -10,7 +10,7 @@
#ifndef __TFM_SPM_DB_FUNC_INC__
#define __TFM_SPM_DB_FUNC_INC__
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "psa_manifest/sid.h"
{# Produce a build error if heap_size is presented in the manifest, because of the dynamic memory allocation is not supported now. #}
diff --git a/secure_fw/spm/model_func/tfm_veneers.c b/secure_fw/spm/model_func/tfm_veneers.c
new file mode 100644
index 0000000..0da2ca9
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_veneers.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#include "tfm_secure_api.h"
+#include "tfm/spm_partition_defs.h"
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+/******** TFM_SP_STORAGE ********/
+psa_status_t tfm_sst_set_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_get_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_get_info_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_sst_get_support_req(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+/******** TFM_SP_ITS ********/
+psa_status_t tfm_its_set_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_get_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_get_info_req(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_its_remove_req(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+/******** TFM_SP_AUDIT_LOG ********/
+psa_status_t audit_core_retrieve_record(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_add_record(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_get_info(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_get_record_info(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t audit_core_delete_record(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+/******** TFM_SP_CRYPTO ********/
+psa_status_t tfm_crypto_get_key_attributes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_open_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_close_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_reset_key_attributes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_import_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_destroy_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_export_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_export_public_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_copy_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_compute(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_compare(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_verify(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_hash_clone(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_compute(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_sign_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_sign_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_encrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_decrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_encrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_decrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_generate_iv(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_set_iv(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_cipher_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_encrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_decrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_encrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_decrypt_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_generate_nonce(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_set_nonce(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_set_lengths(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_update_ad(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_update(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_finish(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_verify(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_sign_hash(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_verify_hash(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_asymmetric_encrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_asymmetric_decrypt(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_setup(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_get_capacity(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_set_capacity(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_input_bytes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_input_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_key_agreement(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_output_bytes(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_output_key(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_derivation_abort(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_raw_key_agreement(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_generate_random(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t tfm_crypto_generate_key(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+/******** TFM_SP_PLATFORM ********/
+psa_status_t platform_sp_system_reset(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_ioctl(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_nv_counter_read(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t platform_sp_nv_counter_increment(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+/******** TFM_SP_INITIAL_ATTESTATION ********/
+psa_status_t initial_attest_get_token(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t initial_attest_get_token_size(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t initial_attest_get_public_key(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST ********/
+psa_status_t spm_core_test_sfn(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_sfn_init_success(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_sfn_direct_recursion(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST_2 ********/
+psa_status_t spm_core_test_2_slave_service(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_sfn_invert(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_check_caller_client_id(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_get_every_second_byte(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_prepare_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_core_test_2_execute_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_TEST_PARTITION ********/
+psa_status_t tfm_secure_client_service_sfn_run_tests(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+/******** TFM_IRQ_TEST_1 ********/
+psa_status_t spm_irq_test_1_prepare_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+psa_status_t spm_irq_test_1_execute_test_scenario(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+/******** TFM_SP_SST_TEST ********/
+psa_status_t tfm_sst_test_prepare(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_CLIENT_2 ********/
+psa_status_t tfm_secure_client_2_call(psa_invec *, size_t, psa_outvec *, size_t);
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+/******** TFM_SP_MULTI_CORE_TEST ********/
+#endif /* TFM_MULTI_CORE_TEST */
+
+
+#define TFM_VENEER_FUNCTION(partition_name, sfn_name) \
+ __tfm_secure_gateway_attributes__ \
+ psa_status_t tfm_##sfn_name##_veneer(psa_invec *in_vec, \
+ size_t in_len, \
+ psa_outvec *out_vec, \
+ size_t out_len) \
+ { \
+ bool is_ns = tfm_core_is_ns_client(); \
+ \
+ TFM_CORE_IOVEC_SFN_REQUEST(partition_name, \
+ is_ns, \
+ (void *) sfn_name, \
+ in_vec, in_len, out_vec, out_len); \
+ }
+
+#ifdef TFM_PARTITION_SECURE_STORAGE
+/******** TFM_SP_STORAGE ********/
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_set_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_info_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_remove_req)
+TFM_VENEER_FUNCTION(TFM_SP_STORAGE, tfm_sst_get_support_req)
+#endif /* TFM_PARTITION_SECURE_STORAGE */
+
+#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE
+/******** TFM_SP_ITS ********/
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_set_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_get_info_req)
+TFM_VENEER_FUNCTION(TFM_SP_ITS, tfm_its_remove_req)
+#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */
+
+#ifdef TFM_PARTITION_AUDIT_LOG
+/******** TFM_SP_AUDIT_LOG ********/
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_retrieve_record)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_add_record)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_get_info)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_get_record_info)
+TFM_VENEER_FUNCTION(TFM_SP_AUDIT_LOG, audit_core_delete_record)
+#endif /* TFM_PARTITION_AUDIT_LOG */
+
+#ifdef TFM_PARTITION_CRYPTO
+/******** TFM_SP_CRYPTO ********/
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_get_key_attributes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_open_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_close_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_reset_key_attributes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_import_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_destroy_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_public_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_copy_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_compute)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_compare)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_verify)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_hash_clone)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_compute)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_sign_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_sign_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_verify_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_mac_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_generate_iv)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_set_iv)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_decrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_decrypt_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_generate_nonce)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_set_nonce)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_set_lengths)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_update_ad)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_update)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_finish)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_verify)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_sign_hash)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_verify_hash)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_asymmetric_encrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_asymmetric_decrypt)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_setup)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_get_capacity)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_set_capacity)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_input_bytes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_input_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_key_agreement)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_output_bytes)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_output_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_derivation_abort)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_raw_key_agreement)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_generate_random)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_generate_key)
+#endif /* TFM_PARTITION_CRYPTO */
+
+#ifdef TFM_PARTITION_PLATFORM
+/******** TFM_SP_PLATFORM ********/
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_system_reset)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_ioctl)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_nv_counter_read)
+TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_nv_counter_increment)
+#endif /* TFM_PARTITION_PLATFORM */
+
+#ifdef TFM_PARTITION_INITIAL_ATTESTATION
+/******** TFM_SP_INITIAL_ATTESTATION ********/
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_token)
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_token_size)
+TFM_VENEER_FUNCTION(TFM_SP_INITIAL_ATTESTATION, initial_attest_get_public_key)
+#endif /* TFM_PARTITION_INITIAL_ATTESTATION */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST ********/
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, spm_core_test_sfn)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, spm_core_test_sfn_init_success)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST, spm_core_test_sfn_direct_recursion)
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST_2 ********/
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_slave_service)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_sfn_invert)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_check_caller_client_id)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_get_every_second_byte)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_prepare_test_scenario)
+TFM_VENEER_FUNCTION(TFM_SP_CORE_TEST_2, spm_core_test_2_execute_test_scenario)
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_TEST_PARTITION ********/
+TFM_VENEER_FUNCTION(TFM_SP_SECURE_TEST_PARTITION, tfm_secure_client_service_sfn_run_tests)
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_PARTITION_TEST_CORE_IPC
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE_IPC */
+
+#ifdef TFM_ENABLE_IRQ_TEST
+/******** TFM_IRQ_TEST_1 ********/
+TFM_VENEER_FUNCTION(TFM_IRQ_TEST_1, spm_irq_test_1_prepare_test_scenario)
+TFM_VENEER_FUNCTION(TFM_IRQ_TEST_1, spm_irq_test_1_execute_test_scenario)
+#endif /* TFM_ENABLE_IRQ_TEST */
+
+#ifdef TFM_PARTITION_TEST_SST
+/******** TFM_SP_SST_TEST ********/
+TFM_VENEER_FUNCTION(TFM_SP_SST_TEST, tfm_sst_test_prepare)
+#endif /* TFM_PARTITION_TEST_SST */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_CLIENT_2 ********/
+TFM_VENEER_FUNCTION(TFM_SP_SECURE_CLIENT_2, tfm_secure_client_2_call)
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_MULTI_CORE_TEST
+/******** TFM_SP_MULTI_CORE_TEST ********/
+#endif /* TFM_MULTI_CORE_TEST */
+
diff --git a/secure_fw/spm/model_func/tfm_veneers.c.template b/secure_fw/spm/model_func/tfm_veneers.c.template
new file mode 100644
index 0000000..f6b482e
--- /dev/null
+++ b/secure_fw/spm/model_func/tfm_veneers.c.template
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+{{utilities.donotedit_warning}}
+
+#include "tfm_secure_api.h"
+#include "tfm/spm_partition_defs.h"
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+/******** {{manifest.manifest.name}} ********/
+ {% for sec_func in manifest.manifest.secure_functions %}
+psa_status_t {{sec_func.signal.lower()}}(psa_invec *, size_t, psa_outvec *, size_t);
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
+
+#define TFM_VENEER_FUNCTION(partition_name, sfn_name) \
+ __tfm_secure_gateway_attributes__ \
+ psa_status_t tfm_##sfn_name##_veneer(psa_invec *in_vec, \
+ size_t in_len, \
+ psa_outvec *out_vec, \
+ size_t out_len) \
+ { \
+ bool is_ns = tfm_core_is_ns_client(); \
+ \
+ TFM_CORE_IOVEC_SFN_REQUEST(partition_name, \
+ is_ns, \
+ (void *) sfn_name, \
+ in_vec, in_len, out_vec, out_len); \
+ }
+
+{% for manifest in manifests %}
+ {% if manifest.attr.conditional %}
+#ifdef {{manifest.attr.conditional}}
+ {% endif %}
+/******** {{manifest.manifest.name}} ********/
+ {% for sec_func in manifest.manifest.secure_functions %}
+TFM_VENEER_FUNCTION({{manifest.manifest.name}}, {{sec_func.signal.lower()}})
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+{% endfor %}
diff --git a/secure_fw/spm/model_ipc/CMakeLists.inc b/secure_fw/spm/model_ipc/CMakeLists.inc
new file mode 100644
index 0000000..a95fd99
--- /dev/null
+++ b/secure_fw/spm/model_ipc/CMakeLists.inc
@@ -0,0 +1,76 @@
+#-------------------------------------------------------------------------------
+# 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_IPC_SPM_DIR ${CMAKE_CURRENT_LIST_DIR})
+set(SFW_SPM_DIR "${SFW_IPC_SPM_DIR}/..")
+set(SFW_SPM_ARCH_DIR "${SFW_SPM_DIR}/arch")
+set(SFW_SPM_INIT_DIR "${SFW_SPM_DIR}/init")
+
+set (SFW_IPC_SPM_SRC
+ "${SFW_SPM_INIT_DIR}/tfm_boot_data.c"
+ "${SFW_SPM_INIT_DIR}/tfm_core.c"
+ "${SFW_IPC_SPM_DIR}/spm_ipc.c"
+ "${SFW_IPC_SPM_DIR}/spm_psa_client_call.c"
+ "${SFW_IPC_SPM_DIR}/tfm_core_svcalls_ipc.c"
+ "${SFW_IPC_SPM_DIR}/tfm_message_queue.c"
+ "${SFW_IPC_SPM_DIR}/../runtime/tfm_utils.c"
+ "${SFW_IPC_SPM_DIR}/../runtime/tfm_core_utils.c"
+ "${SFW_IPC_SPM_DIR}/../runtime/spm_api.c"
+ "${SFW_IPC_SPM_DIR}/../runtime/tfm_spm_services.c"
+ "${SFW_IPC_SPM_DIR}/../runtime/tfm_secure_api.c"
+ "${SFW_IPC_SPM_DIR}/tfm_pools.c"
+ "${SFW_IPC_SPM_DIR}/tfm_thread.c"
+ "${SFW_IPC_SPM_DIR}/tfm_wait.c"
+ )
+
+if (DEFINED TFM_MULTI_CORE_TOPOLOGY AND TFM_MULTI_CORE_TOPOLOGY)
+ list(APPEND SFW_IPC_SPM_SRC "${SFW_IPC_SPM_DIR}/tfm_rpc.c"
+ "${SFW_IPC_SPM_DIR}/tfm_spe_mailbox.c"
+ "${SFW_IPC_SPM_DIR}/tfm_multi_core.c"
+ "${SFW_IPC_SPM_DIR}/tfm_multi_core_mem_check.c"
+ )
+else ()
+ list(APPEND SFW_IPC_SPM_SRC "${SFW_IPC_SPM_DIR}/tfm_nspm_ipc.c"
+ "${SFW_IPC_SPM_DIR}/tfm_psa_api_veneers.c"
+ "${SFW_IPC_SPM_DIR}/../runtime/tfm_core_mem_check.c"
+ )
+endif ()
+
+#Append all our source files to global lists.
+list(APPEND ALL_SRC_C ${SFW_IPC_SPM_SRC})
+unset(SFW_IPC_SPM_SRC)
+
+#Setting include directories
+embedded_include_directories(PATH ${SFW_IPC_SPM_DIR} ABSOLUTE)
+embedded_include_directories(PATH ${SFW_IPC_SPM_DIR}/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm/include ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm/arch/include ABSOLUTE)
diff --git a/secure_fw/spm/model_ipc/include/tfm_internal_defines.h b/secure_fw/spm/model_ipc/include/tfm_internal_defines.h
new file mode 100644
index 0000000..e948e7e
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_internal_defines.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_INTERNAL_DEFINES_H__
+#define __TFM_INTERNAL_DEFINES_H__
+
+#include <inttypes.h>
+
+/* IPC internal return status */
+#define IPC_SUCCESS 0
+#define IPC_ERROR_BAD_PARAMETERS (INT32_MIN)
+#define IPC_ERROR_SHORT_BUFFER (INT32_MIN + 1)
+#define IPC_ERROR_VERSION (INT32_MIN + 2)
+#define IPC_ERROR_MEMORY_CHECK (INT32_MIN + 3)
+#define IPC_ERROR_GENERIC (INT32_MIN + 0x1F)
+
+#endif
diff --git a/secure_fw/spm/model_ipc/include/tfm_list.h b/secure_fw/spm/model_ipc/include/tfm_list.h
new file mode 100644
index 0000000..9764503
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_list.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_LIST_H__
+#define __TFM_LIST_H__
+
+/* List structure */
+struct tfm_list_node_t {
+ struct tfm_list_node_t *prev;
+ struct tfm_list_node_t *next;
+};
+
+/**
+ * \brief Initialize list head.
+ *
+ * \param[in] head List head need to be initialized.
+ */
+__STATIC_INLINE void tfm_list_init(struct tfm_list_node_t *head)
+{
+ head->next = head;
+ head->prev = head;
+}
+
+/**
+ * \brief Add one node to list tail.
+ *
+ * \param[in] head List head initialized by \ref tfm_list_init.
+ * \param[in] node List node want to be added.
+ */
+__STATIC_INLINE void
+tfm_list_add_tail(struct tfm_list_node_t *head, struct tfm_list_node_t *node)
+{
+ head->prev->next = node;
+ node->prev = head->prev;
+ head->prev = node;
+ node->next = head;
+}
+
+/**
+ * \brief Check if a list is empty.
+ *
+ * \param[in] head List head initialized by \ref tfm_list_init.
+ *
+ * \returns returns 1 for empty, or 0 for not.
+ */
+__STATIC_INLINE int32_t tfm_list_is_empty(struct tfm_list_node_t *head)
+{
+ return (head->next == head);
+}
+
+/**
+ * \brief Insert one node to list head.
+ *
+ * \param[in] head List head initialized by \ref tfm_list_init.
+ * \param[in] node List node want to be inserted.
+ */
+__STATIC_INLINE void
+tfm_list_insert_first(struct tfm_list_node_t *head,
+ struct tfm_list_node_t *node)
+{
+ node->next = head->next;
+ node->prev = head;
+ head->next->prev = node;
+ head->next = node;
+}
+
+/**
+ * \brief Retrieve the fist node from list.
+ *
+ * \param[in] head List head initialized by \ref tfm_list_init.
+ *
+ * \returns Returns the pointer to first list node.
+ */
+__STATIC_INLINE
+struct tfm_list_node_t *tfm_list_first_node(struct tfm_list_node_t *head)
+{
+ return head->next;
+}
+
+/**
+ * \brief Delete one node from list.
+ *
+ * \param[in] node List node want to be deleted.
+ */
+__STATIC_INLINE void tfm_list_del_node(struct tfm_list_node_t *node)
+{
+ node->prev->next = node->next;
+ node->next->prev = node->prev;
+}
+
+/* Go through each node of a list */
+#define TFM_LIST_FOR_EACH(node, head) \
+ for (node = (head)->next; node != head; node = node->next)
+
+#endif
diff --git a/secure_fw/spm/model_ipc/include/tfm_message_queue.h b/secure_fw/spm/model_ipc/include/tfm_message_queue.h
new file mode 100644
index 0000000..a11fb3b
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_message_queue.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_MESSAGE_QUEUE_H__
+#define __TFM_MESSAGE_QUEUE_H__
+
+#include "psa/service.h"
+#include "tfm_wait.h"
+
+#define TFM_MSG_MAGIC 0x15154343
+/* Message struct to collect parameter from client */
+struct tfm_msg_body_t {
+ int32_t magic;
+ struct tfm_spm_service_t *service; /* RoT service pointer */
+ struct tfm_conn_handle_t *handle; /* Connected Service handle */
+ struct tfm_event_t ack_evnt; /* Event for ack reponse */
+ psa_msg_t msg; /* PSA message body */
+ psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body */
+ psa_outvec outvec[PSA_MAX_IOVEC];
+ psa_outvec *caller_outvec; /*
+ * Save caller outvec pointer for
+ * write length update
+ */
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+ const void *caller_data; /*
+ * Pointer to the private data of the
+ * caller. It identifies the NSPE PSA
+ * client calls in multi-core topology
+ */
+#endif
+ struct tfm_msg_body_t *next; /* List operators */
+};
+
+struct tfm_msg_queue_t {
+ struct tfm_msg_body_t *head; /* Queue head */
+ struct tfm_msg_body_t *tail; /* Queue tail */
+ uint32_t size; /* Number of the queue member */
+};
+
+/**
+ * \brief Enqueue a message into message queue.
+ *
+ * \param[in] queue Message queue, it will be initialized
+ * if has not been initialized.
+ * \param[in] node Message queue node want to be enqueue.
+ *
+ * \retval IPC_SUCCESS Success.
+ * \retval IPC_ERROR_BAD_PARAMETERS Parameters error.
+ */
+int32_t tfm_msg_enqueue(struct tfm_msg_queue_t *queue,
+ struct tfm_msg_body_t *node);
+
+/**
+ * \brief Dequeue a message from message queue.
+ *
+ * \param[in] queue Message queue.
+ *
+ * \retval node pointer Success.
+ * \retval NULL Queue is NULL or size is zero.
+ */
+struct tfm_msg_body_t *tfm_msg_dequeue(struct tfm_msg_queue_t *queue);
+
+/**
+ * \brief Check if a message queue is empty.
+ *
+ * \param[in] queue Message queue.
+ *
+ * \returns Returns 1 for empty, or 0 for not.
+ */
+int32_t tfm_msg_queue_is_empty(struct tfm_msg_queue_t *queue);
+
+#endif
diff --git a/secure_fw/spm/model_ipc/include/tfm_multi_core.h b/secure_fw/spm/model_ipc/include/tfm_multi_core.h
new file mode 100644
index 0000000..2618804
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_multi_core.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_MULTI_CORE_H__
+#define __TFM_MULTI_CORE_H__
+
+#include <stdbool.h>
+
+/* Security attributes of target memory region in memory access check. */
+struct security_attr_info_t {
+ bool is_valid; /* Whether the target memory region is valid */
+ bool is_secure; /* Secure memory or non-secure memory */
+};
+
+/* Memory access attributes of target memory region in memory access check. */
+struct mem_attr_info_t {
+ bool is_mpu_enabled; /* Whether memory protection unit(s) enabled */
+ bool is_valid; /* Whether the target memory region is valid */
+ bool is_xn; /* Execute Never or not */
+ bool is_priv_rd_allow; /* Privileged read is allowed or not */
+ bool is_priv_wr_allow; /* Privileged write is allowed or not */
+ bool is_unpriv_rd_allow; /* Unprivileged read is allowed or not */
+ bool is_unpriv_wr_allow; /* Unprivileged write is allowed or not */
+};
+
+/**
+ * \brief Retrieve general security isolation configuration information of the
+ * target memory region according to the system memory region layout and
+ * fill the \ref security_attr_info_t.
+ *
+ * \param[in] p Base address of target memory region
+ * \param[in] s Size of target memory region
+ * \param[out] p_attr Address of \ref security_attr_info_t to be filled
+ *
+ * \return void
+ *
+ * \note This function doesn't access any hardware security isolation unit.
+ */
+void tfm_get_mem_region_security_attr(const void *p, size_t s,
+ struct security_attr_info_t *p_attr);
+
+/**
+ * \brief Retrieve general secure memory protection configuration information of
+ * the target memory region according to the system memory region layout
+ * and symbol addresses and fill the \ref mem_attr_info_t.
+ *
+ * \param[in] p Base address of target memory region
+ * \param[in] s Size of target memory region
+ * \param[out] p_attr Address of \ref mem_attr_info_t to be filled
+ *
+ * \return void
+ *
+ * \note This function doesn't access any hardware memory protection unit.
+ * The \ref is_mpu_enabled field is set to false by default.
+ */
+void tfm_get_secure_mem_region_attr(const void *p, size_t s,
+ struct mem_attr_info_t *p_attr);
+
+/**
+ * \brief Retrieve general non-secure memory protection configuration
+ * information of the target memory region according to the system memory
+ * region layout and fill the \ref mem_attr_info_t.
+ *
+ * \param[in] p Base address of target memory region
+ * \param[in] s Size of target memory region
+ * \param[out] p_attr Address of \ref mem_attr_info_t to be filled
+ *
+ * \return void
+ *
+ * \note This function doesn't access any hardware memory protection unit.
+ * The \ref is_mpu_enabled field is set to false by default.
+ */
+void tfm_get_ns_mem_region_attr(const void *p, size_t s,
+ struct mem_attr_info_t *p_attr);
+
+#endif /* __TFM_MULTI_CORE_H__ */
diff --git a/secure_fw/spm/model_ipc/include/tfm_pools.h b/secure_fw/spm/model_ipc/include/tfm_pools.h
new file mode 100644
index 0000000..422484b
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_pools.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_POOLS_H__
+#define __TFM_POOLS_H__
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Resource pool - few known size resources allocation/free is required,
+ * so pool is more applicable than heap.
+ */
+
+/*
+ * Pool Instance:
+ * [ Pool Instance ] + N * [ Pool Chunks ]
+ */
+struct tfm_pool_chunk_t {
+ struct tfm_list_node_t list; /* Chunk list */
+ void *pool; /* Point to the parent pool */
+ uint8_t data[0]; /* Data indicator */
+};
+
+/*
+ * tfm_pool_chunk_t minus the zero length "data" member,
+ * required for standards compliant C
+ */
+struct tfm_pool_chunk_s_t {
+ struct tfm_list_node_t list; /* Chunk list */
+ void *pool; /* Point to the parent pool */
+};
+
+struct tfm_pool_instance_t {
+ size_t chunksz; /* Chunks size of pool member */
+ size_t chunk_count; /* A number of chunks in the pool */
+ struct tfm_list_node_t chunks_list; /* Chunk list head in pool */
+ struct tfm_pool_chunk_s_t chunks[0]; /* Data indicator */
+};
+
+/*
+ * This will declares a static memory pool variable with chunk memory.
+ * Parameters:
+ * name - Variable name, will be used when register
+ * chunksz - chunk size in bytes
+ * num - Number of chunks
+ */
+#define TFM_POOL_DECLARE(name, chunksz, num) \
+ static uint8_t name##_pool_buf[((chunksz) + \
+ sizeof(struct tfm_pool_chunk_t)) * (num) \
+ + sizeof(struct tfm_pool_instance_t)] \
+ __attribute__((aligned(4))); \
+ static struct tfm_pool_instance_t *name = \
+ (struct tfm_pool_instance_t *)name##_pool_buf
+
+/* Get the head size of memory pool */
+#define POOL_HEAD_SIZE (sizeof(struct tfm_pool_instance_t) + \
+ sizeof(struct tfm_pool_chunk_t))
+
+/* Get the whole size of memory pool */
+#define POOL_BUFFER_SIZE(name) sizeof(name##_pool_buf)
+
+/**
+ * \brief Register a memory pool.
+ *
+ * \param[in] pool Pointer to memory pool declared by
+ * \ref TFM_POOL_DECLARE
+ * \param[in] poolsz Size of the pool buffer.
+ * \param[in] chunksz Size of chunks.
+ * \param[in] num Number of chunks.
+ *
+ * \retval IPC_SUCCESS Success.
+ * \retval IPC_ERROR_BAD_PARAMETERS Parameters error.
+ */
+int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
+ size_t chunksz, size_t num);
+
+/**
+ * \brief Allocate a memory from pool.
+ *
+ * \param[in] pool pool pointer decleared by \ref TFM_POOL_DECLARE
+ *
+ * \retval buffer pointer Success.
+ * \retval NULL Failed.
+ */
+void *tfm_pool_alloc(struct tfm_pool_instance_t *pool);
+
+/**
+ * \brief Free the allocated memory.
+ *
+ * \param[in] ptr Buffer pointer want to free.
+ */
+void tfm_pool_free(void *ptr);
+
+/**
+ * \brief Checks whether a pointer points to a chunk data in the pool.
+ *
+ * \param[in] pool Pointer to memory pool declared by
+ * \ref TFM_POOL_DECLARE.
+ * \param[in] data The pointer to check.
+ *
+ * \retval true Data is a chunk data in the pool.
+ * \retval false Data is not a chunk data in the pool.
+ */
+bool is_valid_chunk_data_in_pool(struct tfm_pool_instance_t *pool,
+ uint8_t *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_POOLS_H__ */
diff --git a/secure_fw/spm/model_ipc/include/tfm_rpc.h b/secure_fw/spm/model_ipc/include/tfm_rpc.h
new file mode 100644
index 0000000..cf573f8
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_rpc.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*
+ * Definitions of Remote Procedure Call (RPC) functionalities in TF-M, which
+ * sits between upper TF-M SPM and underlying mailbox implementation.
+ */
+
+#ifndef __TFM_RPC_H__
+#define __TFM_RPC_H__
+
+#ifdef TFM_MULTI_CORE_TOPOLOGY
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "cmsis_compiler.h"
+#include "psa/client.h"
+#include "psa/service.h"
+#include "tfm_thread.h"
+#include "tfm_wait.h"
+#include "tfm_message_queue.h"
+
+#define TFM_RPC_SUCCESS (0)
+#define TFM_RPC_INVAL_PARAM (INT32_MIN + 1)
+#define TFM_RPC_CONFLICT_CALLBACK (INT32_MIN + 2)
+
+/*
+ * This structure holds the parameters used in a PSA client call.
+ * The parameters are passed from non-secure core to secure core.
+ */
+struct client_call_params_t {
+ uint32_t sid;
+ psa_handle_t handle;
+ int32_t type;
+ const psa_invec *in_vec;
+ size_t in_len;
+ psa_outvec *out_vec;
+ size_t out_len;
+ uint32_t version;
+};
+
+/*
+ * The underlying mailbox communication implementation should provide
+ * the specific operations to complete the RPC functionalities.
+ *
+ * It includes the following operations:
+ * handle_req() - Handle PSA client call request from NSPE
+ * reply() - Reply PSA client call return result to NSPE. The parameter
+ * owner identifies the owner of the PSA client call.
+ * get_caller_data() - Get the private data of NSPE client from mailbox to
+ * identify the PSA client call.
+ */
+struct tfm_rpc_ops_t {
+ void (*handle_req)(void);
+ void (*reply)(const void *owner, int32_t ret);
+ const void * (*get_caller_data)(int32_t client_id);
+};
+
+/**
+ * \brief RPC handler for \ref psa_framework_version.
+ *
+ * \return version The version of the PSA Framework implementation
+ * that is providing the runtime services.
+ */
+uint32_t tfm_rpc_psa_framework_version(void);
+
+/**
+ * \brief RPC handler for \ref psa_version.
+ *
+ * \param[in] params Base address of parameters
+ * \param[in] ns_caller If 'true', indicate the non-secure caller
+ *
+ * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
+ * caller is not permitted to access the service.
+ * \retval > 0 The version of the implemented RoT Service.
+ */
+uint32_t tfm_rpc_psa_version(const struct client_call_params_t *params,
+ bool ns_caller);
+
+/**
+ * \brief RPC handler for \ref psa_connect.
+ *
+ * \param[in] params Base address of parameters
+ * \param[in] ns_caller If 'true', indicate the non-secure caller
+ *
+ * \retval PSA_SUCCESS Success.
+ * \retval PSA_CONNECTION_BUSY The SPM cannot make the connection
+ * at the moment.
+ * \retval "Does not return" The RoT Service ID and version are not
+ * supported, or the caller is not permitted to
+ * access the service.
+ */
+psa_status_t tfm_rpc_psa_connect(const struct client_call_params_t *params,
+ bool ns_caller);
+
+/**
+ * \brief RPC handler for \ref psa_call.
+ *
+ * \param[in] params Base address of parameters
+ * \param[in] ns_caller If 'true', indicate the non-secure caller
+ *
+ * \retval PSA_SUCCESS Success.
+ * \retval "Does not return" The call is invalid, one or more of the
+ * following are true:
+ * \arg An invalid handle was passed.
+ * \arg The connection is already handling a request.
+ * \arg An invalid memory reference was provided.
+ * \arg in_len + out_len > PSA_MAX_IOVEC.
+ * \arg The message is unrecognized or
+ * incorrectly formatted.
+ */
+psa_status_t tfm_rpc_psa_call(const struct client_call_params_t *params,
+ bool ns_caller);
+
+/**
+ * \brief RPC handler for \ref psa_close.
+ *
+ * \param[in] params Base address of parameters
+ * \param[in] ns_caller If 'true', indicate the non-secure caller
+ *
+ * \retval void Success.
+ * \retval "Does not return" The call is invalid, one or more of the
+ * following are true:
+ * \arg An invalid handle was provided that is not
+ * the null handle..
+ */
+void tfm_rpc_psa_close(const struct client_call_params_t *params,
+ bool ns_caller);
+
+/**
+ * \brief Register underlying mailbox communication operations.
+ *
+ * \param[in] ops_ptr Pointer to the specific operation structure.
+ *
+ * \retval TFM_RPC_SUCCESS Mailbox operations are successfully registered.
+ * \retval Other error code Fail to register mailbox operations.
+ */
+int32_t tfm_rpc_register_ops(const struct tfm_rpc_ops_t *ops_ptr);
+
+/**
+ * \brief Unregister underlying mailbox communication operations.
+ *
+ * Currently one and only one underlying mailbox communication implementation is
+ * allowed in runtime. Thus it is unnecessary to specify the mailbox
+ * communication operation callbacks to be unregistered.
+ *
+ * \param[in] void
+ */
+void tfm_rpc_unregister_ops(void);
+
+/**
+ * \brief Handling PSA client call request
+ *
+ * \param void
+ */
+void tfm_rpc_client_call_handler(void);
+
+/**
+ * \brief Reply PSA client call return result
+ *
+ * \param[in] owner A handle to identify the owner of the PSA
+ * client call.
+ * \param[in] ret PSA client call return result value.
+ */
+void tfm_rpc_client_call_reply(const void *owner, int32_t ret);
+
+/*
+ * Check if the message was allocated for a non-secure request via RPC
+ *
+ * \param[in] msg The message body context pointer
+ * \ref msg_body_t structures
+ *
+ * \retval true The message was allocated for a NS request via RPC.
+ * \retval false Otherwise.
+ */
+__STATIC_INLINE bool is_tfm_rpc_msg(const struct tfm_msg_body_t *msg)
+{
+ /*
+ * FIXME
+ * The ID should be smaller than 0 if the message is allocated by a
+ * non-secure caller.
+ * However, current TF-M implementation use 0 as the default non-secure
+ * caller ID. Therefore, treat the caller as non-secure when client_id == 0.
+ *
+ * This condition check should be improved after TF-M non-secure client ID
+ * management is implemented.
+ */
+ if (msg && (msg->msg.client_id <= 0) && !msg->ack_evnt.owner) {
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * \brief Set the private data of the NS caller in \ref msg_body_t, to identify
+ * the caller after PSA client call is compeleted.
+ *
+ * \param[in] msg The address of \ref msg_body_t structure
+ * \param[in] client_id The client ID of the NS caller.
+ */
+void tfm_rpc_set_caller_data(struct tfm_msg_body_t *msg, int32_t client_id);
+
+#else /* TFM_MULTI_CORE_TOPOLOGY */
+
+/* RPC is only available in multi-core scenario */
+#define is_tfm_rpc_msg(x) (false)
+
+#define tfm_rpc_client_call_handler() do {} while (0)
+
+#define tfm_rpc_client_call_reply(owner, ret) do {} while (0)
+
+#define tfm_rpc_set_caller_data(msg, client_id) do {} while (0)
+
+#endif /* TFM_MULTI_CORE_TOPOLOGY */
+#endif /* __TFM_RPC_H__ */
diff --git a/secure_fw/spm/model_ipc/include/tfm_spe_mailbox.h b/secure_fw/spm/model_ipc/include/tfm_spe_mailbox.h
new file mode 100644
index 0000000..fd07907
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_spe_mailbox.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_SPE_MAILBOX_H__
+#define __TFM_SPE_MAILBOX_H__
+
+#include "tfm_mailbox.h"
+
+/* A single slot structure in SPE mailbox queue */
+struct secure_mailbox_slot_t {
+ struct mailbox_msg_t msg;
+
+ uint8_t ns_slot_idx;
+ mailbox_msg_handle_t msg_handle;
+};
+
+struct secure_mailbox_queue_t {
+ mailbox_queue_status_t empty_slots; /* bitmask of empty slots */
+
+ struct secure_mailbox_slot_t queue[NUM_MAILBOX_QUEUE_SLOT];
+ struct ns_mailbox_queue_t *ns_queue;
+ uint8_t cur_proc_slot_idx; /*
+ * The index of mailbox
+ * queue slot currently
+ * under processing.
+ */
+};
+
+/**
+ * \brief Handle mailbox message(s) from NSPE.
+ *
+ * \retval MAILBOX_SUCCESS Successfully get PSA client call return result.
+ * \retval Other return code Operation failed with an error code.
+ */
+int32_t tfm_mailbox_handle_msg(void);
+
+/**
+ * \brief Return PSA client call return result to NSPE.
+ *
+ * \param[in] handle The handle to the mailbox message
+ * \param[in] reply PSA client call return result to be written
+ * to NSPE.
+ *
+ * \retval MAILBOX_SUCCESS Operation succeeded.
+ * \retval Other return code Operation failed with an error code.
+ */
+int32_t tfm_mailbox_reply_msg(mailbox_msg_handle_t handle, int32_t reply);
+
+/**
+ * \brief SPE mailbox initialization
+ *
+ * \retval MAILBOX_SUCCESS Operation succeeded.
+ * \retval Other return code Operation failed with an error code.
+ */
+int32_t tfm_mailbox_init(void);
+
+/**
+ * \brief Platform specific initialization of SPE mailbox.
+ *
+ * \param[in] s_queue The base address of SPE mailbox queue.
+ *
+ * \retval MAILBOX_SUCCESS Operation succeeded.
+ * \retval Other return code Operation failed with an error code.
+ */
+int32_t tfm_mailbox_hal_init(struct secure_mailbox_queue_t *s_queue);
+
+/**
+ * \brief Notify NSPE that a PSA client call return result is replied.
+ * Implemented by platform specific inter-processor communication driver.
+ *
+ * \retval MAILBOX_SUCCESS The notification is successfully sent out.
+ * \retval Other return code Operation failed with an error code.
+ */
+int32_t tfm_mailbox_hal_notify_peer(void);
+
+/**
+ * \brief Enter critical section of NSPE mailbox
+ */
+void tfm_mailbox_hal_enter_critical(void);
+
+/**
+ * \brief Exit critical section of NSPE mailbox
+ */
+void tfm_mailbox_hal_exit_critical(void);
+
+#endif /* __TFM_SPE_MAILBOX_H__ */
diff --git a/secure_fw/spm/model_ipc/include/tfm_svcalls.h b/secure_fw/spm/model_ipc/include/tfm_svcalls.h
new file mode 100644
index 0000000..d553fc8
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_svcalls.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_SVCALLS_H__
+#define __TFM_SVCALLS_H__
+
+#include <stdint.h>
+
+/**
+ * \brief The C source of SVCall handlers
+ *
+ * \param[in] svc_args The arguments list.
+ * \param[in] exc_return EXC_RETURN value of the SVC.
+ *
+ * \returns EXC_RETURN value indicates where to return.
+ */
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return);
+
+#endif
diff --git a/secure_fw/spm/model_ipc/include/tfm_thread.h b/secure_fw/spm/model_ipc/include/tfm_thread.h
new file mode 100644
index 0000000..925967b
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_thread.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_THREAD_H__
+#define __TFM_THREAD_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include "tfm_arch.h"
+#include "cmsis_compiler.h"
+
+/* State code */
+#define THRD_STATE_CREATING 0
+#define THRD_STATE_RUNNING 1
+#define THRD_STATE_BLOCK 2
+#define THRD_STATE_DETACH 3
+#define THRD_STATE_INVALID 4
+
+/* Security attribute - default as security */
+#define THRD_ATTR_SECURE_OFFSET 16
+#define THRD_ATTR_SECURE (0)
+#define THRD_ATTR_NON_SECURE (1 << THRD_ATTR_SECURE_OFFSET)
+
+/* Lower value has higher priority */
+#define THRD_PRIOR_MASK 0xFF
+#define THRD_PRIOR_HIGHEST 0x0
+#define THRD_PRIOR_MEDIUM 0x7F
+#define THRD_PRIOR_LOWEST 0xFF
+
+/* Error code */
+#define THRD_SUCCESS 0
+#define THRD_ERR_INVALID_PARAM 1
+
+/* Thread entry function type */
+typedef void *(*tfm_core_thrd_entry_t)(void *);
+
+/* Thread context */
+struct tfm_core_thread_t {
+ tfm_core_thrd_entry_t pfn; /* entry function */
+ void *param; /* entry parameter */
+ uintptr_t stk_btm; /* stack bottom (lower address) */
+ uintptr_t stk_top; /* stack top (higher address)*/
+ uint32_t prior; /* priority */
+ uint32_t state; /* state */
+
+ struct tfm_arch_ctx_t arch_ctx; /* State context */
+ struct tfm_core_thread_t *next; /* next thread in list */
+};
+
+/*
+ * Initialize a thread context with the necessary info.
+ *
+ * Parameters :
+ * pth - pointer of caller provided thread context
+ * pfn - thread entry function
+ * param - thread entry function parameter
+ * stk_top - stack pointer top (higher address)
+ * stk_btm - stack pointer bottom (lower address)
+ *
+ * Notes :
+ * Thread contex rely on caller allocated memory; initialize members in
+ * context. This function does not insert thread into schedulable list.
+ */
+void tfm_core_thrd_init(struct tfm_core_thread_t *pth,
+ tfm_core_thrd_entry_t pfn, void *param,
+ uintptr_t stk_top, uintptr_t stk_btm);
+
+/*
+ * Set thread priority.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ * prior - priority value (0~255)
+ *
+ * Notes :
+ * Set thread priority. Priority is set to THRD_PRIOR_MEDIUM in
+ * tfm_core_thrd_init().
+ */
+void __STATIC_INLINE tfm_core_thrd_set_priority(struct tfm_core_thread_t *pth,
+ uint32_t prior)
+{
+ pth->prior &= ~THRD_PRIOR_MASK;
+ pth->prior |= prior & THRD_PRIOR_MASK;
+}
+
+/*
+ * Set thread security attribute.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ * attr_secure - THRD_ATTR_SECURE or THRD_ATTR_NON_SECURE
+ *
+ * Notes
+ * Reuse prior of thread context to shift down non-secure thread priority.
+ */
+void __STATIC_INLINE tfm_core_thrd_set_secure(struct tfm_core_thread_t *pth,
+ uint32_t attr_secure)
+{
+ pth->prior &= ~THRD_ATTR_NON_SECURE;
+ pth->prior |= attr_secure;
+}
+
+/*
+ * Set thread state.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ * new_state - new state of thread
+ *
+ * Return :
+ * None
+ *
+ * Notes :
+ * Thread state is not changed if invalid state value inputed.
+ */
+void tfm_core_thrd_set_state(struct tfm_core_thread_t *pth, uint32_t new_state);
+
+/*
+ * Get thread state.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ *
+ * Return :
+ * State of thread
+ */
+uint32_t __STATIC_INLINE tfm_core_thrd_get_state(struct tfm_core_thread_t *pth)
+{
+ return pth->state;
+}
+
+/*
+ * Set thread state return value.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ * retval - return value to be set for thread state
+ *
+ * Notes :
+ * This API is useful for blocked syscall blocking thread. Syscall
+ * could set its return value to the caller before caller goes.
+ */
+void __STATIC_INLINE tfm_core_thrd_set_retval(struct tfm_core_thread_t *pth,
+ uint32_t retval)
+{
+ TFM_STATE_RET_VAL(&pth->arch_ctx) = retval;
+}
+
+/*
+ * Validate thread context and insert it into schedulable list.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ *
+ * Return :
+ * THRD_SUCCESS for success. Or an error is returned.
+ *
+ * Notes :
+ * This function validates thread info. It returns error if thread info
+ * is not correct. Thread is avaliable after successful tfm_core_thrd_start().
+ */
+uint32_t tfm_core_thrd_start(struct tfm_core_thread_t *pth);
+
+/*
+ * Get current running thread.
+ *
+ * Return :
+ * Current running thread context pointer.
+ */
+struct tfm_core_thread_t *tfm_core_thrd_get_curr_thread(void);
+
+/*
+ * Get next running thread in list.
+ *
+ * Return :
+ * Pointer of next thread to be run.
+ */
+struct tfm_core_thread_t *tfm_core_thrd_get_next_thread(void);
+
+/*
+ * Start scheduler for existing threads
+ *
+ * Parameters:
+ * pth - pointer of the caller context collecting thread
+ *
+ * Notes :
+ * This function should be called only ONCE to start the scheduler.
+ * Caller needs to provide a thread object to collect current context.
+ * The usage of the collected context is caller defined.
+ */
+void tfm_core_thrd_start_scheduler(struct tfm_core_thread_t *pth);
+
+/*
+ * Activate a scheduling action after exception.
+ *
+ * Notes :
+ * This function could be called multiple times before scheduling.
+ */
+void tfm_core_thrd_activate_schedule(void);
+
+/*
+ * Save current architecture context into 'prev' thread and switch to 'next'.
+ *
+ * Parameters :
+ * p_actx - latest caller context
+ * prev - previous thread to be switched out
+ * next - thread to be run
+ *
+ * Notes :
+ * This function could be called multiple times before scheduling.
+ */
+void tfm_core_thrd_switch_context(struct tfm_arch_ctx_t *p_actx,
+ struct tfm_core_thread_t *prev,
+ struct tfm_core_thread_t *next);
+
+#endif
diff --git a/secure_fw/spm/model_ipc/include/tfm_wait.h b/secure_fw/spm/model_ipc/include/tfm_wait.h
new file mode 100644
index 0000000..7d2055b
--- /dev/null
+++ b/secure_fw/spm/model_ipc/include/tfm_wait.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_WAIT_H__
+#define __TFM_WAIT_H__
+
+#include <stddef.h>
+
+#include "cmsis_compiler.h"
+
+/* The magic number has two purposes: corruption detection and debug */
+#define TFM_EVENT_MAGIC 0x65766e74
+
+struct tfm_event_t {
+ uint32_t magic; /* 'evnt' */
+ struct tfm_core_thread_t *owner; /* Event blocked thread */
+};
+
+/*
+ * Initialize an event object.
+ *
+ * Parameters:
+ * pevnt - The pointer of event object allocated by the caller
+ */
+void __STATIC_INLINE tfm_event_init(struct tfm_event_t *pevnt)
+{
+ pevnt->magic = TFM_EVENT_MAGIC;
+ pevnt->owner = NULL;
+}
+
+/*
+ * Wait on an event object.
+ *
+ * Parameters:
+ * pevnt - The pointer of event object allocated by the caller
+ *
+ * Notes:
+ * Block caller thread by calling this function.
+ */
+void tfm_event_wait(struct tfm_event_t *pevnt);
+
+/*
+ * Wake up an event object.
+ *
+ * Parameters :
+ * pevnt - The pointer of event object allocated by the caller
+ * retval - Value to be returned to owner
+ *
+ * Notes:
+ * Wake up the blocked thread and set parameter 'retval' as the return value.
+ */
+void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval);
+
+#endif
diff --git a/secure_fw/spm/spm_ipc.c b/secure_fw/spm/model_ipc/spm_ipc.c
similarity index 99%
rename from secure_fw/spm/spm_ipc.c
rename to secure_fw/spm/model_ipc/spm_ipc.c
index a571454..99f6925 100644
--- a/secure_fw/spm/spm_ipc.c
+++ b/secure_fw/spm/model_ipc/spm_ipc.c
@@ -20,9 +20,9 @@
#include "tfm_api.h"
#include "tfm_secure_api.h"
#include "tfm_memory_utils.h"
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "tfm_peripherals_def.h"
-#include "spm_db.h"
+#include "tfm/spm_db.h"
#include "tfm_core_utils.h"
#include "spm_psa_client_call.h"
#include "tfm_rpc.h"
@@ -32,9 +32,9 @@
#include "tfm_list.h"
#include "tfm_pools.h"
#include "region_defs.h"
-#include "tfm_spm_services_api.h"
+#include "tfm/tfm_spm_services_api.h"
-#include "secure_fw/services/tfm_service_list.inc"
+#include "secure_fw/partitions/tfm_service_list.inc"
/* Extern service variable */
extern struct tfm_spm_service_t service[];
diff --git a/secure_fw/spm/spm_psa_client_call.c b/secure_fw/spm/model_ipc/spm_psa_client_call.c
similarity index 99%
rename from secure_fw/spm/spm_psa_client_call.c
rename to secure_fw/spm/model_ipc/spm_psa_client_call.c
index bf5171e..58aae56 100644
--- a/secure_fw/spm/spm_psa_client_call.c
+++ b/secure_fw/spm/model_ipc/spm_psa_client_call.c
@@ -6,7 +6,7 @@
*/
#include "psa/service.h"
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "tfm_core_utils.h"
#include "tfm_internal_defines.h"
#include "tfm_memory_utils.h"
diff --git a/secure_fw/spm/spm_psa_client_call.h b/secure_fw/spm/model_ipc/spm_psa_client_call.h
similarity index 100%
rename from secure_fw/spm/spm_psa_client_call.h
rename to secure_fw/spm/model_ipc/spm_psa_client_call.h
diff --git a/secure_fw/spm/model_ipc/tfm_core_svcalls_ipc.c b/secure_fw/spm/model_ipc/tfm_core_svcalls_ipc.c
new file mode 100644
index 0000000..2c07bf4
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_core_svcalls_ipc.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <string.h>
+#include "region.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_db.h"
+#include "tfm_api.h"
+#include "tfm_arch.h"
+#include "tfm_core_trustzone.h"
+#include "tfm_internal.h"
+#include "tfm_svcalls.h"
+#include "tfm_utils.h"
+#include "tfm/tfm_core_svc.h"
+
+/* The section names come from the scatter file */
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
+
+#ifdef PLATFORM_SVC_HANDLERS
+extern int32_t platform_svc_handlers(tfm_svc_number_t svc_num,
+ uint32_t *ctx, uint32_t lr);
+#endif
+
+static int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx,
+ uint32_t lr)
+{
+ bool ns_caller = false;
+ struct spm_partition_desc_t *partition = NULL;
+ uint32_t veneer_base =
+ (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
+ uint32_t veneer_limit =
+ (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
+
+ /*
+ * The caller security attribute detection bases on LR of state context.
+ * However, if SP calls PSA APIs based on its customized SVC, the LR may be
+ * occupied by general purpose value while calling SVC.
+ * Check if caller comes from non-secure: return address (ctx[6]) is belongs
+ * to veneer section, and the bit0 of LR (ctx[5]) is zero.
+ */
+ if (ctx[6] >= veneer_base && ctx[6] < veneer_limit &&
+ !(ctx[5] & TFM_VENEER_LR_BIT0_MASK)) {
+ ns_caller = true;
+ }
+
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_core_panic();
+ }
+
+ tfm_spm_validate_caller(partition, ctx, lr, ns_caller);
+
+ switch (svc_num) {
+ case TFM_SVC_PSA_FRAMEWORK_VERSION:
+ return tfm_spm_psa_framework_version();
+ case TFM_SVC_PSA_VERSION:
+ return tfm_spm_psa_version(ctx, ns_caller);
+ case TFM_SVC_PSA_CONNECT:
+ return tfm_spm_psa_connect(ctx, ns_caller);
+ case TFM_SVC_PSA_CALL:
+ return tfm_spm_psa_call(ctx, ns_caller, lr);
+ case TFM_SVC_PSA_CLOSE:
+ tfm_spm_psa_close(ctx, ns_caller);
+ break;
+ case TFM_SVC_PSA_WAIT:
+ return tfm_spm_psa_wait(ctx);
+ case TFM_SVC_PSA_GET:
+ return tfm_spm_psa_get(ctx);
+ case TFM_SVC_PSA_SET_RHANDLE:
+ tfm_spm_psa_set_rhandle(ctx);
+ break;
+ case TFM_SVC_PSA_READ:
+ return tfm_spm_psa_read(ctx);
+ case TFM_SVC_PSA_SKIP:
+ return tfm_spm_psa_skip(ctx);
+ case TFM_SVC_PSA_WRITE:
+ tfm_spm_psa_write(ctx);
+ break;
+ case TFM_SVC_PSA_REPLY:
+ tfm_spm_psa_reply(ctx);
+ break;
+ case TFM_SVC_PSA_NOTIFY:
+ tfm_spm_psa_notify(ctx);
+ break;
+ case TFM_SVC_PSA_CLEAR:
+ tfm_spm_psa_clear();
+ break;
+ case TFM_SVC_PSA_EOI:
+ tfm_spm_psa_eoi(ctx);
+ break;
+ case TFM_SVC_ENABLE_IRQ:
+ tfm_spm_enable_irq(ctx);
+ break;
+ case TFM_SVC_DISABLE_IRQ:
+ tfm_spm_disable_irq(ctx);
+ break;
+ case TFM_SVC_PSA_PANIC:
+ tfm_spm_psa_panic();
+ break;
+ case TFM_SVC_SPM_REQUEST:
+ tfm_spm_request_handler((const struct tfm_state_context_t *)ctx);
+ break;
+ case TFM_SVC_PSA_LIFECYCLE:
+ return tfm_spm_get_lifecycle_state();
+ default:
+#ifdef PLATFORM_SVC_HANDLERS
+ return (platform_svc_handlers(svc_num, ctx, lr));
+#else
+ ERROR_MSG("Unknown SVC number requested!");
+ return PSA_ERROR_GENERIC_ERROR;
+#endif
+ }
+ return PSA_SUCCESS;
+}
+
+uint32_t tfm_core_svc_handler(uint32_t *svc_args, uint32_t exc_return)
+{
+ tfm_svc_number_t svc_number = TFM_SVC_SFN_REQUEST;
+ /*
+ * 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(exc_return)) {
+ /* SV called directly from secure context. Check instruction for
+ * svc_number
+ */
+ svc_number = ((tfm_svc_number_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_HANDLER_MODE:
+ tfm_arch_clear_fp_status();
+ exc_return = tfm_spm_init();
+ break;
+ case TFM_SVC_GET_BOOT_DATA:
+ tfm_core_get_boot_data_handler(svc_args);
+ break;
+ default:
+ svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, exc_return);
+ break;
+ }
+
+ return exc_return;
+}
+
+__attribute__ ((naked)) void tfm_core_handler_mode(void)
+{
+ __ASM volatile("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_HANDLER_MODE));
+}
+
+void tfm_access_violation_handler(void)
+{
+ while (1) {
+ ;
+ }
+}
diff --git a/secure_fw/spm/model_ipc/tfm_message_queue.c b/secure_fw/spm/model_ipc/tfm_message_queue.c
new file mode 100644
index 0000000..1a7790e
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_message_queue.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include "tfm_internal_defines.h"
+#include "tfm_message_queue.h"
+
+/* Message queue process */
+int32_t tfm_msg_enqueue(struct tfm_msg_queue_t *queue,
+ struct tfm_msg_body_t *node)
+{
+ if (!queue || !node) {
+ return IPC_ERROR_BAD_PARAMETERS;
+ }
+
+ if (queue->size == 0) {
+ queue->head = node;
+ queue->tail = node;
+ } else {
+ queue->tail->next = node;
+ queue->tail = node;
+ }
+ queue->size++;
+ return IPC_SUCCESS;
+}
+
+struct tfm_msg_body_t *tfm_msg_dequeue(struct tfm_msg_queue_t *queue)
+{
+ struct tfm_msg_body_t *pop_node;
+
+ if (!queue) {
+ return NULL;
+ }
+
+ if (queue->size == 0) {
+ return NULL;
+ }
+
+ pop_node = queue->head;
+ queue->head = queue->head->next;
+ queue->size--;
+ return pop_node;
+}
+
+int32_t tfm_msg_queue_is_empty(struct tfm_msg_queue_t *queue)
+{
+ return queue->size == 0 ? 1 : 0;
+}
diff --git a/secure_fw/spm/model_ipc/tfm_multi_core.c b/secure_fw/spm/model_ipc/tfm_multi_core.c
new file mode 100644
index 0000000..0678509
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_multi_core.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "platform/include/tfm_spm_hal.h"
+#include "psa/client.h"
+#include "tfm_internal.h"
+#include "tfm_nspm.h"
+#include "tfm_spe_mailbox.h"
+#include "tfm_utils.h"
+#include "log/tfm_assert.h"
+#include "log/tfm_log.h"
+#include "log/tfm_assert.h"
+
+#define DEFAULT_NS_CLIENT_ID (-1)
+
+int32_t tfm_nspm_get_current_client_id(void)
+{
+ return DEFAULT_NS_CLIENT_ID;
+}
+
+void tfm_nspm_thread_entry(void)
+{
+#ifdef TFM_CORE_DEBUG
+ /* Boot up non-secure core */
+ LOG_MSG("Enabling non-secure core...");
+#endif
+
+ tfm_spm_hal_boot_ns_cpu(tfm_spm_hal_get_ns_VTOR());
+ tfm_spm_hal_wait_for_ns_cpu_ready();
+
+ tfm_mailbox_init();
+
+ /*
+ * TODO
+ * The infinite-loop can be replaced with low-power sleep and resume
+ * operation. It may require privileged access to platform specific
+ * hardware.
+ */
+ while (1) {
+ }
+
+
+ /* NOTREACHED */
+ TFM_ASSERT(false);
+}
+
+void tfm_psa_ipc_request_handler(const uint32_t svc_args[])
+{
+ (void)svc_args;
+
+ /* Should not receive any request from ns-callable in multi-core topology */
+ tfm_core_panic();
+}
diff --git a/secure_fw/spm/model_ipc/tfm_multi_core_mem_check.c b/secure_fw/spm/model_ipc/tfm_multi_core_mem_check.c
new file mode 100644
index 0000000..ccd93d2
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_multi_core_mem_check.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+
+#include "platform/include/tfm_spm_hal.h"
+#include "region_defs.h"
+#include "secure_utilities.h"
+#include "tfm/spm_api.h"
+#include "tfm/spm_db.h"
+#include "tfm_internal.h"
+#include "tfm_multi_core.h"
+#include "tfm_secure_api.h"
+#include "tfm_utils.h"
+#include "region.h"
+
+#ifndef TFM_LVL
+#error TFM_LVL is not defined!
+#endif
+
+/* Follow CMSE flag definitions */
+#define MEM_CHECK_MPU_READWRITE (1 << 0x0)
+#define MEM_CHECK_AU_NONSECURE (1 << 0x1)
+#define MEM_CHECK_MPU_UNPRIV (1 << 0x2)
+#define MEM_CHECK_MPU_READ (1 << 0x3)
+#define MEM_CHECK_MPU_NONSECURE (1 << 0x4)
+#define MEM_CHECK_NONSECURE (MEM_CHECK_AU_NONSECURE | \
+ MEM_CHECK_MPU_NONSECURE)
+
+void tfm_get_mem_region_security_attr(const void *p, size_t s,
+ struct security_attr_info_t *p_attr)
+{
+ p_attr->is_valid = true;
+
+ if (check_address_range(p, s, NS_DATA_START,
+ NS_DATA_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_secure = false;
+ return;
+ }
+
+ if (check_address_range(p, s, NS_CODE_START,
+ NS_CODE_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_secure = false;
+ return;
+ }
+
+ if (check_address_range(p, s, S_DATA_START, S_DATA_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_secure = true;
+ return;
+ }
+
+ if (check_address_range(p, s, S_CODE_START, S_CODE_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_secure = true;
+ return;
+ }
+
+ p_attr->is_valid = false;
+}
+
+#if TFM_LVL == 2
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit);
+REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit);
+REGION_DECLARE(Image$$, TFM_APP_CODE_START, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
+REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
+#endif
+
+void tfm_get_secure_mem_region_attr(const void *p, size_t s,
+ struct mem_attr_info_t *p_attr)
+{
+#if TFM_LVL == 1
+ p_attr->is_mpu_enabled = false;
+ p_attr->is_valid = true;
+
+ if (check_address_range(p, s, S_DATA_START, S_DATA_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = true;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = true;
+ p_attr->is_xn = true;
+ return;
+ }
+
+ if (check_address_range(p, s, S_CODE_START, S_CODE_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = false;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = false;
+ p_attr->is_xn = false;
+ return;
+ }
+
+ p_attr->is_valid = false;
+#elif TFM_LVL == 2
+ uintptr_t base, limit;
+
+ p_attr->is_mpu_enabled = false;
+ p_attr->is_valid = true;
+
+ /* TFM Core unprivileged code region */
+ base = (uintptr_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit) - 1;
+ if (check_address_range(p, s, base, limit) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = false;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = false;
+ p_attr->is_xn = false;
+ return;
+ }
+
+ /* TFM Core unprivileged data region */
+ base = (uintptr_t)®ION_NAME(Image$$, TFM_UNPRIV_DATA, $$RW$$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, TFM_UNPRIV_DATA, $$ZI$$Limit) - 1;
+ if (check_address_range(p, s, base, limit) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = true;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = true;
+ p_attr->is_xn = true;
+ return;
+ }
+
+ /* APP RoT partition RO region */
+ base = (uintptr_t)®ION_NAME(Image$$, TFM_APP_CODE_START, $$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, TFM_APP_CODE_END, $$Base) - 1;
+ if (check_address_range(p, s, base, limit) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = false;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = false;
+ p_attr->is_xn = false;
+ return;
+ }
+
+ /* RW, ZI and stack as one region */
+ base = (uintptr_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base) - 1;
+ if (check_address_range(p, s, base, limit) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = true;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = true;
+ p_attr->is_xn = true;
+ return;
+ }
+
+ /*
+ * Treat the remaining parts in secure data section and secure code section
+ * as privileged regions
+ */
+ base = (uintptr_t)S_DATA_START;
+ limit = (uintptr_t)S_DATA_LIMIT;
+ if (check_address_range(p, s, base, limit) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = true;
+ p_attr->is_unpriv_rd_allow = false;
+ p_attr->is_unpriv_wr_allow = false;
+ p_attr->is_xn = true;
+ return;
+ }
+
+ base = (uintptr_t)S_CODE_START;
+ limit = (uintptr_t)S_CODE_LIMIT;
+ if (check_address_range(p, s, base, limit) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = false;
+ p_attr->is_unpriv_rd_allow = false;
+ p_attr->is_unpriv_wr_allow = false;
+ p_attr->is_xn = false;
+ return;
+ }
+
+ p_attr->is_valid = false;
+#else
+#error "Cannot support current TF-M isolation level"
+#endif
+}
+
+void tfm_get_ns_mem_region_attr(const void *p, size_t s,
+ struct mem_attr_info_t *p_attr)
+{
+ p_attr->is_mpu_enabled = false;
+ p_attr->is_valid = true;
+
+ if (check_address_range(p, s, NS_DATA_START,
+ NS_DATA_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = true;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = true;
+ p_attr->is_xn = true;
+ return;
+ }
+
+ if (check_address_range(p, s, NS_CODE_START,
+ NS_CODE_LIMIT) == TFM_SUCCESS) {
+ p_attr->is_priv_rd_allow = true;
+ p_attr->is_priv_wr_allow = false;
+ p_attr->is_unpriv_rd_allow = true;
+ p_attr->is_unpriv_wr_allow = false;
+ p_attr->is_xn = false;
+ return;
+ }
+
+ p_attr->is_valid = false;
+}
+
+static void security_attr_init(struct security_attr_info_t *p_attr)
+{
+ /* No check if p_attr is valid */
+
+ /*
+ * The initial values may be not a valid combination.
+ * The value in each filed just guarantees the least access permission in
+ * case that the field is incorrectly set later.
+ */
+ p_attr->is_valid = false;
+ p_attr->is_secure = true;
+}
+
+static void mem_attr_init(struct mem_attr_info_t *p_attr)
+{
+ /* No check if p_attr is valid */
+
+ /*
+ * The initial values may be not a valid combination.
+ * The value in each filed just guarantees the least access permission in
+ * case that the field is incorrectly set later.
+ */
+ p_attr->is_mpu_enabled = false;
+ p_attr->is_valid = false;
+ p_attr->is_xn = true;
+ p_attr->is_priv_rd_allow = false;
+ p_attr->is_priv_wr_allow = false;
+ p_attr->is_unpriv_rd_allow = false;
+ p_attr->is_unpriv_wr_allow = false;
+}
+
+/**
+ * \brief Check whether the access permission matches the security settings of
+ * the target memory region
+ *
+ * \param[in] attr The security_attr_info_t containing security settings of
+ * memory region
+ * \param[in] flags The flags indicating the access permissions.
+ *
+ * \return TFM_SUCCESS if the check passes,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+static enum tfm_status_e security_attr_check(struct security_attr_info_t attr,
+ uint8_t flags)
+{
+ bool secure_access;
+
+ if (!attr.is_valid) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ secure_access = flags & MEM_CHECK_NONSECURE ? false : true;
+ /*
+ * Non-secure access should not access secure memory region.
+ * Secure service should not directly access non-secure memory region.
+ */
+ if (secure_access ^ attr.is_secure) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ return TFM_SUCCESS;
+}
+
+/**
+ * \brief Check whether the access permission matches the target non-secure
+ * memory region access attributes.
+ *
+ * \param[in] attr The mem_attr_info_t containing attributes of memory region
+ * \param[in] flags The flags indicating the access permissions.
+ *
+ * \return TFM_SUCCESS if the check passes,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+static enum tfm_status_e ns_mem_attr_check(struct mem_attr_info_t attr,
+ uint8_t flags)
+{
+ /*
+ * Non-secure privileged/unprivileged check is skipped.
+ * Non-secure software should implement the check if it enforces the
+ * isolation between privileged and unprivileged regions.
+ */
+
+ if ((flags & MEM_CHECK_MPU_READWRITE) &&
+ (attr.is_priv_rd_allow || attr.is_unpriv_rd_allow) &&
+ (attr.is_priv_wr_allow || attr.is_unpriv_wr_allow)) {
+ return TFM_SUCCESS;
+ }
+
+ if ((flags & MEM_CHECK_MPU_READ) &&
+ (attr.is_priv_rd_allow || attr.is_unpriv_rd_allow)) {
+ return TFM_SUCCESS;
+ }
+
+ return TFM_ERROR_GENERIC;
+}
+
+/**
+ * \brief Check whether the access permission matches the target secure memory
+ * region access attributes.
+ *
+ * \param[in] attr The mem_attr_info_t containing attributes of memory region
+ * \param[in] flags The flags indicating the access permissions.
+ *
+ * \return TFM_SUCCESS if the check passes,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+static enum tfm_status_e secure_mem_attr_check(struct mem_attr_info_t attr,
+ uint8_t flags)
+{
+#if TFM_LVL == 1
+ /* Privileged/unprivileged is ignored in TFM_LVL == 1 */
+
+ if ((flags & MEM_CHECK_MPU_READWRITE) &&
+ (attr.is_priv_rd_allow || attr.is_unpriv_rd_allow) &&
+ (attr.is_priv_wr_allow || attr.is_unpriv_wr_allow)) {
+ return TFM_SUCCESS;
+ }
+
+ if ((flags & MEM_CHECK_MPU_READ) &&
+ (attr.is_priv_rd_allow || attr.is_unpriv_rd_allow)) {
+ return TFM_SUCCESS;
+ }
+
+ return TFM_ERROR_GENERIC;
+#else
+ if (flags & MEM_CHECK_MPU_UNPRIV) {
+ if ((flags & MEM_CHECK_MPU_READWRITE) && attr.is_unpriv_rd_allow &&
+ attr.is_unpriv_wr_allow) {
+ return TFM_SUCCESS;
+ }
+
+ if ((flags & MEM_CHECK_MPU_READ) && attr.is_unpriv_rd_allow) {
+ return TFM_SUCCESS;
+ }
+ } else {
+ if ((flags & MEM_CHECK_MPU_READWRITE) && attr.is_priv_rd_allow &&
+ attr.is_priv_wr_allow) {
+ return TFM_SUCCESS;
+ }
+
+ if ((flags & MEM_CHECK_MPU_READ) && attr.is_priv_rd_allow) {
+ return TFM_SUCCESS;
+ }
+ }
+
+ return TFM_ERROR_GENERIC;
+#endif
+}
+
+/**
+ * \brief Check whether the access permission matches the memory attributes of
+ * the target memory region
+ *
+ * \param[in] attr The mem_attr_info_t containing memory region attributes
+ * \param[in] flags The flags indicating the access permissions.
+ *
+ * \return TFM_SUCCESS if the check passes,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+static enum tfm_status_e mem_attr_check(struct mem_attr_info_t attr,
+ uint8_t flags)
+{
+ if (!attr.is_valid) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ if (flags & MEM_CHECK_NONSECURE) {
+ return ns_mem_attr_check(attr, flags);
+ }
+
+ return secure_mem_attr_check(attr, flags);
+}
+
+/**
+ * \brief Check whether a memory access is allowed to access to a memory range
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] flags The flags indicating the access permissions.
+ *
+ * \return TFM_SUCCESS if the access is allowed,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+static int32_t has_access_to_region(const void *p, size_t s, uint8_t flags)
+{
+ struct security_attr_info_t security_attr;
+ struct mem_attr_info_t mem_attr;
+
+ if (!p) {
+ return (int32_t)TFM_ERROR_GENERIC;
+ }
+
+ if ((uintptr_t)p > (UINTPTR_MAX - s)) {
+ return (int32_t)TFM_ERROR_GENERIC;
+ }
+
+ /* Abort if not in Handler mode */
+ if (!__get_IPSR()) {
+ tfm_core_panic();
+ }
+
+ security_attr_init(&security_attr);
+
+ /* Retrieve security attributes of target memory region */
+ tfm_spm_hal_get_mem_security_attr(p, s, &security_attr);
+
+ if (security_attr_check(security_attr, flags) != TFM_SUCCESS) {
+ return (int32_t)TFM_ERROR_GENERIC;
+ }
+
+ mem_attr_init(&mem_attr);
+
+ if (security_attr.is_secure) {
+ /* Retrieve access attributes of secure memory region */
+ tfm_spm_hal_get_secure_access_attr(p, s, &mem_attr);
+
+#if TFM_LVL != 1
+ /* Secure MPU must be enabled in Isolation Level 2 and 3 */
+ if (!mem_attr.is_mpu_enabled) {
+ tfm_core_panic();
+ }
+#endif
+ } else {
+ /* Retrieve access attributes of non-secure memory region. */
+ tfm_spm_hal_get_ns_access_attr(p, s, &mem_attr);
+ }
+
+ return (int32_t)mem_attr_check(mem_attr, flags);
+}
+
+int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
+ bool ns_caller,
+ uint32_t privileged)
+{
+ uint8_t flags = MEM_CHECK_MPU_READ;
+
+ if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+ flags |= MEM_CHECK_MPU_UNPRIV;
+ } else if (privileged != TFM_PARTITION_PRIVILEGED_MODE) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ if (ns_caller) {
+ flags |= MEM_CHECK_NONSECURE;
+ }
+
+ return has_access_to_region(p, s, flags);
+}
+
+int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
+ bool ns_caller,
+ uint32_t privileged)
+{
+ uint8_t flags = MEM_CHECK_MPU_READWRITE;
+
+ if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+ flags |= MEM_CHECK_MPU_UNPRIV;
+ } else if (privileged != TFM_PARTITION_PRIVILEGED_MODE) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ if (ns_caller) {
+ flags |= MEM_CHECK_NONSECURE;
+ }
+
+ return has_access_to_region(p, s, flags);
+}
diff --git a/secure_fw/spm/model_ipc/tfm_nspm_ipc.c b/secure_fw/spm/model_ipc/tfm_nspm_ipc.c
new file mode 100644
index 0000000..c5eb993
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_nspm_ipc.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "platform/include/tfm_spm_hal.h"
+#include "psa/error.h"
+#include "tfm_nspm.h"
+#include "tfm_utils.h"
+#include "tfm_internal.h"
+#include "log/tfm_assert.h"
+#include "log/tfm_log.h"
+
+#define DEFAULT_NS_CLIENT_ID ((int32_t)-1)
+
+typedef uint32_t TZ_ModuleId_t;
+typedef uint32_t TZ_MemoryId_t;
+
+int32_t tfm_nspm_get_current_client_id(void)
+{
+ return DEFAULT_NS_CLIENT_ID;
+}
+
+/* TF-M implementation of the CMSIS TZ RTOS thread context management API */
+
+/// 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)
+{
+ 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)
+{
+ /* add attribute 'noinline' to avoid a build error. */
+ (void)module;
+ return 1U;
+}
+
+/// 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)
+{
+ (void)id;
+ return 1U;
+}
+
+/// 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)
+{
+ (void)id;
+ return 1U;
+}
+
+/// 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)
+{
+ (void)id;
+ return 1U;
+}
+
+/*
+ * 'r0' impliedly holds the address of non-secure entry,
+ * given during non-secure partition initialization.
+ */
+__attribute__((naked, section("SFN")))
+void tfm_nspm_thread_entry(void)
+{
+ __ASM volatile(
+#ifndef __ICCARM__
+ ".syntax unified \n"
+#endif
+ "mov r4, r0 \n"
+ "movs r2, #1 \n" /* Clear Bit[0] for S to NS transition */
+ "bics r4, r2 \n"
+ "mov r0, r4 \n"
+ "mov r1, r4 \n"
+ "mov r2, r4 \n"
+ "mov r3, r4 \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"
+ "mov r12, r4 \n"
+ "push {r0, r1} \n"
+ "bxns r0 \n"
+ );
+}
+
+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);
+}
diff --git a/secure_fw/spm/model_ipc/tfm_pools.c b/secure_fw/spm/model_ipc/tfm_pools.c
new file mode 100644
index 0000000..6ab56af
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_pools.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include "tfm_thread.h"
+#include "tfm_wait.h"
+#include "psa/client.h"
+#include "psa/service.h"
+#include "tfm_internal_defines.h"
+#include "cmsis_compiler.h"
+#include "tfm_utils.h"
+#include "tfm_list.h"
+#include "tfm_pools.h"
+#include "tfm_memory_utils.h"
+#include "tfm_core_utils.h"
+
+int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
+ size_t chunksz, size_t num)
+{
+ struct tfm_pool_chunk_t *pchunk;
+ size_t i;
+
+ if (!pool || num == 0) {
+ return IPC_ERROR_BAD_PARAMETERS;
+ }
+
+ /* Ensure buffer is large enough */
+ if (poolsz != ((chunksz + sizeof(struct tfm_pool_chunk_t)) * num +
+ sizeof(struct tfm_pool_instance_t))) {
+ return IPC_ERROR_BAD_PARAMETERS;
+ }
+
+ /* Buffer should be BSS cleared but clear it again */
+ tfm_core_util_memset(pool, 0, poolsz);
+
+ /* Chain pool chunks */
+ tfm_list_init(&pool->chunks_list);
+
+ pchunk = (struct tfm_pool_chunk_t *)pool->chunks;
+ for (i = 0; i < num; i++) {
+ pchunk->pool = pool;
+ tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
+ pchunk = (struct tfm_pool_chunk_t *)&pchunk->data[chunksz];
+ }
+
+ /* Prepare instance and insert to pool list */
+ pool->chunksz = chunksz;
+ pool->chunk_count = num;
+
+ return IPC_SUCCESS;
+}
+
+void *tfm_pool_alloc(struct tfm_pool_instance_t *pool)
+{
+ struct tfm_list_node_t *node;
+ struct tfm_pool_chunk_t *pchunk;
+
+ if (!pool) {
+ return NULL;
+ }
+
+ if (tfm_list_is_empty(&pool->chunks_list)) {
+ return NULL;
+ }
+
+ node = tfm_list_first_node(&pool->chunks_list);
+ pchunk = TFM_GET_CONTAINER_PTR(node, struct tfm_pool_chunk_t, list);
+
+ /* Remove node from list node, it will be added when pool free */
+ tfm_list_del_node(node);
+
+ return &pchunk->data;
+}
+
+void tfm_pool_free(void *ptr)
+{
+ struct tfm_pool_chunk_t *pchunk;
+ struct tfm_pool_instance_t *pool;
+
+ pchunk = TFM_GET_CONTAINER_PTR(ptr, struct tfm_pool_chunk_t, data);
+ pool = (struct tfm_pool_instance_t *)pchunk->pool;
+ tfm_list_add_tail(&pool->chunks_list, &pchunk->list);
+}
+
+bool is_valid_chunk_data_in_pool(struct tfm_pool_instance_t *pool,
+ uint8_t *data)
+{
+ const uintptr_t chunks_start = (uintptr_t)(pool->chunks);
+ const size_t chunks_size = pool->chunksz + sizeof(struct tfm_pool_chunk_t);
+ const size_t chunk_count = pool->chunk_count;
+ const uintptr_t chunks_end = chunks_start + chunks_size * chunk_count;
+ uintptr_t pool_chunk_address = 0;
+
+ /* Check that the message was allocated from the pool. */
+ if ((uintptr_t)data < chunks_start || (uintptr_t)data >= chunks_end) {
+ return false;
+ }
+
+ pool_chunk_address =
+ (uint32_t)TFM_GET_CONTAINER_PTR(data, struct tfm_pool_chunk_t, data);
+
+ /* Make sure that the chunk containing the message is aligned on */
+ /* chunk boundary in the pool. */
+ if ((pool_chunk_address - chunks_start) % chunks_size != 0) {
+ return false;
+ }
+ return true;
+}
diff --git a/secure_fw/spm/model_ipc/tfm_psa_api_veneers.c b/secure_fw/spm/model_ipc/tfm_psa_api_veneers.c
new file mode 100644
index 0000000..e4ba155
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_psa_api_veneers.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include "psa/client.h"
+#include "psa/service.h"
+#include "secure_utilities.h"
+#include "tfm_arch.h"
+#include "tfm_secure_api.h"
+#include "tfm_api.h"
+#include "tfm_svcalls.h"
+
+/* Veneer implementation */
+
+/*
+ * SVC to core directly before touch stack due to:
+ * - Re-entrant detection bases on stack information.
+ * - SVC here stores the current xPSR into stack and recover it back while
+ * exception returns, no leakage of secure state information and no
+ * interference between two sides.
+ */
+
+__tfm_psa_secure_gateway_attributes__
+uint32_t tfm_psa_framework_version_veneer(void)
+{
+ __ASM volatile("SVC %0 \n"
+ "BXNS LR \n"
+ : : "I" (TFM_SVC_PSA_FRAMEWORK_VERSION));
+}
+
+__tfm_psa_secure_gateway_attributes__
+uint32_t tfm_psa_version_veneer(uint32_t sid)
+{
+ __ASM volatile("SVC %0 \n"
+ "BXNS LR \n"
+ : : "I" (TFM_SVC_PSA_VERSION));
+}
+
+__tfm_psa_secure_gateway_attributes__
+psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version)
+{
+ __ASM volatile("SVC %0 \n"
+ "BXNS LR \n"
+ : : "I" (TFM_SVC_PSA_CONNECT));
+}
+
+__tfm_psa_secure_gateway_attributes__
+psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
+ const struct tfm_control_parameter_t *ctrl_param,
+ const psa_invec *in_vec,
+ psa_outvec *out_vec)
+{
+ __ASM volatile("SVC %0 \n"
+ "BXNS LR \n"
+ : : "I" (TFM_SVC_PSA_CALL));
+}
+
+__tfm_psa_secure_gateway_attributes__
+void tfm_psa_close_veneer(psa_handle_t handle)
+{
+ __ASM volatile("SVC %0 \n"
+ "BXNS LR \n"
+ : : "I" (TFM_SVC_PSA_CLOSE));
+}
diff --git a/secure_fw/spm/model_ipc/tfm_rpc.c b/secure_fw/spm/model_ipc/tfm_rpc.c
new file mode 100644
index 0000000..073e4f4
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_rpc.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm/spm_api.h"
+#include "spm_psa_client_call.h"
+#include "tfm_rpc.h"
+#include "tfm_utils.h"
+
+static void default_handle_req(void)
+{
+}
+
+static void default_mailbox_reply(const void *owner, int32_t ret)
+{
+ (void)owner;
+ (void)ret;
+}
+
+static const void *default_get_caller_data(int32_t client_id)
+{
+ (void)client_id;
+
+ return NULL;
+}
+
+static struct tfm_rpc_ops_t rpc_ops = {
+ .handle_req = default_handle_req,
+ .reply = default_mailbox_reply,
+ .get_caller_data = default_get_caller_data,
+};
+
+uint32_t tfm_rpc_psa_framework_version(void)
+{
+ return tfm_spm_client_psa_framework_version();
+}
+
+uint32_t tfm_rpc_psa_version(const struct client_call_params_t *params,
+ bool ns_caller)
+{
+ TFM_CORE_ASSERT(params != NULL);
+
+ return tfm_spm_client_psa_version(params->sid, ns_caller);
+}
+
+psa_status_t tfm_rpc_psa_connect(const struct client_call_params_t *params,
+ bool ns_caller)
+{
+ TFM_CORE_ASSERT(params != NULL);
+
+ return tfm_spm_client_psa_connect(params->sid, params->version, ns_caller);
+}
+
+psa_status_t tfm_rpc_psa_call(const struct client_call_params_t *params,
+ bool ns_caller)
+{
+ TFM_CORE_ASSERT(params != NULL);
+
+ return tfm_spm_client_psa_call(params->handle, params->type,
+ params->in_vec, params->in_len,
+ params->out_vec, params->out_len, ns_caller,
+ TFM_PARTITION_UNPRIVILEGED_MODE);
+}
+
+void tfm_rpc_psa_close(const struct client_call_params_t *params,
+ bool ns_caller)
+{
+ TFM_CORE_ASSERT(params != NULL);
+
+ tfm_spm_client_psa_close(params->handle, ns_caller);
+}
+
+int32_t tfm_rpc_register_ops(const struct tfm_rpc_ops_t *ops_ptr)
+{
+ if (!ops_ptr) {
+ return TFM_RPC_INVAL_PARAM;
+ }
+
+ if (!ops_ptr->handle_req || !ops_ptr->reply || !ops_ptr->get_caller_data) {
+ return TFM_RPC_INVAL_PARAM;
+ }
+
+ /* Currently, one and only one mailbox implementation is supported. */
+ if ((rpc_ops.handle_req != default_handle_req) ||
+ (rpc_ops.reply != default_mailbox_reply) || \
+ (rpc_ops.get_caller_data != default_get_caller_data)) {
+ return TFM_RPC_CONFLICT_CALLBACK;
+ }
+
+ rpc_ops.handle_req = ops_ptr->handle_req;
+ rpc_ops.reply = ops_ptr->reply;
+ rpc_ops.get_caller_data = ops_ptr->get_caller_data;
+
+ return TFM_RPC_SUCCESS;
+}
+
+void tfm_rpc_unregister_ops(void)
+{
+ rpc_ops.handle_req = default_handle_req;
+ rpc_ops.reply = default_mailbox_reply;
+ rpc_ops.get_caller_data = default_get_caller_data;
+}
+
+void tfm_rpc_client_call_handler(void)
+{
+ rpc_ops.handle_req();
+}
+
+void tfm_rpc_client_call_reply(const void *owner, int32_t ret)
+{
+ const struct tfm_msg_body_t *msg = (const struct tfm_msg_body_t *)owner;
+
+ rpc_ops.reply(msg->caller_data, ret);
+}
+
+void tfm_rpc_set_caller_data(struct tfm_msg_body_t *msg, int32_t client_id)
+{
+ msg->caller_data = rpc_ops.get_caller_data(client_id);
+}
diff --git a/secure_fw/spm/model_ipc/tfm_secure_irq_handlers_ipc.inc b/secure_fw/spm/model_ipc/tfm_secure_irq_handlers_ipc.inc
new file mode 100644
index 0000000..22f92cd
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_secure_irq_handlers_ipc.inc
@@ -0,0 +1,51 @@
+/*
+ * 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! ***********/
+
+#include "secure_fw/partitions/secure_storage/psa_manifest/tfm_secure_storage.h"
+#include "secure_fw/partitions/internal_trusted_storage/psa_manifest/tfm_internal_trusted_storage.h"
+#include "secure_fw/partitions/audit_logging/psa_manifest/tfm_audit_logging.h"
+#include "secure_fw/partitions/crypto/psa_manifest/tfm_crypto.h"
+#include "secure_fw/partitions/platform/psa_manifest/tfm_platform.h"
+#include "secure_fw/partitions/initial_attestation/psa_manifest/tfm_initial_attestation.h"
+#include "test/test_services/tfm_core_test/psa_manifest/tfm_test_core.h"
+#include "test/test_services/tfm_core_test_2/psa_manifest/tfm_test_core_2.h"
+#include "test/test_services/tfm_secure_client_service/psa_manifest/tfm_test_client_service.h"
+#include "test/test_services/tfm_ipc_service/psa_manifest/tfm_ipc_service_partition.h"
+#include "test/test_services/tfm_ipc_client/psa_manifest/tfm_ipc_client_partition.h"
+#include "test/test_services/tfm_irq_test_service_1/psa_manifest/tfm_irq_test_service_1.h"
+#include "test/test_services/tfm_sst_test_service/psa_manifest/tfm_sst_test_service.h"
+#include "test/test_services/tfm_secure_client_2/psa_manifest/tfm_secure_client_2.h"
+#include "test/test_services/tfm_multi_core_test/psa_manifest/tfm_multi_core_test.h"
+#include "cmsis_compiler.h"
+
+/* Definitions of the signals of the IRQs (if any) */
+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 */
+
+/* Definitions of privileged IRQ handlers (if any) */
+#ifdef TFM_ENABLE_IRQ_TEST
+void TFM_TIMER0_IRQ_Handler(void)
+{
+ __disable_irq();
+ /* It is OK to call tfm_irq_handler directly from here, as we are already
+ * in handler mode, and we will not be pre-empted as we disabled interrupts
+ */
+ tfm_irq_handler(TFM_IRQ_TEST_1, SPM_CORE_IRQ_TEST_1_SIGNAL_TIMER_0_IRQ, TFM_TIMER0_IRQ);
+ __enable_irq();
+}
+
+#endif /* TFM_ENABLE_IRQ_TEST */
+
diff --git a/secure_fw/spm/model_ipc/tfm_secure_irq_handlers_ipc.inc.template b/secure_fw/spm/model_ipc/tfm_secure_irq_handlers_ipc.inc.template
new file mode 100644
index 0000000..e5a7d6b
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_secure_irq_handlers_ipc.inc.template
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019-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 "cmsis_compiler.h"
+{% macro _irq_record(partition_name, signal, line, priority) -%}
+{ {{ partition_name }}, {{ signal }}, {{ line }}, {{ priority }} },
+{%- endmacro %}
+
+/* Definitions of the signals of the IRQs (if any) */
+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 */
+
+/* Definitions of privileged IRQ handlers (if any) */
+{% 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 %}
+{
+ __disable_irq();
+ /* It is OK to call tfm_irq_handler directly from here, as we are already
+ * in handler mode, and we will not be pre-empted as we disabled interrupts
+ */
+ {% if handler.source %}
+ tfm_irq_handler({{manifest.manifest.name}}, {{handler.signal}}, {{handler.source}});
+ {% else %}
+#error "Interrupt source isn't provided for 'irqs' in partition {{manifest.manifest.name}}"
+ {% endif %}
+ __enable_irq();
+}
+
+ {% endfor %}
+ {% if manifest.attr.conditional %}
+#endif /* {{manifest.attr.conditional}} */
+ {% endif %}
+
+ {% endif %}
+{% endfor %}
diff --git a/secure_fw/spm/model_ipc/tfm_spe_mailbox.c b/secure_fw/spm/model_ipc/tfm_spe_mailbox.c
new file mode 100644
index 0000000..baa02c7
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_spe_mailbox.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "cmsis_compiler.h"
+
+#include "psa/error.h"
+#include "tfm_core_utils.h"
+#include "tfm_utils.h"
+#include "tfm_spe_mailbox.h"
+#include "tfm_rpc.h"
+
+#define NS_CALLER_FLAG (true)
+
+static struct secure_mailbox_queue_t spe_mailbox_queue;
+
+static int32_t tfm_mailbox_dispatch(uint32_t call_type,
+ const struct psa_client_params_t *params,
+ int32_t client_id, int32_t *psa_ret)
+{
+ struct client_call_params_t spm_params = {0};
+
+ TFM_CORE_ASSERT(params != NULL);
+ TFM_CORE_ASSERT(psa_ret != NULL);
+
+ (void)client_id;
+
+ switch (call_type) {
+ case MAILBOX_PSA_FRAMEWORK_VERSION:
+ *psa_ret = tfm_rpc_psa_framework_version();
+ return MAILBOX_SUCCESS;
+ case MAILBOX_PSA_VERSION:
+ spm_params.sid = params->psa_version_params.sid;
+ *psa_ret = tfm_rpc_psa_version(&spm_params, NS_CALLER_FLAG);
+ return MAILBOX_SUCCESS;
+ case MAILBOX_PSA_CONNECT:
+ spm_params.sid = params->psa_connect_params.sid;
+ spm_params.version = params->psa_connect_params.version;
+ *psa_ret = (uint32_t)tfm_rpc_psa_connect(&spm_params, NS_CALLER_FLAG);
+ return MAILBOX_SUCCESS;
+ case MAILBOX_PSA_CALL:
+ spm_params.handle = params->psa_call_params.handle;
+ spm_params.type = params->psa_call_params.type;
+ spm_params.in_vec = params->psa_call_params.in_vec;
+ spm_params.in_len = params->psa_call_params.in_len;
+ spm_params.out_vec = params->psa_call_params.out_vec;
+ spm_params.out_len = params->psa_call_params.out_len;
+ *psa_ret = (uint32_t)tfm_rpc_psa_call(&spm_params, NS_CALLER_FLAG);
+ return MAILBOX_SUCCESS;
+ case MAILBOX_PSA_CLOSE:
+ spm_params.handle = params->psa_close_params.handle;
+ tfm_rpc_psa_close(&spm_params, NS_CALLER_FLAG);
+ return MAILBOX_SUCCESS;
+ default:
+ return MAILBOX_INVAL_PARAMS;
+ }
+}
+
+__STATIC_INLINE void set_spe_queue_empty_status(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ spe_mailbox_queue.empty_slots |= (1 << idx);
+ }
+}
+
+__STATIC_INLINE void clear_spe_queue_empty_status(uint8_t idx)
+{
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ spe_mailbox_queue.empty_slots &= ~(1 << idx);
+ }
+}
+
+__STATIC_INLINE bool get_spe_queue_empty_status(uint8_t idx)
+{
+ if ((idx < NUM_MAILBOX_QUEUE_SLOT) &&
+ (spe_mailbox_queue.empty_slots & (1 << idx))) {
+ return true;
+ }
+
+ return false;
+}
+
+__STATIC_INLINE mailbox_queue_status_t get_nspe_queue_pend_status(
+ const struct ns_mailbox_queue_t *ns_queue)
+{
+ return ns_queue->pend_slots;
+}
+
+__STATIC_INLINE void set_nspe_queue_replied_status(
+ struct ns_mailbox_queue_t *ns_queue,
+ mailbox_queue_status_t mask)
+{
+ ns_queue->replied_slots |= mask;
+}
+
+__STATIC_INLINE void clear_nspe_queue_pend_status(
+ struct ns_mailbox_queue_t *ns_queue,
+ mailbox_queue_status_t mask)
+{
+ ns_queue->pend_slots &= ~mask;
+}
+
+__STATIC_INLINE int32_t get_spe_mailbox_msg_handle(uint8_t idx,
+ mailbox_msg_handle_t *handle)
+{
+ if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ *handle = (mailbox_msg_handle_t)(idx + 1);
+
+ return MAILBOX_SUCCESS;
+}
+
+__STATIC_INLINE int32_t get_spe_mailbox_msg_idx(mailbox_msg_handle_t handle,
+ uint8_t *idx)
+{
+ if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) {
+ return MAILBOX_INVAL_PARAMS;
+ }
+
+ *idx = (uint8_t)(handle - 1);
+
+ return MAILBOX_SUCCESS;
+}
+
+static void mailbox_clean_queue_slot(uint8_t idx)
+{
+ if (idx >= NUM_MAILBOX_QUEUE_SLOT) {
+ return;
+ }
+
+ tfm_core_util_memset(&spe_mailbox_queue.queue[idx], 0,
+ sizeof(spe_mailbox_queue.queue[idx]));
+ set_spe_queue_empty_status(idx);
+}
+
+__STATIC_INLINE struct mailbox_reply_t *get_nspe_reply_addr(uint8_t idx)
+{
+ uint8_t ns_slot_idx;
+
+ if (idx >= NUM_MAILBOX_QUEUE_SLOT) {
+ return NULL;
+ }
+
+ ns_slot_idx = spe_mailbox_queue.queue[idx].ns_slot_idx;
+
+ return &spe_mailbox_queue.ns_queue->queue[ns_slot_idx].reply;
+}
+
+static void mailbox_direct_reply(uint8_t idx, uint32_t result)
+{
+ struct mailbox_reply_t *reply_ptr;
+ uint32_t ret_result = result;
+
+ /* Get reply address */
+ reply_ptr = get_nspe_reply_addr(idx);
+ tfm_core_util_memcpy(&reply_ptr->return_val, &ret_result,
+ sizeof(reply_ptr->return_val));
+
+ mailbox_clean_queue_slot(idx);
+
+ /*
+ * Skip NSPE queue status update after single reply.
+ * Update NSPE queue status after all the mailbox messages are completed
+ */
+}
+
+__STATIC_INLINE int32_t check_mailbox_msg(const struct mailbox_msg_t *msg)
+{
+ /*
+ * TODO
+ * Comprehensive check of mailbox msessage content can be implemented here.
+ */
+ (void)msg;
+ return MAILBOX_SUCCESS;
+}
+
+int32_t tfm_mailbox_handle_msg(void)
+{
+ uint8_t idx;
+ int32_t result;
+ int32_t psa_ret = PSA_ERROR_GENERIC_ERROR;
+ mailbox_queue_status_t mask_bits, pend_slots, reply_slots = 0;
+ struct ns_mailbox_queue_t *ns_queue = spe_mailbox_queue.ns_queue;
+ struct mailbox_msg_t *msg_ptr;
+
+ TFM_CORE_ASSERT(ns_queue != NULL);
+
+ tfm_mailbox_hal_enter_critical();
+
+ /* Check if NSPE mailbox did assert a PSA client call request */
+ if (!ns_queue->pend_slots) {
+ tfm_mailbox_hal_exit_critical();
+ return MAILBOX_NO_PEND_EVENT;
+ }
+
+ pend_slots = get_nspe_queue_pend_status(ns_queue);
+
+ tfm_mailbox_hal_exit_critical();
+
+ for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) {
+ mask_bits = (1 << idx);
+ /* Check if current NSPE mailbox queue slot is pending for handling */
+ if (!(pend_slots & mask_bits)) {
+ continue;
+ }
+
+ /*
+ * TODO
+ * The operations are simplified here. Use the SPE mailbox queue
+ * slot with the same idx as that of the NSPE mailbox queue slot.
+ * A more general implementation should dynamically search and
+ * select an empty SPE mailbox queue slot.
+ */
+ clear_spe_queue_empty_status(idx);
+ spe_mailbox_queue.queue[idx].ns_slot_idx = idx;
+
+ msg_ptr = &spe_mailbox_queue.queue[idx].msg;
+ tfm_core_util_memcpy(msg_ptr, &ns_queue->queue[idx].msg,
+ sizeof(*msg_ptr));
+
+ if (check_mailbox_msg(msg_ptr) != MAILBOX_SUCCESS) {
+ mailbox_clean_queue_slot(idx);
+ continue;
+ }
+
+ get_spe_mailbox_msg_handle(idx,
+ &spe_mailbox_queue.queue[idx].msg_handle);
+
+ /*
+ * Set the current slot index under processing.
+ * The value is used in mailbox_get_caller_data() to identify the
+ * mailbox queue slot.
+ */
+ spe_mailbox_queue.cur_proc_slot_idx = idx;
+
+ result = tfm_mailbox_dispatch(msg_ptr->call_type, &msg_ptr->params,
+ msg_ptr->client_id, &psa_ret);
+ if (result != MAILBOX_SUCCESS) {
+ mailbox_clean_queue_slot(idx);
+ continue;
+ }
+
+ /* Clean up the current slot index under processing */
+ spe_mailbox_queue.cur_proc_slot_idx = NUM_MAILBOX_QUEUE_SLOT;
+
+ if ((msg_ptr->call_type == MAILBOX_PSA_FRAMEWORK_VERSION) ||
+ (msg_ptr->call_type == MAILBOX_PSA_VERSION)) {
+ /*
+ * Directly write the result to NSPE for psa_framework_version() and
+ * psa_version().
+ */
+ reply_slots |= (1 << idx);
+
+ mailbox_direct_reply(idx, psa_ret);
+ } else if ((msg_ptr->call_type == MAILBOX_PSA_CONNECT) ||
+ (msg_ptr->call_type == MAILBOX_PSA_CALL)) {
+ /*
+ * If it failed to deliver psa_connect() or psa_call() request to
+ * TF-M IPC SPM, the failure result should be returned immediately.
+ */
+ if (psa_ret != PSA_SUCCESS) {
+ reply_slots |= (1 << idx);
+ mailbox_direct_reply(idx, psa_ret);
+ }
+ }
+ /*
+ * Skip checking psa_call() since it neither returns immediately nor
+ * has return value.
+ */
+ }
+
+ tfm_mailbox_hal_enter_critical();
+
+ /* Clean the NSPE mailbox pending status. */
+ clear_nspe_queue_pend_status(ns_queue, pend_slots);
+
+ /* Set the NSPE mailbox replied status */
+ set_nspe_queue_replied_status(ns_queue, reply_slots);
+
+ tfm_mailbox_hal_exit_critical();
+
+ if (reply_slots) {
+ tfm_mailbox_hal_notify_peer();
+ }
+
+ return MAILBOX_SUCCESS;
+}
+
+int32_t tfm_mailbox_reply_msg(mailbox_msg_handle_t handle, int32_t reply)
+{
+ uint8_t idx;
+ int32_t ret;
+ struct ns_mailbox_queue_t *ns_queue = spe_mailbox_queue.ns_queue;
+
+ TFM_CORE_ASSERT(ns_queue != NULL);
+
+ /*
+ * If handle == MAILBOX_MSG_NULL_HANDLE, reply to the mailbox message
+ * in the first slot.
+ * When multiple ongoing PSA client calls from NSPE are supported,
+ * additional check might be necessary to avoid spoofing the first slot.
+ */
+ if (handle == MAILBOX_MSG_NULL_HANDLE) {
+ idx = 0;
+ } else {
+ ret = get_spe_mailbox_msg_idx(handle, &idx);
+ if (ret != MAILBOX_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (get_spe_queue_empty_status(idx)) {
+ return MAILBOX_NO_PEND_EVENT;
+ }
+
+ mailbox_direct_reply(idx, (uint32_t)reply);
+
+ tfm_mailbox_hal_enter_critical();
+
+ /* Set the NSPE mailbox replied status */
+ set_nspe_queue_replied_status(ns_queue, (1 << idx));
+
+ tfm_mailbox_hal_exit_critical();
+
+ tfm_mailbox_hal_notify_peer();
+
+ return MAILBOX_SUCCESS;
+}
+
+/* RPC handle_req() callback */
+static void mailbox_handle_req(void)
+{
+ (void)tfm_mailbox_handle_msg();
+}
+
+/* RPC reply() callback */
+static void mailbox_reply(const void *owner, int32_t ret)
+{
+ mailbox_msg_handle_t handle = MAILBOX_MSG_NULL_HANDLE;
+
+ /* If the owner is specified */
+ if (owner) {
+ handle = *((mailbox_msg_handle_t *)owner);
+ }
+
+ (void)tfm_mailbox_reply_msg(handle, ret);
+}
+
+/* RPC get_caller_data() callback */
+static const void *mailbox_get_caller_data(int32_t client_id)
+{
+ uint8_t idx;
+
+ (void)client_id;
+
+ idx = spe_mailbox_queue.cur_proc_slot_idx;
+ if (idx < NUM_MAILBOX_QUEUE_SLOT) {
+ return (const void *)&spe_mailbox_queue.queue[idx].msg_handle;
+ }
+
+ return NULL;
+}
+
+/* Mailbox specific operations callback for TF-M RPC */
+static const struct tfm_rpc_ops_t mailbox_rpc_ops = {
+ .handle_req = mailbox_handle_req,
+ .reply = mailbox_reply,
+ .get_caller_data = mailbox_get_caller_data,
+};
+
+int32_t tfm_mailbox_init(void)
+{
+ int32_t ret;
+
+ tfm_core_util_memset(&spe_mailbox_queue, 0, sizeof(spe_mailbox_queue));
+
+ spe_mailbox_queue.empty_slots =
+ (mailbox_queue_status_t)((1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)) - 1);
+ spe_mailbox_queue.empty_slots +=
+ (mailbox_queue_status_t)(1UL << (NUM_MAILBOX_QUEUE_SLOT - 1));
+
+ /* Register RPC callbacks */
+ ret = tfm_rpc_register_ops(&mailbox_rpc_ops);
+ if (ret != TFM_RPC_SUCCESS) {
+ return MAILBOX_CALLBACK_REG_ERROR;
+ }
+
+ /*
+ * Platform specific initialization.
+ * Initialize Inter-Processor Communication and achieve the base address of
+ * NSPE mailbox queue
+ */
+ ret = tfm_mailbox_hal_init(&spe_mailbox_queue);
+ if (ret != MAILBOX_SUCCESS) {
+ tfm_rpc_unregister_ops();
+
+ return ret;
+ }
+
+ return MAILBOX_SUCCESS;
+}
diff --git a/secure_fw/spm/tfm_spm_db_ipc.inc b/secure_fw/spm/model_ipc/tfm_spm_db_ipc.inc
similarity index 99%
rename from secure_fw/spm/tfm_spm_db_ipc.inc
rename to secure_fw/spm/model_ipc/tfm_spm_db_ipc.inc
index 2dd09bc..3a99b2e 100644
--- a/secure_fw/spm/tfm_spm_db_ipc.inc
+++ b/secure_fw/spm/model_ipc/tfm_spm_db_ipc.inc
@@ -10,7 +10,7 @@
#ifndef __TFM_SPM_DB_IPC_INC__
#define __TFM_SPM_DB_IPC_INC__
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "psa_manifest/sid.h"
/**************************************************************************/
diff --git a/secure_fw/spm/tfm_spm_db_ipc.inc.template b/secure_fw/spm/model_ipc/tfm_spm_db_ipc.inc.template
similarity index 99%
rename from secure_fw/spm/tfm_spm_db_ipc.inc.template
rename to secure_fw/spm/model_ipc/tfm_spm_db_ipc.inc.template
index 86390df..4fcd0fb 100644
--- a/secure_fw/spm/tfm_spm_db_ipc.inc.template
+++ b/secure_fw/spm/model_ipc/tfm_spm_db_ipc.inc.template
@@ -10,7 +10,7 @@
#ifndef __TFM_SPM_DB_IPC_INC__
#define __TFM_SPM_DB_IPC_INC__
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "psa_manifest/sid.h"
{# Produce a build error if heap_size is presented in the manifest, because of the dynamic memory allocation is not supported now. #}
diff --git a/secure_fw/spm/model_ipc/tfm_thread.c b/secure_fw/spm/model_ipc/tfm_thread.c
new file mode 100644
index 0000000..1d66e25
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_thread.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include "tfm_arch.h"
+#include "tfm_thread.h"
+#include "tfm_utils.h"
+#include "tfm_memory_utils.h"
+#include "tfm/tfm_core_svc.h"
+#include "tfm/spm_api.h"
+#include "tfm_core_utils.h"
+
+/* Force ZERO in case ZI(bss) clear is missing */
+static struct tfm_core_thread_t *p_thrd_head = NULL;
+static struct tfm_core_thread_t *p_runn_head = NULL;
+static struct tfm_core_thread_t *p_curr_thrd = NULL;
+
+/* Define Macro to fetch global to support future expansion (PERCPU e.g.) */
+#define LIST_HEAD p_thrd_head
+#define RUNN_HEAD p_runn_head
+#define CURR_THRD p_curr_thrd
+
+static struct tfm_core_thread_t *find_next_running_thread(
+ struct tfm_core_thread_t *pth)
+{
+ while (pth && pth->state != THRD_STATE_RUNNING) {
+ pth = pth->next;
+ }
+
+ return pth;
+}
+
+/* To get next running thread for scheduler */
+struct tfm_core_thread_t *tfm_core_thrd_get_next_thread(void)
+{
+ /*
+ * First RUNNING thread has highest priority since threads are sorted with
+ * priority.
+ */
+ return find_next_running_thread(RUNN_HEAD);
+}
+
+/* To get current thread for caller */
+struct tfm_core_thread_t *tfm_core_thrd_get_curr_thread(void)
+{
+ return CURR_THRD;
+}
+
+/* Insert a new thread into list by descending priority (Highest at head) */
+static void insert_by_prior(struct tfm_core_thread_t **head,
+ struct tfm_core_thread_t *node)
+{
+ if (*head == NULL || (node->prior <= (*head)->prior)) {
+ node->next = *head;
+ *head = node;
+ } else {
+ struct tfm_core_thread_t *iter = *head;
+
+ while (iter->next && (node->prior > iter->next->prior)) {
+ iter = iter->next;
+ }
+ node->next = iter->next;
+ iter->next = node;
+ }
+}
+
+/*
+ * Set first running thread as head to reduce enumerate
+ * depth while searching for a first running thread.
+ */
+static void update_running_head(struct tfm_core_thread_t **runn,
+ struct tfm_core_thread_t *node)
+{
+ if ((node->state == THRD_STATE_RUNNING) &&
+ (*runn == NULL || (node->prior < (*runn)->prior))) {
+ *runn = node;
+ } else {
+ *runn = LIST_HEAD;
+ }
+}
+
+/* Set context members only. No validation here */
+void tfm_core_thrd_init(struct tfm_core_thread_t *pth,
+ tfm_core_thrd_entry_t pfn, void *param,
+ uintptr_t stk_top, uintptr_t stk_btm)
+{
+ pth->prior = THRD_PRIOR_MEDIUM;
+ pth->state = THRD_STATE_CREATING;
+ pth->pfn = pfn;
+ pth->param = param;
+ pth->stk_btm = stk_btm;
+ pth->stk_top = stk_top;
+}
+
+uint32_t tfm_core_thrd_start(struct tfm_core_thread_t *pth)
+{
+ /* Validate parameters before really start */
+ if ((pth->state != THRD_STATE_CREATING) ||
+ (pth->pfn == NULL) ||
+ (pth->stk_btm == 0) ||
+ (pth->stk_top == 0)) {
+ return THRD_ERR_INVALID_PARAM;
+ }
+
+ /* Thread management runs in handler mode; set context for thread mode. */
+ tfm_arch_init_context(&pth->arch_ctx, pth->param, (uintptr_t)pth->pfn,
+ pth->stk_btm, pth->stk_top);
+
+ /* Insert a new thread with priority */
+ insert_by_prior(&LIST_HEAD, pth);
+
+ /* Mark it as RUNNING after insertion */
+ tfm_core_thrd_set_state(pth, THRD_STATE_RUNNING);
+
+ return THRD_SUCCESS;
+}
+
+void tfm_core_thrd_set_state(struct tfm_core_thread_t *pth, uint32_t new_state)
+{
+ TFM_CORE_ASSERT(pth != NULL && new_state < THRD_STATE_INVALID);
+
+ pth->state = new_state;
+ update_running_head(&RUNN_HEAD, pth);
+}
+
+/* Scheduling won't happen immediately but after the exception returns */
+void tfm_core_thrd_activate_schedule(void)
+{
+ tfm_arch_trigger_pendsv();
+}
+
+void tfm_core_thrd_start_scheduler(struct tfm_core_thread_t *pth)
+{
+ /*
+ * There is no selected thread before scheduler start, assign the caller
+ * provided thread as the current thread. Update the hardware PSP/PSPLIM
+ * with the value in thread context to ensure they are identical.
+ * This function can be called only ONCE; further calling triggers assert.
+ */
+ TFM_CORE_ASSERT(CURR_THRD == NULL);
+ TFM_CORE_ASSERT(pth != NULL);
+ TFM_CORE_ASSERT(pth->arch_ctx.sp != 0);
+
+ tfm_arch_update_ctx(&pth->arch_ctx);
+
+ CURR_THRD = pth;
+
+ tfm_core_thrd_activate_schedule();
+}
+
+void tfm_core_thrd_switch_context(struct tfm_arch_ctx_t *p_actx,
+ struct tfm_core_thread_t *prev,
+ struct tfm_core_thread_t *next)
+{
+ TFM_CORE_ASSERT(prev != NULL);
+ TFM_CORE_ASSERT(next != NULL);
+
+ /*
+ * First, update latest context into the current thread context.
+ * Then, update background context with next thread's context.
+ */
+ tfm_core_util_memcpy(&prev->arch_ctx, p_actx, sizeof(*p_actx));
+ tfm_core_util_memcpy(p_actx, &next->arch_ctx, sizeof(next->arch_ctx));
+
+ /* Update current thread indicator */
+ CURR_THRD = next;
+}
diff --git a/secure_fw/spm/model_ipc/tfm_wait.c b/secure_fw/spm/model_ipc/tfm_wait.c
new file mode 100644
index 0000000..efb7be6
--- /dev/null
+++ b/secure_fw/spm/model_ipc/tfm_wait.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include "tfm_thread.h"
+#include "tfm_utils.h"
+#include "tfm_wait.h"
+
+void tfm_event_wait(struct tfm_event_t *pevnt)
+{
+ TFM_CORE_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
+
+ pevnt->owner = tfm_core_thrd_get_curr_thread();
+ tfm_core_thrd_set_state(pevnt->owner, THRD_STATE_BLOCK);
+ tfm_core_thrd_activate_schedule();
+}
+
+void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval)
+{
+ TFM_CORE_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
+
+ if (pevnt->owner && pevnt->owner->state == THRD_STATE_BLOCK) {
+ tfm_core_thrd_set_state(pevnt->owner, THRD_STATE_RUNNING);
+ tfm_core_thrd_set_retval(pevnt->owner, retval);
+ pevnt->owner = NULL;
+ tfm_core_thrd_activate_schedule();
+ }
+}
diff --git a/secure_fw/spm/spm_api.c b/secure_fw/spm/runtime/spm_api.c
similarity index 97%
rename from secure_fw/spm/spm_api.c
rename to secure_fw/spm/runtime/spm_api.c
index 9dae74b..a72b402 100644
--- a/secure_fw/spm/spm_api.c
+++ b/secure_fw/spm/runtime/spm_api.c
@@ -9,16 +9,16 @@
#include <stdio.h>
#include <string.h>
-#include "spm_api.h"
+#include "tfm/spm_api.h"
#include "tfm_spm_hal.h"
#include "tfm_memory_utils.h"
-#include "spm_db.h"
+#include "tfm/spm_db.h"
#include "tfm_internal.h"
#include "tfm_api.h"
#include "tfm_nspm.h"
#include "tfm_core.h"
#include "tfm_peripherals_def.h"
-#include "spm_partition_defs.h"
+#include "tfm/spm_partition_defs.h"
#include "region.h"
#define NON_SECURE_INTERNAL_PARTITION_DB_IDX 0
diff --git a/secure_fw/spm/runtime/tfm_core_mem_check.c b/secure_fw/spm/runtime/tfm_core_mem_check.c
new file mode 100644
index 0000000..17ab074
--- /dev/null
+++ b/secure_fw/spm/runtime/tfm_core_mem_check.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <arm_cmse.h>
+#include "region_defs.h"
+#include "tfm/spm_api.h"
+#include "tfm_api.h"
+
+/**
+ * \brief Check whether the current partition has access to a memory range
+ *
+ * This function assumes, that the current MPU configuration is set for the
+ * partition to be checked. The flags should contain information of the
+ * execution mode of the partition code (priv/unpriv), and access type
+ * (read/write) as specified in "ARMv8-M Security Extensions: Requirements on
+ * Development Tools" chapter "Address range check intrinsic"
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] flags The flags to pass to the cmse_check_address_range func
+ *
+ * \return TFM_SUCCESS if the partition has access to the memory range,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+static enum tfm_status_e has_access_to_region(const void *p, size_t s,
+ int flags)
+{
+ int32_t range_access_allowed_by_mpu;
+
+ /* Use the TT instruction to check access to the partition's regions*/
+ range_access_allowed_by_mpu =
+ cmse_check_address_range((void *)p, s, flags) != NULL;
+
+ if (range_access_allowed_by_mpu) {
+ return TFM_SUCCESS;
+ }
+
+ return TFM_ERROR_GENERIC;
+}
+
+enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s,
+ bool ns_caller,
+ uint32_t privileged)
+{
+ int flags = CMSE_MPU_READ;
+
+ /* In case of NS caller, only force unprivileged check, if the non secure
+ * Thread mode is unprivileged
+ */
+ if (ns_caller) {
+ CONTROL_Type ctrl;
+
+ ctrl.w = __TZ_get_CONTROL_NS();
+ if (ctrl.b.nPRIV == 1) {
+ privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
+ } else {
+ privileged = TFM_PARTITION_PRIVILEGED_MODE;
+ }
+ }
+
+ if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+ flags |= CMSE_MPU_UNPRIV;
+ }
+
+ if (ns_caller) {
+ flags |= CMSE_NONSECURE;
+ }
+
+ return has_access_to_region(p, s, flags);
+}
+
+enum tfm_status_e tfm_core_has_write_access_to_region(const void *p, size_t s,
+ bool ns_caller,
+ uint32_t privileged)
+{
+ int flags = CMSE_MPU_READWRITE;
+
+ /* In case of NS caller, only force unprivileged check, if the non secure
+ * Thread mode is unprivileged
+ */
+ if (ns_caller) {
+ CONTROL_Type ctrl;
+
+ ctrl.w = __TZ_get_CONTROL_NS();
+ if (ctrl.b.nPRIV == 1) {
+ privileged = TFM_PARTITION_UNPRIVILEGED_MODE;
+ } else {
+ privileged = TFM_PARTITION_PRIVILEGED_MODE;
+ }
+ }
+
+ if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+ flags |= CMSE_MPU_UNPRIV;
+ }
+
+ if (ns_caller) {
+ flags |= CMSE_NONSECURE;
+ }
+
+ return has_access_to_region(p, s, flags);
+}
diff --git a/secure_fw/spm/runtime/tfm_core_utils.c b/secure_fw/spm/runtime/tfm_core_utils.c
new file mode 100644
index 0000000..ba9a4ea
--- /dev/null
+++ b/secure_fw/spm/runtime/tfm_core_utils.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "tfm_utils.h"
+#include "tfm_core_utils.h"
+
+union tfm_core_addr_t {
+ uintptr_t uint_addr;
+ uint8_t *p_byte;
+ uint32_t *p_word;
+};
+
+void *tfm_core_util_memcpy(void *dest, const void *src, size_t n)
+{
+ union tfm_core_addr_t p_dest;
+ union tfm_core_addr_t p_src;
+
+ TFM_CORE_ASSERT(dest != src);
+
+ p_dest.p_byte = (uint8_t *)dest;
+ p_src.p_byte = (uint8_t *)src;
+
+ /*
+ * Check src and dest address value to see if word-copy is applicable.
+ * If applicable, use byte-copy for the first several unaligned bytes,
+ * and then, word-copy for aligned memory.
+ */
+ if (!((p_dest.uint_addr ^ p_src.uint_addr) & (sizeof(uint32_t) - 1))) {
+ while (n && (p_dest.uint_addr & (sizeof(uint32_t) - 1))) {
+ *p_dest.p_byte++ = *p_src.p_byte++;
+ n--;
+ }
+
+ while (n >= sizeof(uint32_t)) {
+ *p_dest.p_word++ = *p_src.p_word++;
+ n -= sizeof(uint32_t);
+ }
+ }
+
+ /*
+ * Word-copy is not applicable, use byte-copy for the remaining
+ * unaligned memory.
+ */
+ while (n--) {
+ *p_dest.p_byte++ = *p_src.p_byte++;
+ }
+
+ return dest;
+}
+
+void *tfm_core_util_memset(void *s, int c, size_t n)
+{
+ union tfm_core_addr_t p_mem;
+ uint32_t quad_pattern;
+
+ p_mem.p_byte = (uint8_t *)s;
+ quad_pattern = (((uint8_t)c) << 24) | (((uint8_t)c) << 16) |
+ (((uint8_t)c) << 8) | ((uint8_t)c);
+
+ while (n && (p_mem.uint_addr & (sizeof(uint32_t) - 1))) {
+ *p_mem.p_byte++ = (uint8_t)c;
+ n--;
+ }
+
+ while (n >= sizeof(uint32_t)) {
+ *p_mem.p_word++ = quad_pattern;
+ n -= sizeof(uint32_t);
+ }
+
+ while (n--) {
+ *p_mem.p_byte++ = (uint8_t)c;
+ }
+
+ return s;
+}
diff --git a/secure_fw/spm/runtime/tfm_secure_api.c b/secure_fw/spm/runtime/tfm_secure_api.c
new file mode 100644
index 0000000..eecb62e
--- /dev/null
+++ b/secure_fw/spm/runtime/tfm_secure_api.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include "secure_utilities.h"
+#include "tfm_secure_api.h"
+
+/* This is the "Big Lock" on the secure side, to guarantee single entry
+ * to SPE
+ */
+int32_t tfm_secure_lock;
+
+bool tfm_is_one_bit_set(uint32_t n)
+{
+ return ((n && !(n & (n-1))) ? true : false);
+}
+
+enum tfm_status_e check_address_range(const void *p, size_t s,
+ uintptr_t region_start,
+ uintptr_t region_limit)
+{
+ int32_t range_in_region;
+
+ /* Check for overflow in the range parameters */
+ if ((uintptr_t)p > UINTPTR_MAX - s) {
+ return TFM_ERROR_GENERIC;
+ }
+
+ /* We trust the region parameters, and don't check for overflow */
+
+ /* Calculate the result */
+ range_in_region = ((uintptr_t)p >= region_start) &&
+ ((uintptr_t)((char *) p + s - 1) <= region_limit);
+ if (range_in_region) {
+ return TFM_SUCCESS;
+ } else {
+ return TFM_ERROR_GENERIC;
+ }
+}
+
+void tfm_secure_api_error_handler(void)
+{
+ ERROR_MSG("Security violation when calling secure API");
+ tfm_core_panic();
+}
+
+#ifndef TFM_PSA_API
+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;
+}
+#endif
diff --git a/secure_fw/spm/tfm_spm_db.inc b/secure_fw/spm/runtime/tfm_spm_db.inc
similarity index 100%
rename from secure_fw/spm/tfm_spm_db.inc
rename to secure_fw/spm/runtime/tfm_spm_db.inc
diff --git a/secure_fw/spm/runtime/tfm_spm_services.c b/secure_fw/spm/runtime/tfm_spm_services.c
new file mode 100644
index 0000000..2a04c6e
--- /dev/null
+++ b/secure_fw/spm/runtime/tfm_spm_services.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <arm_cmse.h>
+
+#include "tfm/tfm_core_svc.h"
+#include "tfm_secure_api.h"
+#include "tfm_internal.h"
+#include "secure_fw/include/tfm/tfm_spm_services_api.h"
+#include "tfm/spm_api.h"
+#include "psa/service.h"
+
+#ifndef TFM_PSA_API
+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_core_validate_secure_caller(void)
+{
+ __ASM volatile(
+ "SVC %0\n"
+ "BX lr\n"
+ : : "I" (TFM_SVC_VALIDATE_SECURE_CALLER));
+}
+
+#endif
+
+__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))
+int32_t tfm_core_get_boot_data(uint8_t major_type,
+ struct tfm_boot_data *boot_status,
+ uint32_t len)
+{
+ __ASM volatile(
+ "SVC %0\n"
+ "BX lr\n"
+ : : "I" (TFM_SVC_GET_BOOT_DATA));
+}
+
+__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));
+}
+
+#ifndef TFM_PSA_API
+
+__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));
+}
+
+#endif
diff --git a/secure_fw/spm/runtime/tfm_utils.c b/secure_fw/spm/runtime/tfm_utils.c
new file mode 100644
index 0000000..c1d9d35
--- /dev/null
+++ b/secure_fw/spm/runtime/tfm_utils.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include "tfm_utils.h"
+#include "tfm_spm_hal.h"
+
+void tfm_core_panic(void)
+{
+ /*
+ * FixMe: In the first stage, the SPM will restart the entire system when a
+ * programmer error is detected in either the SPE or NSPE.
+ * In the next stage, the specified error codes are also sent to any NSPE
+ * management firmware. The NSPE management firmware can then decide to pass
+ * those error codes back to the calling task or to use its own
+ * functionality for terminating an execution context.
+ */
+ tfm_spm_hal_system_reset();
+}
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
deleted file mode 100644
index fa0a02d..0000000
--- a/secure_fw/spm/spm_api.h
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
- * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __SPM_API_H__
-#define __SPM_API_H__
-
-/* This file contains the apis exported by the SPM to tfm core */
-#include "tfm_api.h"
-#include "spm_partition_defs.h"
-#include "tfm_secure_api.h"
-#include <stdbool.h>
-#ifdef TFM_PSA_API
-#include "tfm_list.h"
-#include "tfm_wait.h"
-#include "tfm_message_queue.h"
-#include "tfm_secure_api.h"
-#include "tfm_thread.h"
-#endif
-
-#define SPM_INVALID_PARTITION_IDX (~0U)
-
-/* Privileged definitions for partition thread mode */
-#define TFM_PARTITION_PRIVILEGED_MODE 1
-#define TFM_PARTITION_UNPRIVILEGED_MODE 0
-
-enum spm_err_t {
- SPM_ERR_OK = 0,
- SPM_ERR_PARTITION_DB_NOT_INIT,
- SPM_ERR_PARTITION_ALREADY_ACTIVE,
- SPM_ERR_PARTITION_NOT_AVAILABLE,
- SPM_ERR_INVALID_PARAMETER,
- SPM_ERR_INVALID_CONFIG,
-};
-
-#define SPM_PARTITION_STATE_UNINIT 0
-#define SPM_PARTITION_STATE_IDLE 1
-#define SPM_PARTITION_STATE_RUNNING 2
-#define SPM_PARTITION_STATE_HANDLING_IRQ 3
-#define SPM_PARTITION_STATE_SUSPENDED 4
-#define SPM_PARTITION_STATE_BLOCKED 5
-#define SPM_PARTITION_STATE_CLOSED 6
-
-#define SPM_PART_FLAG_APP_ROT 0x01
-#define SPM_PART_FLAG_PSA_ROT 0x02
-#define SPM_PART_FLAG_IPC 0x04
-
-#define TFM_HANDLE_STATUS_IDLE 0
-#define TFM_HANDLE_STATUS_ACTIVE 1
-#define TFM_HANDLE_STATUS_CONNECT_ERROR 2
-
-#ifndef TFM_PSA_API
-/**
- * \brief Holds the iovec parameters that are passed to a service
- *
- * \note The size of the structure is (and have to be) multiple of 8 bytes
- */
-struct iovec_args_t {
- psa_invec in_vec[PSA_MAX_IOVEC]; /*!< Array of psa_invec objects */
- size_t in_len; /*!< Number psa_invec objects in in_vec
- */
- psa_outvec out_vec[PSA_MAX_IOVEC]; /*!< Array of psa_outvec objects */
- size_t out_len; /*!< Number psa_outvec objects in out_vec
- */
-};
-
-/* The size of this struct must be multiple of 4 bytes as it is stacked to an
- * uint32_t[] array
- */
-struct interrupted_ctx_stack_frame_t {
- uint32_t partition_state;
-};
-
-/* The size of this struct must be multiple of 4 bytes as it is stacked to an
- * uint32_t[] array
- */
-struct handler_ctx_stack_frame_t {
- uint32_t partition_state;
- uint32_t caller_partition_idx;
-};
-#endif /* !define(TFM_PSA_API) */
-
-/**
- * \brief Runtime context information of a partition
- */
-struct spm_partition_runtime_data_t {
-#ifdef TFM_PSA_API
- uint32_t signals; /* Service signals had been triggered*/
- struct tfm_event_t signal_evnt; /* Event signal */
- struct tfm_list_node_t service_list;/* Service list */
- struct tfm_core_thread_t sp_thrd; /* Thread object */
- uint32_t assigned_signals; /* All assigned signals */
-#else /* TFM_PSA_API */
- uint32_t partition_state;
- uint32_t caller_partition_idx;
- int32_t caller_client_id;
- uint32_t stack_ptr;
- uint32_t lr;
- struct iovec_args_t iovec_args;
- psa_outvec *orig_outvec;
- uint32_t *ctx_stack_ptr;
-#endif /* TFM_PSA_API */
- uint32_t signal_mask; /*
- * Service signal mask passed by
- * psa_wait()
- */
-};
-
-#ifdef TFM_PSA_API
-
-#define TFM_VERSION_POLICY_RELAXED 0
-#define TFM_VERSION_POLICY_STRICT 1
-
-#define TFM_CONN_HANDLE_MAX_NUM 16
-
-/* RoT connection handle list */
-struct tfm_conn_handle_t {
- void *rhandle; /* Reverse handle value */
- uint32_t status; /*
- * Status of handle, three valid
- * options:
- * TFM_HANDLE_STATUS_ACTIVE,
- * TFM_HANDLE_STATUS_IDLE and
- * TFM_HANDLE_STATUS_CONNECT_ERROR
- */
- int32_t client_id; /*
- * Partition ID of the sender of the
- * message:
- * - secure partition id;
- * - non secure client endpoint id.
- */
- struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
- struct tfm_spm_service_t *service; /* RoT service pointer */
- struct tfm_list_node_t list; /* list node */
-};
-
-/* Service database defined by manifest */
-struct tfm_spm_service_db_t {
- char *name; /* Service name */
- uint32_t partition_id; /* Partition ID which service belong to */
- psa_signal_t signal; /* Service signal */
- uint32_t sid; /* Service identifier */
- bool non_secure_client; /* If can be called by non secure client */
- uint32_t version; /* Service version */
- uint32_t version_policy; /* Service version policy */
-};
-
-/* RoT Service data */
-struct tfm_spm_service_t {
- const struct tfm_spm_service_db_t *service_db;/* Service database pointer */
- struct spm_partition_desc_t *partition; /*
- * Point to secure partition
- * data
- */
- struct tfm_list_node_t handle_list; /* Service handle list */
- struct tfm_msg_queue_t msg_queue; /* Message queue */
- struct tfm_list_node_t list; /* For list operation */
-};
-#endif /* ifdef(TFM_PSA_API) */
-
-/*********************** common definitions ***********************/
-
-/**
- * \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
- */
-uint32_t get_partition_idx(uint32_t partition_id);
-
-/**
- * \brief Get the id of the partition for its index from the db
- *
- * \param[in] partition_idx Partition index
- *
- * \return Partition ID for that partition
- *
- * \note This function doesn't check if partition_idx is valid.
- */
-uint32_t tfm_spm_partition_get_partition_id(uint32_t 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.
- */
-uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
-
-/**
- * \brief Initialize partition database
- *
- * \return Error code \ref spm_err_t
- */
-enum spm_err_t tfm_spm_db_init(void);
-
-/**
- * \brief Change the privilege mode for partition thread mode.
- *
- * \param[in] privileged Privileged mode,
- * \ref TFM_PARTITION_PRIVILEGED_MODE
- * and \ref TFM_PARTITION_UNPRIVILEGED_MODE
- *
- * \note Barrier instructions are not called by this function, and if
- * it is called in thread mode, it might be necessary to call
- * them after this function returns.
- */
-void tfm_spm_partition_change_privilege(uint32_t privileged);
-
-/**
- * \brief Get the current partition mode.
- *
- * \param[in] partition_flags Flags of current partition
- *
- * \retval TFM_PARTITION_PRIVILEGED_MODE Privileged mode
- * \retval TFM_PARTITION_UNPRIVILEGED_MODE Unprivileged mode
- */
-uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags);
-
-/**
- * \brief Handle an SPM request by a secure service
- * \param[in] svc_ctx The stacked SVC context
- */
-void tfm_spm_request_handler(const struct tfm_state_context_t *svc_ctx);
-
-/*********************** library definitions ***********************/
-
-#ifndef TFM_PSA_API
-/**
- * \brief Save interrupted partition context on ctx stack
- *
- * \param[in] partition_idx Partition index
- *
- * \note This function doesn't check if partition_idx is valid.
- * \note This function doesn't whether the ctx stack overflows.
- */
-void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx);
-
-/**
- * \brief Restores interrupted partition context on ctx stack
- *
- * \param[in] partition_idx Partition index
- *
- * \note This function doesn't check if partition_idx is valid.
- * \note This function doesn't whether the ctx stack underflows.
- */
-void tfm_spm_partition_pop_interrupted_ctx(uint32_t partition_idx);
-
-/**
- * \brief Save handler partition context on ctx stack
- *
- * \param[in] partition_idx Partition index
- *
- * \note This function doesn't check if partition_idx is valid.
- * \note This function doesn't whether the ctx stack overflows.
- */
-void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx);
-
-/**
- * \brief Restores handler partition context on ctx stack
- *
- * \param[in] partition_idx Partition index
- *
- * \note This function doesn't check if partition_idx is valid.
- * \note This function doesn't whether the ctx stack underflows.
- */
-void tfm_spm_partition_pop_handler_ctx(uint32_t partition_idx);
-
-/**
- * \brief Get the current runtime data of a partition
- *
- * \param[in] partition_idx Partition index
- *
- * \return The runtime data of the specified partition
- *
- * \note This function doesn't check if partition_idx is valid.
- */
-const struct spm_partition_runtime_data_t *
- tfm_spm_partition_get_runtime_data(uint32_t partition_idx);
-
-/**
- * \brief Returns the index of the partition that has running state
- *
- * \return The index of the partition with the running state, if there is any
- * set. 0 otherwise.
- */
-uint32_t tfm_spm_partition_get_running_partition_idx(void);
-
-/**
- * \brief Save stack pointer and link register for partition in database
- *
- * \param[in] partition_idx Partition index
- * \param[in] stack_ptr Stack pointer to be stored
- * \param[in] lr Link register to be stored
- *
- * \note This function doesn't check if partition_idx is valid.
- */
-void tfm_spm_partition_store_context(uint32_t partition_idx,
- uint32_t stack_ptr, uint32_t lr);
-
-/**
- * \brief Set the current state of a partition
- *
- * \param[in] partition_idx Partition index
- * \param[in] state The state to be set
- *
- * \note This function doesn't check if partition_idx is valid.
- * \note The state has to have the value set of \ref spm_part_state_t.
- */
-void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
-
-/**
- * \brief Set the caller partition index for a given partition
- *
- * \param[in] partition_idx Partition index
- * \param[in] caller_partition_idx The index of the caller partition
- *
- * \note This function doesn't check if any of the partition_idxs are valid.
- */
-void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx,
- uint32_t caller_partition_idx);
-
-/**
-* \brief Set the caller client ID for a given partition
-*
-* \param[in] partition_idx Partition index
-* \param[in] caller_client_id The ID of the calling client
-*
-* \note This function doesn't check if any of the partition_idxs are valid.
-*/
-void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
- int32_t caller_client_id);
-
-
-/**
- * \brief Set the iovec parameters for the partition
- *
- * \param[in] partition_idx Partition index
- * \param[in] args The arguments of the secure function
- *
- * args is expected to be of type int32_t[4] where:
- * args[0] is in_vec
- * args[1] is in_len
- * args[2] is out_vec
- * args[3] is out_len
- *
- * \return Error code \ref spm_err_t
- *
- * \note This function doesn't check if partition_idx is valid.
- * \note This function assumes that the iovecs that are passed in args are
- * valid, and does no sanity check on them at all.
- */
-enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx,
- const int32_t *args);
-
-/**
- * \brief Execute partition init function
- *
- * \return Error code \ref spm_err_t
- */
-enum spm_err_t tfm_spm_partition_init(void);
-
-/**
- * \brief Clears the context info from the database for a partition.
- *
- * \param[in] partition_idx Partition index
- *
- * \note This function doesn't check if partition_idx is valid.
- */
-void tfm_spm_partition_cleanup_context(uint32_t partition_idx);
-
-/**
- * \brief Set the signal mask for a given partition
- *
- * \param[in] partition_idx Partition index
- * \param[in] signal_mask The signal mask to be set for the partition
- *
- * \note This function doesn't check if any of the partition_idxs are valid.
- */
-void tfm_spm_partition_set_signal_mask(uint32_t partition_idx,
- uint32_t signal_mask);
-
-/**
- * \brief Signal that secure partition initialisation is finished
- */
-void tfm_spm_secure_api_init_done(void);
-
-/**
- * \brief Called if veneer is running in thread mode
- */
-uint32_t tfm_spm_partition_request_svc_handler(
- const uint32_t *svc_args, uint32_t lr);
-
-/**
- * \brief Called when secure service returns
- */
-uint32_t tfm_spm_partition_return_handler(uint32_t lr);
-
-/**
- * \brief Called by secure service to check if client is secure
- */
-void tfm_spm_validate_secure_caller_handler(uint32_t *svc_args);
-
-/**
- * \brief Stores caller's client id in state context
- */
-void tfm_spm_get_caller_client_id_handler(uint32_t *svc_args);
-
-/**
- * \brief Checks if a secure service's access to a memory location is permitted
- */
-void tfm_spm_memory_permission_check_handler(uint32_t *svc_args);
-
-/**
- * \brief Check whether a buffer is ok for writing to by the privileged API
- * function.
- *
- * This function checks whether the caller partition owns the buffer, can write
- * to it, and the buffer has proper alignment.
- *
- * \param[in] partition_idx Partition index
- * \param[in] start_addr The start address of the buffer
- * \param[in] len The length of the buffer
- * \param[in] alignment The expected alignment (in bits)
- *
- * \return 1 if the check passes, 0 otherwise.
- *
- * \note For a 0 long buffer the check fails.
- */
-int32_t tfm_spm_check_buffer_access(uint32_t partition_idx,
- void *start_addr,
- size_t len,
- uint32_t alignment);
-
-/**
- * \brief Handle deprivileged request
- */
-extern uint32_t tfm_spm_depriv_req_handler(uint32_t *svc_args,
- uint32_t excReturn);
-
-/**
- * \brief Handle request to return to privileged
- */
-uint32_t tfm_spm_depriv_return_handler(uint32_t *irq_svc_args, uint32_t lr);
-
-/**
- * \brief Handle IRQ enable request
- */
-void tfm_spm_enable_irq_handler(uint32_t *svc_args);
-
-/**
- * \brief Handle IRQ disable request
- */
-void tfm_spm_disable_irq_handler(uint32_t *svc_args);
-
-/**
- * \brief Handle signal wait request
- */
-void tfm_spm_psa_wait(uint32_t *svc_args);
-
-/**
- * \brief Handle request to record IRQ processed
- */
-void tfm_spm_psa_eoi(uint32_t *svc_args);
-#endif /* !defined(TFM_PSA_API) */
-
-#ifdef TFM_PSA_API
-/*************************** IPC definitions **************************/
-
-/**
- * \brief Get the running partition ID.
- *
- * \return Returns the partition ID
- */
-uint32_t tfm_spm_partition_get_running_partition_id(void);
-
-/******************** Service handle management functions ********************/
-
-/**
- * \brief Create connection handle for client connect
- *
- * \param[in] service Target service context pointer
- * \param[in] client_id Partition ID of the sender of the message
- *
- * \retval NULL Create failed
- * \retval "Not NULL" Service handle created
- */
-struct tfm_conn_handle_t *tfm_spm_create_conn_handle(
- struct tfm_spm_service_t *service,
- int32_t client_id);
-
-/**
- * \brief Validate connection handle for client connect
- *
- * \param[in] conn_handle Handle to be validated
- * \param[in] client_id Partition ID of the sender of the message
- *
- * \retval IPC_SUCCESS Success
- * \retval IPC_ERROR_GENERIC Invalid handle
- */
-int32_t tfm_spm_validate_conn_handle(
- const struct tfm_conn_handle_t *conn_handle,
- int32_t client_id);
-
-/******************** Partition management functions *************************/
-
-/**
- * \brief Get current running partition context.
- *
- * \retval NULL Failed
- * \retval "Not NULL" Return the parttion context pointer
- * \ref spm_partition_desc_t structures
- */
-struct spm_partition_desc_t *tfm_spm_get_running_partition(void);
-
-/**
- * \brief Get the service context by service ID.
- *
- * \param[in] sid RoT Service identity
- *
- * \retval NULL Failed
- * \retval "Not NULL" Target service context pointer,
- * \ref tfm_spm_service_t structures
- */
-struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid);
-
-/************************ Message functions **********************************/
-
-/**
- * \brief Get message context by connect handle.
- *
- * \param[in] conn_handle Service connect handle.
- *
- * \return The message body context pointer
- * \ref msg_body_t structures
- */
-struct tfm_msg_body_t *
- tfm_spm_get_msg_buffer_from_conn_handle(struct tfm_conn_handle_t *conn_handle);
-
-/**
- * \brief Fill the message for PSA client call.
- *
- * \param[in] msg Service Message Queue buffer pointer
- * \param[in] service Target service context pointer, which can be
- * obtained by partition management functions
- * \prarm[in] handle Connect handle return by psa_connect().
- * \param[in] type Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
- * PSA_IPC_DISCONNECT
- * \param[in] client_id Partition ID of the sender of the message
- * \param[in] invec Array of input \ref psa_invec structures
- * \param[in] in_len Number of input \ref psa_invec structures
- * \param[in] outvec Array of output \ref psa_outvec structures
- * \param[in] out_len Number of output \ref psa_outvec structures
- * \param[in] caller_outvec Array of caller output \ref psa_outvec structures
- */
-void tfm_spm_fill_msg(struct tfm_msg_body_t *msg,
- struct tfm_spm_service_t *service,
- struct tfm_conn_handle_t *handle,
- int32_t type, int32_t client_id,
- psa_invec *invec, size_t in_len,
- psa_outvec *outvec, size_t out_len,
- psa_outvec *caller_outvec);
-
-/**
- * \brief Send message and wake up the SP who is waiting on
- * message queue, block the current thread and
- * scheduler triggered
- *
- * \param[in] service Target service context pointer, which can be
- * obtained by partition management functions
- * \param[in] msg message created by tfm_spm_create_msg()
- * \ref tfm_msg_body_t structures
- *
- * \retval IPC_SUCCESS Success
- * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
- * \retval IPC_ERROR_GENERIC Failed to enqueue message to service message queue
- */
-int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
- struct tfm_msg_body_t *msg);
-
-/**
- * \brief Check the client version according to
- * version policy
- *
- * \param[in] service Target service context pointer, which can be get
- * by partition management functions
- * \param[in] version Client support version
- *
- * \retval IPC_SUCCESS Success
- * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
- * \retval IPC_ERROR_VERSION Check failed
- */
-int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
- uint32_t version);
-
-/**
- * \brief Check the client access authorization
- *
- * \param[in] sid Target RoT Service identity
- * \param[in] service Target service context pointer, which can be get
- * by partition management functions
- * \param[in] ns_caller Whether from NS caller
- *
- * \retval IPC_SUCCESS Success
- * \retval IPC_ERROR_GENERIC Authorization check failed
- */
-int32_t tfm_spm_check_authorization(uint32_t sid,
- struct tfm_spm_service_t *service,
- bool ns_caller);
-
-/**
- * \brief Check the memory reference is valid.
- *
- * \param[in] buffer Pointer of memory reference
- * \param[in] len Length of memory reference in bytes
- * \param[in] ns_caller From non-secure caller
- * \param[in] access Type of access specified by the
- * \ref tfm_memory_access_e
- * \param[in] privileged Privileged mode or unprivileged mode:
- * \ref TFM_PARTITION_UNPRIVILEGED_MODE
- * \ref TFM_PARTITION_PRIVILEGED_MODE
- *
- * \retval IPC_SUCCESS Success
- * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
- * \retval IPC_ERROR_MEMORY_CHECK Check failed
- */
-int32_t tfm_memory_check(const void *buffer, size_t len, bool ns_caller,
- enum tfm_memory_access_e access,
- uint32_t privileged);
-
-/*
- * PendSV specified function.
- *
- * Parameters :
- * p_actx - Architecture context storage pointer
- *
- * Notes:
- * This is a staging API. Scheduler should be called in SPM finally and
- * this function will be obsoleted later.
- */
-void tfm_pendsv_do_schedule(struct tfm_arch_ctx_t *p_actx);
-
-/**
- * \brief SPM initialization implementation
- *
- * \details This function must be called under handler mode.
- * \retval This function returns an EXC_RETURN value. Other
- * faults would panic the execution and never
- * returned.
- */
-uint32_t tfm_spm_init(void);
-
-/*
- * \brief This function get the current PSA RoT lifecycle state.
- *
- * \return state The current security lifecycle state of the PSA
- * RoT. The PSA state and implementation state are
- * encoded as follows:
- * \arg state[15:8] – PSA lifecycle state
- * \arg state[7:0] – IMPLEMENTATION DEFINED state
- */
-uint32_t tfm_spm_get_lifecycle_state(void);
-
-/* Svcall for PSA Client APIs */
-
-/**
- * \brief SVC handler for \ref psa_framework_version.
- *
- * \return version The version of the PSA Framework implementation
- * that is providing the runtime services to the
- * caller.
- */
-uint32_t tfm_spm_psa_framework_version(void);
-
-/**
- * \brief SVC handler for \ref psa_version.
- *
- * \param[in] args Include all input arguments: sid.
- * \param[in] ns_caller If 'true', call from non-secure client.
- * Or from secure client.
- *
- * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
- * caller is not permitted to access the service.
- * \retval > 0 The version of the implemented RoT Service.
- */
-uint32_t tfm_spm_psa_version(uint32_t *args, bool ns_caller);
-
-/**
- * \brief SVC handler for \ref psa_connect.
- *
- * \param[in] args Include all input arguments:
- * sid, version.
- * \param[in] ns_caller If 'true', call from non-secure client.
- * Or from secure client.
- *
- * \retval PSA_SUCCESS Success.
- * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
- * connection.
- * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
- * connection at the moment.
- * \retval "Does not return" The RoT Service ID and version are not
- * supported, or the caller is not permitted to
- * access the service.
- */
-psa_status_t tfm_spm_psa_connect(uint32_t *args, bool ns_caller);
-
-/**
- * \brief SVC handler for \ref psa_call.
- *
- * \param[in] args Include all input arguments:
- * handle, in_vec, in_len, out_vec, out_len.
- * \param[in] ns_caller If 'true', call from non-secure client.
- * Or from secure client.
- * \param[in] lr EXC_RETURN value of the SVC.
- *
- * \retval >=0 RoT Service-specific status value.
- * \retval <0 RoT Service-specific error code.
- * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
- * RoT Service. The call is a PROGRAMMER ERROR if
- * one or more of the following are true:
- * \arg An invalid handle was passed.
- * \arg The connection is already handling a request.
- * \arg type < 0.
- * \arg An invalid memory reference was provided.
- * \arg in_len + out_len > PSA_MAX_IOVEC.
- * \arg The message is unrecognized by the RoT
- * Service or incorrectly formatted.
- */
-psa_status_t tfm_spm_psa_call(uint32_t *args, bool ns_caller, uint32_t lr);
-
-/**
- * \brief SVC handler for \ref psa_close.
- *
- * \param[in] args Include all input arguments: handle.
- * \param[in] ns_caller If 'true', call from non-secure client.
- * Or from secure client.
- *
- * \retval void Success.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg An invalid handle was provided that is not
- * the null handle.
- * \arg The connection is handling a request.
- */
-void tfm_spm_psa_close(uint32_t *args, bool ns_caller);
-
-/* Svcall for PSA Service APIs */
-
-/**
- * \brief SVC handler for \ref psa_wait.
- *
- * \param[in] args Include all input arguments:
- * signal_mask, timeout.
- *
- * \retval >0 At least one signal is asserted.
- * \retval 0 No signals are asserted. This is only seen when
- * a polling timeout is used.
- */
-psa_signal_t tfm_spm_psa_wait(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_get.
- *
- * \param[in] args Include all input arguments: signal, msg.
- *
- * \retval PSA_SUCCESS Success, *msg will contain the delivered
- * message.
- * \retval PSA_ERROR_DOES_NOT_EXIST Message could not be delivered.
- * \retval "Does not return" The call is invalid because one or more of the
- * following are true:
- * \arg signal has more than a single bit set.
- * \arg signal does not correspond to an RoT Service.
- * \arg The RoT Service signal is not currently
- * asserted.
- * \arg The msg pointer provided is not a valid memory
- * reference.
- */
-psa_status_t tfm_spm_psa_get(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_set_rhandle.
- *
- * \param[in] args Include all input arguments:
- * msg_handle, rhandle.
- *
- * \retval void Success, rhandle will be provided with all
- * subsequent messages delivered on this
- * connection.
- * \retval "Does not return" msg_handle is invalid.
- */
-void tfm_spm_psa_set_rhandle(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_read.
- *
- * \param[in] args Include all input arguments:
- * msg_handle, invec_idx, buffer, num_bytes.
- *
- * \retval >0 Number of bytes copied.
- * \retval 0 There was no remaining data in this input
- * vector.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg msg_handle is invalid.
- * \arg msg_handle does not refer to a request
- * message.
- * \arg invec_idx is equal to or greater than
- * \ref PSA_MAX_IOVEC.
- * \arg the memory reference for buffer is invalid or
- * not writable.
- */
-size_t tfm_spm_psa_read(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_skip.
- *
- * \param[in] args Include all input arguments:
- * msg_handle, invec_idx, num_bytes.
- *
- * \retval >0 Number of bytes skipped.
- * \retval 0 There was no remaining data in this input
- * vector.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg msg_handle is invalid.
- * \arg msg_handle does not refer to a request
- * message.
- * \arg invec_idx is equal to or greater than
- * \ref PSA_MAX_IOVEC.
- */
-size_t tfm_spm_psa_skip(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_write.
- *
- * \param[in] args Include all input arguments:
- * msg_handle, outvec_idx, buffer, num_bytes.
- *
- * \retval void Success
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg msg_handle is invalid.
- * \arg msg_handle does not refer to a request
- * message.
- * \arg outvec_idx is equal to or greater than
- * \ref PSA_MAX_IOVEC.
- * \arg The memory reference for buffer is invalid.
- * \arg The call attempts to write data past the end
- * of the client output vector.
- */
-void tfm_spm_psa_write(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_reply.
- *
- * \param[in] args Include all input arguments:
- * msg_handle, status.
- *
- * \retval void Success.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg msg_handle is invalid.
- * \arg An invalid status code is specified for the
- * type of message.
- */
-void tfm_spm_psa_reply(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_notify.
- *
- * \param[in] args Include all input arguments: partition_id.
- *
- * \retval void Success.
- * \retval "Does not return" partition_id does not correspond to a Secure
- * Partition.
- */
-void tfm_spm_psa_notify(uint32_t *args);
-
-/**
- * \brief SVC handler for \ref psa_clear.
- *
- * \retval void Success.
- * \retval "Does not return" The Secure Partition's doorbell signal is not
- * currently asserted.
- */
-void tfm_spm_psa_clear(void);
-
-/**
- * \brief SVC handler for \ref psa_eoi.
- *
- * \param[in] args Include all input arguments: irq_signal.
- *
- * \retval void Success.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg irq_signal is not an interrupt signal.
- * \arg irq_signal indicates more than one signal.
- * \arg irq_signal is not currently asserted.
- */
-void tfm_spm_psa_eoi(uint32_t *args);
-
-/**
- * \brief SVC hander of enabling irq_line of the specified irq_signal.
- *
- * \param[in] args Include all input arguments: irq_signal.
- *
- * \retval void Success.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg irq_signal is not an interrupt signal.
- * \arg irq_signal indicates more than one signal.
- */
-void tfm_spm_enable_irq(uint32_t *args);
-
-/**
- * \brief SVC hander of disabling irq_line of the specified irq_signal.
- *
- * \param[in] args Include all input arguments: irq_signal.
- *
- * \retval void Success.
- * \retval "Does not return" The call is invalid, one or more of the
- * following are true:
- * \arg irq_signal is not an interrupt signal.
- * \arg irq_signal indicates more than one signal.
- */
-void tfm_spm_disable_irq(uint32_t *args);
-
-/**
- * \brief Validate the whether NS caller re-enter.
- *
- * \param[in] p_cur_sp Pointer to current partition.
- * \param[in] p_ctx Pointer to current stack context.
- * \param[in] exc_return EXC_RETURN value.
- * \param[in] ns_caller If 'true', call from non-secure client.
- * Or from secure client.
- *
- * \retval void Success.
- */
-void tfm_spm_validate_caller(struct spm_partition_desc_t *p_cur_sp,
- uint32_t *p_ctx, uint32_t exc_return,
- bool ns_caller);
-
-/**
- * \brief Terminate execution within the calling Secure Partition and will not
- * return.
- *
- * \retval "Does not return"
- */
-void tfm_spm_psa_panic(void);
-
-/**
- * \brief Converts a user handle into a corresponded handle instance.
- */
-struct tfm_conn_handle_t *tfm_spm_to_handle_instance(psa_handle_t user_handle);
-
-#endif /* defined(TFM_PSA_API) */
-
-#endif /*__SPM_API_H__ */
diff --git a/secure_fw/spm/spm_db.h b/secure_fw/spm/spm_db.h
deleted file mode 100644
index 656bdac..0000000
--- a/secure_fw/spm/spm_db.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __SPM_DB_H__
-#define __SPM_DB_H__
-
-#include <stdint.h>
-#include "spm_api.h"
-#include "target_cfg.h"
-#ifdef TFM_PSA_API
-#include "tfm_spm_hal.h"
-#endif
-
-struct spm_partition_desc_t;
-struct spm_partition_db_t;
-
-typedef void(*sp_entry_point)(void);
-
-#define TFM_PARTITION_TYPE_APP "APPLICATION-ROT"
-#define TFM_PARTITION_TYPE_PSA "PSA-ROT"
-
-#ifdef TFM_PSA_API
-#define TFM_PRIORITY_LOW THRD_PRIOR_LOWEST
-#define TFM_PRIORITY_NORMAL THRD_PRIOR_MEDIUM
-#define TFM_PRIORITY_HIGH THRD_PRIOR_HIGHEST
-#else
-#define TFM_PRIORITY_LOW 0xFF
-#define TFM_PRIORITY_NORMAL 0x7F
-#define TFM_PRIORITY_HIGH 0
-#endif
-
-#define TFM_PRIORITY(LEVEL) TFM_PRIORITY_##LEVEL
-
-/**
- * Holds the fields of the partition DB used by the SPM code. The values of
- * these fields are calculated at compile time, and set during initialisation
- * phase.
- */
-struct spm_partition_static_data_t {
-#ifdef TFM_PSA_API
- uint32_t psa_framework_version;
-#endif /* defined(TFM_PSA_API) */
- uint32_t partition_id;
- uint32_t partition_flags;
- uint32_t partition_priority;
- sp_entry_point partition_init;
- uint32_t dependencies_num;
- int32_t *p_dependencies;
-};
-
-/**
- * Holds the fields that define a partition for SPM. The fields are further
- * divided to structures, to keep the related fields close to each other.
- */
-struct spm_partition_desc_t {
- struct spm_partition_runtime_data_t runtime_data;
- const struct spm_partition_static_data_t *static_data;
- /** A list of platform_data pointers */
- const struct tfm_spm_partition_platform_data_t **platform_data_list;
-#ifdef TFM_PSA_API
- const struct tfm_spm_partition_memory_data_t *memory_data;
-#endif
-};
-
-struct spm_partition_db_t {
- uint32_t is_init;
- uint32_t partition_count;
-#ifndef TFM_PSA_API
- uint32_t running_partition_idx;
-#endif /* !defined(TFM_PSA_API) */
- struct spm_partition_desc_t *partitions;
-};
-
-#ifdef TFM_PSA_API
-#define PART_REGION_ADDR(partition, region) \
- (uint32_t)®ION_NAME(Image$$, partition, region)
-#endif
-
-#endif /* __SPM_DB_H__ */
diff --git a/secure_fw/spm/spm_partition_defs.h b/secure_fw/spm/spm_partition_defs.h
deleted file mode 100644
index 4e32baf..0000000
--- a/secure_fw/spm/spm_partition_defs.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __SPM_PARTITION_DEFS_H__
-#define __SPM_PARTITION_DEFS_H__
-
-/* FixMe: allocations to be settled.
- * 8 bits reserved by TFM for secure partition Id in this prototype
- */
-#define TFM_SP_BASE 256
-
-/* A reserved partition ID that is used for uninitialised data */
-#define INVALID_PARTITION_ID (~0U)
-
-/* ***** partition ID-s internal to the TFM ***** */
-#define TFM_INTERNAL_PARTITIONS (2)
-
-/* From the SPM point of view the non secure processing environment is handled
- * as a special secure partition. This simplifies the context switch
- * operations.
- */
-#define TFM_SP_NON_SECURE_ID (0)
-/* A dummy partition for TFM_SP_CORE is created to handle secure partition
- * calls done directly from the core, before NS execution started.
- */
-#define TFM_SP_CORE_ID (1)
-
-#include "psa_manifest/pid.h"
-
-/* This limit is only used to define the size of the database reserved for
- * partitions. There's no requirement that it match the number of partitions
- * that get registered in a specific build
- */
-#define SPM_MAX_PARTITIONS (TFM_MAX_USER_PARTITIONS + TFM_INTERNAL_PARTITIONS)
-
-#endif /* __SPM_PARTITION_DEFS_H__ */