SPM: Correct 'invalid parameter' error handling

- 'Invalid parameter' is regarded as 'programmer error' instead of
  return 'PSA_ERROR_INVALID_ARGUMENT'.
- 'Programmer error' should be handled inside SPM instead of interface,
  as SPM needs to decide the error handling based on the caller
  attribute.
- Keep the parameters range check inside the interface to give an explicit
  hint.
- Correct 'type' casting to avoid lose sign bit.

Change-Id: I35a5b70b5dc1ea7072c45f0ebac0630f65edfa00
Signed-off-by: Shawn Shan <Shawn.Shan@arm.com>
diff --git a/interface/include/psa/client.h b/interface/include/psa/client.h
index d92de02..7aee1e5 100644
--- a/interface/include/psa/client.h
+++ b/interface/include/psa/client.h
@@ -130,6 +130,14 @@
 /**
  * \brief Call an RoT Service on an established connection.
  *
+ * \note  FF-M 1.0 proposes 6 parameters for psa_call but the secure gateway ABI
+ *        support at most 4 parameters. TF-M chooses to encode 'in_len',
+ *        'out_len', and 'type' into a 32-bit integer to improve efficiency.
+ *        Compared with struct-based encoding, this method saves extra memory
+ *        check and memory copy operation. The disadvantage is that the 'type'
+ *        range has to be reduced into a 16-bit integer. So with this encoding,
+ *        the valid range for 'type' is 0-32767.
+ *
  * \param[in] handle            A handle to an established connection.
  * \param[in] type              The request type.
  *                              Must be zero( \ref PSA_IPC_CALL) or positive.
diff --git a/interface/src/psa/psa_client.c b/interface/src/psa/psa_client.c
index 00d95ee..6960ac6 100644
--- a/interface/src/psa/psa_client.c
+++ b/interface/src/psa/psa_client.c
@@ -56,10 +56,9 @@
 {
     if ((type > INT16_MAX) ||
         (type < INT16_MIN) ||
-        (in_len > PSA_MAX_IOVEC) ||
-        (out_len > PSA_MAX_IOVEC) ||
-        ((in_len + out_len) > PSA_MAX_IOVEC)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
+        (in_len > UINT8_MAX) ||
+        (out_len > UINT8_MAX)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
     return psa_call_param_pack(handle,
diff --git a/interface/src/tfm_psa_ns_api.c b/interface/src/tfm_psa_ns_api.c
index 9d60a11..751216d 100644
--- a/interface/src/tfm_psa_ns_api.c
+++ b/interface/src/tfm_psa_ns_api.c
@@ -50,10 +50,9 @@
 {
     if ((type > INT16_MAX) ||
         (type < INT16_MIN) ||
-        (in_len > PSA_MAX_IOVEC) ||
-        (out_len > PSA_MAX_IOVEC) ||
-        ((in_len + out_len) > PSA_MAX_IOVEC)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
+        (in_len > UINT8_MAX) ||
+        (out_len > UINT8_MAX)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
     return tfm_ns_interface_dispatch(
diff --git a/secure_fw/spm/ffm/psa_client_service_apis.c b/secure_fw/spm/ffm/psa_client_service_apis.c
index 2f57c0c..57c1b82 100644
--- a/secure_fw/spm/ffm/psa_client_service_apis.c
+++ b/secure_fw/spm/ffm/psa_client_service_apis.c
@@ -78,7 +78,7 @@
     privileged = tfm_spm_partition_get_privileged_mode(
         partition->p_static->flags);
 
-    type = (int32_t)((args[1] & TYPE_MASK) >> TYPE_OFFSET);
+    type = (int32_t)(int16_t)((args[1] & TYPE_MASK) >> TYPE_OFFSET);
     in_num = (size_t)((args[1] & IN_LEN_MASK) >> IN_LEN_OFFSET);
     out_num = (size_t)((args[1] & OUT_LEN_MASK) >> OUT_LEN_OFFSET);
     inptr = (psa_invec *)args[2];