blob: 66ef67c72016eb9da37787a8f24d136533b6746f [file] [log] [blame]
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +00001/*
Bence Balogh7e2c83b2023-11-28 15:33:12 +01002 * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +00003 * 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;
Imre Kis16464822023-08-11 16:16:30 +020054 int i = 0;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000055
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
Imre Kis16464822023-08-11 16:16:30 +020065static uint32_t psa_virt_to_phys_u32(struct rpc_caller_interface *caller, void *va)
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000066{
67 return (uintptr_t)psa_ipc_virt_to_phys(caller->context, va);
68}
69
Imre Kis16464822023-08-11 16:16:30 +020070psa_handle_t psa_connect(struct rpc_caller_interface *caller, uint32_t sid,
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000071 uint32_t version)
72{
Imre Kis16464822023-08-11 16:16:30 +020073 struct s_openamp_msg *resp_msg;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000074 struct ns_openamp_msg *req_msg;
Imre Kis16464822023-08-11 16:16:30 +020075 psa_ipc_call_handle rpc_handle;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000076 size_t resp_len;
77 uint8_t *resp;
78 uint8_t *req;
79 int ret;
80
Imre Kis16464822023-08-11 16:16:30 +020081 rpc_handle = psa_ipc_caller_begin(caller, &req, sizeof(struct ns_openamp_msg));
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000082 if (!rpc_handle) {
83 EMSG("psa_connect: could not get rpc handle");
84 return PSA_ERROR_GENERIC_ERROR;
85 }
86
87 req_msg = (struct ns_openamp_msg *)req;
88
89 req_msg->call_type = OPENAMP_PSA_CONNECT;
90 req_msg->params.psa_connect_params.sid = sid;
91 req_msg->params.psa_connect_params.version = version;
92
Imre Kis16464822023-08-11 16:16:30 +020093 ret = psa_ipc_caller_invoke(rpc_handle, 0, &resp, &resp_len);
94 if (ret != RPC_SUCCESS) {
95 EMSG("invoke failed: %d", ret);
96 return PSA_NULL_HANDLE;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +000097 }
98
Imre Kis16464822023-08-11 16:16:30 +020099 resp_msg = (struct s_openamp_msg *)resp;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000100
Imre Kis16464822023-08-11 16:16:30 +0200101 psa_ipc_caller_end(rpc_handle);
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000102
103 return resp_msg ? (psa_handle_t)resp_msg->reply : PSA_NULL_HANDLE;
104}
105
Imre Kis16464822023-08-11 16:16:30 +0200106static psa_status_t __psa_call(struct rpc_caller_interface *caller, psa_handle_t psa_handle,
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000107 int32_t client_id, int32_t type,
108 const struct psa_invec *in_vec, size_t in_len,
109 struct psa_outvec *out_vec, size_t out_len)
110{
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000111 struct s_openamp_msg *resp_msg = NULL;
112 struct psa_outvec *out_vec_param;
113 struct psa_invec *in_vec_param;
114 struct ns_openamp_msg *req_msg;
Imre Kis16464822023-08-11 16:16:30 +0200115 psa_ipc_call_handle rpc_handle;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000116 size_t in_vec_len;
117 size_t header_len;
118 uint8_t *payload;
119 size_t resp_len;
120 uint8_t *resp;
121 uint8_t *req;
122 int ret;
123 int i;
124
125 if ((psa_handle == PSA_NULL_HANDLE) || !caller)
126 return PSA_ERROR_INVALID_ARGUMENT;
127
128 header_len = psa_call_header_len(in_vec, in_len, out_vec, out_len);
129 in_vec_len = psa_call_in_vec_len(in_vec, in_len);
130
Imre Kis16464822023-08-11 16:16:30 +0200131 rpc_handle = psa_ipc_caller_begin(caller, &req, header_len + in_vec_len);
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000132 if (!rpc_handle) {
133 EMSG("psa_call: could not get handle");
134 return PSA_ERROR_GENERIC_ERROR;
135 }
136
137 payload = req + header_len;
138
139 out_vec_param = psa_call_out_vec_param(req, in_len);
140 in_vec_param = psa_call_in_vec_param(req);
141
142 req_msg = (struct ns_openamp_msg *)req;
143
144 req_msg->call_type = OPENAMP_PSA_CALL;
145 req_msg->request_id = 1234;
146 req_msg->client_id = client_id;
147 req_msg->params.psa_call_params.handle = psa_handle;
148 req_msg->params.psa_call_params.type = type;
149 req_msg->params.psa_call_params.in_len = in_len;
150 req_msg->params.psa_call_params.in_vec = psa_virt_to_phys_u32(caller, in_vec_param);
151 req_msg->params.psa_call_params.out_len = out_len;
152 req_msg->params.psa_call_params.out_vec = psa_virt_to_phys_u32(caller, out_vec_param);
153
154 for (i = 0; i < in_len; i++) {
155 in_vec_param[i].base = psa_virt_to_phys_u32(caller, payload);
156 in_vec_param[i].len = in_vec[i].len;
157
158 unaligned_memcpy(payload, psa_u32_to_ptr(in_vec[i].base),
159 in_vec[i].len);
160 payload += in_vec[i].len;
161 }
162
163 for (i = 0; i < out_len; i++) {
164 out_vec_param[i].base = 0;
165 out_vec_param[i].len = out_vec[i].len;
166 }
167
Imre Kis16464822023-08-11 16:16:30 +0200168 ret = psa_ipc_caller_invoke(rpc_handle, 0, &resp, &resp_len);
169 if (ret != RPC_SUCCESS) {
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000170 EMSG("psa_call: invoke failed: %d", ret);
171 return PSA_ERROR_GENERIC_ERROR;
172 }
173
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000174 resp_msg = (struct s_openamp_msg *)resp;
175
176 if (!resp_msg || !out_len || resp_msg->reply != PSA_SUCCESS)
177 goto caller_end;
178
Bence Balogh7e2c83b2023-11-28 15:33:12 +0100179 out_vec_param = (struct psa_outvec *)psa_ipc_phys_to_virt(caller->context,
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000180 psa_u32_to_ptr(resp_msg->params.out_vec));
181
182 for (i = 0; i < resp_msg->params.out_len; i++) {
183 out_vec[i].len = out_vec_param[i].len;
184 unaligned_memcpy(psa_u32_to_ptr(out_vec[i].base),
Bence Balogh7e2c83b2023-11-28 15:33:12 +0100185 psa_ipc_phys_to_virt(caller->context,
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000186 psa_u32_to_ptr(out_vec_param[i].base)),
187 out_vec[i].len);
188 }
189
190caller_end:
Imre Kis16464822023-08-11 16:16:30 +0200191 psa_ipc_caller_end(rpc_handle);
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000192
193 return resp_msg ? resp_msg->reply : PSA_ERROR_COMMUNICATION_FAILURE;
194}
195
Imre Kis16464822023-08-11 16:16:30 +0200196psa_status_t psa_call_client_id(struct rpc_caller_interface *caller,
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000197 psa_handle_t psa_handle, int32_t client_id,
198 int32_t type, const struct psa_invec *in_vec,
199 size_t in_len, struct psa_outvec *out_vec,
200 size_t out_len)
201{
202 return __psa_call(caller, psa_handle, client_id, type, in_vec, in_len,
203 out_vec, out_len);
204}
205
Imre Kis16464822023-08-11 16:16:30 +0200206psa_status_t psa_call(struct rpc_caller_interface *caller, psa_handle_t psa_handle,
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000207 int32_t type, const struct psa_invec *in_vec,
208 size_t in_len, struct psa_outvec *out_vec, size_t out_len)
209{
210 return __psa_call(caller, psa_handle, 0, type, in_vec, in_len, out_vec,
211 out_len);
212}
213
Imre Kis16464822023-08-11 16:16:30 +0200214void psa_close(struct rpc_caller_interface *caller, psa_handle_t psa_handle)
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000215{
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000216 struct ns_openamp_msg *req_msg;
Imre Kis16464822023-08-11 16:16:30 +0200217 psa_ipc_call_handle rpc_handle;
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000218 size_t resp_len;
219 uint8_t *resp;
220 uint8_t *req;
221 int ret;
222
223 if ((psa_handle == PSA_NULL_HANDLE) || !caller)
224 return;
225
Imre Kis16464822023-08-11 16:16:30 +0200226 rpc_handle = psa_ipc_caller_begin(caller, &req, sizeof(struct ns_openamp_msg));
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000227 if (!rpc_handle) {
228 EMSG("psa_close: could not get handle");
229 return;
230 }
231
232 req_msg = (struct ns_openamp_msg *)req;
233
234 req_msg->call_type = OPENAMP_PSA_CLOSE;
235 req_msg->params.psa_close_params.handle = psa_handle;
236
Imre Kis16464822023-08-11 16:16:30 +0200237 ret = psa_ipc_caller_invoke(rpc_handle, 0, &resp, &resp_len);
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000238 if (ret != TS_RPC_CALL_ACCEPTED) {
239 EMSG("psa_close: invoke failed: %d", ret);
240 return;
241 }
242
Imre Kis16464822023-08-11 16:16:30 +0200243 psa_ipc_caller_end(rpc_handle);
Rui Miguel Silva93cbebf2021-12-03 19:13:03 +0000244}