Merge remote-tracking branch 'feature-ipc' into 'master'
* Remote feature-ipc: (31 commits)
Platform: Correct region name
Core: Add ZI and RW regions for seucre data in memory check
Core: free connection handle in psa_reply
Core: Support set reverse handle during connecting
Core: Fix thread list handling
Core: Config isolation for partitions with PSA API
Core: Implement the IPC Secure Client API
Core: Implement PSA service functions
Core: Add memory check function for IPC
Core: Adapt PSA API veneer with implemented handler
Platform: Align region name in armclang and gcc
Core: Add secure partition manager for IPC
Core: Enhance manifest to align with PSA
Core: Add IPC Client and Service Secure Partition
Core: Add list, message queue, and pool functions
Core: Fundamental components for secure IPC
Core: Update IPC implementation framework
Core: Align with PSA FF specification 1.0-beta-0
Crypto: Conditional reference PSA types by PSA FF version
Cmake: Disable regression tests for IPC configuration
...
Change-Id: I6527765ab71fe30e7e9fe93c705d899730970789
Signed-off-by: Edison Ai <edison.ai@arm.com>
diff --git a/CommonConfig.cmake b/CommonConfig.cmake
index 3aaca75..1bbf95a 100644
--- a/CommonConfig.cmake
+++ b/CommonConfig.cmake
@@ -102,6 +102,9 @@
set (SERVICES_TEST_ENABLED OFF)
set (TEST_FRAMEWORK_S OFF)
set (TEST_FRAMEWORK_NS OFF)
+set (TFM_PSA_API OFF)
+set (TFM_LEGACY_API ON)
+set (CORE_TEST_IPC OFF)
if(${TARGET_PLATFORM} STREQUAL "AN521" OR ${TARGET_PLATFORM} STREQUAL "AN519")
set (REFERENCE_PLATFORM ON)
@@ -114,6 +117,19 @@
set(SERVICES_TEST_ENABLED ON)
endif()
+if (CORE_IPC)
+ set(TFM_PSA_API ON)
+ set(CORE_TEST_IPC ON)
+endif()
+
+if (TFM_PSA_API)
+ add_definitions(-DTFM_PSA_API)
+endif()
+
+if (TFM_LEGACY_API)
+ add_definitions(-DTFM_LEGACY_API)
+endif()
+
if (SERVICES_TEST_ENABLED)
set(SERVICE_TEST_S ON)
set(SERVICE_TEST_NS ON)
@@ -141,13 +157,22 @@
set(TFM_PARTITION_TEST_CORE ON)
endif()
+if (CORE_TEST_IPC)
+ add_definitions(-DCORE_TEST_IPC)
+ set(TFM_PARTITION_TEST_SECURE_SERVICES ON)
+ set(TEST_FRAMEWORK_NS ON)
+endif()
+
if (SERVICE_TEST_S)
add_definitions(-DSERVICES_TEST_S)
- add_definitions(-DTFM_PARTITION_TEST_SECURE_SERVICES)
set(TEST_FRAMEWORK_S ON)
set(TFM_PARTITION_TEST_SECURE_SERVICES ON)
endif()
+if (TFM_PARTITION_TEST_SECURE_SERVICES)
+ add_definitions(-DTFM_PARTITION_TEST_SECURE_SERVICES)
+endif()
+
if (SERVICE_TEST_NS)
add_definitions(-DSERVICES_TEST_NS)
set(TEST_FRAMEWORK_NS ON)
diff --git a/ConfigCoreIPC.cmake b/ConfigCoreIPC.cmake
new file mode 100644
index 0000000..545fd49
--- /dev/null
+++ b/ConfigCoreIPC.cmake
@@ -0,0 +1,49 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#This file holds information of a specific build configuration of this project.
+
+#Include board specific config (CPU, etc...), select platform specific build
+#system settings file
+if(NOT DEFINED TARGET_PLATFORM)
+ message(FATAL_ERROR "ERROR: TARGET_PLATFORM is not set in command line")
+elseif(${TARGET_PLATFORM} STREQUAL "AN521")
+ set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/Mps2AN521.cmake")
+elseif(${TARGET_PLATFORM} STREQUAL "AN519")
+ set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/Mps2AN519.cmake")
+elseif(${TARGET_PLATFORM} STREQUAL "MUSCA_A")
+ set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/musca_a.cmake")
+elseif(${TARGET_PLATFORM} STREQUAL "MUSCA_B1")
+ set(PLATFORM_CMAKE_FILE "${CMAKE_CURRENT_LIST_DIR}/platform/ext/musca_b1.cmake")
+else()
+ message(FATAL_ERROR "ERROR: Target \"${TARGET_PLATFORM}\" is not supported.")
+endif()
+
+##These variables select how the projects are built. Each project will set
+#various project specific settings (e.g. what files to build, macro
+#definitions) based on these.
+set (REGRESSION False)
+set (CORE_TEST False)
+set (CORE_IPC True)
+
+# TF-M isolation level: 1..3
+set (TFM_LVL 1)
+
+#BL2 bootloader(MCUBoot) related settings
+if(NOT DEFINED BL2)
+ set(BL2 True)
+endif()
+
+if(NOT DEFINED MCUBOOT_NO_SWAP)
+ set(MCUBOOT_NO_SWAP False)
+endif()
+
+if(NOT DEFINED MCUBOOT_RAM_LOADING)
+ set(MCUBOOT_RAM_LOADING False)
+endif()
+
+include ("${CMAKE_CURRENT_LIST_DIR}/CommonConfig.cmake")
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index e19051a..c9b9fa2 100755
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -64,6 +64,12 @@
list(APPEND NS_APP_SRC "${APP_DIR}/psa_api_test.c")
endif()
+if (NOT DEFINED TFM_PSA_API)
+ message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ")
+elseif (TFM_PSA_API)
+ list(APPEND NS_APP_SRC "${INTERFACE_DIR}/src/tfm_psa_ns_api.c")
+endif()
+
set(BUILD_CMSIS_CORE On)
set(BUILD_RETARGET On)
set(BUILD_NATIVE_DRIVERS On)
diff --git a/interface/include/psa_client.h b/interface/include/psa_client.h
index 9fe25d9..71adb80 100644
--- a/interface/include/psa_client.h
+++ b/interface/include/psa_client.h
@@ -15,117 +15,125 @@
#include <stdint.h>
#include <stddef.h>
-/* ******** ******** PSA Common API ******** ******** */
+/*********************** PSA Client Macros and Types *************************/
-/* FixMe: PSA FF v0.9 has not been released. All PSA API subject to change */
-#define PSA_FRAMEWORK_VERSION (0x0009)
+#define PSA_FRAMEWORK_VERSION (0x0100)
#define PSA_VERSION_NONE (0)
/* PSA response types */
#define PSA_SUCCESS (0)
#define PSA_CONNECTION_REFUSED (INT32_MIN + 1)
+#define PSA_CONNECTION_BUSY (INT32_MIN + 2)
#define PSA_DROP_CONNECTION (INT32_MIN)
/* PSA message handles */
#define PSA_NULL_HANDLE ((psa_handle_t)0)
-typedef int32_t psa_error_t;
-typedef int32_t psa_handle_t;
typedef int32_t psa_status_t;
+typedef int32_t psa_handle_t;
/**
- * A read-only input memory region provided to a RoT Service.
+ * A read-only input memory region provided to an RoT Service.
*/
typedef struct psa_invec {
- const void *base; /*!< the start address of the memory buffer */
- size_t len; /*!< the size in bytes */
+ const void *base; /*!< the start address of the memory buffer */
+ size_t len; /*!< the size in bytes */
} psa_invec;
/**
- * A writable output memory region provided to a RoT Service.
+ * A writable output memory region provided to an RoT Service.
*/
typedef struct psa_outvec {
- void *base; /*!< the start address of the memory buffer */
- size_t len; /*!< the size in bytes */
+ void *base; /*!< the start address of the memory buffer */
+ size_t len; /*!< the size in bytes */
} psa_outvec;
+/*************************** PSA Client API **********************************/
+
/**
* \brief Retrieve the version of the PSA Framework API that is implemented.
*
- * \return The version of the PSA Framework implementation that is providing
- * the runtime services to the caller.
- * \return The major and minor version are encoded as follows:
- * \arg version[15:8] -- major version number
- * \arg version[7:0] -- minor version number
+ * \return version The version of the PSA Framework implementation
+ * that is providing the runtime services to the
+ * caller. The major and minor version are encoded
+ * as follows:
+ * \arg version[15:8] -- major version number.
+ * \arg version[7:0] -- minor version number.
*/
uint32_t psa_framework_version(void);
-/* ******** ******** PSA Client API ******** ******** */
-
/**
- * \brief Retrieve the minor version of a RoT Service or indicate that
- * it is not present on this system.
+ * \brief Retrieve the minor version of an RoT Service or indicate that it is
+ * not present on this system.
*
- * \param[in] sid ID of the RoT Service to query
+ * \param[in] sid ID of the RoT Service to query.
*
- * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
- * caller is not permitted to access the service
- * \retval >0 The minor version of the implemented RoT Service
+ * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the
+ * caller is not permitted to access the service.
+ * \retval > 0 The minor version of the implemented RoT
+ * Service.
*/
uint32_t psa_version(uint32_t sid);
/**
- * \brief Connect to a RoT Service by its SID.
+ * \brief Connect to an RoT Service by its SID.
*
- * \param[in] sid ID of the RoT Service to connect to
- * \param[in] minor_version Requested version of the RoT Service
+ * \param[in] sid ID of the RoT Service to connect to.
+ * \param[in] minor_version Requested version of the RoT Service.
*
- * \retval >0 A handle for the connection
- * \retval PSA_CONNECTION_REFUSED The RoT Service has refused the connection
- * \retval "Does not return" The RoT Service ID and version are not
- * supported, or the caller is not permitted
- * to access the service
+ * \retval > 0 A handle for the connection.
+ * \retval PSA_CONNECTION_REFUSED The SPM or RoT Service has refused the
+ * connection.
+ * \retval PSA_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_handle_t psa_connect(uint32_t sid, uint32_t minor_version);
/**
- * \brief Calls a RoT Service on an established connection.
+ * \brief Call an RoT Service on an established connection.
*
- * \param[in] handle A handle to an established connection
- * \param[in] in_vec Array of input \ref psa_invec structures
- * \param[in] in_len Number of input \ref psa_invec structures
- * \param[in] out_vec Array of input \ref psa_outvec structures
- * \param[in] out_len Number of input \ref psa_outvec structures
+ * \param[in] handle A handle to an established connection.
+ * \param[in] in_vec Array of input \ref psa_invec structures.
+ * \param[in] in_len Number of input \ref psa_invec structures.
+ * \param[in/out] out_vec Array of output \ref psa_outvec structures.
+ * \param[in] out_len Number of output \ref psa_outvec structures.
*
- * \retval >=0 Application-specific return code
- * \retval <0 Application-specific error code
- * \retval PSA_DROP_CONNECTION The connection has been dropped by the RoT
- * Service. This indicates that either this or
- * a previous message was invalid
- * \retval "Does not return" The call is invalid, one or more of the following
- * are true:
- * \arg An invalid handle was passed
- * \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
+ * \retval >=0 RoT Service-specific status value.
+ * \retval <0 RoT Service-specific error code.
+ * \retval PSA_DROP_CONNECTION The connection has been dropped by the RoT
+ * Service. This indicates that either this or
+ * a previous message was invalid.
+ * \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 by the RoT
+ * Service or incorrectly formatted.
*/
-psa_error_t psa_call(psa_handle_t handle,
- const psa_invec *in_vec,
- size_t in_len,
- const psa_outvec *out_vec,
- size_t out_len);
+psa_status_t psa_call(psa_handle_t handle,
+ const psa_invec *in_vec,
+ size_t in_len,
+ psa_outvec *out_vec,
+ size_t out_len);
/**
- * \brief Closes a connection to a RoT Service.
+ * \brief Close a connection to an RoT Service.
*
- * \param[in] handle A handle to an established connection, or the
- * null handle
+ * \param[in] handle A handle to an established connection, or the
+ * null handle.
*
- * \retval void Success
- * \retval "Does not return" An invalid handle was provided that is not the
- * null handle
+ * \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 psa_close(psa_handle_t handle);
diff --git a/interface/include/psa_service.h b/interface/include/psa_service.h
index e27b420..6453aed 100644
--- a/interface/include/psa_service.h
+++ b/interface/include/psa_service.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -14,11 +14,16 @@
#include <inttypes.h>
+/********************** PSA Secure Partition Macros and Types ****************/
+
/* PSA wait timeouts */
#define PSA_POLL (0x00000000u)
#define PSA_BLOCK (0x80000000u)
-/* doorbell signal */
+/* A mask value that includes all Secure Partition signals */
+#define PSA_WAIT_ANY (~0u)
+
+/* Doorbell signal */
#define PSA_DOORBELL (0x00000008u)
/* PSA message types */
@@ -26,225 +31,217 @@
#define PSA_IPC_CALL (2)
#define PSA_IPC_DISCONNECT (3)
-/* PSA response types */
-#define PSA_CONNECTION_ACCEPTED (0)
-
-/* maximum number of input and output vectors */
+/* Maximum number of input and output vectors */
#define PSA_MAX_IOVEC (4)
+/* Return code from psa_get() */
+#define PSA_ERR_NOMSG (INT32_MIN + 3)
+
+/* Store a set of one or more Secure Partition signals */
typedef uint32_t psa_signal_t;
/**
- * Describes a message received by a RoT Service after calling \ref psa_get().
+ * Describe a message received by an RoT Service after calling \ref psa_get().
*/
typedef struct psa_msg_t {
- uint32_t type;
- psa_handle_t handle;
- void *rhandle;
- size_t in_size[PSA_MAX_IOVEC];
- size_t out_size[PSA_MAX_IOVEC];
+ uint32_t type; /* One of the following values:
+ * \ref PSA_IPC_CONNECT
+ * \ref PSA_IPC_CALL
+ * \ref PSA_IPC_DISCONNECT
+ */
+ psa_handle_t handle; /* A reference generated by the SPM to the
+ * message returned by psa_get().
+ */
+ int32_t client_id; /* Partition ID of the sender of the message */
+ void *rhandle; /* Be useful for binding a connection to some
+ * application-specific data or function
+ * pointer within the RoT Service
+ * implementation.
+ */
+ size_t in_size[PSA_MAX_IOVEC]; /* Provide the size of each client input
+ * vector in bytes.
+ */
+ size_t out_size[PSA_MAX_IOVEC];/* Provide the size of each client output
+ * vector in bytes.
+ */
} psa_msg_t;
-/* ******** ******** PSA Secure Function API ******** ******** */
+/************************* PSA Secure Partition API **************************/
/**
- * \brief Returns the set of signals that have been asserted for a Sercure
- * Partition.
+ * \brief Return the Secure Partition interrupt signals that have been asserted
+ * from a subset of signals provided by the caller.
*
- * \param[in] timeout Specify either blocking or polling operation
+ * \param[in] signal_mask A set of signals to query. Signals that are not
+ * in this set will be ignored.
+ * \param[in] timeout Specify either blocking \ref PSA_BLOCK or
+ * polling \ref PSA_POLL operation.
*
- * \retval >0 At least one signal is asserted
- * \retval 0 No signals are asserted. This is only seen if the
- * caller used a polling 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.
*/
-uint32_t psa_wait_any(uint32_t timeout);
+psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout);
/**
- * \brief Returns the Secure Partition interrupt signals that have been
- * asserted from the subset of signals indicated in the bitmask provided.
- *
- * \param[in] signal_mask A set of interrupt and doorbell signals to query.
- * Signals that are not in this set will be ignored
- * \param[in] timeout Specify either blocking or polling operation
- *
- * \retval >0 At least one signal is asserted
- * \retval 0 No signals are asserted. This case is only seen if
- * caller used a polling timeout
- * \retval "Does not return" The call is invalid, one or more of the following
- * are true:
- * \arg signal_mask does not include any interrupt or
- * doorbell signals
- * \arg signal_mask includes one or more RoT Service
- * signals
- */
-uint32_t psa_wait_interrupt(psa_signal_t signal_mask, uint32_t timeout);
-
-/**
- * \brief Get the message which corresponds to a given RoT Service signal
+ * \brief Retrieve the message which corresponds to a given RoT Service signal
* and remove the message from the RoT Service queue.
*
- * \param[in] signal The signal value for an asserted RoT Service
- * \param[out] msg Pointer to \ref psa_msg_t object for receiving
- * the message
+ * \param[in] signal The signal value for an asserted RoT Service.
+ * \param[out] msg Pointer to \ref psa_msg_t object for receiving
+ * the message.
*
- * \retval void Success
- * \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 a RoT Service
- * \arg The RoT Service signal is not currently asserted
- * \arg The msg pointer provided is not a valid memory
- * reference
+ * \retval PSA_SUCCESS Success, *msg will contain the delivered
+ * message.
+ * \retval PSA_ERR_NOMSG 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.
*/
-void psa_get(psa_signal_t signal, psa_msg_t *msg);
+psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg);
/**
- * \brief Get the Partition ID of the sender of a message.
+ * \brief Associate some RoT Service private data with a client connection.
*
- * \param[in] msg_handle Message handle for an incoming message
+ * \param[in] msg_handle Handle for the client's message.
+ * \param[in] rhandle Reverse handle allocated by the RoT Service.
*
- * \retval >0 ID of a Secure Partition
- * \retval <0 ID of an NSPE client
- * \retval "Does not return" msg_handle is invalid
- *
- * \note Bit[31] is set if the caller is from the NSPE.
- */
-int32_t psa_identity(psa_handle_t msg_handle);
-
-/**
- * \brief Associates some caller-provided private data with a specified client
- * connection.
- *
- * \param[in] msg_handle Handle for the client's message
- * \param[in] rhandle Reverse handle allocated by the RoT Service
- *
- * \retval void Success, rhandle will be provided with all
- * subsequent messages delivered on this connection
- * \retval "Does not return" msg_handle is invalid
+ * \retval void Success, rhandle will be provided with all
+ * subsequent messages delivered on this
+ * connection.
+ * \retval "Does not return" msg_handle is invalid.
*/
void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle);
/**
- * \brief Read a message parameter or part of a message parameter from the
- * client input vector.
+ * \brief Read a message parameter or part of a message parameter from a client
+ * input vector.
*
- * \param[in] msg_handle Handle for the client's message
- * \param[in] invec_idx Index of the input vector to read from. Must be
- * less than \ref PSA_MAX_IOVEC
- * \param[out] buffer Buffer in the Secure Partition to copy the
- * requested data to
- * \param[in] num_bytes Maximum number of bytes to be read from the client
- * input vector
+ * \param[in] msg_handle Handle for the client's message.
+ * \param[in] invec_idx Index of the input vector to read from. Must be
+ * less than \ref PSA_MAX_IOVEC.
+ * \param[out] buffer Buffer in the Secure Partition to copy the
+ * requested data to.
+ * \param[in] num_bytes Maximum number of bytes to be read from the
+ * client input vector.
*
- * \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 \ref PSA_IPC_CALL
- * message
- * \arg invec_idx is equal to or greater than
- * PSA_MAX_IOVEC
- * \arg the memory reference for buffer is invalid or
- * not writable
+ * \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
+ * \ref PSA_IPC_CALL 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 psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
- void *buffer, size_t num_bytes);
+ void *buffer, size_t num_bytes);
/**
- * \brief Skip a given number of bytes for an input vector.
+ * \brief Skip over part of a client input vector.
*
- * \param[in] msg_handle Handle for the client's message
- * \param[in] invec_idx Index of input vector in message to skip from.
- * Must be less than \ref PSA_MAX_IOVEC
- * \param[in] num_bytes Maximum number of bytes to skip in the client input
- * vector
+ * \param[in] msg_handle Handle for the client's message.
+ * \param[in] invec_idx Index of input vector to skip from. Must be
+ * less than \ref PSA_MAX_IOVEC.
+ * \param[in] num_bytes Maximum number of bytes to skip in the client
+ * input vector.
*
- * \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 \ref PSA_IPC_CALL
- * message
- * \arg invec_idx is equal to or greater than
- * PSA_MAX_IOVEC
+ * \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
+ * \ref PSA_IPC_CALL message.
+ * \arg invec_idx is equal to or greater than
+ * \ref PSA_MAX_IOVEC.
*/
size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes);
/**
- * \brief Write a message response to the client output vector.
+ * \brief Write a message response to a client output vector.
*
- * \param[in] msg_handle Handle for the client's message
- * \param[out] outvec_idx Index of output vector in message to write to.
- * Must be less than \ref PSA_MAX_IOVEC
- * \param[in] buffer Buffer with the data to write
- * \param[in] num_bytes Number of bytes to write to the client output
- * vector
+ * \param[in] msg_handle Handle for the client's message.
+ * \param[out] outvec_idx Index of output vector in message to write to.
+ * Must be less than \ref PSA_MAX_IOVEC.
+ * \param[in] buffer Buffer with the data to write.
+ * \param[in] num_bytes Number of bytes to write to the client output
+ * vector.
*
- * \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 \ref PSA_IPC_CALL
- * 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
+ * \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
+ * \ref PSA_IPC_CALL 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 psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
- const void *buffer, size_t num_bytes);
+ const void *buffer, size_t num_bytes);
/**
- * \brief Completes handling of a specific message and unblocks the client.
+ * \brief Complete handling of a specific message and unblock the client.
*
- * \param[in] msg_handle Handle for the client's message or the null handle
- * \param[in] retval Return value to be reported to the client
+ * \param[in] msg_handle Handle for the client's message.
+ * \param[in] status Message result value to be reported to the
+ * client.
*
- * \retval void Success
- * \retval "Does not return" The call is invalid, one or more of the following
- * are true:
- * \arg msg_handle is invalid and is not the null handle
- * \arg An invalid return code is specified for the type
- * of message
+ * \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 psa_end(psa_handle_t msg_handle, psa_error_t retval);
+void psa_reply(psa_handle_t msg_handle, psa_status_t status);
/**
- * \brief Sends a PSA_DOORBELL signal to a specific Secure Partition.
+ * \brief Send a PSA_DOORBELL signal to a specific Secure Partition.
*
- * \param[in] partition_id Secure Partition ID of the target partition
+ * \param[in] partition_id Secure Partition ID of the target partition.
*
- * \retval void Success
- * \retval "Does not return" partition_id does not correspond to a Secure
- * Partition
+ * \retval void Success.
+ * \retval "Does not return" partition_id does not correspond to a Secure
+ * Partition.
*/
void psa_notify(int32_t partition_id);
/**
- * \brief Clears the PSA_DOORBELL signal.
+ * \brief Clear the PSA_DOORBELL signal.
*
- * \retval void Success
- * \retval "Does not return" The Secure Partition's doorbell signal is not
- * currently asserted
+ * \retval void Success.
+ * \retval "Does not return" The Secure Partition's doorbell signal is not
+ * currently asserted.
*/
void psa_clear(void);
/**
- * \brief Informs the SPM that an interrupt has been handled (end of interrupt).
+ * \brief Inform the SPM that an interrupt has been handled (end of interrupt).
*
- * \param[in] irq_signal The interrupt signal that has been processed
+ * \param[in] irq_signal The interrupt signal that has been processed.
*
- * \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
+ * \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 psa_eoi(uint32_t irq_signal);
+void psa_eoi(psa_signal_t irq_signal);
#ifdef __cplusplus
}
diff --git a/interface/include/tfm_api.h b/interface/include/tfm_api.h
index be36e2e..2ba93c0 100644
--- a/interface/include/tfm_api.h
+++ b/interface/include/tfm_api.h
@@ -13,7 +13,6 @@
#endif
#include <stdint.h>
-
#include "psa_client.h"
#define TFM_INVALID_CLIENT_ID 0
@@ -80,6 +79,54 @@
*/
enum tfm_status_e tfm_register_client_id (int32_t ns_client_id);
+/**
+ * \brief Retrieve the version of the PSA Framework API that is implemented
+ *
+ * \return The version of the PSA Framework
+ */
+uint32_t tfm_psa_framework_version_veneer(void);
+
+/**
+ * \brief Return version of secure function provided by secure binary
+ *
+ * \param[in] sid ID of secure service
+ *
+ * \return Version number of secure function
+ */
+uint32_t tfm_psa_version_veneer(uint32_t sid);
+
+/**
+ * \brief Connect to secure function
+ *
+ * \param[in] sid ID of secure service
+ * \param[in] minor_version Minor version of SF requested by client
+ *
+ * \return Returns handle to connection
+ */
+psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version);
+
+/**
+ * \brief Call a secure function referenced by a connection handle
+ *
+ * \param[in] handle Handle to connection
+ * \param[in] in_vecs invec containing pointer/count of input vectors
+ * \param[in] out_vecs invec containing pointer/count of output vectors
+ *
+ * \return Returns \ref psa_status_t status code
+ */
+psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
+ const psa_invec *in_vecs,
+ const psa_invec *out_vecs);
+
+/**
+ * \brief Close connection to secure function referenced by a connection handle
+ *
+ * \param[in] handle Handle to connection
+ *
+ * \return Returns \ref psa_status_t status code
+ */
+psa_status_t tfm_psa_close_veneer(psa_handle_t handle);
+
//================ End Secure function declarations ==========================//
#ifdef __cplusplus
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index c238b35..966d8c1 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -35,6 +35,14 @@
psa_status_t tfm_tfm_crypto_destroy_key_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_get_key_information_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_export_key_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_key_policy_init_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_key_policy_set_usage_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_key_policy_get_usage_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_key_policy_get_algorithm_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_set_key_policy_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_get_key_policy_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_get_key_lifetime_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_set_key_lifetime_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
@@ -46,6 +54,14 @@
psa_status_t tfm_tfm_crypto_hash_finish_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_hash_verify_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
psa_status_t tfm_tfm_crypto_hash_abort_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_mac_update_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_mac_abort_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_aead_decrypt_wrapper_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_tfm_crypto_aead_encrypt_wrapper_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
/******** TFM_SP_PLATFORM ********/
psa_status_t tfm_platform_sp_system_reset_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
@@ -74,6 +90,14 @@
psa_status_t tfm_tfm_secure_client_service_sfn_run_tests_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PSA_API */
+
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PSA_API */
+
#ifdef __cplusplus
}
#endif
diff --git a/interface/include/tfm_veneers.h.template b/interface/include/tfm_veneers.h.template
index 4a5727c..78829fa 100644
--- a/interface/include/tfm_veneers.h.template
+++ b/interface/include/tfm_veneers.h.template
@@ -20,7 +20,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
-/******** @@manifest.tfm_partition_name@@ ********/
+/******** @@manifest.name@@ ********/
psa_status_t tfm_@@manifest.secure_functions.tfm_symbol@@_veneer(struct psa_invec *in_vec, size_t in_len, struct psa_outvec *out_vec, size_t out_len);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
diff --git a/interface/src/tfm_psa_ns_api.c b/interface/src/tfm_psa_ns_api.c
new file mode 100644
index 0000000..159eef9
--- /dev/null
+++ b/interface/src/tfm_psa_ns_api.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "interface/include/psa_client.h"
+#include "tfm_ns_lock.h"
+#include "tfm_api.h"
+
+/**** API functions ****/
+
+uint32_t psa_framework_version(void)
+{
+ return tfm_ns_lock_dispatch((veneer_fn)tfm_psa_framework_version_veneer,
+ 0,
+ 0,
+ 0,
+ 0);
+}
+
+uint32_t psa_version(uint32_t sid)
+{
+ return tfm_ns_lock_dispatch((veneer_fn)tfm_psa_version_veneer,
+ sid,
+ 0,
+ 0,
+ 0);
+}
+
+psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
+{
+ return tfm_ns_lock_dispatch((veneer_fn)tfm_psa_connect_veneer,
+ sid,
+ minor_version,
+ 0,
+ 0);
+}
+
+psa_status_t psa_call(psa_handle_t handle,
+ const psa_invec *in_vec,
+ size_t in_len,
+ psa_outvec *out_vec,
+ size_t out_len)
+{
+ /* FixMe: sanity check can be added to offload some NS thread checks from
+ * TFM secure API
+ */
+
+ /* Due to v8M restrictions, TF-M NS API needs to add another layer of
+ * serialization in order for NS to pass arguments to S
+ */
+ psa_invec in_vecs, out_vecs;
+
+ in_vecs.base = in_vec;
+ in_vecs.len = in_len;
+ out_vecs.base = out_vec;
+ out_vecs.len = out_len;
+ return tfm_ns_lock_dispatch((veneer_fn)tfm_psa_call_veneer,
+ (uint32_t)handle,
+ (uint32_t)&in_vecs,
+ (uint32_t)&out_vecs,
+ 0);
+}
+
+void psa_close(psa_handle_t handle)
+{
+ tfm_ns_lock_dispatch((veneer_fn)tfm_psa_close_veneer,
+ (uint32_t)handle,
+ 0,
+ 0,
+ 0);
+}
+
diff --git a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
index 61bb849..5231947 100644
--- a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
+++ b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
@@ -120,6 +120,16 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_DATA))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_DATA))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA))
+#endif /* TFM_PSA_API */
__copy_table_end__ = .;
} > FLASH
@@ -168,6 +178,18 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK))
+#endif /* TFM_PSA_API */
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
@@ -313,6 +335,34 @@
Image$$TFM_SP_SECURE_TEST_PARTITION$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST : ALIGN(32)
+ {
+ *ipc_service_test*:*(.text*)
+ *ipc_service_test*:*(.rodata*)
+ *(TFM_SP_IPC_SERVICE_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST : ALIGN(32)
+ {
+ *ipc_client_test*:*(.text*)
+ *ipc_client_test*:*(.rodata*)
+ *(TFM_SP_IPC_CLIENT_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+
+#endif /* TFM_PSA_API */
.ARM.extab :
{
@@ -661,6 +711,58 @@
Image$$TFM_SP_SECURE_TEST_PARTITION_STACK$$ZI$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST_DATA : ALIGN(32)
+ {
+ *ipc_service_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA);
+
+ .TFM_SP_IPC_SERVICE_TEST_BSS : ALIGN(32)
+ {
+ *ipc_service_test*:*(.bss*)
+ *ipc_service_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS);
+
+ .TFM_SP_IPC_SERVICE_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK);
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST_DATA : ALIGN(32)
+ {
+ *ipc_client_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA);
+
+ .TFM_SP_IPC_CLIENT_TEST_BSS : ALIGN(32)
+ {
+ *ipc_client_test*:*(.bss*)
+ *ipc_client_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS);
+
+ .TFM_SP_IPC_CLIENT_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK);
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK);
+
+#endif /* TFM_PSA_API */
.TFM_SP_SECURE_TEST_PARTITION_DATA : ALIGN(32)
{
@@ -720,8 +822,8 @@
. = ALIGN(4);
} > RAM AT> FLASH
- Image$$TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
- Image$$TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS : ALIGN(4)
{
@@ -731,8 +833,11 @@
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT> FLASH
- Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
- Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
diff --git a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template
index 43c9372..6a3ac44 100644
--- a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template
+++ b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template
@@ -94,9 +94,9 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (LOADADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_DATA))
+ LONG (LOADADDR(.@@manifest.name@@_DATA))
+ LONG (ADDR(.@@manifest.name@@_DATA))
+ LONG (SIZEOF(.@@manifest.name@@_DATA))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -115,10 +115,10 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (ADDR(.@@manifest.tfm_partition_name@@_BSS))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_BSS))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_STACK))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_STACK))
+ LONG (ADDR(.@@manifest.name@@_BSS))
+ LONG (SIZEOF(.@@manifest.name@@_BSS))
+ LONG (ADDR(.@@manifest.name@@_STACK))
+ LONG (SIZEOF(.@@manifest.name@@_STACK))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -156,7 +156,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@ : ALIGN(32)
+ .@@manifest.name@@ : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.text*)
@@ -166,13 +166,13 @@
@@manifest.tfm_linker_pattern.object_list@@(.text*)
@@manifest.tfm_linker_pattern.object_list@@(.rodata*)
@!GENERATOR_CONDITIONAL_END!@
- *(@@manifest.tfm_partition_name@@_ATTR_FN)
+ *(@@manifest.name@@_ATTR_FN)
. = ALIGN(32);
} > FLASH
- Image$$@@manifest.tfm_partition_name@@$$RO$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$RO$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
+ Image$$@@manifest.name@@$$RO$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$RO$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -311,7 +311,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@_DATA : ALIGN(32)
+ .@@manifest.name@@_DATA : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.data*)
@@ -321,10 +321,10 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Base = ADDR(.@@manifest.tfm_partition_name@@_DATA);
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Limit = ADDR(.@@manifest.tfm_partition_name@@_DATA) + SIZEOF(.@@manifest.tfm_partition_name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Base = ADDR(.@@manifest.name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Limit = ADDR(.@@manifest.name@@_DATA) + SIZEOF(.@@manifest.name@@_DATA);
- .@@manifest.tfm_partition_name@@_BSS : ALIGN(32)
+ .@@manifest.name@@_BSS : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.bss*)
@@ -336,15 +336,15 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_BSS);
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_BSS) + SIZEOF(.@@manifest.tfm_partition_name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Base = ADDR(.@@manifest.name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.name@@_BSS) + SIZEOF(.@@manifest.name@@_BSS);
- .@@manifest.tfm_partition_name@@_STACK : ALIGN(128)
+ .@@manifest.name@@_STACK : ALIGN(128)
{
. += @@manifest.stack_size@@;
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_STACK);
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_STACK) + SIZEOF(.@@manifest.tfm_partition_name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Base = ADDR(.@@manifest.name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.name@@_STACK) + SIZEOF(.@@manifest.name@@_STACK);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -409,8 +409,8 @@
. = ALIGN(4);
} > RAM AT> FLASH
- Image$$TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
- Image$$TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS : ALIGN(4)
{
@@ -420,8 +420,11 @@
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT> FLASH
- Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
- Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
diff --git a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
index c01cd10..26aa140 100644
--- a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
+++ b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
@@ -117,6 +117,15 @@
}
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ TFM_SP_IPC_CLIENT_TEST +0 ALIGN 32 {
+ *ipc_client_test.* (+RO)
+ }
+ TFM_SP_IPC_SERVICE_TEST +0 ALIGN 32 {
+ *ipc_service_test.* (+RO)
+ }
+#endif /* TFM_PSA_API */
+
/* Shared area between BL2 and runtime to exchange data */
TFM_SHARED_DATA S_DATA_START ALIGN 32 OVERLAY EMPTY BOOT_TFM_SHARED_DATA_SIZE {
}
@@ -214,6 +223,22 @@
}
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ TFM_SP_IPC_CLIENT_TEST_DATA +0 ALIGN 32 {
+ ipc_client_test.o (+RW +ZI)
+ }
+
+ TFM_SP_IPC_CLIENT_TEST_STACK +0 ALIGN 128 EMPTY 0x1000 {
+ }
+
+ TFM_SP_IPC_SERVICE_TEST_DATA +0 ALIGN 32 {
+ ipc_service_test.o (+RW +ZI)
+ }
+
+ TFM_SP_IPC_SERVICE_TEST_STACK +0 ALIGN 128 EMPTY 0x1000 {
+ }
+#endif /* TFM_PSA_API */
+
#endif /* TFM_LVL == 1 */
/* This empty, zero long execution region is here to mark the limit address
diff --git a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
index ea78e05..06d2181 100644
--- a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
+++ b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
@@ -120,6 +120,16 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_DATA))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_DATA))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA))
+#endif /* TFM_PSA_API */
__copy_table_end__ = .;
} > FLASH
@@ -168,6 +178,18 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK))
+#endif /* TFM_PSA_API */
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
@@ -313,6 +335,34 @@
Image$$TFM_SP_SECURE_TEST_PARTITION$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST : ALIGN(32)
+ {
+ *ipc_service_test*:*(.text*)
+ *ipc_service_test*:*(.rodata*)
+ *(TFM_SP_IPC_SERVICE_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST : ALIGN(32)
+ {
+ *ipc_client_test*:*(.text*)
+ *ipc_client_test*:*(.rodata*)
+ *(TFM_SP_IPC_CLIENT_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+
+#endif /* TFM_PSA_API */
.ARM.extab :
{
@@ -661,6 +711,58 @@
Image$$TFM_SP_SECURE_TEST_PARTITION_STACK$$ZI$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST_DATA : ALIGN(32)
+ {
+ *ipc_service_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA);
+
+ .TFM_SP_IPC_SERVICE_TEST_BSS : ALIGN(32)
+ {
+ *ipc_service_test*:*(.bss*)
+ *ipc_service_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS);
+
+ .TFM_SP_IPC_SERVICE_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK);
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST_DATA : ALIGN(32)
+ {
+ *ipc_client_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA);
+
+ .TFM_SP_IPC_CLIENT_TEST_BSS : ALIGN(32)
+ {
+ *ipc_client_test*:*(.bss*)
+ *ipc_client_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS);
+
+ .TFM_SP_IPC_CLIENT_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK);
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK);
+
+#endif /* TFM_PSA_API */
.TFM_SP_SECURE_TEST_PARTITION_DATA : ALIGN(32)
{
@@ -720,8 +822,8 @@
. = ALIGN(4);
} > RAM AT> FLASH
- Image$$TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
- Image$$TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS : ALIGN(4)
{
@@ -731,8 +833,11 @@
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT> FLASH
- Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
- Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
diff --git a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template
index 704d7a7..f1689d3 100644
--- a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template
+++ b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template
@@ -94,9 +94,9 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (LOADADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_DATA))
+ LONG (LOADADDR(.@@manifest.name@@_DATA))
+ LONG (ADDR(.@@manifest.name@@_DATA))
+ LONG (SIZEOF(.@@manifest.name@@_DATA))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -115,10 +115,10 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (ADDR(.@@manifest.tfm_partition_name@@_BSS))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_BSS))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_STACK))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_STACK))
+ LONG (ADDR(.@@manifest.name@@_BSS))
+ LONG (SIZEOF(.@@manifest.name@@_BSS))
+ LONG (ADDR(.@@manifest.name@@_STACK))
+ LONG (SIZEOF(.@@manifest.name@@_STACK))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -156,7 +156,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@ : ALIGN(32)
+ .@@manifest.name@@ : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.text*)
@@ -166,13 +166,13 @@
@@manifest.tfm_linker_pattern.object_list@@(.text*)
@@manifest.tfm_linker_pattern.object_list@@(.rodata*)
@!GENERATOR_CONDITIONAL_END!@
- *(@@manifest.tfm_partition_name@@_ATTR_FN)
+ *(@@manifest.name@@_ATTR_FN)
. = ALIGN(32);
} > FLASH
- Image$$@@manifest.tfm_partition_name@@$$RO$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$RO$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
+ Image$$@@manifest.name@@$$RO$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$RO$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -311,7 +311,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@_DATA : ALIGN(32)
+ .@@manifest.name@@_DATA : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.data*)
@@ -321,10 +321,10 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Base = ADDR(.@@manifest.tfm_partition_name@@_DATA);
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Limit = ADDR(.@@manifest.tfm_partition_name@@_DATA) + SIZEOF(.@@manifest.tfm_partition_name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Base = ADDR(.@@manifest.name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Limit = ADDR(.@@manifest.name@@_DATA) + SIZEOF(.@@manifest.name@@_DATA);
- .@@manifest.tfm_partition_name@@_BSS : ALIGN(32)
+ .@@manifest.name@@_BSS : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.bss*)
@@ -336,15 +336,15 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_BSS);
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_BSS) + SIZEOF(.@@manifest.tfm_partition_name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Base = ADDR(.@@manifest.name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.name@@_BSS) + SIZEOF(.@@manifest.name@@_BSS);
- .@@manifest.tfm_partition_name@@_STACK : ALIGN(128)
+ .@@manifest.name@@_STACK : ALIGN(128)
{
. += @@manifest.stack_size@@;
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_STACK);
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_STACK) + SIZEOF(.@@manifest.tfm_partition_name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Base = ADDR(.@@manifest.name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.name@@_STACK) + SIZEOF(.@@manifest.name@@_STACK);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -409,8 +409,8 @@
. = ALIGN(4);
} > RAM AT> FLASH
- Image$$TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
- Image$$TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS : ALIGN(4)
{
@@ -420,8 +420,11 @@
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT> FLASH
- Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
- Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
diff --git a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
index 61bb849..5231947 100644
--- a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
+++ b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
@@ -120,6 +120,16 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_DATA))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_DATA))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA))
+#endif /* TFM_PSA_API */
__copy_table_end__ = .;
} > FLASH
@@ -168,6 +178,18 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK))
+#endif /* TFM_PSA_API */
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
@@ -313,6 +335,34 @@
Image$$TFM_SP_SECURE_TEST_PARTITION$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST : ALIGN(32)
+ {
+ *ipc_service_test*:*(.text*)
+ *ipc_service_test*:*(.rodata*)
+ *(TFM_SP_IPC_SERVICE_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST : ALIGN(32)
+ {
+ *ipc_client_test*:*(.text*)
+ *ipc_client_test*:*(.rodata*)
+ *(TFM_SP_IPC_CLIENT_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+
+#endif /* TFM_PSA_API */
.ARM.extab :
{
@@ -661,6 +711,58 @@
Image$$TFM_SP_SECURE_TEST_PARTITION_STACK$$ZI$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST_DATA : ALIGN(32)
+ {
+ *ipc_service_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA);
+
+ .TFM_SP_IPC_SERVICE_TEST_BSS : ALIGN(32)
+ {
+ *ipc_service_test*:*(.bss*)
+ *ipc_service_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS);
+
+ .TFM_SP_IPC_SERVICE_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK);
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST_DATA : ALIGN(32)
+ {
+ *ipc_client_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA);
+
+ .TFM_SP_IPC_CLIENT_TEST_BSS : ALIGN(32)
+ {
+ *ipc_client_test*:*(.bss*)
+ *ipc_client_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS);
+
+ .TFM_SP_IPC_CLIENT_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK);
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK);
+
+#endif /* TFM_PSA_API */
.TFM_SP_SECURE_TEST_PARTITION_DATA : ALIGN(32)
{
@@ -720,8 +822,8 @@
. = ALIGN(4);
} > RAM AT> FLASH
- Image$$TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
- Image$$TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS : ALIGN(4)
{
@@ -731,8 +833,11 @@
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT> FLASH
- Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
- Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
diff --git a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template
index 43c9372..6a3ac44 100644
--- a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template
+++ b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template
@@ -94,9 +94,9 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (LOADADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_DATA))
+ LONG (LOADADDR(.@@manifest.name@@_DATA))
+ LONG (ADDR(.@@manifest.name@@_DATA))
+ LONG (SIZEOF(.@@manifest.name@@_DATA))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -115,10 +115,10 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (ADDR(.@@manifest.tfm_partition_name@@_BSS))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_BSS))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_STACK))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_STACK))
+ LONG (ADDR(.@@manifest.name@@_BSS))
+ LONG (SIZEOF(.@@manifest.name@@_BSS))
+ LONG (ADDR(.@@manifest.name@@_STACK))
+ LONG (SIZEOF(.@@manifest.name@@_STACK))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -156,7 +156,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@ : ALIGN(32)
+ .@@manifest.name@@ : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.text*)
@@ -166,13 +166,13 @@
@@manifest.tfm_linker_pattern.object_list@@(.text*)
@@manifest.tfm_linker_pattern.object_list@@(.rodata*)
@!GENERATOR_CONDITIONAL_END!@
- *(@@manifest.tfm_partition_name@@_ATTR_FN)
+ *(@@manifest.name@@_ATTR_FN)
. = ALIGN(32);
} > FLASH
- Image$$@@manifest.tfm_partition_name@@$$RO$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$RO$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
+ Image$$@@manifest.name@@$$RO$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$RO$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -311,7 +311,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@_DATA : ALIGN(32)
+ .@@manifest.name@@_DATA : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.data*)
@@ -321,10 +321,10 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Base = ADDR(.@@manifest.tfm_partition_name@@_DATA);
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Limit = ADDR(.@@manifest.tfm_partition_name@@_DATA) + SIZEOF(.@@manifest.tfm_partition_name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Base = ADDR(.@@manifest.name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Limit = ADDR(.@@manifest.name@@_DATA) + SIZEOF(.@@manifest.name@@_DATA);
- .@@manifest.tfm_partition_name@@_BSS : ALIGN(32)
+ .@@manifest.name@@_BSS : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.bss*)
@@ -336,15 +336,15 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_BSS);
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_BSS) + SIZEOF(.@@manifest.tfm_partition_name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Base = ADDR(.@@manifest.name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.name@@_BSS) + SIZEOF(.@@manifest.name@@_BSS);
- .@@manifest.tfm_partition_name@@_STACK : ALIGN(128)
+ .@@manifest.name@@_STACK : ALIGN(128)
{
. += @@manifest.stack_size@@;
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_STACK);
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_STACK) + SIZEOF(.@@manifest.tfm_partition_name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Base = ADDR(.@@manifest.name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.name@@_STACK) + SIZEOF(.@@manifest.name@@_STACK);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -409,8 +409,8 @@
. = ALIGN(4);
} > RAM AT> FLASH
- Image$$TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
- Image$$TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$RW$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA);
.TFM_BSS : ALIGN(4)
{
@@ -420,8 +420,11 @@
. = ALIGN(4);
__bss_end__ = .;
} > RAM AT> FLASH
- Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
- Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
+ Image$$ER_TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
diff --git a/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld b/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld
index 13b4a15..928c952 100644
--- a/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld
+++ b/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld
@@ -120,6 +120,16 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_DATA))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_DATA))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (LOADADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA))
+#endif /* TFM_PSA_API */
__copy_table_end__ = .;
} > FLASH
@@ -168,6 +178,18 @@
LONG (ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK))
LONG (SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK))
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK))
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS))
+ LONG (ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK))
+ LONG (SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK))
+#endif /* TFM_PSA_API */
LONG (ADDR(.TFM_UNPRIV_SCRATCH))
LONG (SIZEOF(.TFM_UNPRIV_SCRATCH))
__zero_table_end__ = .;
@@ -313,6 +335,34 @@
Image$$TFM_SP_SECURE_TEST_PARTITION$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST : ALIGN(32)
+ {
+ *ipc_service_test*:*(.text*)
+ *ipc_service_test*:*(.rodata*)
+ *(TFM_SP_IPC_SERVICE_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST);
+ Image$$TFM_SP_IPC_SERVICE_TEST$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST : ALIGN(32)
+ {
+ *ipc_client_test*:*(.text*)
+ *ipc_client_test*:*(.rodata*)
+ *(TFM_SP_IPC_CLIENT_TEST_ATTR_FN)
+ . = ALIGN(32);
+ } > FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$RO$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST);
+ Image$$TFM_SP_IPC_CLIENT_TEST$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST);
+
+#endif /* TFM_PSA_API */
.ARM.extab :
{
@@ -661,6 +711,58 @@
Image$$TFM_SP_SECURE_TEST_PARTITION_STACK$$ZI$$Limit = ADDR(.TFM_SP_SECURE_TEST_PARTITION_STACK) + SIZEOF(.TFM_SP_SECURE_TEST_PARTITION_STACK);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_SERVICE_TEST_DATA : ALIGN(32)
+ {
+ *ipc_service_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_DATA) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_DATA);
+
+ .TFM_SP_IPC_SERVICE_TEST_BSS : ALIGN(32)
+ {
+ *ipc_service_test*:*(.bss*)
+ *ipc_service_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS);
+ Image$$TFM_SP_IPC_SERVICE_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_BSS) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_BSS);
+
+ .TFM_SP_IPC_SERVICE_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK);
+ Image$$TFM_SP_IPC_SERVICE_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_SERVICE_TEST_STACK) + SIZEOF(.TFM_SP_IPC_SERVICE_TEST_STACK);
+
+#endif /* TFM_PSA_API */
+#ifdef TFM_PSA_API
+ .TFM_SP_IPC_CLIENT_TEST_DATA : ALIGN(32)
+ {
+ *ipc_client_test*:*(.data*)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$RW$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_DATA) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_DATA);
+
+ .TFM_SP_IPC_CLIENT_TEST_BSS : ALIGN(32)
+ {
+ *ipc_client_test*:*(.bss*)
+ *ipc_client_test*:*(COMMON)
+ . = ALIGN(32);
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS);
+ Image$$TFM_SP_IPC_CLIENT_TEST_DATA$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_BSS) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_BSS);
+
+ .TFM_SP_IPC_CLIENT_TEST_STACK : ALIGN(128)
+ {
+ . += 0x1000;
+ } > RAM AT> FLASH
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Base = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK);
+ Image$$TFM_SP_IPC_CLIENT_TEST_STACK$$ZI$$Limit = ADDR(.TFM_SP_IPC_CLIENT_TEST_STACK) + SIZEOF(.TFM_SP_IPC_CLIENT_TEST_STACK);
+
+#endif /* TFM_PSA_API */
.TFM_SP_SECURE_TEST_PARTITION_DATA : ALIGN(32)
{
@@ -734,6 +836,9 @@
Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
+
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
* separate 32 bytes aligned region so that the SAU can programmed to just set
diff --git a/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld.template b/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld.template
index 9a30f32..ec6eaf4 100644
--- a/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld.template
+++ b/platform/ext/target/musca_b1/Device/Source/gcc/musca_s.ld.template
@@ -94,9 +94,9 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (LOADADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_DATA))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_DATA))
+ LONG (LOADADDR(.@@manifest.name@@_DATA))
+ LONG (ADDR(.@@manifest.name@@_DATA))
+ LONG (SIZEOF(.@@manifest.name@@_DATA))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -115,10 +115,10 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- LONG (ADDR(.@@manifest.tfm_partition_name@@_BSS))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_BSS))
- LONG (ADDR(.@@manifest.tfm_partition_name@@_STACK))
- LONG (SIZEOF(.@@manifest.tfm_partition_name@@_STACK))
+ LONG (ADDR(.@@manifest.name@@_BSS))
+ LONG (SIZEOF(.@@manifest.name@@_BSS))
+ LONG (ADDR(.@@manifest.name@@_STACK))
+ LONG (SIZEOF(.@@manifest.name@@_STACK))
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
@@ -156,7 +156,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@ : ALIGN(32)
+ .@@manifest.name@@ : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.text*)
@@ -166,13 +166,13 @@
@@manifest.tfm_linker_pattern.object_list@@(.text*)
@@manifest.tfm_linker_pattern.object_list@@(.rodata*)
@!GENERATOR_CONDITIONAL_END!@
- *(@@manifest.tfm_partition_name@@_ATTR_FN)
+ *(@@manifest.name@@_ATTR_FN)
. = ALIGN(32);
} > FLASH
- Image$$@@manifest.tfm_partition_name@@$$RO$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$RO$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Base = ADDR(.@@manifest.tfm_partition_name@@);
- Image$$@@manifest.tfm_partition_name@@$$Limit = ADDR(.@@manifest.tfm_partition_name@@) + SIZEOF(.@@manifest.tfm_partition_name@@);
+ Image$$@@manifest.name@@$$RO$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$RO$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Base = ADDR(.@@manifest.name@@);
+ Image$$@@manifest.name@@$$Limit = ADDR(.@@manifest.name@@) + SIZEOF(.@@manifest.name@@);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -311,7 +311,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
- .@@manifest.tfm_partition_name@@_DATA : ALIGN(32)
+ .@@manifest.name@@_DATA : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.data*)
@@ -321,10 +321,10 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Base = ADDR(.@@manifest.tfm_partition_name@@_DATA);
- Image$$@@manifest.tfm_partition_name@@_DATA$$RW$$Limit = ADDR(.@@manifest.tfm_partition_name@@_DATA) + SIZEOF(.@@manifest.tfm_partition_name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Base = ADDR(.@@manifest.name@@_DATA);
+ Image$$@@manifest.name@@_DATA$$RW$$Limit = ADDR(.@@manifest.name@@_DATA) + SIZEOF(.@@manifest.name@@_DATA);
- .@@manifest.tfm_partition_name@@_BSS : ALIGN(32)
+ .@@manifest.name@@_BSS : ALIGN(32)
{
@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_linker_pattern.library_list@@
@@manifest.tfm_linker_pattern.library_list@@:*(.bss*)
@@ -336,15 +336,15 @@
@!GENERATOR_CONDITIONAL_END!@
. = ALIGN(32);
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_BSS);
- Image$$@@manifest.tfm_partition_name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_BSS) + SIZEOF(.@@manifest.tfm_partition_name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Base = ADDR(.@@manifest.name@@_BSS);
+ Image$$@@manifest.name@@_DATA$$ZI$$Limit = ADDR(.@@manifest.name@@_BSS) + SIZEOF(.@@manifest.name@@_BSS);
- .@@manifest.tfm_partition_name@@_STACK : ALIGN(128)
+ .@@manifest.name@@_STACK : ALIGN(128)
{
. += @@manifest.stack_size@@;
} > RAM AT> FLASH
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Base = ADDR(.@@manifest.tfm_partition_name@@_STACK);
- Image$$@@manifest.tfm_partition_name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.tfm_partition_name@@_STACK) + SIZEOF(.@@manifest.tfm_partition_name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Base = ADDR(.@@manifest.name@@_STACK);
+ Image$$@@manifest.name@@_STACK$$ZI$$Limit = ADDR(.@@manifest.name@@_STACK) + SIZEOF(.@@manifest.name@@_STACK);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -423,6 +423,9 @@
Image$$TFM_DATA$$ZI$$Base = ADDR(.TFM_BSS);
Image$$TFM_DATA$$ZI$$Limit = ADDR(.TFM_BSS) + SIZEOF(.TFM_BSS);
+ Image$$ER_TFM_DATA$$Base = ADDR(.TFM_DATA);
+ Image$$ER_TFM_DATA$$Limit = ADDR(.TFM_DATA) + SIZEOF(.TFM_DATA) + SIZEOF(.TFM_BSS);
+
/*
* Place the CMSE Veneers (containing the SG instruction) after the code, in a
* separate 32 bytes aligned region so that the SAU can programmed to just set
diff --git a/platform/include/tfm_plat_defs.h b/platform/include/tfm_plat_defs.h
index 66747ee..f0b4297 100644
--- a/platform/include/tfm_plat_defs.h
+++ b/platform/include/tfm_plat_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
@@ -30,7 +30,7 @@
* secure partition at linker time in TF-M Level 3.
*
* \param[in] TFM_PARTITION_NAME TF-M partition name assigned in the manifest
- * file "tfm_partition_name" field.
+ * file "name" field.
*/
#define TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION(TFM_PARTITION_NAME) \
__attribute__((section(TFM_PARTITION_NAME"_ATTR_FN")))
diff --git a/secure_fw/CMakeLists.txt b/secure_fw/CMakeLists.txt
index ab1ced2..57aa6f0 100644
--- a/secure_fw/CMakeLists.txt
+++ b/secure_fw/CMakeLists.txt
@@ -31,8 +31,13 @@
endif()
include(${SECURE_FW_DIR}/spm/CMakeLists.inc)
-include(${SECURE_FW_DIR}/core/CMakeLists.inc)
include(${SECURE_FW_DIR}/ns_callable/CMakeLists.inc)
+#Involve all IPC related sources in ipc's CMakeLists.inc, and switch core between IPC and Library.
+if(TFM_PSA_API)
+ include(${SECURE_FW_DIR}/core/ipc/CMakeLists.inc)
+else()
+ include(${SECURE_FW_DIR}/core/CMakeLists.inc)
+endif()
set(BUILD_CMSIS_CORE On)
set(BUILD_RETARGET On)
@@ -144,7 +149,7 @@
#Set macro definitions for the project.
embedded_set_target_compile_defines(TARGET ${PROJECT_OBJ_LIB} LANGUAGE C DEFINES __thumb2__ __ARM_FEATURE_CMSE=3 TFM_LVL=${TFM_LVL} DAUTH_CHIP_DEFAULT APPEND)
- if (REGRESSION OR CORE_TEST)
+ if (REGRESSION OR CORE_TEST OR CORE_IPC)
if (DEFINED TFM_PARTITION_TEST_SECURE_SERVICES AND TFM_PARTITION_TEST_SECURE_SERVICES)
#The test service veneers in the tfm_secure_tests library may not be
#referenced in the secure binary so the veneer objects are explicitly loaded
@@ -202,6 +207,12 @@
embedded_set_target_link_defines(TARGET ${EXE_NAME} DEFINES "BL2")
endif()
+ if (NOT DEFINED TFM_PSA_API)
+ message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ")
+ elseif (TFM_PSA_API)
+ embedded_set_target_link_defines(TARGET ${PROJECT_NAME} DEFINES "TFM_PSA_API")
+ endif()
+
if(CORE_TEST)
set(SECURE_AXF_DIR_PREFIX "${CMAKE_BINARY_DIR}/unit_test/")
set_target_properties(${EXE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SECURE_AXF_DIR_PREFIX})
diff --git a/secure_fw/core/CMakeLists.inc b/secure_fw/core/CMakeLists.inc
index c7e4392..0b290d5 100644
--- a/secure_fw/core/CMakeLists.inc
+++ b/secure_fw/core/CMakeLists.inc
@@ -69,4 +69,3 @@
else()
include(${PLATFORM_CMAKE_FILE})
endif()
-
diff --git a/secure_fw/core/ipc/CMakeLists.inc b/secure_fw/core/ipc/CMakeLists.inc
new file mode 100644
index 0000000..59c074e
--- /dev/null
+++ b/secure_fw/core/ipc/CMakeLists.inc
@@ -0,0 +1,74 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the "ipc" 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 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.
+
+#Get the current directory where this file is located.
+set(SS_IPC_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 TFM_PSA_API)
+ message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ")
+elseif (TFM_PSA_API)
+ set (SS_IPC_C_SRC "${SS_IPC_DIR}/tfm_svcalls.c"
+ "${SS_IPC_DIR}/psa_service.c"
+ "${SS_IPC_DIR}/psa_client.c"
+ "${SS_IPC_DIR}/tfm_arch_v8m.c"
+ "${SS_IPC_DIR}/tfm_thread.c"
+ "${SS_IPC_DIR}/tfm_wait.c"
+ "${SS_IPC_DIR}/tfm_utils.c"
+ "${SS_IPC_DIR}/tfm_message_queue.c"
+ "${SS_IPC_DIR}/tfm_pools.c"
+ "${SS_IPC_DIR}/tfm_spm.c"
+ "${SS_IPC_DIR}/../tfm_core.c"
+ "${SS_IPC_DIR}/../tfm_secure_api.c"
+ "${SS_IPC_DIR}/../tfm_spm_services.c"
+ "${SS_IPC_DIR}/../tfm_handler.c"
+ "${SS_IPC_DIR}/../tfm_psa_api_client.c"
+ "${SS_IPC_DIR}/../tfm_nspm.c"
+ "${SS_IPC_DIR}/../tfm_boot_data.c"
+ )
+endif()
+
+#Append all our source files to global lists.
+list(APPEND ALL_SRC_C ${SS_IPC_C_SRC})
+unset(SS_IPC_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 ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc ABSOLUTE)
+embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc/include ABSOLUTE)
+
+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/core/ipc/include/tfm_arch_v8m.h b/secure_fw/core/ipc/include/tfm_arch_v8m.h
new file mode 100644
index 0000000..96914c0
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_arch_v8m.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_ARCH_V8M_H__
+#define __TFM_ARCH_V8M_H__
+
+#include "cmsis.h"
+
+#define XPSR_T32 0x01000000
+#define LR_UNPRIVILEGED 0xfffffffd
+
+/* This header file collects the ARCH related operations. */
+struct tfm_state_context_base {
+ uint32_t r0;
+ uint32_t r1;
+ uint32_t r2;
+ uint32_t r3;
+ uint32_t r12;
+ uint32_t ra_lr;
+ uint32_t ra;
+ uint32_t xpsr;
+};
+
+struct tfm_state_context_ext {
+ 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;
+};
+
+struct tfm_state_context {
+ struct tfm_state_context_ext ctxb;
+};
+
+#define TFM_STATE_1ST_ARG(ctx) \
+ (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r0)
+#define TFM_STATE_2ND_ARG(ctx) \
+ (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r1)
+#define TFM_STATE_3RD_ARG(ctx) \
+ (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r2)
+#define TFM_STATE_4TH_ARG(ctx) \
+ (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r3)
+#define TFM_STATE_RET_VAL(ctx) \
+ (((struct tfm_state_context_base *)(ctx)->ctxb.sp)->r0)
+
+__STATIC_INLINE void tfm_trigger_pendsv(void)
+{
+ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+}
+
+void tfm_initialize_context(struct tfm_state_context *ctx,
+ uint32_t r0, uint32_t ra,
+ uint32_t sp, uint32_t sp_limit);
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_internal_defines.h b/secure_fw/core/ipc/include/tfm_internal_defines.h
new file mode 100644
index 0000000..a5382c5
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_internal_defines.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_INTERNAL_DEFINES_H__
+#define __TFM_INTERNAL_DEFINES_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/core/ipc/include/tfm_list.h b/secure_fw/core/ipc/include/tfm_list.h
new file mode 100644
index 0000000..9764503
--- /dev/null
+++ b/secure_fw/core/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/core/ipc/include/tfm_message_queue.h b/secure_fw/core/ipc/include/tfm_message_queue.h
new file mode 100644
index 0000000..6ecb34a
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_message_queue.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_MESSAGE_QUEUE_H__
+#define __TFM_MESSAGE_QUEUE_H__
+
+#define TFM_MSG_QUEUE_MAX_MSG_NUM 128
+#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 */
+ psa_handle_t handle; /* Connected Service handle */
+ struct tfm_event_ctx ack_mtx; /* 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
+ */
+ 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/core/ipc/include/tfm_pools.h b/secure_fw/core/ipc/include/tfm_pools.h
new file mode 100644
index 0000000..1072f78
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_pools.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_POOLS_H__
+#define __TFM_POOLS_H__
+
+/*
+ * 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 */
+};
+
+struct tfm_pool_instance_t {
+ size_t chunksz; /* Chunks size of pool member */
+ struct tfm_list_node_t chunks_list; /* Chunk list head in pool */
+ struct tfm_pool_chunk_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);
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_spm.h b/secure_fw/core/ipc/include/tfm_spm.h
new file mode 100644
index 0000000..e9e18d0
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_spm.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_SPM_H__
+#define __TFM_SPM_H__
+
+#include <stdbool.h>
+#include "tfm_list.h"
+
+#define TFM_SPM_MAX_ROT_SERV_NUM 28
+#define TFM_VERSION_POLICY_RELAXED 0
+#define TFM_VERSION_POLICY_STRICT 1
+
+#define TFM_CONN_HANDLE_MAX_NUM 32
+
+/* RoT connection handle list */
+struct tfm_conn_handle_t {
+ psa_handle_t handle; /* Handle value */
+ void *rhandle; /* Reverse handle value */
+ 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 minor_version; /* Minor version */
+ uint32_t minor_policy; /* Minor version policy */
+};
+
+/* RoT Service data */
+struct tfm_spm_service_t {
+ struct tfm_spm_service_db_t *service_db; /* Service database pointer */
+ struct tfm_spm_ipc_partition_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 */
+};
+
+/*
+ * FixMe: This structure is for IPC partition which is different with library
+ * mode partition. There needs to be an alignment for IPC partition database
+ * and library mode database.
+ */
+/* Secure Partition data */
+struct tfm_spm_ipc_partition_t {
+ int32_t index; /* Partition index */
+ int32_t id; /* Secure partition ID */
+ struct tfm_event_ctx signal_event; /* Event signal */
+ uint32_t signals; /* Service signals had been triggered*/
+ uint32_t signal_mask; /* Service signal mask passed by psa_wait() */
+ struct tfm_list_node_t service_list;/* Service list */
+};
+
+/*************************** Extended SPM functions **************************/
+
+/**
+ * \brief Get the running partition ID.
+ *
+ * \return Returns the partition ID
+ */
+uint32_t tfm_spm_partition_get_running_partition_id_ext(void);
+
+/******************** Service handle management functions ********************/
+
+/**
+ * \brief Create connection handle for client connect
+ *
+ * \param[in] service Target service context pointer
+ *
+ * \retval PSA_NULL_HANDLE Create failed \ref PSA_NULL_HANDLE
+ * \retval >0 Service handle created, \ref psa_handle_t
+ */
+psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service);
+
+/**
+ * \brief Free connection handle which not used anymore.
+ *
+ * \param[in] service Target service context pointer
+ * \param[in] conn_handle Connection handle created by
+ * tfm_spm_create_conn_handle(), \ref psa_handle_t
+ *
+ * \retval IPC_SUCCESS Success
+ * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
+ * \retval "Does not return" Panic for not find service by handle
+ */
+int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle);
+
+/**
+ * \brief Set reverse handle value for connection.
+ *
+ * \param[in] service Target service context pointer
+ * \param[in] conn_handle Connection handle created by
+ * tfm_spm_create_conn_handle(), \ref psa_handle_t
+ * \param[in] rhandle rhandle need to save
+ *
+ * \retval IPC_SUCCESS Success
+ * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
+ * \retval "Does not return" Panic for not find handle node
+ */
+int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle,
+ void *rhandle);
+
+/**
+ * \brief Get reverse handle value from connection hanlde.
+ *
+ * \param[in] service Target service context pointer
+ * \param[in] conn_handle Connection handle created by
+ * tfm_spm_create_conn_handle(), \ref psa_handle_t
+ *
+ * \retval void * Success
+ * \retval "Does not return" Panic for those:
+ * service pointer are NULL
+ * hanlde is \ref PSA_NULL_HANDLE
+ * handle node does not be found
+ */
+void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle);
+
+/******************** Partition management functions *************************/
+
+/**
+ * \brief Get current running partition context.
+ *
+ * \retval NULL Failed
+ * \retval "Not NULL" Return the parttion context pointer
+ * \ref spm_partition_t structures
+ */
+struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void);
+
+/**
+ * \brief Get the service context by signal.
+ *
+ * \param[in] partition Partition context pointer
+ * \ref spm_partition_t structures
+ * \param[in] signal Signal associated with inputs to the Secure
+ * Partition, \ref psa_signal_t
+ *
+ * \retval NULL Failed
+ * \retval "Not NULL" Target service context pointer,
+ * \ref spm_service_t structures
+ */
+struct tfm_spm_service_t *
+tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
+ psa_signal_t signal);
+
+/**
+ * \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 spm_service_t structures
+ */
+struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid);
+
+/**
+ * \brief Get the service context by connection handle.
+ *
+ * \param[in] conn_handle Connection handle created by
+ * tfm_spm_create_conn_handle()
+ *
+ * \retval NULL Failed
+ * \retval "Not NULL" Target service context pointer,
+ * \ref spm_service_t structures
+ */
+struct tfm_spm_service_t *
+ tfm_spm_get_service_by_handle(psa_handle_t conn_handle);
+
+/**
+ * \brief Get the partition context by partition ID.
+ *
+ * \param[in] partition_id Partition identity
+ *
+ * \retval NULL Failed
+ * \retval "Not NULL" Target partition context pointer,
+ * \ref spm_partition_t structures
+ */
+struct tfm_spm_ipc_partition_t *
+ tfm_spm_get_partition_by_id(int32_t partition_id);
+
+/************************ Message functions **********************************/
+
+/**
+ * \brief Get message context by message handle.
+ *
+ * \param[in] msg_handle Message handle which is a reference generated
+ * by the SPM to a specific message.
+ *
+ * \return The message body context pointer
+ * \ref msg_body_t structures
+ */
+struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle);
+
+/**
+ * \brief Create a message for PSA client call.
+ *
+ * \param[in] service Target service context pointer, which can be
+ * obtained by partition management functions
+ * \prarm[in] handle Connect handle return by psa_connect(). Should
+ * be \ref PSA_NULL_HANDLE in psa_connect().
+ * \param[in] type Message type, PSA_IPC_CONNECT, PSA_IPC_CALL or
+ * PSA_IPC_DISCONNECT
+ * \param[in] ns_caller Whether from NS caller
+ * \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
+ *
+ * \retval NULL Failed
+ * \retval "Not NULL" New message body pointer \ref msg_body_t structures
+ */
+struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
+ psa_handle_t handle,
+ uint32_t type, int32_t ns_caller,
+ psa_invec *invec, size_t in_len,
+ psa_outvec *outvec, size_t out_len,
+ psa_outvec *caller_outvec);
+
+/**
+ * \brief Free message which unused anymore
+ *
+ * \param[in] msg Message pointer which want to free
+ * \ref msg_body_t structures
+ *
+ * \retval void Success
+ * \retval "Does not return" Failed
+ */
+void tfm_spm_free_msg(struct tfm_msg_body_t *msg);
+
+/**
+ * \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 spm_create_msg()
+ * \ref 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 minor version according to
+ * version policy
+ *
+ * \param[in] service Target service context pointer, which can be get
+ * by partition management functions
+ * \param[in] minor_version Client support minor 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 minor_version);
+
+/**
+ * \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
+ *
+ * \retval IPC_SUCCESS Success
+ * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input
+ * \retval IPC_ERROR_MEMORY_CHECK Check failed
+ */
+int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller);
+
+/* This function should be called before schedule function */
+void tfm_spm_init(void);
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_spm_signal_defs.h b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
new file mode 100644
index 0000000..e632354
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_spm_signal_defs.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_SPM_SIGNAL_DEFS_H__
+#define __TFM_SPM_SIGNAL_DEFS_H__
+
+#include "test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h"
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_svcalls.h b/secure_fw/core/ipc/include/tfm_svcalls.h
new file mode 100644
index 0000000..c64ce74
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_svcalls.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_SVCALLS_H__
+#define __TFM_SVCALLS_H__
+
+/* 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_svcall_psa_framework_version(void);
+
+/**
+ * \brief SVC handler for \ref psa_version.
+ *
+ * \param[in] args Include all input arguments: sid.
+ * \param[in] ns_caller If 'non-zero', 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 minor version of the implemented RoT
+ * Service.
+ */
+uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for \ref psa_connect.
+ *
+ * \param[in] args Include all input arguments:
+ * sid, minor_version.
+ * \param[in] ns_caller If 'non-zero', call from non-secure client.
+ * Or from secure client.
+ *
+ * \retval > 0 A handle for the connection.
+ * \retval PSA_CONNECTION_REFUSED The SPM or RoT Service has refused the
+ * connection.
+ * \retval PSA_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_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t 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 'non-zero', call from non-secure client.
+ * Or from secure client.
+ *
+ * \retval >=0 RoT Service-specific status value.
+ * \retval <0 RoT Service-specific error code.
+ * \retval PSA_DROP_CONNECTION The connection has been dropped by the RoT
+ * Service. This indicates that either this or
+ * a previous message was invalid.
+ * \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 by the RoT
+ * Service or incorrectly formatted.
+ */
+psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for \ref psa_close.
+ *
+ * \param[in] args Include all input arguments: handle.
+ * \param[in] ns_caller If 'non-zero', 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_svcall_psa_close(uint32_t *args, int32_t ns_caller);
+
+/**
+ * \brief SVC handler for IPC functions
+ *
+ * \param[in] svc_num SVC number
+ * \param[in] ctx Argument context
+ *
+ * \returns Return values from those who has,
+ * or PSA_SUCCESS.
+ */
+int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx);
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_thread.h b/secure_fw/core/ipc/include/tfm_thread.h
new file mode 100644
index 0000000..8a6d863
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_thread.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_THREAD_H__
+#define __TFM_THREAD_H__
+
+#include "tfm_arch_v8m.h"
+#include "cmsis_compiler.h"
+
+/* Status code */
+#define THRD_STAT_CREATING 0
+#define THRD_STAT_RUNNING 1
+#define THRD_STAT_BLOCK 2
+#define THRD_STAT_DETACH 3
+#define THRD_STAT_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_thrd_func_t)(void *);
+
+/* Thread context */
+struct tfm_thrd_ctx {
+ tfm_thrd_func_t pfn; /* entry function */
+ void *param; /* entry parameter */
+ uint8_t *sp_base; /* stack bottom */
+ uint8_t *sp_top; /* stack top */
+ uint32_t prior; /* priority */
+ uint32_t status; /* status */
+
+ struct tfm_state_context state_ctx; /* State context */
+ struct tfm_thrd_ctx *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
+ * sp_base - stack pointer base (higher address)
+ * sp_top - stack pointer top (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_thrd_init(struct tfm_thrd_ctx *pth,
+ tfm_thrd_func_t pfn, void *param,
+ uint8_t *sp_base, uint8_t *sp_top);
+
+/* 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_thrd_init().
+ */
+void __STATIC_INLINE tfm_thrd_priority(struct tfm_thrd_ctx *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_thrd_secure(struct tfm_thrd_ctx *pth,
+ uint32_t attr_secure)
+{
+ pth->prior &= ~THRD_ATTR_NON_SECURE;
+ pth->prior |= attr_secure;
+}
+
+/*
+ * Set thread status.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ * new_status - new status of thread
+ *
+ * Return :
+ * None
+ *
+ * Notes :
+ * Thread status is not changed if invalid status value inputed.
+ */
+void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status);
+
+/*
+ * Get thread status.
+ *
+ * Parameters :
+ * pth - pointer of thread context
+ *
+ * Return :
+ * Status of thread
+ */
+uint32_t __STATIC_INLINE tfm_thrd_get_status(struct tfm_thrd_ctx *pth)
+{
+ return pth->status;
+}
+
+/*
+ * 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_thrd_set_retval(struct tfm_thrd_ctx *pth,
+ uint32_t retval)
+{
+ TFM_STATE_RET_VAL(&pth->state_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_thrd_start().
+ */
+uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth);
+
+/*
+ * Get current running thread.
+ *
+ * Return :
+ * Current running thread context pointer.
+ */
+struct tfm_thrd_ctx *tfm_thrd_curr_thread(void);
+
+/*
+ * Get next running thread in list.
+ *
+ * Return :
+ * Pointer of next thread to be run.
+ */
+struct tfm_thrd_ctx *tfm_thrd_next_thread(void);
+
+/*
+ * Activate a scheduling action after exception.
+ *
+ * Notes :
+ * This function could be called multiple times before scheduling.
+ */
+void tfm_thrd_activate_schedule(void);
+
+/*
+ * Save current context into 'prev' thread and switch to 'next'.
+ *
+ * Parameters :
+ * ctxb - 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_thrd_context_switch(struct tfm_state_context_ext *ctxb,
+ struct tfm_thrd_ctx *prev,
+ struct tfm_thrd_ctx *next);
+
+/*
+ * Exit current running thread.
+ *
+ * Notes :
+ * Remove current thread out of schedulable list.
+ */
+void tfm_thrd_do_exit(void);
+
+/*
+ * PendSV specified function.
+ *
+ * Parameters :
+ * ctxb - State 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_state_context_ext *ctxb);
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_utils.h b/secure_fw/core/ipc/include/tfm_utils.h
new file mode 100644
index 0000000..17f94c0
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_utils.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_UTILS_H__
+#define __TFM_UTILS_H__
+
+/* CPU spin here */
+void tfm_panic(void);
+
+/* Assert and spin */
+#define TFM_ASSERT(cond) \
+ do { \
+ if (!(cond)) { \
+ printf("Assert:%s:%d", __FUNCTION__, __LINE__); \
+ while (1) \
+ ; \
+ } \
+ } while (0)
+
+/* Get container structure start address from member */
+#define TFM_GET_CONTAINER_PTR(ptr, type, member) \
+ (type *)((unsigned long)(ptr) - offsetof(type, member))
+
+int32_t tfm_bitcount(uint32_t n);
+
+#endif
diff --git a/secure_fw/core/ipc/include/tfm_wait.h b/secure_fw/core/ipc/include/tfm_wait.h
new file mode 100644
index 0000000..2bed0ae
--- /dev/null
+++ b/secure_fw/core/ipc/include/tfm_wait.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_WAIT_H__
+#define __TFM_WAIT_H__
+
+#include "cmsis_compiler.h"
+
+#define EVENT_MAGIC 0x65766e74
+#define EVENT_STAT_WAITED 0x0
+#define EVENT_STAT_SIGNALED 0x1
+
+struct tfm_event_ctx {
+ uint32_t magic; /* 'evnt' */
+ struct tfm_thrd_ctx *owner; /* waiting thread */
+ uint32_t status; /* status */
+ uint32_t retval; /* return value */
+};
+
+/*
+ * Initialize an event context.
+ *
+ * Parameters :
+ * pevt - pointer of event context caller provided
+ * stat - initial status (EVENT_STAT_WAITED or EVENT_STAT_SIGNALED)
+ */
+void __STATIC_INLINE tfm_event_init(struct tfm_event_ctx *pevt, uint32_t stat)
+{
+ pevt->magic = EVENT_MAGIC;
+ pevt->status = stat;
+ pevt->owner = NULL;
+ pevt->retval = 0;
+}
+
+/*
+ * Wait on an event.
+ *
+ * Parameters :
+ * pevt - pointer of event context
+ *
+ * Notes :
+ * Thread is blocked if event is not signaled.
+ */
+void tfm_event_wait(struct tfm_event_ctx *pevt);
+
+/*
+ * Signal an event.
+ *
+ * Parameters :
+ * pevt - pointer of event context
+ *
+ * Notes :
+ * Waiting thread on this event will be running.
+ */
+void tfm_event_signal(struct tfm_event_ctx *pevt);
+
+/*
+ * Peek an event status.
+ *
+ * Parameters :
+ * pevt - pointer of event context
+ *
+ * Return :
+ * Status of event.
+ *
+ * Notes :
+ * This function is used for getting event status without blocking thread.
+ */
+uint32_t tfm_event_peek(struct tfm_event_ctx *pevt);
+
+/*
+ * Set event owner return value.
+ *
+ * Parameters :
+ * pevt - pointer of event context
+ * retval - return value of blocked owner thread
+ *
+ * Notes :
+ * Thread return value is set while thread is to be running.
+ */
+void tfm_event_owner_retval(struct tfm_event_ctx *pevt, uint32_t retval);
+
+#endif
diff --git a/secure_fw/core/ipc/psa_client.c b/secure_fw/core/ipc/psa_client.c
new file mode 100644
index 0000000..f8fe605
--- /dev/null
+++ b/secure_fw/core/ipc/psa_client.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_svc.h"
+#include "psa_client.h"
+
+__attribute__((naked))
+uint32_t psa_framework_version(void)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_FRAMEWORK_VERSION));
+}
+
+__attribute__((naked))
+uint32_t psa_version(uint32_t sid)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_VERSION));
+}
+
+__attribute__((naked))
+psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_CONNECT));
+}
+
+__attribute__((naked))
+psa_status_t psa_call(psa_handle_t handle,
+ const psa_invec *in_vec,
+ size_t in_len,
+ psa_outvec *out_vec,
+ size_t out_len)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_CALL));
+}
+
+__attribute__((naked))
+void psa_close(psa_handle_t handle)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_CLOSE));
+}
diff --git a/secure_fw/core/ipc/psa_service.c b/secure_fw/core/ipc/psa_service.c
new file mode 100644
index 0000000..4871971
--- /dev/null
+++ b/secure_fw/core/ipc/psa_service.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_svc.h"
+#include "psa_client.h"
+#include "psa_service.h"
+
+__attribute__((naked))
+psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout)
+
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_WAIT));
+}
+
+__attribute__((naked))
+psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_GET));
+}
+
+__attribute__((naked))
+void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_SET_RHANDLE));
+}
+
+__attribute__((naked))
+size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx,
+ void *buffer, size_t num_bytes)
+
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_READ));
+}
+
+__attribute__((naked))
+size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_SKIP));
+}
+
+__attribute__((naked))
+void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx,
+ const void *buffer, size_t num_bytes)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_WRITE));
+}
+
+__attribute__((naked))
+void psa_reply(psa_handle_t msg_handle, psa_status_t retval)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_REPLY));
+}
+
+__attribute__((naked))
+void psa_notify(int32_t partition_id)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_NOTIFY));
+}
+
+__attribute__((naked))
+void psa_clear(void)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_CLEAR));
+}
+
+__attribute__((naked))
+void psa_eoi(psa_signal_t irq_signal)
+{
+ __ASM("SVC %0 \n"
+ "BX LR \n"
+ : : "I" (TFM_SVC_PSA_EOI));
+}
diff --git a/secure_fw/core/ipc/tfm_arch_v8m.c b/secure_fw/core/ipc/tfm_arch_v8m.c
new file mode 100644
index 0000000..4c976fd
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_arch_v8m.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "tfm_arch_v8m.h"
+#include "cmsis.h"
+#include "psa_client.h"
+#include "psa_service.h"
+#include "tfm_utils.h"
+#include "tfm_thread.h"
+#include "tfm_memory_utils.h"
+
+/* This file contains the ARCH code for ARM V8M */
+
+/*
+ * Thread exit zone.
+ * This function is set as the return address of thread entry and only
+ * privileged thread could return here. Un-privileged thread triggers
+ * fault if it tries to jump here and it gets exit by fault handler.
+ *
+ * The reason of putting this function here is for fault handler checking.
+ * Function address could be checked in fault handler to know it is a REAL
+ * thread exit or just an exception.
+ */
+static void exit_zone(void)
+{
+ tfm_thrd_do_exit();
+}
+
+void tfm_initialize_context(struct tfm_state_context *ctx,
+ uint32_t r0, uint32_t ra,
+ uint32_t sp, uint32_t sp_limit)
+{
+ /*
+ * For security consideration, set unused registers into ZERO;
+ * and only necessary registers are set here.
+ */
+ struct tfm_state_context_base *p_ctxa =
+ (struct tfm_state_context_base *)sp;
+
+ /*
+ * Shift back SP to leave space for holding base context
+ * since thread is kicked off through exception return.
+ */
+ p_ctxa--;
+
+ /* Basic context is considerate at thread start.*/
+ tfm_memset(p_ctxa, 0, sizeof(*p_ctxa));
+ p_ctxa->r0 = r0;
+ p_ctxa->ra = ra;
+ p_ctxa->ra_lr = (uint32_t)exit_zone;
+ p_ctxa->xpsr = XPSR_T32;
+
+ tfm_memset(ctx, 0, sizeof(*ctx));
+ ctx->ctxb.sp = (uint32_t)p_ctxa;
+ ctx->ctxb.sp_limit = sp_limit;
+ ctx->ctxb.lr = LR_UNPRIVILEGED;
+}
+
+/*
+ * 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 ]
+ * [ ........ ] [ ........ ]
+ * [ ........ ]
+ *
+ * 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.
+ */
+__attribute__((naked)) void PendSV_Handler(void)
+{
+ __ASM(
+ "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"
+ );
+}
+
+/* Reserved for future usage */
+__attribute__((naked)) void MemManage_Handler(void)
+{
+ __ASM("b .");
+}
+
+__attribute__((naked)) void BusFault_Handler(void)
+{
+ __ASM("b .");
+}
+__attribute__((naked)) void UsageFault_Handler(void)
+{
+ __ASM("b .");
+}
diff --git a/secure_fw/core/ipc/tfm_message_queue.c b/secure_fw/core/ipc/tfm_message_queue.c
new file mode 100644
index 0000000..83ebf50
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_message_queue.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_thread.h"
+#include "tfm_wait.h"
+#include "psa_client.h"
+#include "psa_service.h"
+#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/core/ipc/tfm_pools.c b/secure_fw/core/ipc/tfm_pools.c
new file mode 100644
index 0000000..83342b8
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_pools.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.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"
+
+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_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;
+
+ 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);
+}
diff --git a/secure_fw/core/ipc/tfm_spm.c b/secure_fw/core/ipc/tfm_spm.c
new file mode 100644
index 0000000..a019a9f
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_spm.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "psa_client.h"
+#include "psa_service.h"
+#include "tfm_utils.h"
+#include "spm_api.h"
+#include "spm_db.h"
+#include "spm_db_setup.h"
+#include "tfm_internal_defines.h"
+#include "tfm_wait.h"
+#include "tfm_message_queue.h"
+#include "tfm_list.h"
+#include "tfm_pools.h"
+#include "tfm_spm.h"
+#include "tfm_spm_signal_defs.h"
+#include "tfm_thread.h"
+#include "region_defs.h"
+#include "tfm_nspm.h"
+#include "tfm_memory_utils.h"
+
+/*
+ * IPC partitions.
+ * FixMe: Need to get align with spm_partition_db_t.
+ */
+static struct tfm_spm_ipc_partition_t
+ g_spm_ipc_partition[SPM_MAX_PARTITIONS] = {};
+
+/* Extern SPM variable */
+extern struct spm_partition_db_t g_spm_partition_db;
+
+/* Pools */
+TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t),
+ TFM_CONN_HANDLE_MAX_NUM);
+TFM_POOL_DECLARE(spm_service_pool, sizeof(struct tfm_spm_service_t),
+ TFM_SPM_MAX_ROT_SERV_NUM);
+TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
+ TFM_MSG_QUEUE_MAX_MSG_NUM);
+
+static struct tfm_spm_service_db_t g_spm_service_db[] = {
+ #include "secure_fw/services/tfm_service_list.inc"
+};
+
+/********************** SPM functions for handler mode ***********************/
+
+/* Service handle management functions */
+psa_handle_t tfm_spm_create_conn_handle(struct tfm_spm_service_t *service)
+{
+ struct tfm_conn_handle_t *node;
+
+ TFM_ASSERT(service);
+
+ /* Get buffer for handle list structure from handle pool */
+ node = (struct tfm_conn_handle_t *)tfm_pool_alloc(conn_handle_pool);
+ if (!node) {
+ return PSA_NULL_HANDLE;
+ }
+
+ /* Global unique handle, use handle buffer address directly */
+ node->handle = (psa_handle_t)node;
+
+ /* Add handle node to list for next psa functions */
+ tfm_list_add_tail(&service->handle_list, &node->list);
+
+ return node->handle;
+}
+
+static struct tfm_conn_handle_t *
+tfm_spm_find_conn_handle_node(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle)
+{
+ struct tfm_conn_handle_t *handle_node;
+ struct tfm_list_node_t *node, *head;
+
+ TFM_ASSERT(service);
+
+ head = &service->handle_list;
+ TFM_LIST_FOR_EACH(node, head) {
+ handle_node = TFM_GET_CONTAINER_PTR(node, struct tfm_conn_handle_t,
+ list);
+ if (handle_node->handle == conn_handle) {
+ return handle_node;
+ }
+ }
+ return NULL;
+}
+
+int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle)
+{
+ struct tfm_conn_handle_t *node;
+
+ TFM_ASSERT(service);
+
+ /* There are many handles for each RoT Service */
+ node = tfm_spm_find_conn_handle_node(service, conn_handle);
+ if (!node) {
+ tfm_panic();
+ }
+
+ /* Remove node from handle list */
+ tfm_list_del_node(&node->list);
+
+ /* Back handle buffer to pool */
+ tfm_pool_free(node);
+ return IPC_SUCCESS;
+}
+
+int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle,
+ void *rhandle)
+{
+ struct tfm_conn_handle_t *node;
+
+ TFM_ASSERT(service);
+ /* Set reverse handle value only be allowed for a connected handle */
+ TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
+
+ /* There are many handles for each RoT Service */
+ node = tfm_spm_find_conn_handle_node(service, conn_handle);
+ if (!node) {
+ tfm_panic();
+ }
+
+ node->rhandle = rhandle;
+ return IPC_SUCCESS;
+}
+
+void *tfm_spm_get_rhandle(struct tfm_spm_service_t *service,
+ psa_handle_t conn_handle)
+{
+ struct tfm_conn_handle_t *node;
+
+ TFM_ASSERT(service);
+ /* Get reverse handle value only be allowed for a connected handle */
+ TFM_ASSERT(conn_handle != PSA_NULL_HANDLE);
+
+ /* There are many handles for each RoT Service */
+ node = tfm_spm_find_conn_handle_node(service, conn_handle);
+ if (!node) {
+ tfm_panic();
+ }
+
+ return node->rhandle;
+}
+
+/* Partition management functions */
+struct tfm_spm_service_t *
+tfm_spm_get_service_by_signal(struct tfm_spm_ipc_partition_t *partition,
+ psa_signal_t signal)
+{
+ struct tfm_list_node_t *node, *head;
+ struct tfm_spm_service_t *service;
+
+ TFM_ASSERT(partition);
+
+ if (tfm_list_is_empty(&partition->service_list)) {
+ tfm_panic();
+ }
+
+ head = &partition->service_list;
+ TFM_LIST_FOR_EACH(node, head) {
+ service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t, list);
+ if (service->service_db->signal == signal) {
+ return service;
+ }
+ }
+ return NULL;
+}
+
+struct tfm_spm_service_t *tfm_spm_get_service_by_sid(uint32_t sid)
+{
+ uint32_t i;
+ struct tfm_list_node_t *node, *head;
+ struct tfm_spm_service_t *service;
+
+ for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
+ /* Skip partition without IPC flag */
+ if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
+ SPM_PART_FLAG_IPC) == 0) {
+ continue;
+ }
+
+ if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
+ continue;
+ }
+
+ head = &g_spm_ipc_partition[i].service_list;
+ TFM_LIST_FOR_EACH(node, head) {
+ service = TFM_GET_CONTAINER_PTR(node, struct tfm_spm_service_t,
+ list);
+ if (service->service_db->sid == sid) {
+ return service;
+ }
+ }
+ }
+ return NULL;
+}
+
+struct tfm_spm_service_t *
+ tfm_spm_get_service_by_handle(psa_handle_t conn_handle)
+{
+ uint32_t i;
+ struct tfm_conn_handle_t *handle;
+ struct tfm_list_node_t *service_node, *service_head;
+ struct tfm_list_node_t *handle_node, *handle_head;
+ struct tfm_spm_service_t *service;
+
+ for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
+ /* Skip partition without IPC flag */
+ if ((tfm_spm_partition_get_flags(g_spm_ipc_partition[i].index) &
+ SPM_PART_FLAG_IPC) == 0) {
+ continue;
+ }
+
+ if (tfm_list_is_empty(&g_spm_ipc_partition[i].service_list)) {
+ continue;
+ }
+
+ service_head = &g_spm_ipc_partition[i].service_list;
+ TFM_LIST_FOR_EACH(service_node, service_head) {
+ service = TFM_GET_CONTAINER_PTR(service_node,
+ struct tfm_spm_service_t, list);
+ handle_head = &service->handle_list;
+ TFM_LIST_FOR_EACH(handle_node, handle_head) {
+ handle = TFM_GET_CONTAINER_PTR(handle_node,
+ struct tfm_conn_handle_t, list);
+ if (handle->handle == conn_handle) {
+ return service;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+struct tfm_spm_ipc_partition_t *
+ tfm_spm_get_partition_by_id(int32_t partition_id)
+{
+ uint32_t i;
+
+ for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
+ if (g_spm_ipc_partition[i].id == partition_id) {
+ return &g_spm_ipc_partition[i];
+ }
+ }
+ return NULL;
+}
+
+struct tfm_spm_ipc_partition_t *tfm_spm_get_running_partition(void)
+{
+ uint32_t spid;
+
+ spid = tfm_spm_partition_get_running_partition_id_ext();
+
+ return tfm_spm_get_partition_by_id(spid);
+}
+
+int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
+ uint32_t minor_version)
+{
+ TFM_ASSERT(service);
+
+ switch (service->service_db->minor_policy) {
+ case TFM_VERSION_POLICY_RELAXED:
+ if (minor_version < service->service_db->minor_version) {
+ return IPC_ERROR_VERSION;
+ }
+ break;
+ case TFM_VERSION_POLICY_STRICT:
+ if (minor_version != service->service_db->minor_version) {
+ return IPC_ERROR_VERSION;
+ }
+ break;
+ default:
+ return IPC_ERROR_VERSION;
+ }
+ return IPC_SUCCESS;
+}
+
+/* Message functions */
+struct tfm_msg_body_t *tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
+{
+ /*
+ * There may be one error handle passed by the caller in two conditions:
+ * 1. Not a valid message handle.
+ * 2. Handle between different Partitions. Partition A passes one handle
+ * belong to other Partitions and tries to access other's data.
+ * So, need do necessary checking to prevent those conditions.
+ */
+ struct tfm_msg_body_t *msg;
+ uint32_t partition_id;
+
+ msg = (struct tfm_msg_body_t *)msg_handle;
+ if (!msg) {
+ return NULL;
+ }
+
+ /*
+ * FixMe: For condition 1: using a magic number to define it's a message.
+ * It needs to be an enhancement to check the handle belong to service.
+ */
+ if (msg->magic != TFM_MSG_MAGIC) {
+ return NULL;
+ }
+
+ /* For condition 2: check if the partition ID is same */
+ partition_id = tfm_spm_partition_get_running_partition_id_ext();
+ if (partition_id != msg->service->partition->id) {
+ return NULL;
+ }
+
+ return msg;
+}
+
+struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
+ psa_handle_t handle,
+ uint32_t type, int32_t ns_caller,
+ psa_invec *invec, size_t in_len,
+ psa_outvec *outvec, size_t out_len,
+ psa_outvec *caller_outvec)
+{
+ struct tfm_msg_body_t *msg = NULL;
+ uint32_t i;
+
+ TFM_ASSERT(service);
+ TFM_ASSERT(!(invec == NULL && in_len != 0));
+ TFM_ASSERT(!(outvec == NULL && out_len != 0));
+ TFM_ASSERT(in_len <= PSA_MAX_IOVEC);
+ TFM_ASSERT(out_len <= PSA_MAX_IOVEC);
+ TFM_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
+
+ /* Get message buffer from message pool */
+ msg = (struct tfm_msg_body_t *)tfm_pool_alloc(msg_db_pool);
+ if (!msg) {
+ return NULL;
+ }
+
+ /* Clear message buffer before using it */
+ tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
+
+ tfm_event_init(&msg->ack_mtx, EVENT_STAT_WAITED);
+ msg->magic = TFM_MSG_MAGIC;
+ msg->service = service;
+ msg->handle = handle;
+ msg->caller_outvec = caller_outvec;
+ /* Get current partition id */
+ if (ns_caller) {
+ msg->msg.client_id = tfm_nspm_get_current_client_id();
+ } else {
+ msg->msg.client_id = tfm_spm_partition_get_running_partition_id_ext();
+ }
+
+ /* Copy contents */
+ msg->msg.type = type;
+
+ for (i = 0; i < in_len; i++) {
+ msg->msg.in_size[i] = invec[i].len;
+ msg->invec[i].base = invec[i].base;
+ }
+
+ for (i = 0; i < out_len; i++) {
+ msg->msg.out_size[i] = outvec[i].len;
+ msg->outvec[i].base = outvec[i].base;
+ /* Out len is used to record the writed number, set 0 here again */
+ msg->outvec[i].len = 0;
+ }
+
+ /* Use message address as handle */
+ msg->msg.handle = (psa_handle_t)msg;
+
+ /* For connected handle, set rhandle to every message */
+ if (handle != PSA_NULL_HANDLE) {
+ msg->msg.rhandle = tfm_spm_get_rhandle(service, handle);
+ }
+
+ return msg;
+}
+
+void tfm_spm_free_msg(struct tfm_msg_body_t *msg)
+{
+ tfm_pool_free(msg);
+}
+
+int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
+ struct tfm_msg_body_t *msg)
+{
+ TFM_ASSERT(service);
+ TFM_ASSERT(msg);
+
+ /* Enqueue message to service message queue */
+ if (tfm_msg_enqueue(&service->msg_queue, msg) != IPC_SUCCESS) {
+ return IPC_ERROR_GENERIC;
+ }
+
+ /* Messages put. Update signals */
+ service->partition->signals |= service->service_db->signal;
+
+ /* Save return value for blocked threads */
+ tfm_event_owner_retval(&service->partition->signal_event,
+ service->partition->signals &
+ service->partition->signal_mask);
+
+ /* Wake waiting thread up */
+ tfm_event_signal(&service->partition->signal_event);
+
+ tfm_event_wait(&msg->ack_mtx);
+
+ return IPC_SUCCESS;
+}
+
+/* SPM extend functions */
+uint32_t tfm_spm_partition_get_running_partition_id_ext(void)
+{
+ struct tfm_thrd_ctx *pth = tfm_thrd_curr_thread();
+ struct spm_partition_desc_t *partition;
+
+ partition = TFM_GET_CONTAINER_PTR(pth, struct spm_partition_desc_t,
+ sp_thrd);
+ return partition->static_data.partition_id;
+}
+
+static struct tfm_thrd_ctx *
+tfm_spm_partition_get_thread_info_ext(uint32_t partition_idx)
+{
+ return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
+}
+
+static uint32_t tfm_spm_partition_get_stack_base_ext(uint32_t partition_idx)
+{
+ return (uint32_t)&(g_spm_partition_db.partitions[partition_idx].
+ stack[TFM_STACK_SIZE]);
+}
+
+static uint32_t tfm_spm_partition_get_stack_limit_ext(uint32_t partition_idx)
+{
+ return (uint32_t)&g_spm_partition_db.partitions[partition_idx].stack;
+}
+
+static tfm_thrd_func_t
+ tfm_spm_partition_get_init_func_ext(uint32_t partition_idx)
+{
+ return (tfm_thrd_func_t)(g_spm_partition_db.partitions[partition_idx].
+ static_data.partition_init);
+}
+
+static uint32_t tfm_spm_partition_get_priority_ext(uint32_t partition_idx)
+{
+ return g_spm_partition_db.partitions[partition_idx].static_data.
+ partition_priority;
+}
+
+/* Macros to pick linker symbols and allow references to sections in all level*/
+#define REGION_DECLARE_EXT(a, b, c) extern uint32_t REGION_NAME(a, b, c)
+
+REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$ZI$$Base);
+REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$ZI$$Limit);
+REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$RW$$Base);
+REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$RW$$Limit);
+REGION_DECLARE_EXT(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
+REGION_DECLARE_EXT(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
+REGION_DECLARE_EXT(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+REGION_DECLARE_EXT(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+
+/*
+ * \brief Check the memory whether in the given range.
+ *
+ * \param[in] buffer Pointer of memory reference
+ * \param[in] len Length of memory reference in bytes
+ * \param[in] base The base address
+ * \param[in] limit The limit address, the first byte of next
+ * area memory
+ *
+ * \retval IPC_SUCCESS Success
+ * \retval IPC_ERROR_MEMORY_CHECK Check failed
+ */
+static int32_t memory_check_range(const void *buffer, size_t len,
+ uintptr_t base, uintptr_t limit)
+{
+ if (((uintptr_t)buffer >= base) &&
+ ((uintptr_t)((uint8_t *)buffer + len - 1) < limit)) {
+ return IPC_SUCCESS;
+ }
+ return IPC_ERROR_MEMORY_CHECK;
+}
+
+/* FixMe: This is only valid for TFM LVL 1 now */
+int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller)
+{
+ uintptr_t base, limit;
+
+ /* If len is zero, this indicates an empty buffer and base is ignored */
+ if (len == 0) {
+ return IPC_SUCCESS;
+ }
+
+ if (!buffer) {
+ return IPC_ERROR_BAD_PARAMETERS;
+ }
+
+ if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
+ return IPC_ERROR_MEMORY_CHECK;
+ }
+
+ if (ns_caller) {
+ base = (uintptr_t)NS_DATA_START;
+ limit = (uintptr_t)(NS_DATA_START + NS_DATA_SIZE);
+ if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
+ return IPC_SUCCESS;
+ }
+ } else {
+ base = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$RW$$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$RW$$Limit);
+ if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
+ return IPC_SUCCESS;
+ }
+
+ base = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$ZI$$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$ZI$$Limit);
+ if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
+ return IPC_SUCCESS;
+ }
+
+ base = (uintptr_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
+ if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
+ return IPC_SUCCESS;
+ }
+
+ base = (uintptr_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+ limit = (uintptr_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH,
+ $$ZI$$Limit);
+ if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
+ return IPC_SUCCESS;
+ }
+ }
+
+ return IPC_ERROR_MEMORY_CHECK;
+}
+
+/********************** SPM functions for thread mode ************************/
+
+void tfm_spm_init(void)
+{
+ uint32_t i, num;
+ struct tfm_spm_ipc_partition_t *partition;
+ struct tfm_spm_service_t *service;
+ struct tfm_thrd_ctx *pth;
+
+ tfm_pool_init(conn_handle_pool,
+ POOL_BUFFER_SIZE(conn_handle_pool),
+ sizeof(struct tfm_conn_handle_t),
+ TFM_CONN_HANDLE_MAX_NUM);
+ tfm_pool_init(spm_service_pool, POOL_BUFFER_SIZE(spm_service_pool),
+ sizeof(struct tfm_spm_service_t),
+ TFM_SPM_MAX_ROT_SERV_NUM);
+ tfm_pool_init(msg_db_pool, POOL_BUFFER_SIZE(msg_db_pool),
+ sizeof(struct tfm_msg_body_t),
+ TFM_MSG_QUEUE_MAX_MSG_NUM);
+
+ /* Init partition first for it will be used when init service */
+ for (i = 0; i < SPM_MAX_PARTITIONS; i++) {
+ if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) {
+ continue;
+ }
+ g_spm_ipc_partition[i].index = i;
+ g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
+ tfm_event_init(&g_spm_ipc_partition[i].signal_event, EVENT_STAT_WAITED);
+ tfm_list_init(&g_spm_ipc_partition[i].service_list);
+
+ pth = tfm_spm_partition_get_thread_info_ext(i);
+ if (!pth) {
+ tfm_panic();
+ }
+
+ tfm_thrd_init(pth,
+ tfm_spm_partition_get_init_func_ext(i),
+ NULL,
+ (uint8_t *)tfm_spm_partition_get_stack_base_ext(i),
+ (uint8_t *)tfm_spm_partition_get_stack_limit_ext(i));
+ pth->prior = tfm_spm_partition_get_priority_ext(i);
+
+ /* Kick off */
+ if (tfm_thrd_start(pth) != THRD_SUCCESS) {
+ tfm_panic();
+ }
+ }
+
+ /* Init Service */
+ num = sizeof(g_spm_service_db) / sizeof(struct tfm_spm_service_db_t);
+ for (i = 0; i < num; i++) {
+ partition =
+ tfm_spm_get_partition_by_id(g_spm_service_db[i].partition_id);
+ if (!partition) {
+ tfm_panic();
+ }
+ service = (struct tfm_spm_service_t *)tfm_pool_alloc(spm_service_pool);
+ if (!service) {
+ tfm_panic();
+ }
+ service->service_db = &g_spm_service_db[i];
+ service->partition = partition;
+ tfm_list_init(&service->handle_list);
+ tfm_list_add_tail(&partition->service_list, &service->list);
+ }
+
+ /* All thread inited.... trigger scheduler */
+ tfm_thrd_activate_schedule();
+}
diff --git a/secure_fw/core/ipc/tfm_svcalls.c b/secure_fw/core/ipc/tfm_svcalls.c
new file mode 100644
index 0000000..a566056
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_svcalls.c
@@ -0,0 +1,976 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "psa_client.h"
+#include "psa_service.h"
+#include "tfm_svc.h"
+#include "tfm_svcalls.h"
+#include "tfm_thread.h"
+#include "tfm_wait.h"
+#include "tfm_utils.h"
+#include "tfm_internal_defines.h"
+#include "tfm_message_queue.h"
+#include "tfm_spm.h"
+#include "tfm_api.h"
+#include "tfm_secure_api.h"
+#include "tfm_memory_utils.h"
+
+#define PSA_TIMEOUT_MASK PSA_BLOCK
+
+/************************* SVC handler for PSA Client APIs *******************/
+
+uint32_t tfm_svcall_psa_framework_version(void)
+{
+ return PSA_FRAMEWORK_VERSION;
+}
+
+uint32_t tfm_svcall_psa_version(uint32_t *args, int32_t ns_caller)
+{
+ uint32_t sid;
+ struct tfm_spm_service_t *service;
+
+ TFM_ASSERT(args != NULL);
+ sid = (uint32_t)args[0];
+ /*
+ * It should return PSA_VERSION_NONE if the RoT Service is not
+ * implemented.
+ */
+ service = tfm_spm_get_service_by_sid(sid);
+ if (!service) {
+ return PSA_VERSION_NONE;
+ }
+
+ /*
+ * It should return PSA_VERSION_NONE if the caller is not authorized
+ * to access the RoT Service.
+ */
+ if (ns_caller && !service->service_db->non_secure_client) {
+ return PSA_VERSION_NONE;
+ }
+
+ return service->service_db->minor_version;
+}
+
+psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller)
+{
+ uint32_t sid;
+ uint32_t minor_version;
+ struct tfm_spm_service_t *service;
+ struct tfm_msg_body_t *msg;
+
+ TFM_ASSERT(args != NULL);
+ sid = (uint32_t)args[0];
+ minor_version = (uint32_t)args[1];
+
+ /* It is a fatal error if the RoT Service does not exist on the platform */
+ service = tfm_spm_get_service_by_sid(sid);
+ if (!service) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the caller is not authorized to access the RoT
+ * Service.
+ */
+ if (ns_caller && !service->service_db->non_secure_client) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the version of the RoT Service requested is not
+ * supported on the platform.
+ */
+ if (tfm_spm_check_client_version(service, minor_version) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+
+ /* No input or output needed for connect message */
+ msg = tfm_spm_create_msg(service, PSA_NULL_HANDLE, PSA_IPC_CONNECT,
+ ns_caller, NULL, 0, NULL, 0, NULL);
+ if (!msg) {
+ return PSA_NULL_HANDLE;
+ }
+
+ /*
+ * Send message and wake up the SP who is waiting on message queue,
+ * and scheduler triggered
+ */
+ tfm_spm_send_event(service, msg);
+
+ return PSA_NULL_HANDLE;
+}
+
+psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller)
+{
+ psa_handle_t handle;
+ psa_invec *inptr, invecs[PSA_MAX_IOVEC];
+ psa_outvec *outptr, outvecs[PSA_MAX_IOVEC];
+ size_t in_num, out_num;
+ struct tfm_spm_service_t *service;
+ struct tfm_msg_body_t *msg;
+ int i;
+
+ TFM_ASSERT(args != NULL);
+ handle = (psa_handle_t)args[0];
+ if (!ns_caller) {
+ inptr = (psa_invec *)args[1];
+ in_num = (size_t)args[2];
+ outptr = (psa_outvec *)args[3];
+ /*
+ * FixMe: 5th parameter is pushed at stack top before SVC; plus
+ * exception stacked contents, 5th parameter is now at 8th position
+ * in SVC handler. However, if thread mode applies FloatPoint, then
+ * FloatPoint context is pushed into stack and then 5th parameter
+ * will not be args[8].
+ * Will refine it later.
+ */
+ out_num = (size_t)args[8];
+ } else {
+ /*
+ * FixMe: From non-secure caller, vec and len are composed into a new
+ * struct parameter. Need to extract them.
+ */
+ if (tfm_memory_check((void *)args[1], sizeof(uint32_t),
+ ns_caller) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+ if (tfm_memory_check((void *)args[2], sizeof(uint32_t),
+ ns_caller) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+
+ inptr = (psa_invec *)((psa_invec *)args[1])->base;
+ in_num = ((psa_invec *)args[1])->len;
+ outptr = (psa_outvec *)((psa_invec *)args[2])->base;
+ out_num = ((psa_invec *)args[2])->len;
+ }
+
+ /* It is a fatal error if in_len + out_len > PSA_MAX_IOVEC. */
+ if (in_num + out_num > PSA_MAX_IOVEC) {
+ tfm_panic();
+ }
+
+ /* It is a fatal error if an invalid handle was passed. */
+ service = tfm_spm_get_service_by_handle(handle);
+ if (!service) {
+ /* FixMe: Need to implement one mechanism to resolve this failure. */
+ tfm_panic();
+ }
+
+ /* It is a fatal error if an invalid memory reference was provide. */
+ if (tfm_memory_check((void *)inptr, in_num * sizeof(psa_invec),
+ ns_caller) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+ if (tfm_memory_check((void *)outptr, out_num * sizeof(psa_outvec),
+ ns_caller) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+
+ tfm_memset(invecs, 0, sizeof(invecs));
+ tfm_memset(outvecs, 0, sizeof(outvecs));
+
+ /* Copy the address out to avoid TOCTOU attacks. */
+ tfm_memcpy(invecs, inptr, in_num * sizeof(psa_invec));
+ tfm_memcpy(outvecs, outptr, out_num * sizeof(psa_outvec));
+
+ /*
+ * It is a fatal error if an invalid payload memory reference
+ * was provided.
+ */
+ for (i = 0; i < in_num; i++) {
+ if (tfm_memory_check((void *)invecs[i].base, invecs[i].len,
+ ns_caller) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+ }
+ for (i = 0; i < out_num; i++) {
+ if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
+ ns_caller) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+ }
+
+ /*
+ * FixMe: Need to check if the message is unrecognized by the RoT
+ * Service or incorrectly formatted.
+ */
+ msg = tfm_spm_create_msg(service, handle, PSA_IPC_CALL, ns_caller, invecs,
+ in_num, outvecs, out_num, outptr);
+ if (!msg) {
+ /* FixMe: Need to implement one mechanism to resolve this failure. */
+ tfm_panic();
+ }
+
+ /*
+ * Send message and wake up the SP who is waiting on message queue,
+ * and scheduler triggered
+ */
+ if (tfm_spm_send_event(service, msg) != IPC_SUCCESS) {
+ /* FixMe: Need to refine failure process here. */
+ tfm_panic();
+ }
+ return PSA_SUCCESS;
+}
+
+void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller)
+{
+ psa_handle_t handle;
+ struct tfm_spm_service_t *service;
+ struct tfm_msg_body_t *msg;
+
+ TFM_ASSERT(args != NULL);
+ handle = args[0];
+ /* It will have no effect if called with the NULL handle */
+ if (handle == PSA_NULL_HANDLE) {
+ return;
+ }
+
+ /*
+ * It is a fatal error if an invalid handle was provided that is not the
+ * null handle..
+ */
+ service = tfm_spm_get_service_by_handle(handle);
+ if (!service) {
+ /* FixMe: Need to implement one mechanism to resolve this failure. */
+ tfm_panic();
+ }
+
+ /* No input or output needed for close message */
+ msg = tfm_spm_create_msg(service, handle, PSA_IPC_DISCONNECT, ns_caller,
+ NULL, 0, NULL, 0, NULL);
+ if (!msg) {
+ /* FixMe: Need to implement one mechanism to resolve this failure. */
+ return;
+ }
+
+ /*
+ * Send message and wake up the SP who is waiting on message queue,
+ * and scheduler triggered
+ */
+ tfm_spm_send_event(service, msg);
+}
+
+/*********************** SVC handler 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.
+ */
+static psa_signal_t tfm_svcall_psa_wait(uint32_t *args)
+{
+ psa_signal_t signal_mask;
+ uint32_t timeout;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
+
+ TFM_ASSERT(args != NULL);
+ signal_mask = (psa_signal_t)args[0];
+ timeout = args[1];
+
+ /*
+ * Timeout[30:0] are reserved for future use.
+ * SPM must ignore the value of RES.
+ */
+ timeout &= PSA_TIMEOUT_MASK;
+
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_panic();
+ }
+
+ /*
+ * Expected signals are included in signal wait mask, ignored signals
+ * should not be set and affect caller thread status. Save this mask for
+ * further checking while signals are ready to be set.
+ */
+ partition->signal_mask = signal_mask;
+
+ /*
+ * tfm_event_wait() blocks the caller thread if no signals are available.
+ * In this case, the return value of this function is temporary set into
+ * runtime context. After new signal(s) are available, the return value
+ * is updated with the available signal(s) and blocked thread gets to run.
+ */
+ if ((timeout == PSA_BLOCK) && ((partition->signals & signal_mask) == 0)) {
+ tfm_event_wait(&partition->signal_event);
+ }
+
+ return partition->signals & signal_mask;
+}
+
+/**
+ * \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_ERR_NOMSG 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 a RoT Service.
+ * \arg The RoT Service signal is not currently
+ * asserted.
+ * \arg The msg pointer provided is not a valid memory
+ * reference.
+ */
+static psa_status_t tfm_svcall_psa_get(uint32_t *args)
+{
+ psa_signal_t signal;
+ psa_msg_t *msg = NULL;
+ struct tfm_spm_service_t *service = NULL;
+ struct tfm_msg_body_t *tmp_msg = NULL;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
+
+ TFM_ASSERT(args != NULL);
+ signal = (psa_signal_t)args[0];
+ msg = (psa_msg_t *)args[1];
+
+ /*
+ * Only one message could be retrieved every time for psa_get(). It is a
+ * fatal error if the input signal has more than a signal bit set.
+ */
+ if (tfm_bitcount(signal) != 1) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the input msg pointer is not a valid memory
+ * reference.
+ */
+ if (tfm_memory_check((void *)msg, sizeof(psa_msg_t),
+ false) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the caller call psa_get() when no message has
+ * been set. The caller must call this function after a RoT Service signal
+ * is returned by psa_wait().
+ */
+ if (partition->signals == 0) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the RoT Service signal is not currently asserted.
+ */
+ if ((partition->signals & signal) == 0) {
+ tfm_panic();
+ }
+
+ /*
+ * Get Rot service by signal from partition. It is a fatal error if geting
+ * failed which mean the input signal is not correspond to a RoT service.
+ */
+ service = tfm_spm_get_service_by_signal(partition, signal);
+ if (!service) {
+ tfm_panic();
+ }
+
+ tmp_msg = tfm_msg_dequeue(&service->msg_queue);
+ if (!tmp_msg) {
+ return PSA_ERR_NOMSG;
+ }
+
+ tfm_memcpy(msg, &tmp_msg->msg, sizeof(psa_msg_t));
+
+ /*
+ * There may be mutiple messages for this RoT Service signal, do not clear
+ * its mask until no remaining message.
+ */
+ if (tfm_msg_queue_is_empty(&service->msg_queue)) {
+ partition->signals &= ~signal;
+ }
+
+ return PSA_SUCCESS;
+}
+
+/**
+ * \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.
+ */
+static void tfm_svcall_psa_set_rhandle(uint32_t *args)
+{
+ psa_handle_t msg_handle;
+ void *rhandle = NULL;
+ struct tfm_msg_body_t *msg = NULL;
+
+ TFM_ASSERT(args != NULL);
+ msg_handle = (psa_handle_t)args[0];
+ rhandle = (void *)args[1];
+
+ /* It is a fatal error if message handle is invalid */
+ msg = tfm_spm_get_msg_from_handle(msg_handle);
+ if (!msg) {
+ tfm_panic();
+ }
+
+ /*
+ * Connection handle is not created while SP is processing PSA_IPC_CONNECT
+ * message. Store reverse handle temporarily and re-set it after the
+ * connection created.
+ */
+ if (msg->handle != PSA_NULL_HANDLE) {
+ tfm_spm_set_rhandle(msg->service, msg->handle, rhandle);
+ } else {
+ msg->msg.rhandle = rhandle;
+ }
+}
+
+/**
+ * \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
+ * \ref PSA_IPC_CALL 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.
+ */
+static size_t tfm_svcall_psa_read(uint32_t *args)
+{
+ psa_handle_t msg_handle;
+ uint32_t invec_idx;
+ void *buffer = NULL;
+ size_t num_bytes;
+ size_t bytes;
+ struct tfm_msg_body_t *msg = NULL;
+
+ TFM_ASSERT(args != NULL);
+ msg_handle = (psa_handle_t)args[0];
+ invec_idx = args[1];
+ buffer = (void *)args[2];
+ num_bytes = (size_t)args[3];
+
+ /* It is a fatal error if message handle is invalid */
+ msg = tfm_spm_get_msg_from_handle(msg_handle);
+ if (!msg) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if message handle does not refer to a PSA_IPC_CALL
+ * message
+ */
+ if (msg->msg.type != PSA_IPC_CALL) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if invec_idx is equal to or greater than
+ * PSA_MAX_IOVEC
+ */
+ if (invec_idx >= PSA_MAX_IOVEC) {
+ tfm_panic();
+ }
+
+ /* There was no remaining data in this input vector */
+ if (msg->msg.in_size[invec_idx] == 0) {
+ return 0;
+ }
+
+ /*
+ * It is a fatal error if the memory reference for buffer is invalid or
+ * not writable
+ */
+ /* FixMe: write permission check to be added */
+ if (tfm_memory_check(buffer, num_bytes, false) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+
+ bytes = num_bytes > msg->msg.in_size[invec_idx] ?
+ msg->msg.in_size[invec_idx] : num_bytes;
+
+ tfm_memcpy(buffer, msg->invec[invec_idx].base, bytes);
+
+ /* There maybe some remaining data */
+ msg->invec[invec_idx].base += bytes;
+ msg->msg.in_size[invec_idx] -= bytes;
+
+ return bytes;
+}
+
+/**
+ * \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
+ * \ref PSA_IPC_CALL message.
+ * \arg invec_idx is equal to or greater than
+ * \ref PSA_MAX_IOVEC.
+ */
+static size_t tfm_svcall_psa_skip(uint32_t *args)
+{
+ psa_handle_t msg_handle;
+ uint32_t invec_idx;
+ size_t num_bytes;
+ struct tfm_msg_body_t *msg = NULL;
+
+ TFM_ASSERT(args != NULL);
+ msg_handle = (psa_handle_t)args[0];
+ invec_idx = args[1];
+ num_bytes = (size_t)args[2];
+
+ /* It is a fatal error if message handle is invalid */
+ msg = tfm_spm_get_msg_from_handle(msg_handle);
+ if (!msg) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if message handle does not refer to a PSA_IPC_CALL
+ * message
+ */
+ if (msg->msg.type != PSA_IPC_CALL) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if invec_idx is equal to or greater than
+ * PSA_MAX_IOVEC
+ */
+ if (invec_idx >= PSA_MAX_IOVEC) {
+ tfm_panic();
+ }
+
+ /* There was no remaining data in this input vector */
+ if (msg->msg.in_size[invec_idx] == 0) {
+ return 0;
+ }
+
+ /*
+ * If num_bytes is greater than the remaining size of the input vector then
+ * the remaining size of the input vector is used.
+ */
+ if (num_bytes > msg->msg.in_size[invec_idx]) {
+ num_bytes = msg->msg.in_size[invec_idx];
+ }
+
+ /* There maybe some remaining data */
+ msg->invec[invec_idx].base += num_bytes;
+ msg->msg.in_size[invec_idx] -= num_bytes;
+
+ return num_bytes;
+}
+
+/**
+ * \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
+ * \ref PSA_IPC_CALL 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.
+ */
+static void tfm_svcall_psa_write(uint32_t *args)
+{
+ psa_handle_t msg_handle;
+ uint32_t outvec_idx;
+ void *buffer = NULL;
+ size_t num_bytes;
+ struct tfm_msg_body_t *msg = NULL;
+
+ TFM_ASSERT(args != NULL);
+ msg_handle = (psa_handle_t)args[0];
+ outvec_idx = args[1];
+ buffer = (void *)args[2];
+ num_bytes = (size_t)args[3];
+
+ /* It is a fatal error if message handle is invalid */
+ msg = tfm_spm_get_msg_from_handle(msg_handle);
+ if (!msg) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if message handle does not refer to a PSA_IPC_CALL
+ * message
+ */
+ if (msg->msg.type != PSA_IPC_CALL) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if outvec_idx is equal to or greater than
+ * PSA_MAX_IOVEC
+ */
+ if (outvec_idx >= PSA_MAX_IOVEC) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the call attempts to write data past the end of
+ * the client output vector
+ */
+ if (num_bytes > msg->msg.out_size[outvec_idx] -
+ msg->outvec[outvec_idx].len) {
+ tfm_panic();
+ }
+
+ /* It is a fatal error if the memory reference for buffer is valid */
+ if (tfm_memory_check(buffer, num_bytes, false) != IPC_SUCCESS) {
+ tfm_panic();
+ }
+
+ tfm_memcpy(msg->outvec[outvec_idx].base + msg->outvec[outvec_idx].len,
+ buffer, num_bytes);
+
+ /* Update the write number */
+ msg->outvec[outvec_idx].len += num_bytes;
+}
+
+static void update_caller_outvec_len(struct tfm_msg_body_t *msg)
+{
+ int32_t i = 0;
+
+ /*
+ * FixeMe: abstract these part into dedicated functions to avoid
+ * accessing thread context in psa layer
+ */
+ TFM_ASSERT(msg->ack_mtx.owner->status == THRD_STAT_BLOCK);
+
+ while (msg->msg.out_size[i] != 0) {
+ TFM_ASSERT(msg->caller_outvec[i].base == msg->outvec[i].base);
+ msg->caller_outvec[i].len = msg->outvec[i].len;
+ i++;
+ }
+}
+/**
+ * \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.
+ */
+static void tfm_svcall_psa_reply(uint32_t *args)
+{
+ psa_handle_t msg_handle;
+ psa_status_t status;
+ struct tfm_spm_service_t *service = NULL;
+ struct tfm_msg_body_t *msg = NULL;
+ psa_handle_t connect_handle;
+ int32_t ret = PSA_SUCCESS;
+
+ TFM_ASSERT(args != NULL);
+ msg_handle = (psa_handle_t)args[0];
+ status = (psa_status_t)args[1];
+
+ /* It is a fatal error if message handle is invalid */
+ msg = tfm_spm_get_msg_from_handle(msg_handle);
+ if (!msg) {
+ tfm_panic();
+ }
+
+ /*
+ * RoT Service information is needed in this function, stored it in message
+ * body structure. Only two parameters are passed in this function: handle
+ * and status, so it is useful and simply to do like this.
+ */
+ service = msg->service;
+ if (!service) {
+ tfm_panic();
+ }
+
+ /*
+ * Three type of message are passed in this function: CONNECT, CALL,
+ * DISCONNECT. It needs to process differently for each type.
+ */
+ switch (msg->msg.type) {
+ case PSA_IPC_CONNECT:
+ /*
+ * Reply to PSA_IPC_CONNECT message. Connect handle is created if the
+ * input status is PSA_SUCCESS. Others return values are based on the
+ * input status.
+ */
+ if (status == PSA_SUCCESS) {
+ connect_handle = tfm_spm_create_conn_handle(service);
+ if (connect_handle == PSA_NULL_HANDLE) {
+ tfm_panic();
+ }
+ ret = connect_handle;
+
+ /* Set reverse handle after connection created if needed. */
+ if (msg->msg.rhandle) {
+ tfm_spm_set_rhandle(service, connect_handle, msg->msg.rhandle);
+ }
+ } else if (status == PSA_CONNECTION_REFUSED) {
+ ret = PSA_CONNECTION_REFUSED;
+ } else if (status == PSA_CONNECTION_BUSY) {
+ ret = PSA_CONNECTION_BUSY;
+ } else {
+ tfm_panic();
+ }
+ break;
+ case PSA_IPC_CALL:
+ /* Reply to PSA_IPC_CALL message. Return values are based on status */
+ if (status == PSA_SUCCESS) {
+ ret = PSA_SUCCESS;
+ } else if (status == PSA_DROP_CONNECTION) {
+ ret = PSA_DROP_CONNECTION;
+ } else if ((status >= (INT32_MIN + 1)) &&
+ (status <= (INT32_MIN + 127))) {
+ tfm_panic();
+ } else if ((status >= (INT32_MIN + 128)) && (status <= -1)) {
+ ret = status;
+ } else if ((status >= 1) && (status <= INT32_MAX)) {
+ ret = status;
+ } else {
+ tfm_panic();
+ }
+
+ /*
+ * The total number of bytes written to a single parameter must be
+ * reported to the client by updating the len member of the psa_outvec
+ * structure for the parameter before returning from psa_call().
+ */
+ update_caller_outvec_len(msg);
+ break;
+ case PSA_IPC_DISCONNECT:
+ /* Service handle is not used anymore */
+ tfm_spm_free_conn_handle(service, msg->handle);
+
+ /*
+ * If the message type is PSA_IPC_DISCONNECT, then the status code is
+ * ignored
+ */
+ break;
+ default:
+ tfm_panic();
+ }
+
+ /* Save return value for blocked threads */
+ tfm_event_owner_retval(&msg->ack_mtx, ret);
+
+ /* Wake waiting thread up */
+ tfm_event_signal(&msg->ack_mtx);
+
+ /* Message should not be unsed anymore */
+ tfm_spm_free_msg(msg);
+}
+
+/**
+ * \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.
+ */
+static void tfm_svcall_psa_notify(uint32_t *args)
+{
+ int32_t partition_id;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
+
+ TFM_ASSERT(args != NULL);
+ partition_id = (int32_t)args[0];
+
+ /*
+ * The value of partition_id must be greater than zero as the target of
+ * notification must be a Secure Partition, providing a Non-secure
+ * Partition ID is a fatal error.
+ */
+ if (!TFM_CLIENT_ID_IS_S(partition_id)) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if partition_id does not correspond to a Secure
+ * Partition.
+ */
+ partition = tfm_spm_get_partition_by_id(partition_id);
+ if (!partition) {
+ tfm_panic();
+ }
+
+ partition->signals |= PSA_DOORBELL;
+
+ /*
+ * The target partition may be blocked with waiting for signals after
+ * called psa_wait(). Set the return value with the available signals
+ * before wake it up with tfm_event_signal().
+ */
+ tfm_event_owner_retval(&partition->signal_event,
+ partition->signals & partition->signal_mask);
+
+ /* Wake waiting thread up */
+ tfm_event_signal(&partition->signal_event);
+}
+
+/**
+ * \brief SVC handler for \ref psa_clear.
+ *
+ * \retval void Success.
+ * \retval "Does not return" The Secure Partition's doorbell signal is not
+ * currently asserted.
+ */
+static void tfm_svcall_psa_clear(uint32_t *args)
+{
+ struct tfm_spm_ipc_partition_t *partition = NULL;
+
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_panic();
+ }
+
+ /*
+ * It is a fatal error if the Secure Partition's doorbell signal is not
+ * currently asserted.
+ */
+ if ((partition->signals & PSA_DOORBELL) == 0) {
+ tfm_panic();
+ }
+ partition->signals &= ~PSA_DOORBELL;
+}
+
+/**
+ * \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.
+ */
+static void tfm_svcall_psa_eoi(uint32_t *args)
+{
+ psa_signal_t irq_signal;
+ struct tfm_spm_ipc_partition_t *partition = NULL;
+
+ TFM_ASSERT(args != NULL);
+ irq_signal = (psa_signal_t)args[0];
+
+ partition = tfm_spm_get_running_partition();
+ if (!partition) {
+ tfm_panic();
+ }
+
+ /*
+ * FixMe: It is a fatal error if passed signal is not an interrupt signal.
+ */
+
+ /* It is a fatal error if passed signal indicates more than one signals. */
+ if (tfm_bitcount(partition->signals) != 1) {
+ tfm_panic();
+ }
+
+ /* It is a fatal error if passed signal is not currently asserted */
+ if ((partition->signals & irq_signal) == 0) {
+ tfm_panic();
+ }
+
+ partition->signals &= ~irq_signal;
+
+ /* FixMe: re-enable interrupt */
+}
+
+int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx)
+{
+ switch (svc_num) {
+ case TFM_SVC_SCHEDULE:
+ tfm_thrd_activate_schedule();
+ break;
+ case TFM_SVC_PSA_FRAMEWORK_VERSION:
+ return tfm_svcall_psa_framework_version();
+ case TFM_SVC_PSA_VERSION:
+ return tfm_svcall_psa_version(ctx, 0);
+ case TFM_SVC_PSA_CONNECT:
+ return tfm_svcall_psa_connect(ctx, 0);
+ case TFM_SVC_PSA_CALL:
+ return tfm_svcall_psa_call(ctx, 0);
+ case TFM_SVC_PSA_CLOSE:
+ tfm_svcall_psa_close(ctx, 0);
+ break;
+ case TFM_SVC_PSA_WAIT:
+ return tfm_svcall_psa_wait(ctx);
+ case TFM_SVC_PSA_GET:
+ return tfm_svcall_psa_get(ctx);
+ case TFM_SVC_PSA_SET_RHANDLE:
+ tfm_svcall_psa_set_rhandle(ctx);
+ break;
+ case TFM_SVC_PSA_READ:
+ return tfm_svcall_psa_read(ctx);
+ case TFM_SVC_PSA_SKIP:
+ return tfm_svcall_psa_skip(ctx);
+ case TFM_SVC_PSA_WRITE:
+ tfm_svcall_psa_write(ctx);
+ break;
+ case TFM_SVC_PSA_REPLY:
+ tfm_svcall_psa_reply(ctx);
+ break;
+ case TFM_SVC_PSA_NOTIFY:
+ tfm_svcall_psa_notify(ctx);
+ break;
+ case TFM_SVC_PSA_CLEAR:
+ tfm_svcall_psa_clear(ctx);
+ break;
+ case TFM_SVC_PSA_EOI:
+ tfm_svcall_psa_eoi(ctx);
+ break;
+ default:
+ break;
+ }
+ return PSA_SUCCESS;
+}
diff --git a/secure_fw/core/ipc/tfm_thread.c b/secure_fw/core/ipc/tfm_thread.c
new file mode 100644
index 0000000..cd01259
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_thread.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_arch_v8m.h"
+#include "tfm_thread.h"
+#include "tfm_utils.h"
+#include "tfm_memory_utils.h"
+
+/* Force ZERO in case ZI(bss) clear is missing */
+static struct tfm_thrd_ctx *p_thrd_head = NULL;
+static struct tfm_thrd_ctx *p_runn_head = NULL;
+static struct tfm_thrd_ctx *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_thrd_ctx *find_next_running_thread(struct tfm_thrd_ctx *pth)
+{
+ while (pth && pth->status != THRD_STAT_RUNNING) {
+ pth = pth->next;
+ }
+
+ return pth;
+}
+
+/* To get next running thread for scheduler */
+struct tfm_thrd_ctx *tfm_thrd_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_thrd_ctx *tfm_thrd_curr_thread()
+{
+ return CURR_THRD;
+}
+
+/* Insert a new thread into list by descending priority (Highest at head) */
+static void insert_by_prior(struct tfm_thrd_ctx **head,
+ struct tfm_thrd_ctx *node)
+{
+ if (*head == NULL || (node->prior <= (*head)->prior)) {
+ node->next = *head;
+ *head = node;
+ } else {
+ struct tfm_thrd_ctx *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_thrd_ctx **runn,
+ struct tfm_thrd_ctx *node)
+{
+ if ((node->status == THRD_STAT_RUNNING) &&
+ (*runn == NULL || (node->prior < (*runn)->prior))) {
+ *runn = node;
+ } else {
+ *runn = find_next_running_thread(LIST_HEAD);
+ }
+}
+
+/* Set context members only. No validation here */
+void tfm_thrd_init(struct tfm_thrd_ctx *pth,
+ tfm_thrd_func_t pfn, void *param,
+ uint8_t *sp_base, uint8_t *sp_top)
+{
+ pth->prior = THRD_PRIOR_MEDIUM;
+ pth->status = THRD_STAT_CREATING;
+ pth->pfn = pfn;
+ pth->param = param;
+ pth->sp_base = sp_base;
+ pth->sp_top = sp_top;
+}
+
+uint32_t tfm_thrd_start(struct tfm_thrd_ctx *pth)
+{
+ /* Validate parameters before really start */
+ if ((pth->status != THRD_STAT_CREATING) ||
+ (pth->pfn == NULL) ||
+ (pth->sp_base == NULL) ||
+ (pth->sp_top == NULL)) {
+ return THRD_ERR_INVALID_PARAM;
+ }
+
+ /* Thread management runs in handler mode; set context for thread mode. */
+ tfm_initialize_context(&pth->state_ctx,
+ (uint32_t)pth->param, (uint32_t)pth->pfn,
+ (uint32_t)pth->sp_base, (uint32_t)pth->sp_top);
+
+ /* Insert a new thread with priority */
+ insert_by_prior(&LIST_HEAD, pth);
+
+ /* Mark it as RUNNING after insertion */
+ tfm_thrd_set_status(pth, THRD_STAT_RUNNING);
+
+ return THRD_SUCCESS;
+}
+
+void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status)
+{
+ TFM_ASSERT(pth != NULL && new_status < THRD_STAT_INVALID);
+
+ pth->status = new_status;
+ update_running_head(&RUNN_HEAD, pth);
+}
+
+/*
+ * TEMP WORKAROUND: The caller function who called thread module init needs to
+ * be returned. The caller is not a thread. Create a dummy IDLE thread to
+ * collect caller context; and schedule back to the caller with this context
+ * after all other real threads blocked.
+ *
+ * This WORKAROUND needs to be removed after IPC NSPM takes place.
+ */
+#define DUMMY_IDLE_TAG 0xDEEDDEED
+static uint8_t idle_stack[32] __attribute__((aligned(8)));
+static struct tfm_thrd_ctx idle_thread;
+static struct tfm_thrd_ctx *init_idle_thread(struct tfm_thrd_ctx *pth)
+{
+ /*
+ * IDLE thread is a thread with the lowest priority.
+ * It gets scheduled after all other higher priority threads get blocked.
+ * The entry of IDLE thread is a dummy and has no mean.
+ */
+ tfm_thrd_init(pth, (tfm_thrd_func_t)DUMMY_IDLE_TAG, NULL,
+ (uint8_t *)&idle_stack[32], (uint8_t *)idle_stack);
+ tfm_thrd_priority(pth, THRD_PRIOR_LOWEST);
+ tfm_thrd_start(pth);
+ return pth;
+}
+
+/* Scheduling won't happen immediately but after the exception returns */
+void tfm_thrd_activate_schedule(void)
+{
+ /*
+ * The current thread can be NULL only when initializing. Create the IDLE
+ * thread and set it as the current thread to collect caller context.
+ */
+ if (CURR_THRD == NULL) {
+ CURR_THRD = init_idle_thread(&idle_thread);
+ }
+
+ tfm_trigger_pendsv();
+}
+
+/* Remove current thread out of the schedulable list */
+void tfm_thrd_do_exit(void)
+{
+ CURR_THRD->status = THRD_STAT_DETACH;
+ tfm_trigger_pendsv();
+}
+
+void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb,
+ struct tfm_thrd_ctx *prev,
+ struct tfm_thrd_ctx *next)
+{
+ /* Update latest context into the current thread context */
+ tfm_memcpy(&prev->state_ctx.ctxb, ctxb, sizeof(*ctxb));
+ /* Update background context with next thread's context */
+ tfm_memcpy(ctxb, &next->state_ctx.ctxb, sizeof(next->state_ctx.ctxb));
+ /* Set current thread indicator with next thread */
+ CURR_THRD = next;
+}
+
+/*
+ * This function is a reference implementation for PendSV handler in
+ * isolation level 1. More jobs (sandboxing e.g.) need to be done while
+ * scheduling in other isolation levels.
+ */
+void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb)
+{
+ struct tfm_thrd_ctx *pth = tfm_thrd_next_thread();
+
+ /* Swith context if another thread ready to run */
+ if (pth && pth != CURR_THRD) {
+ tfm_thrd_context_switch(ctxb, CURR_THRD, pth);
+ }
+}
diff --git a/secure_fw/core/ipc/tfm_utils.c b/secure_fw/core/ipc/tfm_utils.c
new file mode 100644
index 0000000..1586633
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_utils.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_utils.h"
+
+void tfm_panic(void)
+{
+ while (1)
+ ;
+}
+
+int32_t tfm_bitcount(uint32_t n)
+{
+ int32_t count = 0;
+ uint8_t tmp;
+
+ while (n) {
+ tmp = n & 0xFF;
+ while (tmp) {
+ count += tmp & 0x1;
+ tmp >>= 1;
+ }
+ n >>= 8;
+ }
+
+ return count;
+}
diff --git a/secure_fw/core/ipc/tfm_wait.c b/secure_fw/core/ipc/tfm_wait.c
new file mode 100644
index 0000000..814ec89
--- /dev/null
+++ b/secure_fw/core/ipc/tfm_wait.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include "tfm_arch_v8m.h"
+#include "tfm_thread.h"
+#include "tfm_utils.h"
+#include "tfm_wait.h"
+
+void tfm_event_wait(struct tfm_event_ctx *pevt)
+{
+ struct tfm_thrd_ctx *curr_thrd = tfm_thrd_curr_thread();
+
+ TFM_ASSERT(pevt && pevt->magic == EVENT_MAGIC);
+
+ if (pevt->status == EVENT_STAT_WAITED) {
+ pevt->owner = curr_thrd;
+ pevt->retval = TFM_STATE_1ST_ARG(&pevt->owner->state_ctx);
+ tfm_thrd_set_status(pevt->owner, THRD_STAT_BLOCK);
+ tfm_thrd_activate_schedule();
+ }
+
+ pevt->status = EVENT_STAT_WAITED;
+}
+
+/* Peek the status to see if caller would block. */
+uint32_t tfm_event_peek(struct tfm_event_ctx *pevt)
+{
+ TFM_ASSERT(pevt && pevt->magic == EVENT_MAGIC);
+
+ return pevt->status;
+}
+
+void tfm_event_signal(struct tfm_event_ctx *pevt)
+{
+ TFM_ASSERT(pevt && pevt->magic == EVENT_MAGIC);
+
+ pevt->status = EVENT_STAT_SIGNALED;
+
+ /*
+ * Wake the blocked owner up and keep the status as EVENT_STAT_WAITED
+ * if there is an owner. Or the second event wait caller will return
+ * without block since status is EVENT_STAT_SIGNALED.
+ */
+ if (pevt->owner && pevt->owner->status == THRD_STAT_BLOCK) {
+ tfm_thrd_set_status(pevt->owner, THRD_STAT_RUNNING);
+ tfm_thrd_set_retval(pevt->owner, pevt->retval);
+ pevt->status = EVENT_STAT_WAITED;
+ tfm_thrd_activate_schedule();
+ }
+}
+
+void tfm_event_owner_retval(struct tfm_event_ctx *pmtx, uint32_t retval)
+{
+ TFM_ASSERT(pmtx && pmtx->magic == EVENT_MAGIC);
+
+ pmtx->retval = retval;
+}
diff --git a/secure_fw/core/tfm_core.c b/secure_fw/core/tfm_core.c
index 81eeccd..7cf6508 100644
--- a/secure_fw/core/tfm_core.c
+++ b/secure_fw/core/tfm_core.c
@@ -15,6 +15,14 @@
#include "secure_utilities.h"
#include "secure_fw/spm/spm_api.h"
#include "secure_fw/include/tfm_spm_services_api.h"
+#ifdef TFM_PSA_API
+#include "psa_client.h"
+#include "psa_service.h"
+#include "tfm_thread.h"
+#include "tfm_wait.h"
+#include "tfm_message_queue.h"
+#include "tfm_spm.h"
+#endif
/*
* Avoids the semihosting issue
@@ -165,6 +173,10 @@
*/
}
+#ifdef TFM_PSA_API
+ tfm_spm_init();
+#endif
+
#ifdef TFM_CORE_DEBUG
/* Jumps to non-secure code */
LOG_MSG("Jumping to non-secure code...");
diff --git a/secure_fw/core/tfm_handler.c b/secure_fw/core/tfm_handler.c
index ee59ea1..15965bf 100644
--- a/secure_fw/core/tfm_handler.c
+++ b/secure_fw/core/tfm_handler.c
@@ -17,11 +17,18 @@
#include "tfm_api.h"
#include "tfm_internal.h"
#include "tfm_memory_utils.h"
+#ifdef TFM_PSA_API
+#include <stdbool.h>
+#include "tfm_svcalls.h"
+#endif
/* This SVC handler is called when a secure partition requests access to a
* buffer area
*/
extern int32_t tfm_core_set_buffer_area_handler(const uint32_t args[]);
+#ifdef TFM_PSA_API
+extern void tfm_psa_ipc_request_handler(const uint32_t svc_args[]);
+#endif
struct tfm_fault_context_s {
uint32_t R0;
@@ -172,12 +179,36 @@
case TFM_SVC_SET_SHARE_AREA:
tfm_core_set_buffer_area_handler(svc_args);
break;
+#ifdef TFM_PSA_API
+ case TFM_SVC_IPC_REQUEST:
+ tfm_psa_ipc_request_handler(svc_args);
+ break;
+#endif
case TFM_SVC_PRINT:
printf("\e[1;34m[Sec Thread] %s\e[0m\r\n", (char *)svc_args[0]);
break;
case TFM_SVC_GET_BOOT_DATA:
tfm_core_get_boot_data_handler(svc_args);
break;
+#ifdef TFM_PSA_API
+ case TFM_SVC_PSA_FRAMEWORK_VERSION:
+ case TFM_SVC_PSA_VERSION:
+ case TFM_SVC_PSA_CONNECT:
+ case TFM_SVC_PSA_CALL:
+ case TFM_SVC_PSA_CLOSE:
+ case TFM_SVC_PSA_WAIT:
+ case TFM_SVC_PSA_GET:
+ case TFM_SVC_PSA_SET_RHANDLE:
+ case TFM_SVC_PSA_READ:
+ case TFM_SVC_PSA_SKIP:
+ case TFM_SVC_PSA_WRITE:
+ case TFM_SVC_PSA_REPLY:
+ case TFM_SVC_PSA_NOTIFY:
+ case TFM_SVC_PSA_CLEAR:
+ case TFM_SVC_PSA_EOI:
+ svc_args[0] = SVC_Handler_IPC(svc_number, svc_args);
+ break;
+#endif
default:
LOG_MSG("Unknown SVC number requested!");
break;
diff --git a/secure_fw/core/tfm_psa_api_client.c b/secure_fw/core/tfm_psa_api_client.c
new file mode 100644
index 0000000..4b35c58
--- /dev/null
+++ b/secure_fw/core/tfm_psa_api_client.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018, 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_secure_api.h"
+#include "tfm_api.h"
+#include "tfm_svcalls.h"
+
+/* FixMe: check if this is really needed */
+extern int32_t tfm_secure_lock;
+
+__attribute__ ((always_inline)) __STATIC_INLINE
+int32_t tfm_psa_veneer_sanity_check(struct tfm_sfn_req_s *desc_ptr)
+{
+ if (desc_ptr->ns_caller) {
+ if (tfm_secure_lock != 0) {
+ /* Secure domain is already locked!
+ * FixMe: Decide if this is a fault or permitted in case of PSA
+ * API usage
+ */
+ return TFM_ERROR_SECURE_DOMAIN_LOCKED;
+ }
+ } else {
+ /* Secure partition should not call a different secure partition
+ * using TFM PSA veneers
+ */
+ return TFM_ERROR_INVALID_EXC_MODE;
+ }
+ return TFM_SUCCESS;
+}
+
+/* Veneer implementation */
+
+#define TFM_CORE_NS_IPC_REQUEST_VENEER(fn, a, b, c, d) \
+ return tfm_core_ns_ipc_request(fn, (int32_t)a, (int32_t)b, \
+ (int32_t)c, (int32_t)d)
+
+__attribute__ ((always_inline)) __STATIC_INLINE
+int32_t tfm_core_ns_ipc_request(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;
+ int32_t res;
+
+ desc.sfn = fn;
+ desc.args = args;
+ desc.ns_caller = cmse_nonsecure_caller();
+
+ if (__get_active_exc_num() != EXC_NUM_THREAD_MODE)
+ {
+ /* FIXME: Proper error handling to be implemented */
+ return TFM_ERROR_INVALID_EXC_MODE;
+ } else {
+ __ASM("MOV r0, %1\n"
+ "SVC %2\n"
+ "MOV %0, r0\n"
+ : "=r" (res)
+ : "r" (desc_ptr), "I" (TFM_SVC_IPC_REQUEST)
+ : "r0");
+ return res;
+ }
+}
+
+/* FixMe: these functions need to have different attributes compared to those
+ * legacy veneers which may be called by secure partitions.
+ * They won't call legacy SFN but instead will be handlers for TF-M
+ */
+
+__tfm_secure_gateway_attributes__
+uint32_t tfm_psa_framework_version_veneer(void)
+{
+ TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_framework_version, 0, 0,
+ 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+uint32_t tfm_psa_version_veneer(uint32_t sid)
+{
+ TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_version, sid, 0, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version)
+{
+ TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_connect, sid,
+ minor_version, 0, 0);
+}
+
+__tfm_secure_gateway_attributes__
+psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
+ const psa_invec *in_vecs,
+ const psa_invec *out_vecs)
+{
+ TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_call, handle, in_vecs,
+ out_vecs, 0);
+}
+
+__tfm_secure_gateway_attributes__
+psa_status_t tfm_psa_close_veneer(psa_handle_t handle)
+{
+ TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_close, handle, 0, 0, 0);
+}
+
+void tfm_psa_ipc_request_handler(uint32_t svc_ctx[])
+{
+ uint32_t *r0_ptr = svc_ctx;
+
+ /* The only argument to the SVC call is stored in the stacked r0 */
+ struct tfm_sfn_req_s *desc_ptr = (struct tfm_sfn_req_s *) *r0_ptr;
+
+ if(tfm_psa_veneer_sanity_check(desc_ptr) != TFM_SUCCESS) {
+ /* FixMe: consider error handling - this may be critical error */
+ *r0_ptr = TFM_ERROR_INVALID_PARAMETER;
+ return;
+ }
+
+ /* Store SVC return value in stacked r0 */
+ *r0_ptr = desc_ptr->sfn((int32_t)desc_ptr->args,
+ desc_ptr->ns_caller,
+ 0,
+ 0);
+
+ return;
+}
diff --git a/secure_fw/core/tfm_secure_api.c b/secure_fw/core/tfm_secure_api.c
index 14f82ef..8bcbec1 100644
--- a/secure_fw/core/tfm_secure_api.c
+++ b/secure_fw/core/tfm_secure_api.c
@@ -40,7 +40,7 @@
/* This is the "Big Lock" on the secure side, to guarantee single entry
* to SPE
*/
-static int32_t tfm_secure_lock;
+int32_t tfm_secure_lock;
static int32_t tfm_secure_api_initializing = 1;
static int32_t is_iovec_api_call(void)
@@ -367,12 +367,13 @@
caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
/* Check partition state consistency */
- if (((caller_flags&SPM_PART_FLAG_SECURE) != 0) != (!desc_ptr->ns_caller)) {
+ if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0)
+ != (!desc_ptr->ns_caller)) {
/* Partition state inconsistency detected */
return TFM_SECURE_LOCK_FAILED;
}
- if((caller_flags & SPM_PART_FLAG_SECURE) == 0) {
+ if((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) {
/* Disable NS exception handling while secure service is running.
* FixMe:
* This restriction is applied to limit the number of possible attack
@@ -396,7 +397,7 @@
/* Make thread mode unprivileged while untrusted partition init is
* executed
*/
- if ((partition_flags & SPM_PART_FLAG_TRUSTED) == 0) {
+ if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
CONTROL_Type ctrl;
ctrl.w = __get_CONTROL();
@@ -436,7 +437,7 @@
caller_partition_idx);
tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn);
- if ((caller_flags&SPM_PART_FLAG_SECURE)) {
+ if ((caller_flags & SPM_PART_FLAG_APP_ROT)) {
tfm_spm_partition_set_caller_client_id(partition_idx,
caller_partition_id);
} else {
@@ -562,7 +563,7 @@
tfm_secure_lock--;
- if((return_partition_flags & SPM_PART_FLAG_SECURE) == 0) {
+ if((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) {
/* Re-enable NS exceptions when secure service returns to NS client.
* FixMe:
* To be removed when pre-emption and context management issues have
@@ -578,7 +579,7 @@
/* Restore privilege for thread mode during TF-M init. This is only
* have to be done if the partition is not trusted.
*/
- if ((current_partition_flags & SPM_PART_FLAG_TRUSTED) == 0) {
+ if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) {
CONTROL_Type ctrl;
ctrl.w = __get_CONTROL();
@@ -596,7 +597,7 @@
ERROR_MSG("Failed to configure sandbox for partition!");
tfm_secure_api_error_handler();
}
- if (return_partition_flags&SPM_PART_FLAG_SECURE) {
+ if (return_partition_flags & SPM_PART_FLAG_APP_ROT) {
/* Restore share status */
tfm_spm_partition_set_share(
return_partition_idx,
@@ -607,7 +608,7 @@
#endif
#if TFM_LVL == 1
- if (!(return_partition_flags & SPM_PART_FLAG_SECURE) ||
+ if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) ||
(tfm_secure_api_initializing)) {
/* In TFM level 1 context restore is only done when
* returning to NS or after initialization
@@ -832,7 +833,7 @@
uint32_t caller_partition_flags =
tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx);
- if (!(running_partition_flags&SPM_PART_FLAG_SECURE)) {
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
/* This handler shouldn't be called from outside partition context.
* Partitions are only allowed to run while S domain is locked.
*/
@@ -841,7 +842,7 @@
}
/* Store return value in r0 */
- if (caller_partition_flags&SPM_PART_FLAG_SECURE) {
+ if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) {
res = TFM_SUCCESS;
}
svc_args[0] = res;
@@ -915,7 +916,7 @@
tfm_spm_partition_get_runtime_data(running_partition_idx);
int res = 0;
- if (!(running_partition_flags&SPM_PART_FLAG_SECURE)) {
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
/* This handler shouldn't be called from outside partition context.
* Partitions are only allowed to run while S domain is locked.
*/
@@ -959,7 +960,7 @@
int32_t flags = 0;
void *rangeptr;
- if (!(running_partition_flags&SPM_PART_FLAG_SECURE) || (size == 0)) {
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) || (size == 0)) {
/* This handler should only be called from a secure partition. */
svc_args[0] = TFM_ERROR_INVALID_PARAMETER;
return;
@@ -1132,7 +1133,7 @@
/* tfm_core_set_buffer_area() returns int32_t */
int32_t *res_ptr = (int32_t *)&args[0];
- if (!(running_partition_flags&SPM_PART_FLAG_SECURE)) {
+ if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) {
/* This handler should only be called from a secure partition. */
*res_ptr = TFM_ERROR_INVALID_PARAMETER;
return;
@@ -1140,7 +1141,7 @@
switch (args[0]) {
case TFM_BUFFER_SHARE_DEFAULT:
- share = (!(caller_partition_flags&SPM_PART_FLAG_SECURE)) ?
+ share = (!(caller_partition_flags & SPM_PART_FLAG_APP_ROT)) ?
(TFM_BUFFER_SHARE_NS_CODE) : (TFM_BUFFER_SHARE_SCRATCH);
break;
case TFM_BUFFER_SHARE_SCRATCH:
diff --git a/secure_fw/core/tfm_svc.h b/secure_fw/core/tfm_svc.h
index 60c9ac8..44ad9ff 100644
--- a/secure_fw/core/tfm_svc.h
+++ b/secure_fw/core/tfm_svc.h
@@ -20,6 +20,27 @@
TFM_SVC_SPM_REQUEST,
TFM_SVC_PRINT,
TFM_SVC_GET_BOOT_DATA,
+#ifdef TFM_PSA_API
+ TFM_SVC_IPC_REQUEST,
+ TFM_SVC_SCHEDULE,
+ /* PSA Client SVC */
+ TFM_SVC_PSA_FRAMEWORK_VERSION,
+ TFM_SVC_PSA_VERSION,
+ TFM_SVC_PSA_CONNECT,
+ TFM_SVC_PSA_CALL,
+ TFM_SVC_PSA_CLOSE,
+ /* PSA Service SVC */
+ TFM_SVC_PSA_WAIT,
+ TFM_SVC_PSA_GET,
+ TFM_SVC_PSA_SET_RHANDLE,
+ TFM_SVC_PSA_READ,
+ TFM_SVC_PSA_SKIP,
+ TFM_SVC_PSA_WRITE,
+ TFM_SVC_PSA_REPLY,
+ TFM_SVC_PSA_NOTIFY,
+ TFM_SVC_PSA_CLEAR,
+ TFM_SVC_PSA_EOI,
+#endif
} tfm_svc_number_t;
#define SVC(code) __ASM("svc %0" : : "I" (code))
diff --git a/secure_fw/ns_callable/tfm_veneers.c b/secure_fw/ns_callable/tfm_veneers.c
index ed69b94..9e9063f 100644
--- a/secure_fw/ns_callable/tfm_veneers.c
+++ b/secure_fw/ns_callable/tfm_veneers.c
@@ -30,6 +30,14 @@
psa_status_t tfm_crypto_destroy_key(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_get_key_information(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_export_key(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_policy_init(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_policy_set_usage(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_policy_get_usage(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_key_policy_get_algorithm(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_set_key_policy(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_get_key_policy(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_get_key_lifetime(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_set_key_lifetime(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_cipher_set_iv(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_cipher_encrypt_setup(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_cipher_decrypt_setup(struct psa_invec *, size_t, struct psa_outvec *, size_t);
@@ -41,6 +49,14 @@
psa_status_t tfm_crypto_hash_finish(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_hash_verify(struct psa_invec *, size_t, struct psa_outvec *, size_t);
psa_status_t tfm_crypto_hash_abort(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_sign_setup(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify_setup(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_update(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_sign_finish(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_verify_finish(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_mac_abort(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_decrypt_wrapper(struct psa_invec *, size_t, struct psa_outvec *, size_t);
+psa_status_t tfm_crypto_aead_encrypt_wrapper(struct psa_invec *, size_t, struct psa_outvec *, size_t);
/******** TFM_SP_PLATFORM ********/
psa_status_t platform_sp_system_reset(struct psa_invec *, size_t, struct psa_outvec *, size_t);
@@ -69,6 +85,14 @@
psa_status_t tfm_secure_client_service_sfn_run_tests(struct psa_invec *, size_t, struct psa_outvec *, size_t);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PSA_API */
+
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PSA_API */
+
#define TFM_VENEER_FUNCTION(partition_name, sfn_name) \
__tfm_secure_gateway_attributes__ \
@@ -101,6 +125,14 @@
TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_destroy_key)
TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_get_key_information)
TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_export_key)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_policy_init)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_policy_set_usage)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_policy_get_usage)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_key_policy_get_algorithm)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_set_key_policy)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_get_key_policy)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_get_key_lifetime)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_set_key_lifetime)
TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_set_iv)
TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_encrypt_setup)
TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_cipher_decrypt_setup)
@@ -112,6 +144,14 @@
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_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_aead_decrypt_wrapper)
+TFM_VENEER_FUNCTION(TFM_SP_CRYPTO, tfm_crypto_aead_encrypt_wrapper)
/******** TFM_SP_PLATFORM ********/
TFM_VENEER_FUNCTION(TFM_SP_PLATFORM, platform_sp_system_reset)
@@ -140,3 +180,11 @@
TFM_VENEER_FUNCTION(TFM_SP_SECURE_TEST_PARTITION, tfm_secure_client_service_sfn_run_tests)
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+#endif /* TFM_PSA_API */
+
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PSA_API */
+
diff --git a/secure_fw/ns_callable/tfm_veneers.c.template b/secure_fw/ns_callable/tfm_veneers.c.template
index 0386d05..d57dc18 100644
--- a/secure_fw/ns_callable/tfm_veneers.c.template
+++ b/secure_fw/ns_callable/tfm_veneers.c.template
@@ -15,7 +15,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
-/******** @@manifest.tfm_partition_name@@ ********/
+/******** @@manifest.name@@ ********/
psa_status_t @@manifest.secure_functions.tfm_symbol@@(struct psa_invec *, size_t, struct psa_outvec *, size_t);
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@@ -39,8 +39,8 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
-/******** @@manifest.tfm_partition_name@@ ********/
-TFM_VENEER_FUNCTION(@@manifest.tfm_partition_name@@, @@manifest.secure_functions.tfm_symbol@@)
+/******** @@manifest.name@@ ********/
+TFM_VENEER_FUNCTION(@@manifest.name@@, @@manifest.secure_functions.tfm_symbol@@)
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
diff --git a/secure_fw/services/audit_logging/manifest.yaml b/secure_fw/services/audit_logging/manifest.yaml
index 694b822..371ce2d 100644
--- a/secure_fw/services/audit_logging/manifest.yaml
+++ b/secure_fw/services/audit_logging/manifest.yaml
@@ -1,18 +1,16 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
{
- "name": "AUDIT_LOG",
- "type": "TRUSTED",
- "tfm_partition_name": "TFM_SP_AUDIT_LOG",
- "tfm_trusted": true,
+ "name": "TFM_SP_AUDIT_LOG",
+ "type": "PSA-ROT",
"priority": "NORMAL",
"id": "0x00000101",
- "entry_point": "main",
+ "entry_point": "audit_core_init",
"stack_size": "0x1000",
"heap_size": "0x0400",
"mmio_regions" : [
@@ -22,7 +20,6 @@
"conditional": "AUDIT_UART_REDIRECTION"
}
],
- "tfm_init_symbol": "audit_core_init",
"secure_functions": [
{
"sfid": "TFM_AUDIT_RETRIEVE_RECORD_SFID",
diff --git a/secure_fw/services/crypto/manifest.yaml b/secure_fw/services/crypto/manifest.yaml
index e1030a3..fecd540 100644
--- a/secure_fw/services/crypto/manifest.yaml
+++ b/secure_fw/services/crypto/manifest.yaml
@@ -6,16 +6,13 @@
#-------------------------------------------------------------------------------
{
- "name": "CRYPTO",
- "type": "TRUSTED",
- "tfm_partition_name": "TFM_SP_CRYPTO",
- "tfm_trusted": true,
+ "name": "TFM_SP_CRYPTO",
+ "type": "PSA-ROT",
"priority": "NORMAL",
"id": "0x00000102",
- "entry_point": "main",
+ "entry_point": "tfm_crypto_init",
"stack_size": "0x2000",
"heap_size": "0x0400",
- "tfm_init_symbol": "tfm_crypto_init",
"secure_functions": [
{
"sfid": "TFM_CRYPTO_IMPORT_KEY_SFID",
diff --git a/secure_fw/services/initial_attestation/manifest.yaml b/secure_fw/services/initial_attestation/manifest.yaml
index 2c83291..e57eee0 100644
--- a/secure_fw/services/initial_attestation/manifest.yaml
+++ b/secure_fw/services/initial_attestation/manifest.yaml
@@ -6,13 +6,11 @@
#-------------------------------------------------------------------------------
{
- "name": "INITIAL_ATTESTATION",
- "type": "TRUSTED",
- "tfm_partition_name": "TFM_SP_INITIAL_ATTESTATION",
- "tfm_trusted": true,
+ "name": "TFM_SP_INITIAL_ATTESTATION",
+ "type": "PSA-ROT",
"priority": "NORMAL",
"id": "0x00000103",
- "entry_point": "main",
+ "entry_point": "attest_init",
"stack_size": "0x0400",
"heap_size": "0x0400",
"tfm_init_symbol": "attest_init",
diff --git a/secure_fw/services/platform/manifest.yaml b/secure_fw/services/platform/manifest.yaml
index 8688ed6..e66b54e 100644
--- a/secure_fw/services/platform/manifest.yaml
+++ b/secure_fw/services/platform/manifest.yaml
@@ -1,21 +1,18 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
{
- "name": "SP_PLATFORM",
- "type": "TRUSTED",
- "tfm_partition_name": "TFM_SP_PLATFORM",
- "tfm_trusted": true,
+ "name": "TFM_SP_PLATFORM",
+ "type": "PSA-ROT",
"priority": "NORMAL",
"id": "0x00000102",
- "entry_point": "main",
+ "entry_point": "platform_sp_init",
"stack_size": "0x0400",
"heap_size": "0x0400",
- "tfm_init_symbol": "platform_sp_init",
"secure_functions": [
{
"sfid": "TFM_SP_PLATFORM_SYSTEM_RESET_SFID",
diff --git a/secure_fw/services/secure_storage/manifest.yaml b/secure_fw/services/secure_storage/manifest.yaml
index f6f63c1..86e2bc7 100644
--- a/secure_fw/services/secure_storage/manifest.yaml
+++ b/secure_fw/services/secure_storage/manifest.yaml
@@ -6,16 +6,13 @@
#-------------------------------------------------------------------------------
{
- "name": "SST",
- "type": "TRUSTED",
- "tfm_partition_name": "TFM_SP_STORAGE",
- "tfm_trusted": true,
+ "name": "TFM_SP_STORAGE",
+ "type": "PSA-ROT",
"priority": "NORMAL",
"id": "0x00000100",
- "entry_point": "main",
+ "entry_point": "tfm_sst_init",
"stack_size": "0x2000",
"heap_size": "0x0400",
- "tfm_init_symbol": "tfm_sst_init",
"secure_functions": [
{
"sfid": "TFM_SST_SET_SFID",
diff --git a/secure_fw/services/tfm_partition_defs.inc b/secure_fw/services/tfm_partition_defs.inc
index 2fe3ac6..ab0cb28 100644
--- a/secure_fw/services/tfm_partition_defs.inc
+++ b/secure_fw/services/tfm_partition_defs.inc
@@ -32,6 +32,14 @@
#define TFM_SP_SECURE_TEST_PARTITION_ID (TFM_SP_BASE + 7)
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
-#define TFM_MAX_USER_PARTITIONS (8)
+#ifdef TFM_PSA_API
+#define TFM_SP_IPC_SERVICE_TEST_ID (TFM_SP_BASE + 8)
+#endif /* TFM_PSA_API */
+
+#ifdef TFM_PSA_API
+#define TFM_SP_IPC_CLIENT_TEST_ID (TFM_SP_BASE + 9)
+#endif /* TFM_PSA_API */
+
+#define TFM_MAX_USER_PARTITIONS (10)
#endif /* __TFM_PARTITION_DEFS_INC__ */
diff --git a/secure_fw/services/tfm_partition_defs.inc.template b/secure_fw/services/tfm_partition_defs.inc.template
index ad05eeb..12eeefc 100644
--- a/secure_fw/services/tfm_partition_defs.inc.template
+++ b/secure_fw/services/tfm_partition_defs.inc.template
@@ -14,7 +14,7 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
-#define @@manifest.tfm_partition_name@@_ID (TFM_SP_BASE + @!GENERATOR_ITERATION_COUNTER!@)
+#define @@manifest.name@@_ID (TFM_SP_BASE + @!GENERATOR_ITERATION_COUNTER!@)
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#endif /* @@attr.conditional@@ */
@!GENERATOR_CONDITIONAL_END!@
diff --git a/secure_fw/services/tfm_partition_list.inc b/secure_fw/services/tfm_partition_list.inc
index 7d3aadc..12213a6 100644
--- a/secure_fw/services/tfm_partition_list.inc
+++ b/secure_fw/services/tfm_partition_list.inc
@@ -11,46 +11,70 @@
#define __TFM_PARTITION_LIST_INC__
/******** TFM_SP_STORAGE ********/
-PARTITION_DECLARE(TFM_SP_STORAGE, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_DECLARE(TFM_SP_STORAGE, 0
+ , "PSA-ROT", 0x00000100, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_STORAGE, tfm_sst_init);
/******** TFM_SP_AUDIT_LOG ********/
-PARTITION_DECLARE(TFM_SP_AUDIT_LOG, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_DECLARE(TFM_SP_AUDIT_LOG, 0
+ , "PSA-ROT", 0x00000101, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_AUDIT_LOG, audit_core_init);
#ifdef AUDIT_UART_REDIRECTION
PARTITION_ADD_PERIPHERAL(TFM_SP_AUDIT_LOG, TFM_PERIPHERAL_UART1);
#endif /* AUDIT_UART_REDIRECTION */
/******** TFM_SP_CRYPTO ********/
-PARTITION_DECLARE(TFM_SP_CRYPTO, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_DECLARE(TFM_SP_CRYPTO, 0
+ , "PSA-ROT", 0x00000102, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_CRYPTO, tfm_crypto_init);
/******** TFM_SP_PLATFORM ********/
-PARTITION_DECLARE(TFM_SP_PLATFORM, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_DECLARE(TFM_SP_PLATFORM, 0
+ , "PSA-ROT", 0x00000102, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_PLATFORM, platform_sp_init);
/******** TFM_SP_INITIAL_ATTESTATION ********/
-PARTITION_DECLARE(TFM_SP_INITIAL_ATTESTATION, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_DECLARE(TFM_SP_INITIAL_ATTESTATION, 0
+ , "PSA-ROT", 0x00000103, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_INITIAL_ATTESTATION, attest_init);
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST ********/
-PARTITION_DECLARE(TFM_SP_CORE_TEST, SPM_PART_FLAG_SECURE);
+PARTITION_DECLARE(TFM_SP_CORE_TEST, 0
+ , "APPLICATION-ROT", 0x00000002, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_CORE_TEST, core_test_init);
PARTITION_ADD_PERIPHERAL(TFM_SP_CORE_TEST, TFM_PERIPHERAL_FPGA_IO);
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PARTITION_TEST_CORE
/******** TFM_SP_CORE_TEST_2 ********/
-PARTITION_DECLARE(TFM_SP_CORE_TEST_2, SPM_PART_FLAG_SECURE);
+PARTITION_DECLARE(TFM_SP_CORE_TEST_2, 0
+ , "APPLICATION-ROT", 0x00000003, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_CORE_TEST_2, core_test_2_init);
#endif /* TFM_PARTITION_TEST_CORE */
#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
/******** TFM_SP_SECURE_TEST_PARTITION ********/
-PARTITION_DECLARE(TFM_SP_SECURE_TEST_PARTITION, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
+PARTITION_DECLARE(TFM_SP_SECURE_TEST_PARTITION, 0
+ , "PSA-ROT", 0x00000005, NORMAL);
PARTITION_ADD_INIT_FUNC(TFM_SP_SECURE_TEST_PARTITION, tfm_secure_client_service_init);
PARTITION_ADD_PERIPHERAL(TFM_SP_SECURE_TEST_PARTITION, TFM_PERIPHERAL_STD_UART);
#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+PARTITION_DECLARE(TFM_SP_IPC_SERVICE_TEST, 0
+ | SPM_PART_FLAG_IPC
+ , "APPLICATION-ROT", 0x00000007, HIGH);
+PARTITION_ADD_INIT_FUNC(TFM_SP_IPC_SERVICE_TEST, ipc_service_test_main);
+#endif /* TFM_PSA_API */
+
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+PARTITION_DECLARE(TFM_SP_IPC_CLIENT_TEST, 0
+ | SPM_PART_FLAG_IPC
+ , "APPLICATION-ROT", 0x00000006, NORMAL);
+PARTITION_ADD_INIT_FUNC(TFM_SP_IPC_CLIENT_TEST, ipc_client_init);
+#endif /* TFM_PSA_API */
+
#endif /* __TFM_PARTITION_LIST_INC__ */
diff --git a/secure_fw/services/tfm_partition_list.inc.template b/secure_fw/services/tfm_partition_list.inc.template
index 3c5812b..5ab855e 100644
--- a/secure_fw/services/tfm_partition_list.inc.template
+++ b/secure_fw/services/tfm_partition_list.inc.template
@@ -14,18 +14,18 @@
@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
#ifdef @@attr.conditional@@
@!GENERATOR_CONDITIONAL_END!@
-/******** @@manifest.tfm_partition_name@@ ********/
-@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_trusted@@
-PARTITION_DECLARE(@@manifest.tfm_partition_name@@, SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED);
-@!GENERATOR_CONDITIONAL_ELSE!@
-PARTITION_DECLARE(@@manifest.tfm_partition_name@@, SPM_PART_FLAG_SECURE);
+/******** @@manifest.name@@ ********/
+PARTITION_DECLARE(@@manifest.name@@, 0
+@!GENERATOR_CONDITIONAL_START!@ @@manifest.tfm_partition_ipc@@
+ | SPM_PART_FLAG_IPC
@!GENERATOR_CONDITIONAL_END!@
-PARTITION_ADD_INIT_FUNC(@@manifest.tfm_partition_name@@, @@manifest.tfm_init_symbol@@);
+ , "@@manifest.type@@", @@manifest.id@@, @@manifest.priority@@);
+PARTITION_ADD_INIT_FUNC(@@manifest.name@@, @@manifest.entry_point@@);
@!GENERATOR_CONDITIONAL_START!@ @@manifest.mmio_regions.conditional@@
#ifdef @@manifest.mmio_regions.conditional@@
@!GENERATOR_CONDITIONAL_END!@
@!GENERATOR_CONDITIONAL_START!@ @@manifest.mmio_regions.name@@
-PARTITION_ADD_PERIPHERAL(@@manifest.tfm_partition_name@@, @@manifest.mmio_regions.name@@);
+PARTITION_ADD_PERIPHERAL(@@manifest.name@@, @@manifest.mmio_regions.name@@);
@!GENERATOR_CONDITIONAL_END!@
@!GENERATOR_CONDITIONAL_START!@ @@manifest.mmio_regions.conditional@@
#endif /* @@manifest.mmio_regions.conditional@@ */
diff --git a/secure_fw/services/tfm_service_list.inc b/secure_fw/services/tfm_service_list.inc
new file mode 100644
index 0000000..e953f2d
--- /dev/null
+++ b/secure_fw/services/tfm_service_list.inc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
+
+#ifndef __TFM_SERVICE_LIST_INC__
+#define __TFM_SERVICE_LIST_INC__
+
+/******** TFM_SP_STORAGE ********/
+
+/******** TFM_SP_AUDIT_LOG ********/
+
+/******** TFM_SP_CRYPTO ********/
+
+/******** TFM_SP_PLATFORM ********/
+
+/******** TFM_SP_INITIAL_ATTESTATION ********/
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST ********/
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_CORE
+/******** TFM_SP_CORE_TEST_2 ********/
+#endif /* TFM_PARTITION_TEST_CORE */
+
+#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
+/******** TFM_SP_SECURE_TEST_PARTITION ********/
+#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
+
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_SERVICE_TEST ********/
+{"IPC_SID_BASIC", TFM_SP_IPC_SERVICE_TEST_ID, IPC_BASIC_SIGNAL, 0x00001000, true, 1, TFM_VERSION_POLICY_STRICT},
+#endif /* TFM_PSA_API */
+
+#ifdef TFM_PSA_API
+/******** TFM_SP_IPC_CLIENT_TEST ********/
+#endif /* TFM_PSA_API */
+
+#endif /* __TFM_SERVICE_LIST_INC__ */
diff --git a/secure_fw/services/tfm_service_list.inc.template b/secure_fw/services/tfm_service_list.inc.template
new file mode 100644
index 0000000..f247fec
--- /dev/null
+++ b/secure_fw/services/tfm_service_list.inc.template
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+@!GENERATOR_DONOTEDIT_WARNING!@
+
+#ifndef __TFM_SERVICE_LIST_INC__
+#define __TFM_SERVICE_LIST_INC__
+
+@!GENERATOR_BLOCK_START!@
+@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
+#ifdef @@attr.conditional@@
+@!GENERATOR_CONDITIONAL_END!@
+/******** @@manifest.name@@ ********/
+@!GENERATOR_CONDITIONAL_START!@ @@manifest.services@@
+{"@@manifest.services.name@@", @@manifest.name@@_ID, @@manifest.services.signal@@, @@manifest.services.sid@@, @@manifest.services.non_secure_clients@@, @@manifest.services.minor_version@@, TFM_VERSION_POLICY_@@manifest.services.minor_policy@@},
+@!GENERATOR_CONDITIONAL_END!@
+@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
+#endif /* @@attr.conditional@@ */
+@!GENERATOR_CONDITIONAL_END!@
+
+@!GENERATOR_BLOCK_END!@
+#endif /* __TFM_SERVICE_LIST_INC__ */
diff --git a/secure_fw/services/tfm_sfid_list.inc b/secure_fw/services/tfm_sfid_list.inc
deleted file mode 100644
index 8f833bf..0000000
--- a/secure_fw/services/tfm_sfid_list.inc
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-/*********** WARNING: This is an auto-generated file. Do not edit! ***********/
-
-#ifndef __TFM_SFID_LIST_INC__
-#define __TFM_SFID_LIST_INC__
-
- /******** TFM_SP_STORAGE ********/
- {tfm_sst_set, TFM_SST_SET_SFID},
- {tfm_sst_get, TFM_SST_GET_SFID},
- {tfm_sst_get_info, TFM_SST_GET_INFO_SFID},
- {tfm_sst_remove, TFM_SST_REMOVE_SFID},
- {tfm_sst_get_support, TFM_SST_GET_SUPPORT_SFID},
-
- /******** TFM_SP_AUDIT_LOG ********/
- {audit_core_retrieve_record, TFM_AUDIT_RETRIEVE_RECORD_SFID},
- {audit_core_add_record, TFM_AUDIT_ADD_RECORD_SFID},
- {audit_core_get_info, TFM_AUDIT_GET_INFO_SFID},
- {audit_core_get_record_info, TFM_AUDIT_GET_RECORD_INFO_SFID},
- {audit_core_delete_record, TFM_AUDIT_DELETE_RECORD_SFID},
-
- /******** TFM_SP_CRYPTO ********/
- {tfm_crypto_import_key, TFM_CRYPTO_IMPORT_KEY_SFID},
- {tfm_crypto_destroy_key, TFM_CRYPTO_DESTROY_KEY_SFID},
- {tfm_crypto_get_key_information, TFM_CRYPTO_GET_KEY_INFORMATION_SFID},
- {tfm_crypto_export_key, TFM_CRYPTO_EXPORT_KEY_SFID},
- {tfm_crypto_key_policy_init, TFM_CRYPTO_KEY_POLICY_INIT_SFID},
- {tfm_crypto_key_policy_set_usage, TFM_CRYPTO_KEY_POLICY_SET_USAGE_SFID},
- {tfm_crypto_key_policy_get_usage, TFM_CRYPTO_KEY_POLICY_GET_USAGE_SFID},
- {tfm_crypto_key_policy_get_algorithm, TFM_CRYPTO_KEY_POLICY_GET_ALGORITHM_SFID},
- {tfm_crypto_set_key_policy, TFM_CRYPTO_SET_KEY_POLICY_SFID},
- {tfm_crypto_get_key_policy, TFM_CRYPTO_GET_KEY_POLICY_SFID},
- {tfm_crypto_get_key_lifetime, TFM_CRYPTO_GET_KEY_LIFETIME_SFID},
- {tfm_crypto_set_key_lifetime, TFM_CRYPTO_SET_KEY_LIFETIME_SFID},
- {tfm_crypto_cipher_set_iv, TFM_CRYPTO_CIPHER_SET_IV_SFID},
- {tfm_crypto_cipher_encrypt_setup, TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SFID},
- {tfm_crypto_cipher_decrypt_setup, TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SFID},
- {tfm_crypto_cipher_update_wrapper, TFM_CRYPTO_CIPHER_UPDATE_SFID},
- {tfm_crypto_cipher_abort, TFM_CRYPTO_CIPHER_ABORT_SFID},
- {tfm_crypto_cipher_finish, TFM_CRYPTO_CIPHER_FINISH_SFID},
- {tfm_crypto_hash_setup, TFM_CRYPTO_HASH_SETUP_SFID},
- {tfm_crypto_hash_update, TFM_CRYPTO_HASH_UPDATE_SFID},
- {tfm_crypto_hash_finish, TFM_CRYPTO_HASH_FINISH_SFID},
- {tfm_crypto_hash_verify, TFM_CRYPTO_HASH_VERIFY_SFID},
- {tfm_crypto_hash_abort, TFM_CRYPTO_HASH_ABORT_SFID},
- {tfm_crypto_mac_sign_setup, TFM_CRYPTO_MAC_SIGN_SETUP_SFID},
- {tfm_crypto_mac_verify_setup, TFM_CRYPTO_MAC_VERIFY_SETUP_SFID},
- {tfm_crypto_mac_update, TFM_CRYPTO_MAC_UPDATE_SFID},
- {tfm_crypto_mac_sign_finish, TFM_CRYPTO_MAC_SIGN_FINISH_SFID},
- {tfm_crypto_mac_verify_finish, TFM_CRYPTO_MAC_VERIFY_FINISH_SFID},
- {tfm_crypto_mac_abort, TFM_CRYPTO_MAC_ABORT_SFID},
- {tfm_crypto_aead_decrypt_wrapper, TFM_CRYPTO_AEAD_DECRYPT_SFID},
- {tfm_crypto_aead_encrypt_wrapper, TFM_CRYPTO_AEAD_ENCRYPT_SFID},
-
- /******** TFM_SP_PLATFORM ********/
- {platform_sp_system_reset, TFM_SP_PLATFORM_SYSTEM_RESET_SFID},
-
- /******** TFM_SP_INITIAL_ATTESTATION ********/
- {initial_attest_get_token, TFM_ATTEST_GET_TOKEN_SFID},
- {initial_attest_get_token_size, TFM_ATTEST_GET_TOKEN_SIZE_SFID},
-
-#ifdef TFM_PARTITION_TEST_CORE
- /******** TFM_SP_CORE_TEST ********/
- {spm_core_test_sfn, TFM_CORE_TEST_SFN_SFID},
- {spm_core_test_sfn_init_success, TFM_CORE_TEST_SFN_INIT_SUCCESS_SFID},
- {spm_core_test_sfn_direct_recursion, TFM_CORE_TEST_SFN_DIRECT_RECURSION_SFID},
-#endif /* TFM_PARTITION_TEST_CORE */
-
-#ifdef TFM_PARTITION_TEST_CORE
- /******** TFM_SP_CORE_TEST_2 ********/
- {spm_core_test_2_slave_service, TFM_CORE_TEST_2_SFN_SLAVE_SERVICE_SFID},
- {spm_core_test_2_sfn_invert, TFM_CORE_TEST_2_SFN_INVERT_SFID},
- {spm_core_test_2_check_caller_client_id, TFM_CORE_TEST_2_SFN_CHECK_CALLER_CLIENT_ID_SFID},
- {spm_core_test_2_get_every_second_byte, TFM_CORE_TEST_2_SFN_GET_EVERY_SECOND_BYTE},
-#endif /* TFM_PARTITION_TEST_CORE */
-
-#ifdef TFM_PARTITION_TEST_SECURE_SERVICES
- /******** TFM_SP_SECURE_TEST_PARTITION ********/
- {tfm_secure_client_service_sfn_run_tests, TFM_SECURE_CLIENT_SFN_RUN_TESTS_SFID},
-#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */
-
-#endif /* __TFM_SFID_LIST_INC__ */
diff --git a/secure_fw/services/tfm_sfid_list.inc.template b/secure_fw/services/tfm_sfid_list.inc.template
deleted file mode 100644
index 7f9bb92..0000000
--- a/secure_fw/services/tfm_sfid_list.inc.template
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-@!GENERATOR_DONOTEDIT_WARNING!@
-
-#ifndef __TFM_SFID_LIST_INC__
-#define __TFM_SFID_LIST_INC__
-
-@!GENERATOR_BLOCK_START!@
-@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
-#ifdef @@attr.conditional@@
-@!GENERATOR_CONDITIONAL_END!@
- /******** @@manifest.tfm_partition_name@@ ********/
- {@@manifest.secure_functions.tfm_symbol@@, @@manifest.secure_functions.sfid@@},
-@!GENERATOR_CONDITIONAL_START!@ @@attr.conditional@@
-#endif /* @@attr.conditional@@ */
-@!GENERATOR_CONDITIONAL_END!@
-
-@!GENERATOR_BLOCK_END!@
-#endif /* __TFM_SFID_LIST_INC__ */
diff --git a/secure_fw/spm/spm_api.c b/secure_fw/spm/spm_api.c
index efc4306..ff4eb11 100644
--- a/secure_fw/spm/spm_api.c
+++ b/secure_fw/spm/spm_api.c
@@ -118,7 +118,7 @@
g_spm_partition_db.partition_count]);
part_ptr->static_data.partition_id = TFM_SP_CORE_ID;
part_ptr->static_data.partition_flags =
- SPM_PART_FLAG_SECURE | SPM_PART_FLAG_TRUSTED;
+ SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_PSA_ROT;
part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT;
++g_spm_partition_db.partition_count;
@@ -142,6 +142,11 @@
for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) {
part = &g_spm_partition_db.partitions[idx];
tfm_spm_hal_configure_default_isolation(part->platform_data);
+#ifdef TFM_PSA_API
+ if (part->static_data.partition_flags & SPM_PART_FLAG_IPC) {
+ continue;
+ }
+#endif
if (part->static_data.partition_init == NULL) {
tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE);
tfm_spm_partition_set_caller_partition_idx(idx,
diff --git a/secure_fw/spm/spm_api.h b/secure_fw/spm/spm_api.h
index 0fa4c86..89d4564 100644
--- a/secure_fw/spm/spm_api.h
+++ b/secure_fw/spm/spm_api.h
@@ -33,8 +33,9 @@
};
enum spm_part_flag_mask_t {
- SPM_PART_FLAG_SECURE = 0x01,
- SPM_PART_FLAG_TRUSTED = 0x02,
+ SPM_PART_FLAG_APP_ROT = 0x01,
+ SPM_PART_FLAG_PSA_ROT = 0x02,
+ SPM_PART_FLAG_IPC = 0x04
};
/**
diff --git a/secure_fw/spm/spm_db.h b/secure_fw/spm/spm_db.h
index 512ede1..6b28f94 100644
--- a/secure_fw/spm/spm_db.h
+++ b/secure_fw/spm/spm_db.h
@@ -8,8 +8,37 @@
#ifndef __SPM_DB_H__
#define __SPM_DB_H__
+
+#ifdef TFM_PSA_API
+#include "tfm_thread.h"
+#endif
+
+struct spm_partition_desc_t;
+struct spm_partition_db_t;
+
typedef psa_status_t(*sp_init_function)(void);
+#define TFM_PARTITION_TYPE_APP "APPLICATION-ROT"
+#define TFM_PARTITION_TYPE_PSA "PSA-ROT"
+
+#define TFM_STACK_SIZE 1024
+
+#ifdef TFM_PSA_API
+enum tfm_partition_priority {
+ TFM_PRIORITY_LOW = THRD_PRIOR_LOWEST,
+ TFM_PRIORITY_NORMAL = THRD_PRIOR_MEDIUM,
+ TFM_PRIORITY_HIGH = THRD_PRIOR_HIGHEST,
+};
+#else
+enum tfm_partition_priority {
+ TFM_PRIORITY_LOW = 0xFF,
+ TFM_PRIORITY_NORMAL = 0x7F,
+ 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
@@ -18,6 +47,7 @@
struct spm_partition_static_data_t {
uint32_t partition_id;
uint32_t partition_flags;
+ uint32_t partition_priority;
sp_init_function partition_init;
};
@@ -32,6 +62,15 @@
#if TFM_LVL != 1
struct tfm_spm_partition_memory_data_t memory_data;
#endif
+#ifdef TFM_PSA_API
+ struct tfm_thrd_ctx sp_thrd;
+ /*
+ * FixMe: Hard code stack is not aligned with the definition in the
+ * manifest. It will use the partition stacks in the linker scripts/sct
+ * files include Level 1 to 3.
+ */
+ uint8_t stack[TFM_STACK_SIZE] __attribute__((aligned(8)));
+#endif
};
/* Macros to pick linker symbols and allow to form the partition data base */
diff --git a/secure_fw/spm/spm_db_setup.h b/secure_fw/spm/spm_db_setup.h
index f4102cf1..d79fed9 100644
--- a/secure_fw/spm/spm_db_setup.h
+++ b/secure_fw/spm/spm_db_setup.h
@@ -31,10 +31,11 @@
struct spm_partition_desc_t partitions[SPM_MAX_PARTITIONS];
};
-#define PARTITION_INIT_STATIC_DATA(data, partition, flags) \
- do { \
- data.partition_id = partition##_ID; \
- data.partition_flags = flags; \
+#define PARTITION_INIT_STATIC_DATA(data, partition, flags, id, priority) \
+ do { \
+ data.partition_id = partition##_ID; \
+ data.partition_flags = flags; \
+ data.partition_priority = TFM_PRIORITY(priority); \
} while (0)
#if TFM_LVL == 1
@@ -75,7 +76,7 @@
} while (0)
#endif
-#define PARTITION_DECLARE(partition, flags) \
+#define PARTITION_DECLARE(partition, flag, type, id, priority) \
do { \
REGION_DECLARE(Image$$, partition, $$Base); \
REGION_DECLARE(Image$$, partition, $$Limit); \
@@ -87,13 +88,24 @@
REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Limit); \
REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Base); \
REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Limit); \
+ int32_t flags = flag; \
+ if (tfm_memcmp(type, TFM_PARTITION_TYPE_APP, \
+ strlen(TFM_PARTITION_TYPE_APP)) == 0) { \
+ flags |= SPM_PART_FLAG_APP_ROT; \
+ } else if (tfm_memcmp(type, TFM_PARTITION_TYPE_PSA, \
+ strlen(TFM_PARTITION_TYPE_PSA)) == 0) { \
+ flags |= SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT; \
+ } else { \
+ return SPM_ERR_INVALID_CONFIG; \
+ } \
struct spm_partition_desc_t *part_ptr; \
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \
return SPM_ERR_INVALID_CONFIG; \
} \
part_ptr = &(g_spm_partition_db.partitions[ \
g_spm_partition_db.partition_count]); \
- PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags); \
+ PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags, \
+ id, priority); \
PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \
PARTITION_INIT_MEMORY_DATA(part_ptr->memory_data, partition); \
++g_spm_partition_db.partition_count; \
diff --git a/test/CMakeLists.inc b/test/CMakeLists.inc
index cb36a19..ffc662c 100644
--- a/test/CMakeLists.inc
+++ b/test/CMakeLists.inc
@@ -35,3 +35,4 @@
include(${CMAKE_CURRENT_LIST_DIR}/suites/attestation/CMakeLists.inc)
include(${CMAKE_CURRENT_LIST_DIR}/suites/qcbor/CMakeLists.inc)
include(${CMAKE_CURRENT_LIST_DIR}/test_services/CMakeLists.inc)
+include(${CMAKE_CURRENT_LIST_DIR}/suites/ipc/CMakeLists.inc)
diff --git a/test/framework/non_secure_suites.c b/test/framework/non_secure_suites.c
index b458224..7c442c7 100644
--- a/test/framework/non_secure_suites.c
+++ b/test/framework/non_secure_suites.c
@@ -17,6 +17,7 @@
#include "test/suites/qcbor/non_secure/qcbor_ns_tests.h"
#include "test/suites/invert/non_secure/invert_ns_tests.h"
#include "test/suites/core/non_secure/core_ns_tests.h"
+#include "test/suites/ipc/non_secure/ipc_ns_tests.h"
static struct test_suite_t test_suites[] = {
#if TFM_LVL == 3
@@ -69,6 +70,11 @@
/* Non-secure interactive test cases */
{®ister_testsuite_ns_core_interactive, 0, 0, 0},
#endif
+
+#ifdef CORE_TEST_IPC
+ /* Non-secure IPC test cases */
+ {®ister_testsuite_ns_ipc_interface, 0, 0, 0},
+#endif
};
void start_integ_test(void)
diff --git a/test/framework/secure_suites.c b/test/framework/secure_suites.c
index 0f7bb64..4caf4ae 100644
--- a/test/framework/secure_suites.c
+++ b/test/framework/secure_suites.c
@@ -15,6 +15,7 @@
#include "test/suites/attestation/secure/attestation_s_tests.h"
#include "test/suites/invert/secure/invert_s_tests.h"
#include "test/suites/crypto/secure/crypto_s_tests.h"
+#include "test/suites/ipc/secure/ipc_s_tests.h"
static struct test_suite_t test_suites[] = {
#if TFM_LVL == 3
@@ -48,6 +49,11 @@
/* Note: since this is sample code, only run if test services are enabled */
{®ister_testsuite_s_invert_interface, 0, 0, 0},
#endif /* TFM_PARTITION_TEST_CORE*/
+
+#ifdef CORE_TEST_IPC
+ /* Secure IPC test cases */
+ {®ister_testsuite_s_ipc_interface, 0, 0, 0},
+#endif
#endif /* SERVICES_TEST_S */
#endif /* TFM_LVL == 3 */
};
diff --git a/test/suites/ipc/CMakeLists.inc b/test/suites/ipc/CMakeLists.inc
new file mode 100644
index 0000000..c88de5b
--- /dev/null
+++ b/test/suites/ipc/CMakeLists.inc
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the "ipc test" 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 repo.
+#
+#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(IPC_TEST_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 CORE_TEST_IPC)
+ message(FATAL_ERROR "Incomplete build configuration: CORE_TEST_IPC is undefined. ")
+elseif(CORE_TEST_IPC)
+ list(APPEND ALL_SRC_C_S "${IPC_TEST_DIR}/secure/ipc_s_interface_testsuite.c")
+ list(APPEND ALL_SRC_C_NS "${IPC_TEST_DIR}/non_secure/ipc_ns_interface_testsuite.c")
+
+ #Setting include directories
+ embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
+ embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
+endif()
diff --git a/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c b/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c
new file mode 100644
index 0000000..ad86b95
--- /dev/null
+++ b/test/suites/ipc/non_secure/ipc_ns_interface_testsuite.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include "ipc_ns_tests.h"
+#include "psa_client.h"
+#include "test/framework/test_framework_helpers.h"
+
+#define IPC_TEST_SERVICE1_SID (0x1000)
+#define IPC_TEST_SERVICE1_MIN_VER (0x0001)
+
+/* List of tests */
+static void tfm_ipc_test_1001(struct test_result_t *ret);
+static void tfm_ipc_test_1002(struct test_result_t *ret);
+static void tfm_ipc_test_1003(struct test_result_t *ret);
+static void tfm_ipc_test_1004(struct test_result_t *ret);
+
+static struct test_t ipc_veneers_tests[] = {
+ {&tfm_ipc_test_1001, "TFM_IPC_TEST_1001",
+ "Get PSA framework version", {0} },
+ {&tfm_ipc_test_1002, "TFM_IPC_TEST_1002",
+ "Get minor version of a RoT Service", {0} },
+ {&tfm_ipc_test_1003, "TFM_IPC_TEST_1003",
+ "Connect to a RoT Service", {0} },
+ {&tfm_ipc_test_1004, "TFM_IPC_TEST_1004",
+ "Call a RoT Service", {0} }
+};
+
+void register_testsuite_ns_ipc_interface(struct test_suite_t *p_test_suite)
+{
+ uint32_t list_size;
+
+ list_size = (sizeof(ipc_veneers_tests) / sizeof(ipc_veneers_tests[0]));
+
+ set_testsuite("IPC non-secure interface test (TFM_IPC_TEST_1XXX)",
+ ipc_veneers_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Retrieve the version of the PSA Framework API.
+ *
+ * \note This is a functional test only and doesn't
+ * mean to test all possible combinations of
+ * input parameters and return values.
+ */
+static void tfm_ipc_test_1001(struct test_result_t *ret)
+{
+ uint32_t version;
+
+ version = psa_framework_version();
+ if (version == PSA_FRAMEWORK_VERSION) {
+ TEST_LOG("The version of the PSA Framework API is %d.\r\n", version);
+ } else {
+ TEST_FAIL("The version of the PSA Framework API is not valid!\r\n");
+ return;
+ }
+}
+
+/**
+ * \brief Retrieve the minor version of a RoT Service.
+ */
+static void tfm_ipc_test_1002(struct test_result_t *ret)
+{
+ uint32_t version;
+
+ version = psa_version(IPC_TEST_SERVICE1_SID);
+ if (version == PSA_VERSION_NONE) {
+ TEST_FAIL("RoT Service is not implemented or caller is not authorized" \
+ "to access it!\r\n");
+ return;
+ } else {
+ /* Valid version number */
+ TEST_LOG("The minor version is %d.\r\n", version);
+ }
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Connect to a RoT Service by its SID.
+ */
+static void tfm_ipc_test_1003(struct test_result_t *ret)
+{
+ psa_handle_t handle;
+
+ handle = psa_connect(IPC_TEST_SERVICE1_SID, IPC_TEST_SERVICE1_MIN_VER);
+ if (handle > 0) {
+ TEST_LOG("Connect success!\r\n");
+ } else {
+ TEST_FAIL("The RoT Service has refused the connection!\r\n");
+ return;
+ }
+ psa_close(handle);
+ ret->val = TEST_PASSED;
+}
+
+/**
+ * \brief Call a RoT Service.
+ */
+static void tfm_ipc_test_1004(struct test_result_t *ret)
+{
+ char str1[] = "str1";
+ char str2[] = "str2";
+ char str3[128], str4[128];
+ struct psa_invec invecs[2] = {{str1, sizeof(str1)/sizeof(char)},
+ {str2, sizeof(str2)/sizeof(char)}};
+ struct psa_outvec outvecs[2] = {{str3, sizeof(str3)/sizeof(char)},
+ {str4, sizeof(str4)/sizeof(char)}};
+ psa_handle_t handle;
+ psa_status_t status;
+ uint32_t min_version;
+
+ min_version = psa_version(IPC_TEST_SERVICE1_SID);
+ TEST_LOG("TFM service support minor version is %d.\r\n", min_version);
+ handle = psa_connect(IPC_TEST_SERVICE1_SID, IPC_TEST_SERVICE1_MIN_VER);
+ status = psa_call(handle, invecs, 2, outvecs, 2);
+ if (status >= 0) {
+ TEST_LOG("psa_call is successful!\r\n");
+ } else if (status == PSA_DROP_CONNECTION) {
+ TEST_FAIL("The connection has been dropped by the RoT Service!\r\n");
+ return;
+ } else {
+ TEST_FAIL("psa_call is failed!\r\n");
+ return;
+ }
+ TEST_LOG("outvec1 is: %s\r\n", outvecs[0].base);
+ TEST_LOG("outvec2 is: %s\r\n", outvecs[1].base);
+ psa_close(handle);
+ ret->val = TEST_PASSED;
+}
diff --git a/test/suites/ipc/non_secure/ipc_ns_tests.h b/test/suites/ipc/non_secure/ipc_ns_tests.h
new file mode 100644
index 0000000..12f3bb6
--- /dev/null
+++ b/test/suites/ipc/non_secure/ipc_ns_tests.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __IPC_NS_TESTS_H__
+#define __IPC_NS_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for ipc non-secure interface.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void register_testsuite_ns_ipc_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IPC_NS_TESTS_H__ */
diff --git a/test/suites/ipc/secure/ipc_s_interface_testsuite.c b/test/suites/ipc/secure/ipc_s_interface_testsuite.c
new file mode 100644
index 0000000..62258b8
--- /dev/null
+++ b/test/suites/ipc/secure/ipc_s_interface_testsuite.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "ipc_s_tests.h"
+#include "psa_client.h"
+#include "test/framework/test_framework_helpers.h"
+
+/* List of tests */
+static void tfm_ipc_test_1001(struct test_result_t *ret);
+
+static struct test_t ipc_veneers_tests[] = {
+ {&tfm_ipc_test_1001, "TFM_IPC_TEST_1001", "Secure functional", {0} },
+};
+
+void register_testsuite_s_ipc_interface(struct test_suite_t *p_test_suite)
+{
+ uint32_t list_size;
+
+ list_size = (sizeof(ipc_veneers_tests) / sizeof(ipc_veneers_tests[0]));
+
+ set_testsuite("IPC secure interface test (TFM_IPC_TEST_1XXX)",
+ ipc_veneers_tests, list_size, p_test_suite);
+}
+
+/**
+ * \brief Functional test of the Secure interface
+ *
+ * \note This is a functional test only and doesn't
+ * mean to test all possible combinations of
+ * input parameters and return values.
+ */
+static void tfm_ipc_test_1001(struct test_result_t *ret)
+{
+ ret->val = TEST_PASSED;
+}
diff --git a/test/suites/ipc/secure/ipc_s_tests.h b/test/suites/ipc/secure/ipc_s_tests.h
new file mode 100644
index 0000000..3b6a755
--- /dev/null
+++ b/test/suites/ipc/secure/ipc_s_tests.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __IPC_S_TESTS_H__
+#define __IPC_S_TESTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "test/framework/test_framework.h"
+
+/**
+ * \brief Register testsuite for ipc secure interface.
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void register_testsuite_s_ipc_interface(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IPC_S_TESTS_H__ */
diff --git a/test/test_services/CMakeLists.inc b/test/test_services/CMakeLists.inc
index 7006095..b91ae2c 100644
--- a/test/test_services/CMakeLists.inc
+++ b/test/test_services/CMakeLists.inc
@@ -48,6 +48,14 @@
list(APPEND ALL_SRC_C_NS "${CORE_TEST_DIR}/tfm_secure_client_service/tfm_secure_client_service_api.c")
endif()
+if (NOT DEFINED CORE_TEST_IPC)
+ message(FATAL_ERROR "Incomplete build configuration: CORE_TEST_IPC is undefined. ")
+elseif (CORE_TEST_IPC)
+ list(APPEND ALL_SRC_C_S "${CORE_TEST_DIR}/tfm_ipc_service/tfm_ipc_service_test.c"
+ "${CORE_TEST_DIR}/tfm_ipc_client/tfm_ipc_client_test.c"
+ )
+endif()
+
embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE)
diff --git a/test/test_services/tfm_core_test/manifest.yaml b/test/test_services/tfm_core_test/manifest.yaml
index 076b650..58abfe1 100644
--- a/test/test_services/tfm_core_test/manifest.yaml
+++ b/test/test_services/tfm_core_test/manifest.yaml
@@ -1,17 +1,16 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
{
- "name": "TFM_CORE_TEST",
- "tfm_partition_name": "TFM_SP_CORE_TEST",
- "type": "SECURE",
+ "name": "TFM_SP_CORE_TEST",
+ "type": "APPLICATION-ROT",
"priority": "NORMAL",
"id": "0x00000002",
- "entry_point": "main",
+ "entry_point": "core_test_init",
"stack_size": "0x0400",
"heap_size": "0x0400",
"mmio_regions": [
@@ -20,7 +19,6 @@
"permission": "READ-WRITE"
}
],
- "tfm_init_symbol": "core_test_init",
"secure_functions": [
{
"sfid": "TFM_CORE_TEST_SFN_SFID",
diff --git a/test/test_services/tfm_core_test_2/manifest.yaml b/test/test_services/tfm_core_test_2/manifest.yaml
index b5b4fce..d95209f 100644
--- a/test/test_services/tfm_core_test_2/manifest.yaml
+++ b/test/test_services/tfm_core_test_2/manifest.yaml
@@ -1,20 +1,18 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
{
- "name": "TFM_CORE_TEST_2",
- "tfm_partition_name": "TFM_SP_CORE_TEST_2",
- "type": "SECURE",
+ "name": "TFM_SP_CORE_TEST_2",
+ "type": "APPLICATION-ROT",
"priority": "NORMAL",
"id": "0x00000003",
- "entry_point": "main",
+ "entry_point": "core_test_2_init",
"stack_size": "0x0400",
"heap_size": "0x0400",
- "tfm_init_symbol": "core_test_2_init",
"secure_functions": [
{
"sfid": "TFM_CORE_TEST_2_SFN_SLAVE_SERVICE_SFID",
diff --git a/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml b/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml
new file mode 100644
index 0000000..781caa0
--- /dev/null
+++ b/test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml
@@ -0,0 +1,27 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+ "name": "TFM_SP_IPC_CLIENT_TEST",
+ "type": "APPLICATION-ROT",
+ "priority": "NORMAL",
+ "id": "0x00000006",
+ "entry_point": "ipc_client_init",
+ "stack_size": "0x1000",
+ "heap_size": "0",
+ "secure_functions": [
+ ],
+ "tfm_partition_ipc": true,
+ "source_files": [
+ "ipc_client_test.c",
+ ],
+ "tfm_linker_pattern": {
+ "library_list": [
+ "*ipc_client_test*"
+ ]
+ }
+}
diff --git a/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c b/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c
new file mode 100644
index 0000000..f343a04
--- /dev/null
+++ b/test/test_services/tfm_ipc_client/tfm_ipc_client_test.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include "psa_client.h"
+#include "secure_utilities.h"
+
+/* These SID should be same with service manifest.*/
+#define IPC_TEST_SERVICE1_SID (0x1000)
+#define IPC_TEST_SERVICE1_MIN_VER (0x0001)
+
+int ipc_client_init(void)
+{
+ psa_handle_t handle;
+ psa_status_t status;
+ char str1[] = "123";
+ char str2[] = "456";
+ char str3[64], str4[64];
+ struct psa_invec invecs[2] = {{str1, sizeof(str1)/sizeof(char)},
+ {str2, sizeof(str2)/sizeof(char)}};
+ struct psa_outvec outvecs[2] = {{str3, sizeof(str3)/sizeof(char)},
+ {str4, sizeof(str4)/sizeof(char)}};
+
+
+ LOG_MSG("hello! this is ipc client test sp!");
+
+ handle = psa_connect(IPC_TEST_SERVICE1_SID, IPC_TEST_SERVICE1_MIN_VER);
+ if (handle > 0) {
+ LOG_MSG("Connect success!");
+ } else {
+ LOG_MSG("The RoT Service has refused the connection!");
+ }
+
+ status = psa_call(handle, invecs, 2, outvecs, 2);
+ if (status >= 0) {
+ LOG_MSG("Call success!");
+ } else {
+ LOG_MSG("Call failed!");
+ }
+
+ psa_close(handle);
+ return 0;
+}
diff --git a/test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h b/test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h
new file mode 100644
index 0000000..759ccfa
--- /dev/null
+++ b/test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_IPC_SERVICE_PARTITION_H__
+#define __TFM_IPC_SERVICE_PARTITION_H__
+
+/* FixMe: hardcode it for the tool cannot support now */
+#ifdef TFM_PSA_API
+#define IPC_BASIC_SIGNAL (1 << (0 + 4))
+#endif /* TFM_PSA_API */
+
+#endif /* __TFM_IPC_SERVICE_PARTITION_H__ */
diff --git a/test/test_services/tfm_ipc_service/tfm_ipc_service_partition.yaml b/test/test_services/tfm_ipc_service/tfm_ipc_service_partition.yaml
new file mode 100644
index 0000000..e9fcf32
--- /dev/null
+++ b/test/test_services/tfm_ipc_service/tfm_ipc_service_partition.yaml
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+ "name": "TFM_SP_IPC_SERVICE_TEST",
+ "type": "APPLICATION-ROT",
+ "priority": "HIGH",
+ "id": "0x00000007",
+ "entry_point": "ipc_service_test_main",
+ "stack_size": "0x1000",
+ "heap_size": "0",
+ "secure_functions": [
+ ],
+ "tfm_partition_ipc": true,
+ "services" : [{
+ "name": "IPC_SID_BASIC",
+ "sid": "0x00001000",
+ "signal": "IPC_BASIC_SIGNAL",
+ "non_secure_clients": "true",
+ "minor_version": 1,
+ "minor_policy": "STRICT"
+ }
+ ],
+ "source_files": [
+ "./ipc_service_test.c",
+ ],
+ "tfm_linker_pattern": {
+ "library_list": [
+ "*ipc_service_test*"
+ ]
+ }
+}
diff --git a/test/test_services/tfm_ipc_service/tfm_ipc_service_test.c b/test/test_services/tfm_ipc_service/tfm_ipc_service_test.c
new file mode 100644
index 0000000..e8f25a8
--- /dev/null
+++ b/test/test_services/tfm_ipc_service/tfm_ipc_service_test.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include "psa_client.h"
+#include "psa_service.h"
+#include "secure_fw/core/secure_utilities.h"
+#include "secure_fw/core/tfm_secure_api.h"
+#include "tfm_api.h"
+#include "tfm_ipc_service_partition.h"
+
+#define IPC_SERVICE_BUFFER_LEN 64
+
+static int inuse = 0;
+
+static psa_status_t ipc_service_call(psa_msg_t *msg)
+{
+ int i;
+ uint8_t rec_buf[IPC_SERVICE_BUFFER_LEN];
+ uint8_t send_buf[IPC_SERVICE_BUFFER_LEN] = "It is just for IPC call test.";
+
+ for (i = 0; i < PSA_MAX_IOVEC; i++) {
+ if (msg->in_size[i] != 0) {
+ psa_read(msg->handle, i, rec_buf, IPC_SERVICE_BUFFER_LEN);
+ }
+ if (msg->out_size[i] != 0) {
+ psa_write(msg->handle, i, send_buf, IPC_SERVICE_BUFFER_LEN);
+ }
+ }
+ return PSA_SUCCESS;
+}
+
+/* Test thread */
+void ipc_service_test_main(void *param)
+{
+ uint32_t signals = 0;
+ psa_msg_t msg;
+ psa_status_t r;
+
+ while (1) {
+ signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+ if (signals & IPC_BASIC_SIGNAL) {
+ psa_get(IPC_BASIC_SIGNAL, &msg);
+ switch (msg.type) {
+ case PSA_IPC_CONNECT:
+ if (inuse) {
+ r = PSA_CONNECTION_REFUSED;
+ } else {
+ inuse = 1;
+ r = PSA_SUCCESS;
+ }
+ psa_reply(msg.handle, r);
+ break;
+ case PSA_IPC_CALL:
+ psa_reply(msg.handle, ipc_service_call(&msg));
+ break;
+ case PSA_IPC_DISCONNECT:
+ assert (inuse == 1);
+ inuse = 0;
+ psa_reply(msg.handle, PSA_SUCCESS);
+ break;
+ default:
+ /* cannot get here? [broken SPM]. TODO*/
+ break;
+ }
+ }
+ }
+
+ return;
+}
diff --git a/test/test_services/tfm_secure_client_service/manifest.yaml b/test/test_services/tfm_secure_client_service/manifest.yaml
index 9ab5b62..79728ee 100644
--- a/test/test_services/tfm_secure_client_service/manifest.yaml
+++ b/test/test_services/tfm_secure_client_service/manifest.yaml
@@ -1,18 +1,16 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
#-------------------------------------------------------------------------------
{
- "name": "TFM_SECURE_CLIENT",
- "tfm_partition_name": "TFM_SP_SECURE_TEST_PARTITION",
- "type": "TRUSTED",
- "tfm_trusted": true,
+ "name": "TFM_SP_SECURE_TEST_PARTITION",
+ "type": "PSA-ROT",
"priority": "NORMAL",
"id": "0x00000005",
- "entry_point": "main",
+ "entry_point": "tfm_secure_client_service_init",
"stack_size": "0x1000",
"heap_size": "0x0400",
"mmio_regions": [
@@ -21,7 +19,6 @@
"permission": "READ-WRITE"
}
],
- "tfm_init_symbol": "tfm_secure_client_service_init",
"secure_functions": [
{
"sfid": "TFM_SECURE_CLIENT_SFN_RUN_TESTS_SFID",
diff --git a/tools/tfm_generated_file_list.yaml b/tools/tfm_generated_file_list.yaml
index 2669953..23cc0a2 100644
--- a/tools/tfm_generated_file_list.yaml
+++ b/tools/tfm_generated_file_list.yaml
@@ -1,5 +1,5 @@
#-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -22,9 +22,9 @@
"output": "secure_fw/services/tfm_partition_list.inc"
},
{
- "name": "Secure Function list",
- "short_name": "tfm_sfid_list",
- "output": "secure_fw/services/tfm_sfid_list.inc"
+ "name": "Secure Service list",
+ "short_name": "tfm_service_list",
+ "output": "secure_fw/services/tfm_service_list.inc"
},
{
"name": "AN521 secure ld file",
diff --git a/tools/tfm_manifest_list.yaml b/tools/tfm_manifest_list.yaml
index 15486d5..bbcdffd 100644
--- a/tools/tfm_manifest_list.yaml
+++ b/tools/tfm_manifest_list.yaml
@@ -77,6 +77,24 @@
"conditional": "TFM_PARTITION_TEST_SECURE_SERVICES",
"version_major": 0,
"version_minor": 1
+ },
+ {
+ "name": "TFM IPC Service Test",
+ "short_name": "TFM_IPC_Service",
+ "manifest": "test/test_services/tfm_ipc_service/tfm_ipc_service_partition.yaml",
+ "tfm_extensions": true,
+ "conditional": "TFM_PSA_API",
+ "version_major": 0,
+ "version_minor": 1
+ },
+ {
+ "name": "TFM IPC Client Service",
+ "short_name": "TFM_IPC_Client",
+ "manifest": "test/test_services/tfm_ipc_client/tfm_ipc_client_partition.yaml",
+ "tfm_extensions": true,
+ "conditional": "TFM_PSA_API",
+ "version_major": 0,
+ "version_minor": 1
}
]
}