1 /*
2  * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
3  * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company)
4  * or an affiliate of Cypress Semiconductor Corporation. All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  */
9 
10 #include "async.h"
11 #include "config_impl.h"
12 #include "spm.h"
13 #include "ffm/mailbox_agent_api.h"
14 #include "ffm/psa_api.h"
15 #include "tfm_rpc.h"
16 #include "utilities.h"
17 #include "private/assert.h"
18 #include "load/partition_defs.h"
19 #include "tfm_psa_call_pack.h"
20 
default_handle_req(void)21 static void default_handle_req(void)
22 {
23 }
24 
default_mailbox_reply(const void * owner,int32_t ret)25 static void default_mailbox_reply(const void *owner, int32_t ret)
26 {
27     (void)owner;
28     (void)ret;
29 }
30 
31 static struct tfm_rpc_ops_t rpc_ops = {
32     .handle_req = default_handle_req,
33     .reply      = default_mailbox_reply,
34 };
35 
tfm_rpc_psa_framework_version(void)36 uint32_t tfm_rpc_psa_framework_version(void)
37 {
38     return tfm_spm_client_psa_framework_version();
39 }
40 
tfm_rpc_psa_version(uint32_t sid)41 uint32_t tfm_rpc_psa_version(uint32_t sid)
42 {
43     return tfm_spm_client_psa_version(sid);
44 }
45 
tfm_rpc_psa_call(psa_handle_t handle,uint32_t control,const struct client_params_t * params,const void * client_data_stateless)46 psa_status_t tfm_rpc_psa_call(psa_handle_t handle, uint32_t control,
47                               const struct client_params_t *params,
48                               const void *client_data_stateless)
49 {
50     SPM_ASSERT(params != NULL);
51     SPM_ASSERT(client_data_stateless != NULL);
52 
53     return agent_psa_call(handle, control, params, client_data_stateless);
54 }
55 
56 /* Following PSA APIs are only needed by connection-based services */
57 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
58 
tfm_rpc_psa_connect(uint32_t sid,uint32_t version,int32_t ns_client_id,const void * client_data)59 psa_status_t tfm_rpc_psa_connect(uint32_t sid,
60                                  uint32_t version,
61                                  int32_t ns_client_id,
62                                  const void *client_data)
63 {
64     SPM_ASSERT(client_data != NULL);
65 
66     return agent_psa_connect(sid, version, ns_client_id, client_data);
67 }
68 
tfm_rpc_psa_close(psa_handle_t handle,int32_t ns_client_id)69 psa_status_t tfm_rpc_psa_close(psa_handle_t handle, int32_t ns_client_id)
70 {
71     return agent_psa_close(handle, ns_client_id);
72 }
73 
74 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
75 
tfm_rpc_register_ops(const struct tfm_rpc_ops_t * ops_ptr)76 int32_t tfm_rpc_register_ops(const struct tfm_rpc_ops_t *ops_ptr)
77 {
78     if (!ops_ptr) {
79         return TFM_RPC_INVAL_PARAM;
80     }
81 
82     if (!ops_ptr->handle_req || !ops_ptr->reply) {
83         return TFM_RPC_INVAL_PARAM;
84     }
85 
86     /* Currently, one and only one mailbox implementation is supported. */
87     if ((rpc_ops.handle_req != default_handle_req) ||
88         (rpc_ops.reply != default_mailbox_reply)) {
89         return TFM_RPC_CONFLICT_CALLBACK;
90     }
91 
92     rpc_ops.handle_req = ops_ptr->handle_req;
93     rpc_ops.reply = ops_ptr->reply;
94 
95     return TFM_RPC_SUCCESS;
96 }
97 
tfm_rpc_unregister_ops(void)98 void tfm_rpc_unregister_ops(void)
99 {
100     rpc_ops.handle_req = default_handle_req;
101     rpc_ops.reply = default_mailbox_reply;
102 }
103 
tfm_rpc_client_call_handler(void)104 void tfm_rpc_client_call_handler(void)
105 {
106     rpc_ops.handle_req();
107 }
108 
109 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
tfm_rpc_client_call_reply(void)110 void tfm_rpc_client_call_reply(void)
111 {
112     psa_msg_t msg;
113     psa_status_t status = psa_get(ASYNC_MSG_REPLY, &msg);
114     struct connection_t *handle = (struct connection_t *)msg.rhandle;
115 
116     rpc_ops.reply(handle->client_data, status);
117 
118     if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
119         spm_free_connection(handle);
120     } else {
121         handle->status = TFM_HANDLE_STATUS_IDLE;
122     }
123 }
124 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
125