SPM: Redirect PSA API runtimely instead of statically

The previous PSA API redirecting is statically performed in header
files, based on C preprocessors exported by the configuration system.
The C preprocessors make the configuration maintenance harder, and
users could not find the exact PSA API name in debug symbols, which
is confusing.

Now the redirecting turns into a runtime behavior. SPRTL calls
corresponded ABI for PSA API. The ABI is set in the Secure Partition
local storage by SPM when booting, based on Secure Partition types.
Check 'prv_process_metadata' and 'psa_api_ipc.c' for details.

Co-authored-by: Ken Liu <ken.liu@arm.com>
Signed-off-by: Sherry Zhang <sherry.zhang2@arm.com>
Change-Id: Ifc974941ddb6653389d9deca9f18f754b8f25b27
diff --git a/interface/include/psa_interface_redirect.h b/interface/include/psa_interface_redirect.h
index f8d24bd..70d9f02 100644
--- a/interface/include/psa_interface_redirect.h
+++ b/interface/include/psa_interface_redirect.h
@@ -12,9 +12,6 @@
 
 #if CONFIG_TFM_PSA_API_SUPERVISOR_CALL == 1
 
-#define psa_framework_version    psa_framework_version_svc
-#define psa_version              psa_version_svc
-#define tfm_psa_call_pack        tfm_psa_call_pack_svc
 #define psa_wait                 psa_wait_svc
 #define psa_get                  psa_get_svc
 #define psa_read                 psa_read_svc
@@ -31,8 +28,6 @@
 
 /* Following PSA APIs are only needed by connection-based services */
 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
-#define psa_connect              psa_connect_svc
-#define psa_close                psa_close_svc
 #define psa_set_rhandle          psa_set_rhandle_svc
 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
 
@@ -51,9 +46,6 @@
 
 #elif CONFIG_TFM_PSA_API_CROSS_CALL == 1
 
-#define psa_framework_version    psa_framework_version_cross
-#define psa_version              psa_version_cross
-#define tfm_psa_call_pack        tfm_psa_call_pack_cross
 #define psa_wait                 psa_wait_cross
 #define psa_get                  psa_get_cross
 #define psa_read                 psa_read_cross
@@ -70,8 +62,6 @@
 
 /* Following PSA APIs are only needed by connection-based services */
 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
-#define psa_connect              psa_connect_cross
-#define psa_close                psa_close_cross
 #define psa_set_rhandle          psa_set_rhandle_cross
 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
 
@@ -97,17 +87,12 @@
 
 #elif CONFIG_TFM_PSA_API_SFN_CALL == 1
 
-#define psa_framework_version    psa_framework_version_sfn
-#define psa_version              psa_version_sfn
-#define tfm_psa_call_pack        psa_call_pack_sfn
 #define psa_read                 psa_read_sfn
 #define psa_skip                 psa_skip_sfn
 #define psa_write                psa_write_sfn
 #define psa_panic                psa_panic_sfn
 /* Following PSA APIs are only needed by connection-based services */
 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
-#define psa_connect              psa_connect_sfn
-#define psa_close                psa_close_sfn
 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
 #if CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1
 #define psa_wait                 psa_wait_sfn
diff --git a/secure_fw/partitions/lib/runtime/CMakeLists.txt b/secure_fw/partitions/lib/runtime/CMakeLists.txt
index a83a80f..cf34b93 100644
--- a/secure_fw/partitions/lib/runtime/CMakeLists.txt
+++ b/secure_fw/partitions/lib/runtime/CMakeLists.txt
@@ -26,6 +26,7 @@
         $<$<BOOL:${CONFIG_TFM_PARTITION_META}>:./sprt_partition_metadata_indicator.c>
         $<$<BOOL:${CONFIG_TFM_PARTITION_META}>:./rt_main.c>
         $<$<BOOL:${CONFIG_TFM_SPM_BACKEND_IPC}>:./sfn_common_thread.c>
+        $<$<BOOL:${CONFIG_TFM_SPM_BACKEND_IPC}>:./psa_api_ipc.c>
         $<$<BOOL:${TFM_SP_LOG_RAW_ENABLED}>:./tfm_sp_log_raw.c>
         $<$<BOOL:${TFM_SP_LOG_RAW_ENABLED}>:${CMAKE_SOURCE_DIR}/platform/ext/common/tfm_hal_sp_logdev_periph.c>
 )
@@ -44,7 +45,7 @@
         $<$<BOOL:${TFM_SP_LOG_RAW_ENABLED}>:TFM_SP_LOG_RAW_ENABLED>
 )
 
