blob: 830f461f3fa838008595c1316e1481c598c851d4 [file] [log] [blame]
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +00001/*
2 * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved.
3 * Copyright (c) 2021-2023, Linaro Limited. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8#include <stddef.h>
9#include <stdint.h>
10#include <string.h>
11#include <trace.h>
12
13#include <protocols/rpc/common/packed-c/status.h>
14#include <psa/error.h>
15#include <rpc_caller.h>
16
17#include <psa/client.h>
18#include <psa_ipc_caller.h>
19#include "service_psa_ipc_openamp_lib.h"
20
21static inline void *unaligned_memcpy(void *dst_init, const void *src_init,
22 size_t len)
23{
24 char *dst = dst_init;
25 const char *src = src_init;
26
27 while (len--)
28 *dst++ = *src++;
29
30 return dst_init;
31}
32
33static struct psa_invec *psa_call_in_vec_param(uint8_t *req)
34{
35 return (struct psa_invec *)(req + sizeof(struct ns_openamp_msg));
36}
37
38static struct psa_outvec *psa_call_out_vec_param(uint8_t *req, size_t in_len)
39{
40 return (struct psa_outvec *)(req + sizeof(struct ns_openamp_msg) +
41 (in_len * sizeof(struct psa_invec)));
42}
43
44static size_t psa_call_header_len(const struct psa_invec *in_vec, size_t in_len,
45 struct psa_outvec *out_vec, size_t out_len)
46{
47 return sizeof(struct ns_openamp_msg) + (in_len * sizeof(*in_vec)) +
48 (out_len * sizeof(*out_vec));
49}
50
51static size_t psa_call_in_vec_len(const struct psa_invec *in_vec, size_t in_len)
52{
53 size_t req_len = 0;
54 int i;
55
56 if (!in_vec || !in_len)
57 return 0;
58
59 for (i = 0; i < in_len; i++)
60 req_len += in_vec[i].len;
61
62 return req_len;
63}
64
65static uint32_t psa_virt_to_phys_u32(struct rpc_caller *caller, void *va)
66{
67 return (uintptr_t)psa_ipc_virt_to_phys(caller->context, va);
68}
69
70psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
71 uint32_t version)
72{
73 rpc_opstatus_t opstatus = PSA_SUCCESS;
74 struct s_openamp_msg *resp_msg = NULL;
75 struct ns_openamp_msg *req_msg;
76 rpc_call_handle rpc_handle;
77 size_t resp_len;
78 uint8_t *resp;
79 uint8_t *req;
80 int ret;
81
82 rpc_handle = rpc_caller_begin(caller, &req,
83 sizeof(struct ns_openamp_msg));
84 if (!rpc_handle) {
85 EMSG("psa_connect: could not get rpc handle");
86 return PSA_ERROR_GENERIC_ERROR;
87 }
88
89 req_msg = (struct ns_openamp_msg *)req;
90
91 req_msg->call_type = OPENAMP_PSA_CONNECT;
92 req_msg->params.psa_connect_params.sid = sid;
93 req_msg->params.psa_connect_params.version = version;
94
95 ret = rpc_caller_invoke(caller, rpc_handle, 0, &opstatus, &resp,
96 &resp_len);
97 if (ret != TS_RPC_CALL_ACCEPTED) {
98 EMSG("psa_connect: invoke failed: %d", ret);
99 return PSA_ERROR_GENERIC_ERROR;
100 }
101
102 if (opstatus == PSA_SUCCESS)
103 resp_msg = (struct s_openamp_msg *)resp;
104
105 rpc_caller_end(caller, rpc_handle);
106
107 return resp_msg ? (psa_handle_t)resp_msg->reply : PSA_NULL_HANDLE;
108}
109
110static psa_status_t __psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
111 int32_t client_id, int32_t type,
112 const struct psa_invec *in_vec, size_t in_len,
113 struct psa_outvec *out_vec, size_t out_len)
114{
115 rpc_opstatus_t opstatus = PSA_SUCCESS;
116 struct s_openamp_msg *resp_msg = NULL;
117 struct psa_outvec *out_vec_param;
118 struct psa_invec *in_vec_param;
119 struct ns_openamp_msg *req_msg;
120 rpc_call_handle rpc_handle;
121 size_t in_vec_len;
122 size_t header_len;
123 uint8_t *payload;
124 size_t resp_len;
125 uint8_t *resp;
126 uint8_t *req;
127 int ret;
128 int i;
129
130 if ((psa_handle == PSA_NULL_HANDLE) || !caller)
131 return PSA_ERROR_INVALID_ARGUMENT;
132
133 header_len = psa_call_header_len(in_vec, in_len, out_vec, out_len);
134 in_vec_len = psa_call_in_vec_len(in_vec, in_len);
135
136 rpc_handle = rpc_caller_begin(caller, &req, header_len + in_vec_len);
137 if (!rpc_handle) {
138 EMSG("psa_call: could not get handle");
139 return PSA_ERROR_GENERIC_ERROR;
140 }
141
142 payload = req + header_len;
143
144 out_vec_param = psa_call_out_vec_param(req, in_len);
145 in_vec_param = psa_call_in_vec_param(req);
146
147 req_msg = (struct ns_openamp_msg *)req;
148
149 req_msg->call_type = OPENAMP_PSA_CALL;
150 req_msg->request_id = 1234;
151 req_msg->client_id = client_id;
152 req_msg->params.psa_call_params.handle = psa_handle;
153 req_msg->params.psa_call_params.type = type;
154 req_msg->params.psa_call_params.in_len = in_len;
155 req_msg->params.psa_call_params.in_vec = psa_virt_to_phys_u32(caller, in_vec_param);
156 req_msg->params.psa_call_params.out_len = out_len;
157 req_msg->params.psa_call_params.out_vec = psa_virt_to_phys_u32(caller, out_vec_param);
158
159 for (i = 0; i < in_len; i++) {
160 in_vec_param[i].base = psa_virt_to_phys_u32(caller, payload);
161 in_vec_param[i].len = in_vec[i].len;
162
163 unaligned_memcpy(payload, psa_u32_to_ptr(in_vec[i].base),
164 in_vec[i].len);
165 payload += in_vec[i].len;
166 }
167
168 for (i = 0; i < out_len; i++) {
169 out_vec_param[i].base = 0;
170 out_vec_param[i].len = out_vec[i].len;
171 }
172
173 ret = rpc_caller_invoke(caller, rpc_handle, 0, &opstatus, &resp,
174 &resp_len);
175 if (ret != TS_RPC_CALL_ACCEPTED) {
176 EMSG("psa_call: invoke failed: %d", ret);
177 return PSA_ERROR_GENERIC_ERROR;
178 }
179
180 if (opstatus != PSA_SUCCESS) {
181 EMSG("psa_call: psa_status invoke failed: %ld", opstatus);
182 return PSA_ERROR_GENERIC_ERROR;
183 }
184
185 resp_msg = (struct s_openamp_msg *)resp;
186
187 if (!resp_msg || !out_len || resp_msg->reply != PSA_SUCCESS)
188 goto caller_end;
189
190 out_vec_param = (struct psa_outvec *)psa_ipc_phys_to_virt(caller,
191 psa_u32_to_ptr(resp_msg->params.out_vec));
192
193 for (i = 0; i < resp_msg->params.out_len; i++) {
194 out_vec[i].len = out_vec_param[i].len;
195 unaligned_memcpy(psa_u32_to_ptr(out_vec[i].base),
196 psa_ipc_phys_to_virt(caller,
197 psa_u32_to_ptr(out_vec_param[i].base)),
198 out_vec[i].len);
199 }
200
201caller_end:
202 rpc_caller_end(caller, rpc_handle);
203
204 return resp_msg ? resp_msg->reply : PSA_ERROR_COMMUNICATION_FAILURE;
205}
206
207psa_status_t psa_call_client_id(struct rpc_caller *caller,
208 psa_handle_t psa_handle, int32_t client_id,
209 int32_t type, const struct psa_invec *in_vec,
210 size_t in_len, struct psa_outvec *out_vec,
211 size_t out_len)
212{
213 return __psa_call(caller, psa_handle, client_id, type, in_vec, in_len,
214 out_vec, out_len);
215}
216
217psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
218 int32_t type, const struct psa_invec *in_vec,
219 size_t in_len, struct psa_outvec *out_vec, size_t out_len)
220{
221 return __psa_call(caller, psa_handle, 0, type, in_vec, in_len, out_vec,
222 out_len);
223}
224
225void psa_close(struct rpc_caller *caller, psa_handle_t psa_handle)
226{
227 rpc_opstatus_t opstatus = PSA_SUCCESS;
228 struct ns_openamp_msg *req_msg;
229 rpc_call_handle rpc_handle;
230 size_t resp_len;
231 uint8_t *resp;
232 uint8_t *req;
233 int ret;
234
235 if ((psa_handle == PSA_NULL_HANDLE) || !caller)
236 return;
237
238 rpc_handle = rpc_caller_begin(caller, &req,
239 sizeof(struct ns_openamp_msg));
240 if (!rpc_handle) {
241 EMSG("psa_close: could not get handle");
242 return;
243 }
244
245 req_msg = (struct ns_openamp_msg *)req;
246
247 req_msg->call_type = OPENAMP_PSA_CLOSE;
248 req_msg->params.psa_close_params.handle = psa_handle;
249
250 ret = rpc_caller_invoke(caller, rpc_handle, 0, &opstatus, &resp,
251 &resp_len);
252 if (ret != TS_RPC_CALL_ACCEPTED) {
253 EMSG("psa_close: invoke failed: %d", ret);
254 return;
255 }
256
257 rpc_caller_end(caller, rpc_handle);
258}