SPM: Add runtime SFN backend
A backend for implementing 'SFN'. This runtime backend is selected
if:
- All partitions included in the current build are 'SFN' partitions.
- Isolation level 1.
The configuration is generated by tooling, and output to the
generated file 'config_impl.h'.
Change-Id: I819c78c7a912f86174d102d389a2714ae17e5062
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
Co-authored-by: Mingyang Sun <mingyang.sun@arm.com>
diff --git a/secure_fw/spm/CMakeLists.txt b/secure_fw/spm/CMakeLists.txt
index eccc807..3686ad1 100755
--- a/secure_fw/spm/CMakeLists.txt
+++ b/secure_fw/spm/CMakeLists.txt
@@ -53,7 +53,7 @@
$<$<BOOL:${TFM_PSA_API}>:cmsis_psa/spm_thread_call.c>
$<$<BOOL:${TFM_PSA_API}>:cmsis_psa/static_load.c>
$<$<BOOL:${TFM_PSA_API}>:ffm/psa_api.c>
- $<$<BOOL:${TFM_PSA_API}>:ffm/backend_ipc.c>
+ $<$<BOOL:${TFM_PSA_API}>:ffm/backend.c>
$<$<BOOL:${TFM_PSA_API}>:cmsis_psa/tfm_core_svcalls_ipc.c>
$<$<AND:$<BOOL:${TFM_PSA_API}>,$<NOT:$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>>>:cmsis_psa/tfm_nspm_ipc.c>
$<$<BOOL:${TFM_PSA_API}>:cmsis_psa/tfm_pools.c>
diff --git a/secure_fw/spm/cmsis_psa/psa_interface_sfn.c b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
new file mode 100644
index 0000000..5e566cf
--- /dev/null
+++ b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "current.h"
+#include "tfm_psa_call_pack.h"
+#include "ffm/backend.h"
+#include "ffm/psa_api.h"
+#include "psa/client.h"
+
+#ifdef CONFIG_TFM_PSA_API_SFN_CALL
+
+uint32_t psa_framework_version_sfn(void)
+{
+ return tfm_spm_client_psa_framework_version();
+}
+
+uint32_t psa_version_sfn(uint32_t sid)
+{
+ return tfm_spm_client_psa_version(sid);
+}
+
+psa_handle_t psa_connect_sfn(uint32_t sid, uint32_t version)
+{
+ struct partition_t *p_client, *p_target;
+ psa_status_t stat;
+
+ p_client = GET_CURRENT_COMPONENT();
+
+ stat = tfm_spm_client_psa_connect(sid, version);
+
+ p_target = GET_CURRENT_COMPONENT();
+ if (p_client == p_target) {
+ /* There should be errors if the 'current' is not switched. */
+ TFM_CORE_ASSERT(stat < PSA_SUCCESS);
+
+ return stat;
+ }
+
+ return (psa_handle_t)tfm_spm_partition_psa_reply(
+ p_target->p_msg->msg.handle, stat);
+}
+
+psa_status_t psa_call_pack_sfn(psa_handle_t handle, uint32_t ctrl_param,
+ const psa_invec *in_vec, psa_outvec *out_vec)
+{
+ struct partition_t *p_client, *p_target;
+ psa_status_t stat;
+
+ p_client = GET_CURRENT_COMPONENT();
+
+ stat = tfm_spm_client_psa_call(handle, ctrl_param, in_vec, out_vec);
+
+ p_target = GET_CURRENT_COMPONENT();
+ if (p_client == p_target) {
+ /* There should be errors if the 'current' is not switched. */
+ TFM_CORE_ASSERT(stat < PSA_SUCCESS);
+ return stat;
+ }
+
+ return (psa_status_t)tfm_spm_partition_psa_reply(
+ p_target->p_msg->msg.handle, stat);
+}
+
+void psa_close_sfn(psa_handle_t handle)
+{
+ struct partition_t *p_client, *p_target;
+
+ p_client = GET_CURRENT_COMPONENT();
+
+ tfm_spm_client_psa_close(handle);
+
+ p_target = GET_CURRENT_COMPONENT();
+ if (p_client == p_target) {
+ /* There should be problems if the 'current' is not switched. */
+ return;
+ }
+
+ (void)tfm_spm_partition_psa_reply(p_target->p_msg->msg.handle, PSA_SUCCESS);
+}
+
+psa_signal_t psa_wait_sfn(psa_signal_t signal_mask, uint32_t timeout)
+{
+ /*
+ * TODO:
+ * Need to trigger scheduler here, when 'psa_wait'
+ * is needed (interrupt case, e.g.).
+ */
+ return tfm_spm_partition_psa_wait(signal_mask, timeout);
+}
+
+size_t psa_read_sfn(psa_handle_t msg_handle, uint32_t invec_idx,
+ void *buffer, size_t num_bytes)
+{
+ return tfm_spm_partition_psa_read(msg_handle, invec_idx,
+ buffer, num_bytes);
+}
+
+size_t psa_skip_sfn(psa_handle_t msg_handle, uint32_t invec_idx,
+ size_t num_bytes)
+{
+ return tfm_spm_partition_psa_skip(msg_handle, invec_idx, num_bytes);
+}
+
+void psa_write_sfn(psa_handle_t msg_handle, uint32_t outvec_idx,
+ const void *buffer, size_t num_bytes)
+{
+ tfm_spm_partition_psa_write(msg_handle, outvec_idx, buffer, num_bytes);
+}
+
+void psa_panic_sfn(void)
+{
+ tfm_spm_partition_psa_panic();
+}
+
+#endif /* CONFIG_TFM_PSA_API_SFN_CALL */
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.c b/secure_fw/spm/cmsis_psa/spm_ipc.c
index 8198389..7db60ba 100755
--- a/secure_fw/spm/cmsis_psa/spm_ipc.c
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.c
@@ -9,6 +9,7 @@
#include <stdbool.h>
#include "bitops.h"
#include "critical_section.h"
+#include "current.h"
#include "fih.h"
#include "psa/client.h"
#include "psa/service.h"
@@ -141,7 +142,7 @@
return NULL;
}
- p_handle->service = service;
+ p_handle->internal_msg.service = service;
p_handle->status = TFM_HANDLE_STATUS_IDLE;
p_handle->client_id = client_id;
@@ -310,7 +311,7 @@
struct partition_t *tfm_spm_get_running_partition(void)
{
- return GET_THRD_OWNER(CURRENT_THREAD);
+ return GET_CURRENT_COMPONENT();
}
int32_t tfm_spm_check_client_version(struct service_t *service,
@@ -439,11 +440,12 @@
TFM_CORE_ASSERT(in_len + out_len <= PSA_MAX_IOVEC);
/* Clear message buffer before using it */
- spm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
+ spm_memset(&msg->msg, 0, sizeof(psa_msg_t));
THRD_SYNC_INIT(&msg->ack_evnt);
msg->magic = TFM_MSG_MAGIC;
msg->service = service;
+ msg->p_client = GET_CURRENT_COMPONENT();
msg->caller_outvec = caller_outvec;
msg->msg.client_id = client_id;
@@ -647,7 +649,6 @@
}
#endif /* TFM_FIH_PROFILE_ON */
- /* TODO: Replace this 'BACKEND_IPC' after SFN get involved. */
backend_instance.comp_init_assuredly(partition, service_setting);
}
@@ -722,8 +723,11 @@
* FixeMe: abstract these part into dedicated functions to avoid
* accessing thread context in psa layer
*/
- /* If it is a NS request via RPC, the owner of this message is not set */
- if (!is_tfm_rpc_msg(msg)) {
+ /*
+ * If it is a NS request via RPC, the owner of this message is not set.
+ * Or if it is a SFN message, it does not have owner thread state either.
+ */
+ if ((!is_tfm_rpc_msg(msg)) && (msg->sfn_magic != TFM_MSG_MAGIC_SFN)) {
TFM_CORE_ASSERT(msg->ack_evnt.owner->state == THRD_STATE_BLOCK);
}
diff --git a/secure_fw/spm/cmsis_psa/spm_ipc.h b/secure_fw/spm/cmsis_psa/spm_ipc.h
index 908ae90..a2edf7b 100644
--- a/secure_fw/spm/cmsis_psa/spm_ipc.h
+++ b/secure_fw/spm/cmsis_psa/spm_ipc.h
@@ -59,6 +59,7 @@
#define SPM_INVALID_PARTITION_IDX (~0U)
#define TFM_MSG_MAGIC 0x15154343
+#define TFM_MSG_MAGIC_SFN 0x21216565
/* Get partition by thread or context data */
#define GET_THRD_OWNER(x) TO_CONTAINER(x, struct partition_t, thrd)
@@ -67,8 +68,12 @@
/* Message struct to collect parameter from client */
struct tfm_msg_body_t {
int32_t magic;
- struct service_t *service; /* RoT service pointer */
- struct sync_obj_t ack_evnt; /* Event for ack response */
+ struct partition_t *p_client; /* Caller partition */
+ struct service_t *service; /* RoT service pointer */
+ union {
+ struct sync_obj_t ack_evnt; /* IPC - Ack response event */
+ uint32_t sfn_magic; /* SFN - Indicate a SFN message */
+ };
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];
@@ -95,10 +100,16 @@
void *p_boundaries;
void *p_interrupts;
void *p_metadata;
- struct thread_t thrd;
+ union {
+ struct thread_t thrd; /* IPC model */
+ uint32_t state; /* SFN model */
+ };
struct sync_obj_t waitobj;
struct context_ctrl_t ctx_ctrl;
- struct bi_list_node_t msg_list;
+ union {
+ struct bi_list_node_t msg_list; /* IPC model */
+ struct tfm_msg_body_t *p_msg; /* SFN model */
+ };
uint32_t signals_allowed;
uint32_t signals_waiting;
uint32_t signals_asserted;
@@ -130,7 +141,6 @@
* - non secure client endpoint id.
*/
struct tfm_msg_body_t internal_msg; /* Internal message for message queue */
- struct service_t *service; /* RoT service pointer */
struct bi_list_node_t list; /* list node */
};
diff --git a/secure_fw/spm/cmsis_psa/thread.h b/secure_fw/spm/cmsis_psa/thread.h
index ad1aad9..342d538 100644
--- a/secure_fw/spm/cmsis_psa/thread.h
+++ b/secure_fw/spm/cmsis_psa/thread.h
@@ -30,7 +30,7 @@
#define THRD_ERR_GENERIC 1
/* Thread entry function type */
-typedef void *(*thrd_fn_t)(void *);
+typedef void (*thrd_fn_t)(void *);
/* Thread context */
struct thread_t {
diff --git a/secure_fw/spm/ffm/backend.c b/secure_fw/spm/ffm/backend.c
new file mode 100644
index 0000000..9df5de7
--- /dev/null
+++ b/secure_fw/spm/ffm/backend.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include "config_impl.h"
+
+#if CONFIG_TFM_SPM_BACKEND_SFN == 1
+#include "backend_sfn.c"
+#elif CONFIG_TFM_SPM_BACKEND_IPC == 1
+#include "backend_ipc.c"
+#else
+#error "Invalid configuration."
+#endif
diff --git a/secure_fw/spm/ffm/backend_ipc.c b/secure_fw/spm/ffm/backend_ipc.c
index ee1a4c2..c544f73 100644
--- a/secure_fw/spm/ffm/backend_ipc.c
+++ b/secure_fw/spm/ffm/backend_ipc.c
@@ -41,7 +41,7 @@
/*
* Send message and wake up the SP who is waiting on message queue, block the
- * current thread and triggere scheduler.
+ * current thread and trigger scheduler.
*/
static psa_status_t ipc_messaging(struct service_t *service,
struct tfm_msg_body_t *msg)
@@ -80,13 +80,20 @@
return PSA_SUCCESS;
}
-static void ipc_replying(struct tfm_msg_body_t *p_msg, psa_status_t status)
+static int32_t ipc_replying(struct tfm_msg_body_t *p_msg, int32_t status)
{
if (is_tfm_rpc_msg(p_msg)) {
tfm_rpc_client_call_reply(p_msg, status);
} else {
thrd_wake_up(&p_msg->ack_evnt, status);
}
+
+ /*
+ * 'psa_reply' exists in IPC model only and returns 'void'. Return
+ * 'PSA_SUCCESS' here always since SPM does not forward the status
+ * to the caller.
+ */
+ return PSA_SUCCESS;
}
/* Parameters are treated as assuredly */
diff --git a/secure_fw/spm/ffm/backend_sfn.c b/secure_fw/spm/ffm/backend_sfn.c
new file mode 100644
index 0000000..14736e9
--- /dev/null
+++ b/secure_fw/spm/ffm/backend_sfn.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "compiler_ext_defs.h"
+#include "current.h"
+#include "tfm_spm_hal.h"
+#include "ffm/backend.h"
+#include "load/partition_defs.h"
+#include "load/service_defs.h"
+#include "load/spm_load_api.h"
+#include "psa/error.h"
+#include "psa/service.h"
+#include "spm_ipc.h"
+
+/* SFN Partition state */
+#define SFN_PARTITION_STATE_NOT_INITED 0
+#define SFN_PARTITION_STATE_INITED 1
+
+typedef psa_status_t (*service_fn_t)(psa_msg_t *msg);
+typedef psa_status_t (*sfn_init_fn_t)(void);
+
+/* Declare the global component list */
+struct partition_head_t partition_listhead;
+
+/* TODO: To be checked with the RPC design. */
+static uintptr_t spm_stack_limit;
+static uintptr_t spm_stack_base;
+
+/*
+ * Send message and wake up the SP who is waiting on message queue, block the
+ * current component state and activate the next component.
+ */
+static psa_status_t sfn_messaging(struct service_t *service,
+ struct tfm_msg_body_t *msg)
+{
+ struct partition_t *p_target;
+ psa_status_t status;
+
+ if (!msg || !service || !service->p_ldinf || !service->partition) {
+ tfm_core_panic();
+ }
+
+ msg->sfn_magic = TFM_MSG_MAGIC_SFN;
+ p_target = service->partition;
+ p_target->p_msg = msg;
+
+ SET_CURRENT_COMPONENT(p_target);
+
+ if (p_target->state == SFN_PARTITION_STATE_NOT_INITED) {
+ if (p_target->p_ldinf->entry != 0) {
+ status = ((sfn_init_fn_t)p_target->p_ldinf->entry)();
+ /* Negative value indicates errors. */
+ if (status < PSA_SUCCESS) {
+ tfm_core_panic();
+ }
+ }
+ p_target->state = SFN_PARTITION_STATE_INITED;
+ }
+
+ status = ((service_fn_t)service->p_ldinf->sfn)(&msg->msg);
+
+ return status;
+}
+
+static int32_t sfn_replying(struct tfm_msg_body_t *p_msg, int32_t status)
+{
+ SET_CURRENT_COMPONENT(p_msg->p_client);
+
+ /*
+ * Returning a value here is necessary, because 'psa_reply' is absent
+ * for SFN clients, the 'reply' method is performed by SPM internally
+ * when SFN case, to forward the 'status' to the caller.
+ *
+ * For example:
+ * 'status' MAY contain a 'psa_handle_t' returned by SPM 'connect' and
+ * SPM needs to 'reply' it back to the caller. Treat 'psa_handle_t' value
+ * as SPM specific return value and represnent it as 'psa_status_t'.
+ */
+ return status;
+}
+
+/* Parameters are treated as assuredly */
+void sfn_comp_init_assuredly(struct partition_t *p_pt, uint32_t service_set)
+{
+ const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
+
+ p_pt->p_msg = NULL;
+ p_pt->state = SFN_PARTITION_STATE_NOT_INITED;
+
+ THRD_SYNC_INIT(&p_pt->waitobj);
+
+ /*
+ * Built-in partitions still have thread instances: NS Agent (TZ) and
+ * IDLE partition, and NS Agent (TZ) needs to be specific cared here.
+ */
+ if (p_pldi->flags & PARTITION_MODEL_IPC) {
+ THRD_INIT(&p_pt->thrd, &p_pt->ctx_ctrl,
+ TO_THREAD_PRIORITY(PARTITION_PRIORITY(p_pldi->flags)));
+
+ thrd_start(&p_pt->thrd,
+ POSITION_TO_ENTRY(p_pldi->entry, thrd_fn_t),
+ (void *)tfm_spm_hal_get_ns_entry_point(),
+ LOAD_ALLOCED_STACK_ADDR(p_pldi),
+ LOAD_ALLOCED_STACK_ADDR(p_pldi) + p_pldi->stack_size);
+
+ /* SPM reuses the ns agent stack, use once only at initialization. */
+ if (p_pldi->pid == TFM_SP_NON_SECURE_ID) {
+ spm_stack_limit = p_pt->ctx_ctrl.sp_limit;
+ spm_stack_base = p_pt->ctx_ctrl.sp;
+ }
+ }
+
+ (void)service_set;
+}
+
+static void spm_thread_fn(void *p)
+{
+ struct partition_t *p_part, *p_curr;
+
+ p_curr = GET_CURRENT_COMPONENT();
+ /* Call partition initialization routine one by one. */
+ UNI_LIST_FOR_EACH(p_part, PARTITION_LIST_ADDR) {
+ if (p_part->p_ldinf->flags & PARTITION_MODEL_IPC) {
+ continue;
+ }
+
+ if (p_part->state == SFN_PARTITION_STATE_INITED) {
+ continue;
+ }
+
+ SET_CURRENT_COMPONENT(p_part);
+
+ if (p_part->p_ldinf->entry != 0) {
+ if (((sfn_init_fn_t)p_part->p_ldinf->entry)() < PSA_SUCCESS) {
+ tfm_core_panic();
+ }
+ }
+
+ p_part->state = SFN_PARTITION_STATE_INITED;
+ }
+
+ SET_CURRENT_COMPONENT(p_curr);
+
+ thrd_set_state(CURRENT_THREAD, THRD_STATE_DETACH);
+
+ tfm_arch_trigger_pendsv();
+}
+
+uint32_t sfn_system_run(void)
+{
+ struct thread_t *p_thrd = (struct thread_t *)spm_stack_limit;
+ struct context_ctrl_t *p_ctxctrl = (struct context_ctrl_t *)(p_thrd + 1);
+ uintptr_t sp_limit = (((uintptr_t)(p_ctxctrl + 1)) + 7) & ~0x7;
+ uintptr_t sp_base = spm_stack_base;
+
+ THRD_INIT(p_thrd, p_ctxctrl, THRD_PRIOR_HIGHEST);
+ thrd_start(p_thrd, spm_thread_fn, NULL, sp_limit, sp_base);
+
+ return thrd_start_scheduler(&CURRENT_THREAD);
+}
+
+const struct backend_ops_t backend_instance = {
+ .comp_init_assuredly = sfn_comp_init_assuredly,
+ .system_run = sfn_system_run,
+ .messaging = sfn_messaging,
+ .replying = sfn_replying
+};
diff --git a/secure_fw/spm/ffm/psa_api.c b/secure_fw/spm/ffm/psa_api.c
index af35a2d..561f9ef 100644
--- a/secure_fw/spm/ffm/psa_api.c
+++ b/secure_fw/spm/ffm/psa_api.c
@@ -16,6 +16,7 @@
#include "load/partition_defs.h"
#include "load/service_defs.h"
#include "load/interrupt_defs.h"
+#include "ffm/psa_api.h"
#include "utilities.h"
#include "ffm/backend.h"
#include "ffm/psa_api.h"
@@ -287,7 +288,7 @@
return PSA_ERROR_PROGRAMMER_ERROR;
}
- service = conn_handle->service;
+ service = conn_handle->internal_msg.service;
}
if (!service) {
@@ -407,7 +408,7 @@
TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
}
- service = conn_handle->service;
+ service = conn_handle->internal_msg.service;
if (!service) {
/* FixMe: Need to implement one mechanism to resolve this failure. */
tfm_core_panic();
@@ -469,8 +470,7 @@
if (timeout == PSA_BLOCK &&
(partition->signals_asserted & signal_mask) == 0) {
partition->signals_waiting = signal_mask;
- thrd_wait_on(&partition->waitobj,
- &(tfm_spm_get_running_partition()->thrd));
+ thrd_wait_on(&partition->waitobj, CURRENT_THREAD);
}
return partition->signals_asserted & signal_mask;
@@ -765,7 +765,8 @@
msg->outvec[outvec_idx].len += num_bytes;
}
-void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status)
+int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
+ psa_status_t status)
{
struct service_t *service = NULL;
struct tfm_msg_body_t *msg = NULL;
@@ -878,7 +879,7 @@
conn_handle->status = TFM_HANDLE_STATUS_IDLE;
}
- backend_instance.replying(msg, ret);
+ return backend_instance.replying(msg, ret);
}
void tfm_spm_partition_psa_notify(int32_t partition_id)
@@ -930,7 +931,7 @@
if (irq_info->flih_func) {
/* This API is for SLIH IRQs only */
- psa_panic();
+ tfm_core_panic();
}
/* It is a fatal error if passed signal is not currently asserted */
diff --git a/secure_fw/spm/include/current.h b/secure_fw/spm/include/current.h
new file mode 100644
index 0000000..e69473d
--- /dev/null
+++ b/secure_fw/spm/include/current.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __CURRENT_H__
+#define __CURRENT_H__
+
+#include "thread.h"
+#include "spm_ipc.h"
+
+/* Get current component */
+#define GET_CURRENT_COMPONENT() GET_CTX_OWNER(CURRENT_THREAD->p_context_ctrl)
+/* Set current component */
+#define SET_CURRENT_COMPONENT(p) THRD_UPDATE_CUR_CTXCTRL(&(p)->ctx_ctrl)
+
+#endif /* __CURRENT_H__ */
diff --git a/secure_fw/spm/include/ffm/backend.h b/secure_fw/spm/include/ffm/backend.h
index 7b7ea00..5efeac0 100644
--- a/secure_fw/spm/include/ffm/backend.h
+++ b/secure_fw/spm/include/ffm/backend.h
@@ -37,9 +37,9 @@
/*
* Runtime model-specific message replying.
- * Return the acked status.
+ * Return the connection handle or the acked status code.
*/
- void (*replying)(struct tfm_msg_body_t *p_msg, psa_status_t status);
+ int32_t (*replying)(struct tfm_msg_body_t *p_msg, int32_t status);
};
/* RUNTIME MODEL BACKENDS DECLARATION */
diff --git a/secure_fw/spm/include/ffm/psa_api.h b/secure_fw/spm/include/ffm/psa_api.h
index 6ea3c46..1c78e46 100644
--- a/secure_fw/spm/include/ffm/psa_api.h
+++ b/secure_fw/spm/include/ffm/psa_api.h
@@ -247,14 +247,16 @@
* \param[in] status Message result value to be reported to the
* client.
*
- * \retval void Success.
+ * \retval Positive integer Success, the connection handle.
+ * \retval PSA_SUCCESS Success
* \retval "PROGRAMMER ERROR" The call is invalid, one or more of the
* following are true:
* \arg msg_handle is invalid.
* \arg An invalid status code is specified for the
* type of message.
*/
-void tfm_spm_partition_psa_reply(psa_handle_t msg_handle, psa_status_t status);
+int32_t tfm_spm_partition_psa_reply(psa_handle_t msg_handle,
+ psa_status_t status);
/**
* \brief Function body of \ref psa_norify.