SPM: Handle specific programmer errors in function
Preprocessor 'TFM_PROGRAMMER_ERROR' contains routine related codes,
CheckPatch would treat it as a warning and cause error in static checks
because it does not align with the recommended coding guidelines.
Signed-off-by: Xinyu Zhang <xinyu.zhang@arm.com>
Change-Id: Ie30dde1d018594e08303afbe29b962438240e1d5
diff --git a/secure_fw/spm/cmsis_psa/psa_interface_sfn.c b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
index 5e566cf..9533bad 100644
--- a/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
+++ b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
@@ -34,15 +34,12 @@
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;
+ if (p_client != p_target) {
+ stat = tfm_spm_partition_psa_reply(p_target->p_msg->msg.handle, stat);
}
- return (psa_handle_t)tfm_spm_partition_psa_reply(
- p_target->p_msg->msg.handle, stat);
+ spm_handle_programmer_errors(stat);
+ return (psa_handle_t)stat;
}
psa_status_t psa_call_pack_sfn(psa_handle_t handle, uint32_t ctrl_param,
@@ -56,31 +53,30 @@
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;
+ if (p_client != p_target) {
+ stat = tfm_spm_partition_psa_reply(p_target->p_msg->msg.handle, stat);
}
- return (psa_status_t)tfm_spm_partition_psa_reply(
- p_target->p_msg->msg.handle, stat);
+ spm_handle_programmer_errors(stat);
+ return (psa_status_t)stat;
}
void psa_close_sfn(psa_handle_t handle)
{
struct partition_t *p_client, *p_target;
+ psa_status_t stat;
p_client = GET_CURRENT_COMPONENT();
- tfm_spm_client_psa_close(handle);
+ stat = 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;
+ if (p_client != p_target) {
+ stat = tfm_spm_partition_psa_reply(p_target->p_msg->msg.handle,
+ PSA_SUCCESS);
}
- (void)tfm_spm_partition_psa_reply(p_target->p_msg->msg.handle, PSA_SUCCESS);
+ spm_handle_programmer_errors(stat);
}
psa_signal_t psa_wait_sfn(psa_signal_t signal_mask, uint32_t timeout)
diff --git a/secure_fw/spm/cmsis_psa/spm_thread_call.c b/secure_fw/spm/cmsis_psa/spm_thread_call.c
index 02fdb56..d64f99b 100644
--- a/secure_fw/spm/cmsis_psa/spm_thread_call.c
+++ b/secure_fw/spm/cmsis_psa/spm_thread_call.c
@@ -12,6 +12,7 @@
#include "tfm_arch.h"
#include "utilities.h"
#include "ffm/backend.h"
+#include "ffm/psa_api.h"
#include "psa/client.h"
#include "psa/lifecycle.h"
#include "psa/service.h"
@@ -54,6 +55,8 @@
((struct spcall_abi_frame_t *)frame_addr)->a0 =
tfm_arch_trigger_pendsv();
}
+
+ spm_handle_programmer_errors(((struct spcall_abi_frame_t *)frame_addr)->a0);
}
#endif /* CONFIG_TFM_PSA_API_THREAD_CALL */
diff --git a/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c b/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
index cb412b1..64a941c 100644
--- a/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
+++ b/secure_fw/spm/cmsis_psa/tfm_core_svcalls_ipc.c
@@ -34,20 +34,25 @@
static int32_t SVC_Handler_IPC(uint8_t svc_num, uint32_t *ctx,
uint32_t lr)
{
+ psa_status_t status = PSA_SUCCESS;
+
switch (svc_num) {
case TFM_SVC_PSA_FRAMEWORK_VERSION:
return tfm_spm_client_psa_framework_version();
case TFM_SVC_PSA_VERSION:
return tfm_spm_client_psa_version(ctx[0]);
case TFM_SVC_PSA_CONNECT:
- return tfm_spm_client_psa_connect(ctx[0], ctx[1]);
- case TFM_SVC_PSA_CALL:
- return tfm_spm_client_psa_call((psa_handle_t)ctx[0], ctx[1],
- (const psa_invec *)ctx[2],
- (psa_outvec *)ctx[3]);
- case TFM_SVC_PSA_CLOSE:
- tfm_spm_client_psa_close((psa_handle_t)ctx[0]);
+ status = tfm_spm_client_psa_connect(ctx[0], ctx[1]);
break;
+ case TFM_SVC_PSA_CALL:
+ status = tfm_spm_client_psa_call((psa_handle_t)ctx[0], ctx[1],
+ (const psa_invec *)ctx[2],
+ (psa_outvec *)ctx[3]);
+ break;
+ case TFM_SVC_PSA_CLOSE:
+ status = tfm_spm_client_psa_close((psa_handle_t)ctx[0]);
+ spm_handle_programmer_errors(status);
+ return PSA_SUCCESS;
case TFM_SVC_PSA_WAIT:
return tfm_spm_partition_psa_wait((psa_signal_t)ctx[0], ctx[1]);
case TFM_SVC_PSA_GET:
@@ -103,7 +108,8 @@
return PSA_ERROR_GENERIC_ERROR;
#endif
}
- return PSA_SUCCESS;
+ spm_handle_programmer_errors(status);
+ return status;
}
extern void tfm_flih_func_return(psa_flih_result_t result);
diff --git a/secure_fw/spm/ffm/psa_api.c b/secure_fw/spm/ffm/psa_api.c
index b4cfbf9f..9d3e6e1 100644
--- a/secure_fw/spm/ffm/psa_api.c
+++ b/secure_fw/spm/ffm/psa_api.c
@@ -86,6 +86,17 @@
#endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
+void spm_handle_programmer_errors(psa_status_t status)
+{
+ if (status == PSA_ERROR_PROGRAMMER_ERROR ||
+ status == PSA_ERROR_CONNECTION_REFUSED ||
+ status == PSA_ERROR_CONNECTION_BUSY) {
+ if (!tfm_spm_is_ns_caller()) {
+ tfm_core_panic();
+ }
+ }
+}
+
uint32_t tfm_spm_get_lifecycle_state(void)
{
/*
@@ -143,12 +154,12 @@
*/
service = tfm_spm_get_service_by_sid(sid);
if (!service) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
+ return PSA_ERROR_CONNECTION_REFUSED;
}
/* It is a PROGRAMMER ERROR if connecting to a stateless service. */
if (SERVICE_IS_STATELESS(service->p_ldinf->flags)) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
/*
@@ -156,7 +167,7 @@
* RoT Service.
*/
if (tfm_spm_check_authorization(sid, service, ns_caller) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
+ return PSA_ERROR_CONNECTION_REFUSED;
}
/*
@@ -164,7 +175,7 @@
* not supported on the platform.
*/
if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
+ return PSA_ERROR_CONNECTION_REFUSED;
}
client_id = tfm_spm_get_client_id(ns_caller);
@@ -216,14 +227,14 @@
/* The request type must be zero or positive. */
if (type < 0) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
/* It is a PROGRAMMER ERROR if in_len + out_len > PSA_MAX_IOVEC. */
if ((in_num > PSA_MAX_IOVEC) ||
(out_num > PSA_MAX_IOVEC) ||
(in_num + out_num > PSA_MAX_IOVEC)) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
client_id = tfm_spm_get_client_id(ns_caller);
@@ -233,7 +244,7 @@
index = GET_INDEX_FROM_STATIC_HANDLE(handle);
if (!IS_VALID_STATIC_HANDLE_IDX(index)) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
service = GET_STATELESS_SERVICE(index);
@@ -249,13 +260,13 @@
*/
if (tfm_spm_check_authorization(sid, service, ns_caller)
!= SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_REFUSED);
+ return PSA_ERROR_CONNECTION_REFUSED;
}
version = GET_VERSION_FROM_STATIC_HANDLE(handle);
if (tfm_spm_check_client_version(service, version) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
CRITICAL_SECTION_ENTER(cs_assert);
@@ -263,7 +274,7 @@
CRITICAL_SECTION_LEAVE(cs_assert);
if (!conn_handle) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_CONNECTION_BUSY);
+ return PSA_ERROR_CONNECTION_BUSY;
}
conn_handle->rhandle = NULL;
@@ -274,7 +285,7 @@
/* It is a PROGRAMMER ERROR if an invalid handle was passed. */
if (tfm_spm_validate_conn_handle(conn_handle, client_id)
!= SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
/*
@@ -282,7 +293,7 @@
* handling a request.
*/
if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
/*
@@ -310,7 +321,7 @@
*/
if (tfm_memory_check(inptr, in_num * sizeof(psa_invec), ns_caller,
TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
/*
@@ -320,7 +331,7 @@
*/
if (tfm_memory_check(outptr, out_num * sizeof(psa_outvec), ns_caller,
TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
spm_memset(invecs, 0, sizeof(invecs));
@@ -337,7 +348,7 @@
for (i = 0; i < in_num; i++) {
if (tfm_memory_check(invecs[i].base, invecs[i].len, ns_caller,
TFM_MEMORY_ACCESS_RO, privileged) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
}
@@ -352,7 +363,7 @@
(char *) invecs[i].base ||
(char *) invecs[j].base >=
(char *) invecs[i].base + invecs[i].len)) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
}
}
@@ -364,7 +375,7 @@
for (i = 0; i < out_num; i++) {
if (tfm_memory_check(outvecs[i].base, outvecs[i].len,
ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
}
@@ -375,7 +386,7 @@
msg = tfm_spm_get_msg_buffer_from_conn_handle(conn_handle);
if (!msg) {
/* FixMe: Need to implement one mechanism to resolve this failure. */
- TFM_PROGRAMMER_ERROR(ns_caller, PSA_ERROR_PROGRAMMER_ERROR);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
tfm_spm_fill_msg(msg, service, handle, type, client_id,
@@ -384,7 +395,7 @@
return backend_instance.messaging(service, msg);
}
-void tfm_spm_client_psa_close(psa_handle_t handle)
+psa_status_t tfm_spm_client_psa_close(psa_handle_t handle)
{
struct service_t *service;
struct tfm_msg_body_t *msg;
@@ -394,12 +405,12 @@
/* It will have no effect if called with the NULL handle */
if (handle == PSA_NULL_HANDLE) {
- return;
+ return PSA_SUCCESS;
}
/* It is a PROGRAMMER ERROR if called with a stateless handle. */
if (IS_STATIC_HANDLE(handle)) {
- TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
client_id = tfm_spm_get_client_id(ns_caller);
@@ -410,7 +421,7 @@
* the null handle.
*/
if (tfm_spm_validate_conn_handle(conn_handle, client_id) != SPM_SUCCESS) {
- TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
service = conn_handle->internal_msg.service;
@@ -430,14 +441,14 @@
* request.
*/
if (conn_handle->status == TFM_HANDLE_STATUS_ACTIVE) {
- TFM_PROGRAMMER_ERROR(ns_caller, PROGRAMMER_ERROR_NULL);
+ return PSA_ERROR_PROGRAMMER_ERROR;
}
/* No input or output needed for close message */
tfm_spm_fill_msg(msg, service, handle, PSA_IPC_DISCONNECT, client_id,
NULL, 0, NULL, 0, NULL);
- (void)backend_instance.messaging(service, msg);
+ return backend_instance.messaging(service, msg);
}
/* PSA Partition API function body */
diff --git a/secure_fw/spm/include/ffm/psa_api.h b/secure_fw/spm/include/ffm/psa_api.h
index ded5232..1258c76 100644
--- a/secure_fw/spm/include/ffm/psa_api.h
+++ b/secure_fw/spm/include/ffm/psa_api.h
@@ -13,15 +13,18 @@
#include "psa/client.h"
#include "psa/service.h"
-#define PROGRAMMER_ERROR_NULL
-#define TFM_PROGRAMMER_ERROR(ns_caller, error_status) \
- do { \
- if (ns_caller) { \
- return error_status; \
- } else { \
- tfm_core_panic(); \
- } \
- } while (0)
+/**
+ * \brief This function handles the specific programmer error cases.
+ *
+ * \param[in] status Standard error codes for the SPM.
+ *
+ * \retval void Status will not cause SPM panic
+ * \retval "SPM panic" Following programmer errors are triggered by SP:
+ * \arg PSA_ERROR_PROGRAMMER_ERROR
+ * \arg PSA_ERROR_CONNECTION_REFUSED
+ * \arg PSA_ERROR_CONNECTION_BUSY
+ */
+void spm_handle_programmer_errors(psa_status_t status);
/**
* \brief This function get the current PSA RoT lifecycle state.
@@ -105,14 +108,15 @@
* \param[in] handle Service handle to the connection to be closed,
* \ref psa_handle_t
*
- * \retval void Success.
- * \retval "Does not return" The call is invalid, one or more of the
+ * \retval PSA_SUCCESS Success.
+ * \retval PSA_ERROR_PROGRAMMER_ERROR The call is invalid, one or more of the
* following are true:
+ * \arg Called with a stateless handle.
* \arg An invalid handle was provided that is not
* the null handle.
* \arg The connection is handling a request.
*/
-void tfm_spm_client_psa_close(psa_handle_t handle);
+psa_status_t tfm_spm_client_psa_close(psa_handle_t handle);
/* PSA Partition API function body, for privileged use only. */