Platform: IOCTL for platform-specific services

Introduce new API function in HAL and a new generic platform
service to provide the means for platforms to implement proprietary
functions using a uniform framework and a single secure entry point.

Change-Id: I72ddbb3342ae851fe9851ccb27a54c8f4322b01f
Signed-off-by: Miklos Balint <miklos.balint@arm.com>
diff --git a/interface/include/tfm_platform_api.h b/interface/include/tfm_platform_api.h
index 7cc57ab..9c4e023 100644
--- a/interface/include/tfm_platform_api.h
+++ b/interface/include/tfm_platform_api.h
@@ -10,6 +10,7 @@
 
 #include <limits.h>
 #include <stdbool.h>
+#include <stdint.h>
 #include "tfm_api.h"
 
 #ifdef __cplusplus
@@ -20,7 +21,7 @@
  * \brief TFM secure partition platform API version
  */
 #define TFM_PLATFORM_API_VERSION_MAJOR (0)
-#define TFM_PLATFORM_API_VERSION_MINOR (2)
+#define TFM_PLATFORM_API_VERSION_MINOR (3)
 
 /* The return value is shared with the TF-M partition status value.
  * The Platform return codes shouldn't overlap with predefined TFM status
@@ -38,11 +39,14 @@
     TFM_PLATFORM_ERR_SUCCESS = 0,
     TFM_PLATFORM_ERR_SYSTEM_ERROR = TFM_PLATFORM_ERR_OFFSET,
     TFM_PLATFORM_ERR_INVALID_PARAM,
+    TFM_PLATFORM_ERR_NOT_SUPPORTED,
 
     /* Following entry is only to ensure the error code of int size */
     TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX
 };
 
+typedef int32_t tfm_platform_ioctl_req_t;
+
 /*!
  * \brief Resets the system.
  *
@@ -51,47 +55,18 @@
 enum tfm_platform_err_t tfm_platform_system_reset(void);
 
 /*!
- * \brief Sets pin alternate function for the given pins
+ * \brief Performs a platform-specific service
  *
- * \param[in]  alt_func     Alternate function to set (allowed values vary
+ * \param[in]  request      Request identifier (valid values vary
  *                          based on the platform)
- * \param[in]  pin_mask     Pin mask of the selected pins
- * \param[out] result       Return error value
+ * \param[in]  input        Input buffer to the requested service (or NULL)
+ * \param[in,out] output    Output buffer to the requested service (or NULL)
  *
  * \return Returns values as specified by the \ref tfm_platform_err_t
  */
-enum tfm_platform_err_t
-tfm_platform_set_pin_alt_func(uint32_t alt_func, uint64_t pin_mask,
-                              uint32_t *result);
-
-/*!
- * \brief Sets default in value to use when the alternate function is not
- *        selected for the pin
- *
- * \param[in]  alt_func          Alternate function to use (allowed values vary
- *                               based on the platform)
- * \param[in]  pin_value         Pin value to use
- * \param[in]  default_in_value  Default in value to set
- * \param[out] result            Return error value
- *
- * \return Returns values as specified by the \ref tfm_platform_err_t
- */
-enum tfm_platform_err_t
-tfm_platform_set_pin_default_in(uint32_t alt_func, uint32_t pin_value,
-                                bool default_in_value, uint32_t *result);
-
-/*!
- * \brief Sets pin mode for the selected pins
- *
- * \param[in]  pin_mask     Pin mask of the selected pins
- * \param[in]  pin_mode     Pin mode to set for the selected pins
- * \param[out] result       Return error value
- *
- * \return Returns values as specified by the \ref tfm_platform_err_t
- */
-enum tfm_platform_err_t
-tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
-                          uint32_t *result);
+enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request,
+                                           psa_invec *input,
+                                           psa_outvec *output);
 
 
 #ifdef __cplusplus
