2 * Copyright (c) 2016-2017, Linaro Limited
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
29 #include <kernel/pseudo_ta.h>
30 #include <optee_msg.h>
31 #include <optee_msg_supplicant.h>
32 #include <pta_socket.h>
34 #include <tee/tee_fs_rpc.h>
36 static uint32_t get_instance_id(struct tee_ta_session *sess)
38 return sess->ctx->ops->get_instance_id(sess->ctx);
41 static TEE_Result socket_open(uint32_t instance_id, uint32_t param_types,
42 TEE_Param params[TEE_NUM_PARAMS])
48 struct optee_msg_param msg_params[4];
49 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
50 TEE_PARAM_TYPE_MEMREF_INPUT,
51 TEE_PARAM_TYPE_VALUE_INPUT,
52 TEE_PARAM_TYPE_VALUE_OUTPUT);
54 if (exp_pt != param_types) {
55 DMSG("got param_types 0x%x, expected 0x%x",
57 return TEE_ERROR_BAD_PARAMETERS;
60 memset(msg_params, 0, sizeof(msg_params));
62 va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
64 return TEE_ERROR_OUT_OF_MEMORY;
66 msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
67 msg_params[0].u.value.a = OPTEE_MRC_SOCKET_OPEN;
68 msg_params[0].u.value.b = instance_id;
70 msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
71 msg_params[1].u.value.a = params[0].value.b; /* server port number */
72 msg_params[1].u.value.b = params[2].value.a; /* protocol */
73 msg_params[1].u.value.c = params[0].value.a; /* ip version */
76 msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
77 msg_params[2].u.tmem.buf_ptr = pa;
78 msg_params[2].u.tmem.size = params[1].memref.size;
79 msg_params[2].u.tmem.shm_ref = cookie;
80 memcpy(va, params[1].memref.buffer, params[1].memref.size);
83 msg_params[3].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
85 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 4, msg_params);
87 if (res == TEE_SUCCESS)
88 params[3].value.a = msg_params[3].u.value.a;
93 static TEE_Result socket_close(uint32_t instance_id, uint32_t param_types,
94 TEE_Param params[TEE_NUM_PARAMS])
96 struct optee_msg_param msg_params[1];
97 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
100 TEE_PARAM_TYPE_NONE);
102 if (exp_pt != param_types) {
103 DMSG("got param_types 0x%x, expected 0x%x",
104 param_types, exp_pt);
105 return TEE_ERROR_BAD_PARAMETERS;
108 memset(msg_params, 0, sizeof(msg_params));
110 msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
111 msg_params[0].u.value.a = OPTEE_MRC_SOCKET_CLOSE;
112 msg_params[0].u.value.b = instance_id;
113 msg_params[0].u.value.c = params[0].value.a;
115 return thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 1, msg_params);
118 static TEE_Result socket_send(uint32_t instance_id, uint32_t param_types,
119 TEE_Param params[TEE_NUM_PARAMS])
125 struct optee_msg_param msg_params[3];
126 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
127 TEE_PARAM_TYPE_MEMREF_INPUT,
128 TEE_PARAM_TYPE_VALUE_OUTPUT,
129 TEE_PARAM_TYPE_NONE);
131 if (exp_pt != param_types) {
132 DMSG("got param_types 0x%x, expected 0x%x",
133 param_types, exp_pt);
134 return TEE_ERROR_BAD_PARAMETERS;
137 memset(msg_params, 0, sizeof(msg_params));
139 va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
141 return TEE_ERROR_OUT_OF_MEMORY;
143 msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
144 msg_params[0].u.value.a = OPTEE_MRC_SOCKET_SEND;
145 msg_params[0].u.value.b = instance_id;
146 msg_params[0].u.value.c = params[0].value.a; /* handle */
149 msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
150 msg_params[1].u.tmem.buf_ptr = pa;
151 msg_params[1].u.tmem.size = params[1].memref.size;
152 msg_params[1].u.tmem.shm_ref = cookie;
153 memcpy(va, params[1].memref.buffer, params[1].memref.size);
155 msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INOUT;
156 msg_params[2].u.value.a = params[0].value.b /* timeout */;
159 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 3, msg_params);
160 params[2].value.a = msg_params[2].u.value.b; /* transmitted bytes */
164 static TEE_Result socket_recv(uint32_t instance_id, uint32_t param_types,
165 TEE_Param params[TEE_NUM_PARAMS])
171 struct optee_msg_param msg_params[3];
172 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
173 TEE_PARAM_TYPE_MEMREF_OUTPUT,
175 TEE_PARAM_TYPE_NONE);
177 if (exp_pt != param_types) {
178 DMSG("got param_types 0x%x, expected 0x%x",
179 param_types, exp_pt);
180 return TEE_ERROR_BAD_PARAMETERS;
183 memset(msg_params, 0, sizeof(msg_params));
185 va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
187 return TEE_ERROR_OUT_OF_MEMORY;
189 msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
190 msg_params[0].u.value.a = OPTEE_MRC_SOCKET_RECV;
191 msg_params[0].u.value.b = instance_id;
192 msg_params[0].u.value.c = params[0].value.a; /* handle */
195 msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
196 msg_params[1].u.tmem.buf_ptr = pa;
197 msg_params[1].u.tmem.size = params[1].memref.size;
198 msg_params[1].u.tmem.shm_ref = cookie;
200 msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
201 msg_params[2].u.value.a = params[0].value.b /* timeout */;
204 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 3, msg_params);
205 params[1].memref.size = msg_params[1].u.tmem.size;
206 if (msg_params[1].u.tmem.size)
207 memcpy(params[1].memref.buffer, va, msg_params[1].u.tmem.size);
211 static TEE_Result socket_ioctl(uint32_t instance_id, uint32_t param_types,
212 TEE_Param params[TEE_NUM_PARAMS])
218 struct optee_msg_param msg_params[3];
219 uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
220 TEE_PARAM_TYPE_MEMREF_INOUT,
222 TEE_PARAM_TYPE_NONE);
224 if (exp_pt != param_types) {
225 DMSG("got param_types 0x%x, expected 0x%x",
226 param_types, exp_pt);
227 return TEE_ERROR_BAD_PARAMETERS;
230 memset(msg_params, 0, sizeof(msg_params));
232 va = tee_fs_rpc_cache_alloc(params[1].memref.size, &pa, &cookie);
234 return TEE_ERROR_OUT_OF_MEMORY;
236 msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
237 msg_params[0].u.value.a = OPTEE_MRC_SOCKET_IOCTL;
238 msg_params[0].u.value.b = instance_id;
239 msg_params[0].u.value.c = params[0].value.a; /* handle */
242 msg_params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INOUT;
243 msg_params[1].u.tmem.buf_ptr = pa;
244 msg_params[1].u.tmem.size = params[1].memref.size;
245 msg_params[1].u.tmem.shm_ref = cookie;
246 memcpy(va, params[1].memref.buffer, params[1].memref.size);
248 msg_params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
249 msg_params[2].u.value.a = params[0].value.b; /* ioctl command */
251 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 3, msg_params);
252 if (msg_params[1].u.tmem.size <= params[1].memref.size)
253 memcpy(params[1].memref.buffer, va, msg_params[1].u.tmem.size);
254 params[1].memref.size = msg_params[1].u.tmem.size;
258 typedef TEE_Result (*ta_func)(uint32_t instance_id, uint32_t param_types,
259 TEE_Param params[TEE_NUM_PARAMS]);
261 static const ta_func ta_funcs[] = {
262 [PTA_SOCKET_OPEN] = socket_open,
263 [PTA_SOCKET_CLOSE] = socket_close,
264 [PTA_SOCKET_SEND] = socket_send,
265 [PTA_SOCKET_RECV] = socket_recv,
266 [PTA_SOCKET_IOCTL] = socket_ioctl,
270 * Trusted Application Entry Points
273 static TEE_Result pta_socket_open_session(uint32_t param_types __unused,
274 TEE_Param pParams[TEE_NUM_PARAMS] __unused,
277 struct tee_ta_session *s;
279 /* Check that we're called from a TA */
280 s = tee_ta_get_calling_session();
282 return TEE_ERROR_ACCESS_DENIED;
284 *sess_ctx = (void *)(vaddr_t)get_instance_id(s);
289 static void pta_socket_close_session(void *sess_ctx)
292 struct optee_msg_param msg_params[1];
294 memset(msg_params, 0, sizeof(msg_params));
296 msg_params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
297 msg_params[0].u.value.a = OPTEE_MRC_SOCKET_CLOSE_ALL;
298 msg_params[0].u.value.b = (vaddr_t)sess_ctx;
300 res = thread_rpc_cmd(OPTEE_MSG_RPC_CMD_SOCKET, 1, msg_params);
301 if (res != TEE_SUCCESS)
302 DMSG("OPTEE_MRC_SOCKET_CLOSE_ALL failed: %#" PRIx32, res);
305 static TEE_Result pta_socket_invoke_command(void *sess_ctx, uint32_t cmd_id,
306 uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS])
308 if (cmd_id < ARRAY_SIZE(ta_funcs) && ta_funcs[cmd_id])
309 return ta_funcs[cmd_id]((vaddr_t)sess_ctx, param_types, params);
311 return TEE_ERROR_NOT_IMPLEMENTED;
314 pseudo_ta_register(.uuid = PTA_SOCKET_UUID, .name = "socket",
315 .flags = PTA_DEFAULT_FLAGS,
316 .open_session_entry_point = pta_socket_open_session,
317 .close_session_entry_point = pta_socket_close_session,
318 .invoke_command_entry_point = pta_socket_invoke_command);