blob: 70d6ca30b5bc3a3f320222cee5cfcbcb4e97c2da [file] [log] [blame]
Balint Dobszay3bd6ae92020-11-23 17:57:50 +01001/*
Balint Dobszay1b631eb2021-01-15 11:09:36 +01002 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
Balint Dobszay3bd6ae92020-11-23 17:57:50 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "ffarpc_caller.h"
Balint Dobszay1b631eb2021-01-15 11:09:36 +01008#include <arm_ffa_user.h>
Balint Dobszay3bd6ae92020-11-23 17:57:50 +01009#include <rpc/ffarpc/endpoint/ffarpc_call_args.h>
10#include <rpc/ffarpc/endpoint/ffarpc_call_ops.h>
11#include <protocols/rpc/common/packed-c/status.h>
12#include <fcntl.h>
13#include <sys/ioctl.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <stdint.h>
17#include <stdlib.h>
18#include <string.h>
19
20#define DEFAULT_SHMEM_BUF_SIZE (4096)
21
22static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len);
23static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
24 int *opstatus, uint8_t **resp_buf, size_t *resp_len);
25static void call_end(void *context, rpc_call_handle handle);
26
27static int kernel_write_req_buf(struct ffarpc_caller *s);
28static int kernel_read_resp_buf(struct ffarpc_caller *s);
29static int share_mem_with_partition(struct ffarpc_caller *s);
30static int unshare_mem_with_partition(struct ffarpc_caller *s);
31
32
33
34struct rpc_caller *ffarpc_caller_init(struct ffarpc_caller *s, const char *device_path)
35{
36 struct rpc_caller *base = &s->rpc_caller;
37
38 base->context = s;
39 base->call_begin = call_begin;
40 base->call_invoke = call_invoke;
41 base->call_end = call_end;
42
43 s->device_path = device_path;
44 s->fd = -1;
45 s->call_ep_id = 0;
46 s->shared_mem_handle = 0;
47 s->shared_mem_required_size = DEFAULT_SHMEM_BUF_SIZE;
48 s->req_buf = NULL;
49 s->req_len = 0;
50 s->resp_buf = NULL;
51 s->resp_len = 0;
52 s->is_call_transaction_in_progess = false;
53
54 return base;
55}
56
57void ffarpc_caller_deinit(struct ffarpc_caller *s)
58{
59 s->rpc_caller.context = NULL;
60 s->rpc_caller.call_begin = NULL;
61 s->rpc_caller.call_invoke = NULL;
62 s->rpc_caller.call_end = NULL;
63
64 call_end(s, s);
65 ffarpc_caller_close(s);
66}
67
Balint Dobszay1b631eb2021-01-15 11:09:36 +010068size_t ffarpc_caller_discover(const struct ffarpc_caller *s, const struct uuid_canonical *uuid,
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010069 uint16_t *partition_ids, size_t discover_limit)
70{
71 size_t discover_count = 0;
72
73 if (uuid && partition_ids && s->device_path) {
74 int fd;
75
76 fd = open(s->device_path, O_RDWR);
77
78 if (fd >= 0) {
79 int ioctl_status;
Balint Dobszay1b631eb2021-01-15 11:09:36 +010080 struct ffa_ioctl_ep_desc discovered_partition;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010081
Balint Dobszay1b631eb2021-01-15 11:09:36 +010082 discovered_partition.uuid_ptr = (uintptr_t)&uuid->characters;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010083 discovered_partition.id = 0;
84
Balint Dobszay1b631eb2021-01-15 11:09:36 +010085 ioctl_status = ioctl(fd, FFA_IOC_GET_PART_ID, &discovered_partition);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010086
87 if ((ioctl_status == 0) && (discover_count < discover_limit)) {
88 partition_ids[discover_count] = discovered_partition.id;
89 ++discover_count;
90 }
91
92 close(fd);
93 }
94 }
95
96 return discover_count;
97}
98
99int ffarpc_caller_open(struct ffarpc_caller *s, uint16_t call_ep_id)
100{
101 int ioctl_status = -1;
102
103 if (s->device_path) {
104
105 s->fd = open(s->device_path, O_RDWR);
106
107 if (s->fd >= 0) {
108 /* Allocate resource for session */
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100109 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_INIT, &s->shared_mem_handle);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100110
111 if (ioctl_status == 0) {
112 /* Session successfully opened */
113 s->call_ep_id = call_ep_id;
114 ioctl_status = share_mem_with_partition(s);
115 }
116
117 if (ioctl_status != 0) {
118 /* Resource allocation or sharing error */
119 close(s->fd);
120 s->fd = -1;
121 }
122 }
123 }
124
125 return ioctl_status;
126}
127
128int ffarpc_caller_close(struct ffarpc_caller *s)
129{
130 int ioctl_status = -1;
131
132 if (s->fd >= 0) {
133
134 unshare_mem_with_partition(s);
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100135 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_DEINIT);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100136 close(s->fd);
137 s->fd = -1;
138 s->call_ep_id = 0;
139 }
140
141 return ioctl_status;
142}
143
144static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len)
145{
146 rpc_call_handle handle = NULL;
147 struct ffarpc_caller *s = (struct ffarpc_caller*)context;
148
149 if (!s->is_call_transaction_in_progess) {
150
151 s->is_call_transaction_in_progess = true;
152 handle = s;
153
154 if (req_len > 0) {
155
156 s->req_buf = malloc(req_len);
157
158 if (s->req_buf) {
159
160 *req_buf = s->req_buf;
161 s->req_len = req_len;
162 }
163 else {
164 /* Failed to allocate req buffer */
165 handle = NULL;
166 s->is_call_transaction_in_progess = false;
167 }
168 }
169 else {
170
171 *req_buf = NULL;
172 s->req_buf = NULL;
173 s->req_len = req_len;
174 }
175 }
176
177 return handle;
178}
179
180static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
181 int *opstatus, uint8_t **resp_buf, size_t *resp_len)
182{
183 rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
184 struct ffarpc_caller *s = (struct ffarpc_caller*)context;
185
186 if ((handle == s) && s->is_call_transaction_in_progess) {
187 int kernel_op_status = 0;
188
189 if (s->req_len > 0) {
190 kernel_op_status = kernel_write_req_buf(s);
191 }
192
193 if (kernel_op_status == 0) {
194 /* Make direct call to send the request */
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100195 struct ffa_ioctl_msg_args direct_msg;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100196 memset(&direct_msg, 0, sizeof(direct_msg));
197
198 direct_msg.dst_id = s->call_ep_id;
199 direct_msg.args[FFA_CALL_ARGS_OPCODE] = (uint64_t)opcode;
200 direct_msg.args[FFA_CALL_ARGS_REQ_DATA_LEN] = (uint64_t)s->req_len;
201
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100202 kernel_op_status = ioctl(s->fd, FFA_IOC_MSG_SEND, &direct_msg);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100203
204 if (kernel_op_status == 0) {
205 /* Send completed normally - ffa return args in msg_args struct */
206 s->resp_len = (size_t)direct_msg.args[FFA_CALL_ARGS_RESP_DATA_LEN];
207 rpc_status = (int)direct_msg.args[FFA_CALL_ARGS_RESP_RPC_STATUS];
208 *opstatus = (int)direct_msg.args[FFA_CALL_ARGS_RESP_OP_STATUS];
209
210 if (s->resp_len > 0) {
211 s->resp_buf = malloc(s->resp_len);
212
213 if (s->resp_buf) {
214 kernel_op_status = kernel_read_resp_buf(s);
215
216 if (kernel_op_status != 0) {
217 /* Failed to read response buffer */
218 rpc_status = TS_RPC_ERROR_INTERNAL;
219 }
220 }
221 else {
222 /* Failed to allocate response buffer */
223 s->resp_len = 0;
224 rpc_status = TS_RPC_ERROR_INTERNAL;
225 }
226 }
227 else {
228 /* No response parameters */
229 s->resp_buf = NULL;
230 }
231
232 *resp_len = s->resp_len;
233 *resp_buf = s->resp_buf;
234 }
235 }
236 }
237
238 return rpc_status;
239}
240
241static void call_end(void *context, rpc_call_handle handle)
242{
243 struct ffarpc_caller *s = (struct ffarpc_caller*)context;
244
245 if ((handle == s) && s->is_call_transaction_in_progess) {
246
247 /* Call transaction complete so free resource */
248 free(s->req_buf);
249 s->req_buf = NULL;
250 s->req_len = 0;
251
252 free(s->resp_buf);
253 s->resp_buf = NULL;
254 s->resp_len = 0;
255
256 s->is_call_transaction_in_progess = false;
257 }
258}
259
260static int kernel_write_req_buf(struct ffarpc_caller *s) {
261
262 int ioctl_status;
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100263 struct ffa_ioctl_buf_desc req_descr;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100264
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100265 req_descr.buf_ptr = (uintptr_t)s->req_buf;
266 req_descr.buf_len = s->req_len;
267 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_WRITE, &req_descr);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100268
269 return ioctl_status;
270}
271
272
273static int kernel_read_resp_buf(struct ffarpc_caller *s) {
274
275 int ioctl_status;
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100276 struct ffa_ioctl_buf_desc resp_descr;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100277
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100278 resp_descr.buf_ptr = (uintptr_t)s->resp_buf;
279 resp_descr.buf_len = s->resp_len;
280 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_READ, &resp_descr);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100281
282 return ioctl_status;
283}
284
285static int share_mem_with_partition(struct ffarpc_caller *s) {
286
287 int ioctl_status;
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100288 struct ffa_ioctl_msg_args direct_msg;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100289 memset(&direct_msg, 0, sizeof(direct_msg));
290
291 direct_msg.dst_id = s->call_ep_id;
292 direct_msg.args[FFA_CALL_ARGS_OPCODE] = (uint64_t)FFA_CALL_OPCODE_SHARE_BUF;
293 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_LSW] = (uint32_t)s->shared_mem_handle;
294 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_MSW] = (uint32_t)(s->shared_mem_handle >> 32);
295 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_SIZE] = (uint64_t)s->shared_mem_required_size;
296
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100297 ioctl_status = ioctl(s->fd, FFA_IOC_MSG_SEND, &direct_msg);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100298
299 return ioctl_status;
300}
301
302static int unshare_mem_with_partition(struct ffarpc_caller *s) {
303
304 int ioctl_status;
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100305 struct ffa_ioctl_msg_args direct_msg;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100306 memset(&direct_msg, 0, sizeof(direct_msg));
307
308 direct_msg.dst_id = s->call_ep_id;
309 direct_msg.args[FFA_CALL_ARGS_OPCODE] = (uint64_t)FFA_CALL_OPCODE_UNSHARE_BUF;
310 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_LSW] = (uint32_t)s->shared_mem_handle;
311 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_MSW] = (uint32_t)(s->shared_mem_handle >> 32);
312
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100313 ioctl_status = ioctl(s->fd, FFA_IOC_MSG_SEND, &direct_msg);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100314
315 return ioctl_status;
316}