diff --git a/interface/include/tfm_platform_defs.h b/interface/include/tfm_platform_defs.h
deleted file mode 100644
index 23fe4e0..0000000
--- a/interface/include/tfm_platform_defs.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 2019, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __TFM_PLATFORM_DEFS__
-#define __TFM_PLATFORM_DEFS__
-
-#include <stdint.h>
-#include <limits.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*!
- * \enum tfm_pin_service_type_t
- *
- * \brief Pin service types (supported types may vary based on the platform)
- */
-enum tfm_pin_service_type_t {
-    TFM_PIN_SERVICE_TYPE_SET_ALTFUNC     = 0,   /*!< Set alternate function type */
-    TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN,        /*!< Set default in function type */
-    TFM_PIN_SERVICE_TYPE_SET_PIN_MODE,          /*!< Set pin mode function type */
-    TFM_PIN_SERVICE_TYPE_MAX = INT_MAX          /*!< Max to force enum max size */
-};
-
-/*!
- * \struct tfm_pin_service_args_t
- *
- * \brief Argument list for each platform pin service
- */
-struct tfm_pin_service_args_t {
-    enum tfm_pin_service_type_t type;
-    union {
-        struct set_altfunc { /*!< TFM_PIN_SERVICE_TYPE_SET_ALTFUNC */
-            uint32_t alt_func;
-            uint64_t pin_mask;
-        } set_altfunc;
-        struct set_default_in { /*!< TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN */
-            uint32_t alt_func;
-            uint32_t pin_value;
-            bool default_in_value;
-        } set_default_in;
-        struct set_pin_mode { /*!< TFM_PIN_SERVICE_TYPE_SET_PIN_MODE */
-            uint64_t pin_mask;
-            uint32_t pin_mode;
-        } set_pin_mode;
-    } u;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __TFM_PLATFORM_DEFS__ */
diff --git a/interface/include/tfm_platform_veneers.h b/interface/include/tfm_platform_veneers.h
deleted file mode 100644
index 313927e..0000000
--- a/interface/include/tfm_platform_veneers.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- *
- */
-
-#ifndef __TFM_PLATFORM_VENEERS_H__
-#define __TFM_PLATFORM_VENEERS_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "tfm_platform_api.h"
-
-/*!
- * \brief Resets the system.
- *
- * \return Returns values as specified by the \ref tfm_platform_err_t
- */
-enum tfm_platform_err_t tfm_platform_veneer_system_reset(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __TFM_PLATFORM_VENEERS_H__ */
diff --git a/interface/include/tfm_veneers.h b/interface/include/tfm_veneers.h
index db3de27..71bc9e8 100644
--- a/interface/include/tfm_veneers.h
+++ b/interface/include/tfm_veneers.h
@@ -80,7 +80,7 @@
 #ifdef TFM_PARTITION_PLATFORM
 /******** TFM_SP_PLATFORM ********/
 psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
-psa_status_t tfm_platform_sp_pin_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
+psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len);
 #endif /* TFM_PARTITION_PLATFORM */
 
 /******** TFM_SP_INITIAL_ATTESTATION ********/
diff --git a/interface/src/tfm_platform_api.c b/interface/src/tfm_platform_api.c
index 9b6f787..b3daa07 100644
--- a/interface/src/tfm_platform_api.c
+++ b/interface/src/tfm_platform_api.c
@@ -7,14 +7,13 @@
 
 #include <stdbool.h>
 #include "tfm_platform_api.h"
-#include "tfm_platform_veneers.h"
 #include "tfm_ns_lock.h"
-#include "tfm_platform_defs.h"
 #include "tfm_veneers.h"
 
 enum tfm_platform_err_t tfm_platform_system_reset(void)
 {
-    return tfm_ns_lock_dispatch((veneer_fn)tfm_platform_veneer_system_reset,
+    return (enum tfm_platform_err_t) tfm_ns_lock_dispatch(
+                                (veneer_fn)tfm_platform_sp_system_reset_veneer,
                                 0,
                                 0,
                                 0,
@@ -22,93 +21,32 @@
 }
 
 enum tfm_platform_err_t
-tfm_platform_set_pin_alt_func(uint32_t alt_func, uint64_t pin_mask,
-                              uint32_t *result)
+tfm_platform_ioctl(tfm_platform_ioctl_req_t request,
+                   psa_invec *input, psa_outvec *output)
 {
-    enum tfm_platform_err_t ret;
-    psa_invec in_vec;
-    psa_outvec out_vec;
-    struct tfm_pin_service_args_t args;
+    tfm_platform_ioctl_req_t req = request;
+    struct psa_invec in_vec[2];
+    size_t inlen, outlen;
 
-    if (result == NULL) {
-        return TFM_PLATFORM_ERR_INVALID_PARAM;
+    in_vec[0].base = &req;
+    in_vec[0].len = sizeof(req);
+    if (input != NULL) {
+        in_vec[1].base = input->base;
+        in_vec[1].len = input->len;
+        inlen = 2;
+    } else {
+        inlen = 1;
     }
 
-    args.type = TFM_PIN_SERVICE_TYPE_SET_ALTFUNC;
-    args.u.set_altfunc.alt_func = alt_func;
-    args.u.set_altfunc.pin_mask = pin_mask;
-
-    in_vec.base = (const void *)&args;
-    in_vec.len = sizeof(args);
-
-    out_vec.base = (void *)result;
-    out_vec.len = sizeof(*result);
-
-    ret = tfm_ns_lock_dispatch((veneer_fn)tfm_platform_sp_pin_service_veneer,
-                                (uint32_t)&in_vec,  1,
-                                (uint32_t)&out_vec, 1);
-
-    return ret;
-}
-
-enum tfm_platform_err_t
-tfm_platform_set_pin_default_in(uint32_t alt_func, uint32_t pin_value,
-                              bool default_in_value, uint32_t *result)
-{
-    enum tfm_platform_err_t ret;
-    psa_invec in_vec;
-    psa_outvec out_vec;
-    struct tfm_pin_service_args_t args;
-
-    if (result == NULL) {
-        return TFM_PLATFORM_ERR_INVALID_PARAM;
+    if (output != NULL) {
+        outlen = 1;
+    } else {
+        outlen = 0;
     }
 
-    args.type = TFM_PIN_SERVICE_TYPE_SET_DEFAULT_IN;
-    args.u.set_default_in.alt_func = alt_func;
-    args.u.set_default_in.pin_value = pin_value;
-    args.u.set_default_in.default_in_value = default_in_value;
-
-    in_vec.base = (const void *)&args;
-    in_vec.len = sizeof(args);
-
-    out_vec.base = (void *)result;
-    out_vec.len = sizeof(*result);
-
-    ret = tfm_ns_lock_dispatch((veneer_fn)tfm_platform_sp_pin_service_veneer,
-                                (uint32_t)&in_vec,  1,
-                                (uint32_t)&out_vec, 1);
-
-    return ret;
-}
-
-enum tfm_platform_err_t
-tfm_platform_set_pin_mode(uint64_t pin_mask, uint32_t pin_mode,
-                          uint32_t *result)
-{
-    enum tfm_platform_err_t ret;
-    psa_invec in_vec;
-    psa_outvec out_vec;
-    struct tfm_pin_service_args_t args;
-
-    if (result == NULL) {
-        return TFM_PLATFORM_ERR_INVALID_PARAM;
-    }
-
-    args.type = TFM_PIN_SERVICE_TYPE_SET_PIN_MODE;
-    args.u.set_pin_mode.pin_mask = pin_mask;
-    args.u.set_pin_mode.pin_mode = pin_mode;
-
-    in_vec.base = (const void *)&args;
-    in_vec.len = sizeof(args);
-
-    out_vec.base = (void *)result;
-    out_vec.len = sizeof(*result);
-
-    ret = tfm_ns_lock_dispatch((veneer_fn)tfm_platform_sp_pin_service_veneer,
-                                (uint32_t)&in_vec,  1,
-                                (uint32_t)&out_vec, 1);
-
-    return ret;
+    return (enum tfm_platform_err_t) tfm_ns_lock_dispatch(
+                                (veneer_fn)tfm_platform_sp_ioctl_veneer,
+                                (uint32_t)in_vec, (uint32_t)inlen,
+                                (uint32_t)output, (uint32_t)outlen);
 }