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. */