-target_include_directories(tfm_partitions
+target_include_directories(tfm_sprt
     INTERFACE
         $<BUILD_INTERFACE:$<$<BOOL:${CONFIG_TFM_PARTITION_META}>:${CMAKE_CURRENT_SOURCE_DIR}/include>>
 )
diff --git a/secure_fw/partitions/lib/runtime/psa_api_ipc.c b/secure_fw/partitions/lib/runtime/psa_api_ipc.c
new file mode 100644
index 0000000..3b12232
--- /dev/null
+++ b/secure_fw/partitions/lib/runtime/psa_api_ipc.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "psa/client.h"
+#include "tfm_psa_call_pack.h"
+#include "sprt_partition_metadata_indicator.h"
+#include "runtime_defs.h"
+
+psa_status_t tfm_psa_call_pack(psa_handle_t handle,
+                               uint32_t ctrl_param,
+                               const psa_invec *in_vec,
+                               psa_outvec *out_vec)
+{
+    return PART_METADATA()->psa_fns->psa_call(handle, ctrl_param,
+                                              in_vec, out_vec);
+}
+
+#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
+psa_handle_t psa_connect(uint32_t sid, uint32_t version)
+{
+    return PART_METADATA()->psa_fns->psa_connect(sid, version);
+}
+
+void psa_close(psa_handle_t handle)
+{
+    return PART_METADATA()->psa_fns->psa_close(handle);
+}
+#endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
+
+uint32_t psa_version(uint32_t sid)
+{
+    return PART_METADATA()->psa_fns->psa_version(sid);
+}
+
+uint32_t psa_framework_version(void)
+{
+    return PART_METADATA()->psa_fns->psa_framework_version();
+}
diff --git a/secure_fw/spm/cmsis_psa/psa_interface_cross.c b/secure_fw/spm/cmsis_psa/psa_interface_cross.c
index 5638acb..ef57226 100644
--- a/secure_fw/spm/cmsis_psa/psa_interface_cross.c
+++ b/secure_fw/spm/cmsis_psa/psa_interface_cross.c
@@ -15,6 +15,7 @@
 #include "psa/client.h"
 #include "psa/lifecycle.h"
 #include "psa/service.h"
+#include "runtime_defs.h"
 
 #if defined(__ICCARM__)
 
@@ -422,3 +423,13 @@
 }
 
 #endif /* PSA_FRAMEWORK_HAS_MM_IOVEC */
+
+const struct psa_api_tbl_t psa_api_cross = {
+                                tfm_psa_call_pack_cross,
+#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
+                                psa_connect_cross,
+                                psa_close_cross,
+#endif
+                                psa_version_cross,
+                                psa_framework_version_cross
+                            };
diff --git a/secure_fw/spm/cmsis_psa/psa_interface_sfn.c b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
index eb584f6..0980c11 100644
--- a/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
+++ b/secure_fw/spm/cmsis_psa/psa_interface_sfn.c
@@ -12,7 +12,7 @@
 #include "ffm/psa_api.h"
 #include "psa/client.h"
 
-uint32_t psa_framework_version_sfn(void)
+uint32_t psa_framework_version(void)
 {
     if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
         /* PSA APIs must be called from Thread mode */
@@ -22,7 +22,7 @@
     return tfm_spm_client_psa_framework_version();
 }
 
-uint32_t psa_version_sfn(uint32_t sid)
+uint32_t psa_version(uint32_t sid)
 {
     if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
         /* PSA APIs must be called from Thread mode */
@@ -32,7 +32,7 @@
     return tfm_spm_client_psa_version(sid);
 }
 
