1 /*
2 * Copyright (c) 2019-2022, 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/agent_api.h"
14 #include "ffm/psa_api.h"
15 #include "tfm_rpc.h"
16 #include "utilities.h"
17 #include "load/partition_defs.h"
18 #include "tfm_psa_call_pack.h"
19
default_handle_req(void)20 static void default_handle_req(void)
21 {
22 }
23
default_mailbox_reply(const void * owner,int32_t ret)24 static void default_mailbox_reply(const void *owner, int32_t ret)
25 {
26 (void)owner;
27 (void)ret;
28 }
29
default_get_caller_data(int32_t client_id)30 static const void *default_get_caller_data(int32_t client_id)
31 {
32 (void)client_id;
33
34 return NULL;
35 }
36
37 static struct tfm_rpc_ops_t rpc_ops = {
38 .handle_req = default_handle_req,
39 .reply = default_mailbox_reply,
40 .get_caller_data = default_get_caller_data,
41 };
42
tfm_rpc_psa_framework_version(void)43 uint32_t tfm_rpc_psa_framework_version(void)
44 {
45 return tfm_spm_client_psa_framework_version();
46 }
47
tfm_rpc_psa_version(uint32_t sid)48 uint32_t tfm_rpc_psa_version(uint32_t sid)
49 {
50 return tfm_spm_client_psa_version(sid);
51 }
52
tfm_rpc_psa_call(psa_handle_t handle,uint32_t control,const struct client_params_t * params,const void * client_data_stateless)53 psa_status_t tfm_rpc_psa_call(psa_handle_t handle, uint32_t control,
54 const struct client_params_t *params,
55 const void *client_data_stateless)
56 {
57 SPM_ASSERT(params != NULL);
58
59 return agent_psa_call(handle, control, params, client_data_stateless);
60 }
61
62 /* Following PSA APIs are only needed by connection-based services */
63 #if CONFIG_TFM_CONNECTION_BASED_SERVICE_API == 1
64
tfm_rpc_psa_connect(uint32_t sid,uint32_t version,int32_t ns_client_id,const void * client_data)65 psa_status_t tfm_rpc_psa_connect(uint32_t sid,
66 uint32_t version,
67 int32_t ns_client_id,
68 const void *client_data)
69 {
70 return agent_psa_connect(sid, version, ns_client_id, client_data);
71 }
72
tfm_rpc_psa_close(psa_handle_t handle)73 void tfm_rpc_psa_close(psa_handle_t handle)
74 {
75 psa_close(handle);
76 }
77
78 #endif /* CONFIG_TFM_CONNECTION_BASED_SERVICE_API */
79
tfm_rpc_register_ops(const struct tfm_rpc_ops_t * ops_ptr)80 int32_t tfm_rpc_register_ops(const struct tfm_rpc_ops_t *ops_ptr)
81 {
82 if (!ops_ptr) {
83 return TFM_RPC_INVAL_PARAM;
84 }
85
86 if (!ops_ptr->handle_req || !ops_ptr->reply || !ops_ptr->get_caller_data) {
87 return TFM_RPC_INVAL_PARAM;
88 }
89
90 /* Currently, one and only one mailbox implementation is supported. */
91 if ((rpc_ops.handle_req != default_handle_req) ||
92 (rpc_ops.reply != default_mailbox_reply) ||
93 (rpc_ops.get_caller_data != default_get_caller_data)) {
94 return TFM_RPC_CONFLICT_CALLBACK;
95 }
96
97 rpc_ops.handle_req = ops_ptr->handle_req;
98 rpc_ops.reply = ops_ptr->reply;
99 rpc_ops.get_caller_data = ops_ptr->get_caller_data;
100
101 return TFM_RPC_SUCCESS;
102 }
103
tfm_rpc_unregister_ops(void)104 void tfm_rpc_unregister_ops(void)
105 {
106 rpc_ops.handle_req = default_handle_req;
107 rpc_ops.reply = default_mailbox_reply;
108 rpc_ops.get_caller_data = default_get_caller_data;
109 }
110
tfm_rpc_client_call_handler(void)111 void tfm_rpc_client_call_handler(void)
112 {
113 rpc_ops.handle_req();
114 }
115
116 #if CONFIG_TFM_SPM_BACKEND_IPC == 1
tfm_rpc_client_call_reply(void)117 void tfm_rpc_client_call_reply(void)
118 {
119 psa_msg_t msg;
120 psa_status_t status = psa_get(ASYNC_MSG_REPLY, &msg);
121 struct connection_t *handle = (struct connection_t *)msg.rhandle;
122
123 rpc_ops.reply(handle->caller_data, status);
124
125 if (handle->status == TFM_HANDLE_STATUS_TO_FREE) {
126 spm_free_connection(handle);
127 } else {
128 handle->status = TFM_HANDLE_STATUS_IDLE;
129 }
130 }
131 #endif /* CONFIG_TFM_SPM_BACKEND_IPC == 1 */
132
tfm_rpc_set_caller_data(struct connection_t * handle,int32_t client_id)133 void tfm_rpc_set_caller_data(struct connection_t *handle, int32_t client_id)
134 {
135 handle->caller_data = rpc_ops.get_caller_data(client_id);
136 }
137