blob: ac628a9513de8138176eb3a44746f8de2008dd4b [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,
julhal01c3f4e9a2020-12-15 13:39:01 +000024 int *opstatus, uint8_t **resp_buf, size_t *resp_len);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010025static 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
julhal01c3f4e9a2020-12-15 13:39:01 +000038 rpc_caller_init(base, s);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010039 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;
julhal01c3f4e9a2020-12-15 13:39:01 +000045 s->dest_partition_id = 0;
46 s->dest_iface_id = 0;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010047 s->shared_mem_handle = 0;
48 s->shared_mem_required_size = DEFAULT_SHMEM_BUF_SIZE;
49 s->req_buf = NULL;
50 s->req_len = 0;
51 s->resp_buf = NULL;
52 s->resp_len = 0;
53 s->is_call_transaction_in_progess = false;
54
55 return base;
56}
57
58void ffarpc_caller_deinit(struct ffarpc_caller *s)
59{
60 s->rpc_caller.context = NULL;
61 s->rpc_caller.call_begin = NULL;
62 s->rpc_caller.call_invoke = NULL;
63 s->rpc_caller.call_end = NULL;
64
65 call_end(s, s);
66 ffarpc_caller_close(s);
67}
68
Balint Dobszay1b631eb2021-01-15 11:09:36 +010069size_t ffarpc_caller_discover(const struct ffarpc_caller *s, const struct uuid_canonical *uuid,
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010070 uint16_t *partition_ids, size_t discover_limit)
71{
72 size_t discover_count = 0;
73
74 if (uuid && partition_ids && s->device_path) {
75 int fd;
76
77 fd = open(s->device_path, O_RDWR);
78
79 if (fd >= 0) {
80 int ioctl_status;
Balint Dobszay1b631eb2021-01-15 11:09:36 +010081 struct ffa_ioctl_ep_desc discovered_partition;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010082
Balint Dobszay1b631eb2021-01-15 11:09:36 +010083 discovered_partition.uuid_ptr = (uintptr_t)&uuid->characters;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010084 discovered_partition.id = 0;
85
Balint Dobszay1b631eb2021-01-15 11:09:36 +010086 ioctl_status = ioctl(fd, FFA_IOC_GET_PART_ID, &discovered_partition);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010087
88 if ((ioctl_status == 0) && (discover_count < discover_limit)) {
89 partition_ids[discover_count] = discovered_partition.id;
90 ++discover_count;
91 }
92
93 close(fd);
94 }
95 }
96
julhal01c3f4e9a2020-12-15 13:39:01 +000097 return discover_count;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010098}
99
julhal01c3f4e9a2020-12-15 13:39:01 +0000100int ffarpc_caller_open(struct ffarpc_caller *s, uint16_t dest_partition_id, uint16_t dest_iface_id)
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100101{
julhal01c3f4e9a2020-12-15 13:39:01 +0000102 int ioctl_status = -1;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100103
104 if (s->device_path) {
105
106 s->fd = open(s->device_path, O_RDWR);
107
108 if (s->fd >= 0) {
109 /* Allocate resource for session */
Balint Dobszay1b631eb2021-01-15 11:09:36 +0100110 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_INIT, &s->shared_mem_handle);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100111
112 if (ioctl_status == 0) {
113 /* Session successfully opened */
julhal01c3f4e9a2020-12-15 13:39:01 +0000114 s->dest_partition_id = dest_partition_id;
115 s->dest_iface_id = dest_iface_id;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100116 ioctl_status = share_mem_with_partition(s);
117 }
118
119 if (ioctl_status != 0) {
120 /* Resource allocation or sharing error */
121 close(s->fd);
122 s->fd = -1;
123 }
124 }
125 }
126
julhal01c3f4e9a2020-12-15 13:39:01 +0000127 return ioctl_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100128}
129
130int ffarpc_caller_close(struct ffarpc_caller *s)
131{
julhal01c3f4e9a2020-12-15 13:39:01 +0000132 int ioctl_status = -1;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100133
julhal01c3f4e9a2020-12-15 13:39:01 +0000134 if (s->fd >= 0) {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100135
julhal01c3f4e9a2020-12-15 13:39:01 +0000136 unshare_mem_with_partition(s);
137 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_DEINIT);
138 close(s->fd);
139 s->fd = -1;
140 s->dest_partition_id = 0;
141 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100142
julhal01c3f4e9a2020-12-15 13:39:01 +0000143 return ioctl_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100144}
145
146static rpc_call_handle call_begin(void *context, uint8_t **req_buf, size_t req_len)
147{
148 rpc_call_handle handle = NULL;
149 struct ffarpc_caller *s = (struct ffarpc_caller*)context;
150
julhal01c3f4e9a2020-12-15 13:39:01 +0000151 if (!s->is_call_transaction_in_progess) {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100152
julhal01c3f4e9a2020-12-15 13:39:01 +0000153 s->is_call_transaction_in_progess = true;
154 handle = s;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100155
julhal01c3f4e9a2020-12-15 13:39:01 +0000156 if (req_len > 0) {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100157
julhal01c3f4e9a2020-12-15 13:39:01 +0000158 s->req_buf = malloc(req_len);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100159
julhal01c3f4e9a2020-12-15 13:39:01 +0000160 if (s->req_buf) {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100161
julhal01c3f4e9a2020-12-15 13:39:01 +0000162 *req_buf = s->req_buf;
163 s->req_len = req_len;
164 }
165 else {
166 /* Failed to allocate req buffer */
167 handle = NULL;
168 s->is_call_transaction_in_progess = false;
169 }
170 }
171 else {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100172
julhal01c3f4e9a2020-12-15 13:39:01 +0000173 *req_buf = NULL;
174 s->req_buf = NULL;
175 s->req_len = req_len;
176 }
177 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100178
julhal01c3f4e9a2020-12-15 13:39:01 +0000179 return handle;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100180}
181
182static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t opcode,
julhal01c3f4e9a2020-12-15 13:39:01 +0000183 int *opstatus, uint8_t **resp_buf, size_t *resp_len)
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100184{
julhal01c3f4e9a2020-12-15 13:39:01 +0000185 rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100186 struct ffarpc_caller *s = (struct ffarpc_caller*)context;
187
julhal01c3f4e9a2020-12-15 13:39:01 +0000188 if ((handle == s) && s->is_call_transaction_in_progess) {
189 int kernel_op_status = 0;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100190
julhal01c3f4e9a2020-12-15 13:39:01 +0000191 if (s->req_len > 0) {
192 kernel_op_status = kernel_write_req_buf(s);
193 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100194
julhal01c3f4e9a2020-12-15 13:39:01 +0000195 if (kernel_op_status == 0) {
196 /* Make direct call to send the request */
197 struct ffa_ioctl_msg_args direct_msg;
198 memset(&direct_msg, 0, sizeof(direct_msg));
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100199
julhal01c3f4e9a2020-12-15 13:39:01 +0000200 direct_msg.dst_id = s->dest_partition_id;
201 direct_msg.args[FFA_CALL_ARGS_IFACE_ID_OPCODE] =
202 FFA_CALL_ARGS_COMBINE_IFACE_ID_OPCODE(s->dest_partition_id, opcode);
203 direct_msg.args[FFA_CALL_ARGS_REQ_DATA_LEN] = (uint64_t)s->req_len;
204 direct_msg.args[FFA_CALL_ARGS_ENCODING] = s->rpc_caller.encoding;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100205
julhal01c3f4e9a2020-12-15 13:39:01 +0000206 /* Initialise the caller ID. Depending on the call path, this may
207 * be overridden by a higher privilege execution level, based on its
208 * perspective of the caller identity.
209 */
210 direct_msg.args[FFA_CALL_ARGS_CALLER_ID] = 0;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100211
julhal01c3f4e9a2020-12-15 13:39:01 +0000212 kernel_op_status = ioctl(s->fd, FFA_IOC_MSG_SEND, &direct_msg);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100213
julhal01c3f4e9a2020-12-15 13:39:01 +0000214 if (kernel_op_status == 0) {
215 /* Send completed normally - ffa return args in msg_args struct */
216 s->resp_len = (size_t)direct_msg.args[FFA_CALL_ARGS_RESP_DATA_LEN];
217 rpc_status = (int)direct_msg.args[FFA_CALL_ARGS_RESP_RPC_STATUS];
218 *opstatus = (int)direct_msg.args[FFA_CALL_ARGS_RESP_OP_STATUS];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100219
julhal01c3f4e9a2020-12-15 13:39:01 +0000220 if (s->resp_len > 0) {
221 s->resp_buf = malloc(s->resp_len);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100222
julhal01c3f4e9a2020-12-15 13:39:01 +0000223 if (s->resp_buf) {
224 kernel_op_status = kernel_read_resp_buf(s);
225
226 if (kernel_op_status != 0) {
227 /* Failed to read response buffer */
228 rpc_status = TS_RPC_ERROR_INTERNAL;
229 }
230 }
231 else {
232 /* Failed to allocate response buffer */
233 s->resp_len = 0;
234 rpc_status = TS_RPC_ERROR_INTERNAL;
235 }
236 }
237 else {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100238 /* No response parameters */
julhal01c3f4e9a2020-12-15 13:39:01 +0000239 s->resp_buf = NULL;
240 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100241
julhal01c3f4e9a2020-12-15 13:39:01 +0000242 *resp_len = s->resp_len;
243 *resp_buf = s->resp_buf;
244 }
245 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100246 }
247
julhal01c3f4e9a2020-12-15 13:39:01 +0000248 return rpc_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100249}
250
251static void call_end(void *context, rpc_call_handle handle)
252{
253 struct ffarpc_caller *s = (struct ffarpc_caller*)context;
254
255 if ((handle == s) && s->is_call_transaction_in_progess) {
256
julhal01c3f4e9a2020-12-15 13:39:01 +0000257 /* Call transaction complete so free resource */
258 free(s->req_buf);
259 s->req_buf = NULL;
260 s->req_len = 0;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100261
julhal01c3f4e9a2020-12-15 13:39:01 +0000262 free(s->resp_buf);
263 s->resp_buf = NULL;
264 s->resp_len = 0;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100265
julhal01c3f4e9a2020-12-15 13:39:01 +0000266 s->is_call_transaction_in_progess = false;
267 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100268}
269
270static int kernel_write_req_buf(struct ffarpc_caller *s) {
271
julhal01c3f4e9a2020-12-15 13:39:01 +0000272 int ioctl_status;
273 struct ffa_ioctl_buf_desc req_descr;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100274
julhal01c3f4e9a2020-12-15 13:39:01 +0000275 req_descr.buf_ptr = (uintptr_t)s->req_buf;
276 req_descr.buf_len = s->req_len;
277 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_WRITE, &req_descr);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100278
julhal01c3f4e9a2020-12-15 13:39:01 +0000279 return ioctl_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100280}
281
282
283static int kernel_read_resp_buf(struct ffarpc_caller *s) {
284
julhal01c3f4e9a2020-12-15 13:39:01 +0000285 int ioctl_status;
286 struct ffa_ioctl_buf_desc resp_descr;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100287
julhal01c3f4e9a2020-12-15 13:39:01 +0000288 resp_descr.buf_ptr = (uintptr_t)s->resp_buf;
289 resp_descr.buf_len = s->resp_len;
290 ioctl_status = ioctl(s->fd, FFA_IOC_SHM_READ, &resp_descr);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100291
julhal01c3f4e9a2020-12-15 13:39:01 +0000292 return ioctl_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100293}
294
295static int share_mem_with_partition(struct ffarpc_caller *s) {
296
julhal01c3f4e9a2020-12-15 13:39:01 +0000297 int ioctl_status;
298 struct ffa_ioctl_msg_args direct_msg;
299 memset(&direct_msg, 0, sizeof(direct_msg));
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100300
julhal01c3f4e9a2020-12-15 13:39:01 +0000301 direct_msg.dst_id = s->dest_partition_id;
302 direct_msg.args[FFA_CALL_ARGS_IFACE_ID_OPCODE] =
303 FFA_CALL_ARGS_COMBINE_IFACE_ID_OPCODE(FFA_CALL_MGMT_IFACE_ID, FFA_CALL_OPCODE_SHARE_BUF);
304 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_LSW] = (uint32_t)s->shared_mem_handle;
305 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_MSW] = (uint32_t)(s->shared_mem_handle >> 32);
306 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_SIZE] = (uint64_t)s->shared_mem_required_size;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100307
julhal01c3f4e9a2020-12-15 13:39:01 +0000308 ioctl_status = ioctl(s->fd, FFA_IOC_MSG_SEND, &direct_msg);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100309
julhal01c3f4e9a2020-12-15 13:39:01 +0000310 return ioctl_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100311}
312
313static int unshare_mem_with_partition(struct ffarpc_caller *s) {
314
julhal01c3f4e9a2020-12-15 13:39:01 +0000315 int ioctl_status;
316 struct ffa_ioctl_msg_args direct_msg;
317 memset(&direct_msg, 0, sizeof(direct_msg));
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100318
julhal01c3f4e9a2020-12-15 13:39:01 +0000319 direct_msg.dst_id = s->dest_partition_id;
320 direct_msg.args[FFA_CALL_ARGS_IFACE_ID_OPCODE] =
321 FFA_CALL_ARGS_COMBINE_IFACE_ID_OPCODE(FFA_CALL_MGMT_IFACE_ID, FFA_CALL_OPCODE_UNSHARE_BUF);
322 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_LSW] = (uint32_t)s->shared_mem_handle;
323 direct_msg.args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_MSW] = (uint32_t)(s->shared_mem_handle >> 32);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100324
julhal01c3f4e9a2020-12-15 13:39:01 +0000325 ioctl_status = ioctl(s->fd, FFA_IOC_MSG_SEND, &direct_msg);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100326
julhal01c3f4e9a2020-12-15 13:39:01 +0000327 return ioctl_status;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100328}