-psa_status_t psa_call_pack_sfn(psa_handle_t handle, uint32_t ctrl_param,
+psa_status_t tfm_psa_call_pack(psa_handle_t handle, uint32_t ctrl_param,
                                const psa_invec *in_vec, psa_outvec *out_vec)
 {
     struct partition_t *p_client, *p_target;
@@ -107,7 +107,7 @@
 /* Following PSA APIs are only needed by connection-based services */
 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
 
-psa_handle_t psa_connect_sfn(uint32_t sid, uint32_t version)
+psa_handle_t psa_connect(uint32_t sid, uint32_t version)
 {
     struct partition_t *p_client, *p_target;
     psa_status_t stat;
@@ -134,7 +134,7 @@
     return (psa_handle_t)stat;
 }
 
-void psa_close_sfn(psa_handle_t handle)
+void psa_close(psa_handle_t handle)
 {
     struct partition_t *p_client, *p_target;
     psa_status_t stat;
diff --git a/secure_fw/spm/cmsis_psa/psa_interface_svc.c b/secure_fw/spm/cmsis_psa/psa_interface_svc.c
index 28e27bd..a250210 100644
--- a/secure_fw/spm/cmsis_psa/psa_interface_svc.c
+++ b/secure_fw/spm/cmsis_psa/psa_interface_svc.c
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include "compiler_ext_defs.h"
 #include "config_spm.h"
+#include "runtime_defs.h"
 #include "svc_num.h"
 #include "tfm_psa_call_pack.h"
 #include "utilities.h"
@@ -157,3 +158,14 @@
 #endif
 
 #endif /* CONFIG_TFM_FLIH_API == 1 || CONFIG_TFM_SLIH_API == 1 */
+
+
+const struct psa_api_tbl_t psa_api_svc = {
+                                tfm_psa_call_pack_svc,
+#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
+                                psa_connect_svc,
+                                psa_close_svc,
+#endif
+                                psa_version_svc,
+                                psa_framework_version_svc
+                            };
diff --git a/secure_fw/spm/ffm/backend_ipc.c b/secure_fw/spm/ffm/backend_ipc.c
index 07b01f5..8950e54 100644
--- a/secure_fw/spm/ffm/backend_ipc.c
+++ b/secure_fw/spm/ffm/backend_ipc.c
@@ -102,6 +102,9 @@
     return state;
 }
 
+extern struct psa_api_tbl_t psa_api_cross;
+extern struct psa_api_tbl_t psa_api_svc;
+
 static void prv_process_metadata(struct partition_t *p_pt)
 {
     const struct partition_load_info_t *p_pt_ldi;
@@ -128,6 +131,12 @@
                                     ARCH_CTXCTRL_ALLOCATED_PTR(ctx_ctrl);
 
     p_rt_meta->entry = p_pt_ldi->entry;
+#if TFM_LVL == 1
+    p_rt_meta->psa_fns = &psa_api_cross;
+#else
+    /* TODO: ABI for PRoT partitions needs to be updated based on implementations. */
+    p_rt_meta->psa_fns = &psa_api_svc;
+#endif
     p_rt_meta->n_sfn = 0;
     p_sfn_table = p_rt_meta->sfn_table;
 
diff --git a/secure_fw/spm/include/interface/runtime_defs.h b/secure_fw/spm/include/interface/runtime_defs.h
index 60fee8c..8b57f81 100644
--- a/secure_fw/spm/include/interface/runtime_defs.h
+++ b/secure_fw/spm/include/interface/runtime_defs.h
@@ -10,6 +10,7 @@
 
 #include <stdint.h>
 
+#include "psa/client.h"
 #include "psa/error.h"
 #include "psa/service.h"
 
@@ -17,10 +18,33 @@
 typedef psa_status_t (*service_fn_t)(psa_msg_t *msg);
 typedef psa_status_t (*sfn_init_fn_t)(void);
 
-struct runtime_metadata_t {
-    uintptr_t       entry;          /* Entry function invoked by sprt_main */
-    uint32_t        n_sfn;          /* Number of Secure FuNctions */
-    service_fn_t    sfn_table[];    /* Secure FuNctions Table */
+/* PSA API dispatcher for IPC model. */
+#if CONFIG_TFM_SPM_BACKEND_IPC == 1
+
+typedef psa_status_t (*psa_call_fn_t)(psa_handle_t, uint32_t,
+                                      const psa_invec *in_vec,
+                                      psa_outvec *out_vec);
+typedef psa_handle_t (*psa_connect_fn_t)(uint32_t, uint32_t);
+typedef void         (*psa_close_fn_t)(psa_handle_t);
+typedef uint32_t     (*psa_version_fn_t)(uint32_t);
+typedef uint32_t     (*psa_framework_version_fn_t)(void);
+
+struct psa_api_tbl_t {
+    psa_call_fn_t              psa_call;
+#if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
+    psa_connect_fn_t           psa_connect;
+    psa_close_fn_t             psa_close;
+#endif
+    psa_version_fn_t           psa_version;
+    psa_framework_version_fn_t psa_framework_version;
 };
 
+struct runtime_metadata_t {
+    uintptr_t            entry;      /* Entry function invoked by sprt_main */
+    struct psa_api_tbl_t *psa_fns;   /* PSA API entry table */
+    uint32_t             n_sfn;      /* Number of Secure FuNctions */
+    service_fn_t         sfn_table[];/* Secure FuNctions Table */
+};
+#endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
+
 #endif /* __RUNTIME_DEFS_H__ */