xref: /optee_os/lib/libutee/tee_api.c (revision 7509620b8b95fa57f9c786c15b216cdd3b5ddc7c)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
3b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
4b0104773SPascal Brand  */
5b0104773SPascal Brand #include <stdlib.h>
6b0104773SPascal Brand #include <string.h>
765551e69SJerome Forissier #include <string_ext.h>
8b0104773SPascal Brand #include <tee_api.h>
996c1d8c5SJens Wiklander #include <tee_internal_api_extensions.h>
10ef305e54SJens Wiklander #include <types_ext.h>
11b0104773SPascal Brand #include <user_ta_header.h>
1296c1d8c5SJens Wiklander #include <utee_syscalls.h>
13e86f1266SJens Wiklander #include "tee_api_private.h"
14b0104773SPascal Brand 
15a83ee50aSSadiq Hussain /*
16a83ee50aSSadiq Hussain  * return a known non-NULL invalid pointer when the
17a83ee50aSSadiq Hussain  * requested size is zero
18a83ee50aSSadiq Hussain  */
19a83ee50aSSadiq Hussain #define TEE_NULL_SIZED_VA	((void *)1)
20a83ee50aSSadiq Hussain 
218f07fe6fSJerome Forissier static const void *tee_api_instance_data;
22b0104773SPascal Brand 
23b0104773SPascal Brand /* System API - Internal Client API */
24b0104773SPascal Brand 
25*7509620bSJens Wiklander static void copy_param(struct utee_params *up, uint32_t param_types,
26*7509620bSJens Wiklander 		       const TEE_Param params[TEE_NUM_PARAMS])
27*7509620bSJens Wiklander {
28*7509620bSJens Wiklander 	size_t n = 0;
29*7509620bSJens Wiklander 	uint64_t a = 0;
30*7509620bSJens Wiklander 	uint64_t b = 0;
31*7509620bSJens Wiklander 
32*7509620bSJens Wiklander 	up->types = param_types;
33*7509620bSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
34*7509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
35*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
36*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
37*7509620bSJens Wiklander 			a = params[n].value.a;
38*7509620bSJens Wiklander 			b = params[n].value.b;
39*7509620bSJens Wiklander 			break;
40*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
41*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
42*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
43*7509620bSJens Wiklander 			a = (vaddr_t)params[n].memref.buffer;
44*7509620bSJens Wiklander 			b = params[n].memref.size;
45*7509620bSJens Wiklander 			break;
46*7509620bSJens Wiklander 		default:
47*7509620bSJens Wiklander 			a = 0;
48*7509620bSJens Wiklander 			b = 0;
49*7509620bSJens Wiklander 		}
50*7509620bSJens Wiklander 		up->vals[n * 2] = a;
51*7509620bSJens Wiklander 		up->vals[n * 2 + 1] = b;
52*7509620bSJens Wiklander 	}
53*7509620bSJens Wiklander }
54*7509620bSJens Wiklander 
55*7509620bSJens Wiklander static void copy_gp11_param(struct utee_params *up, uint32_t param_types,
56*7509620bSJens Wiklander 			    const __GP11_TEE_Param params[TEE_NUM_PARAMS])
57*7509620bSJens Wiklander {
58*7509620bSJens Wiklander 	size_t n = 0;
59*7509620bSJens Wiklander 	uint64_t a = 0;
60*7509620bSJens Wiklander 	uint64_t b = 0;
61*7509620bSJens Wiklander 
62*7509620bSJens Wiklander 	up->types = param_types;
63*7509620bSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
64*7509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
65*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INPUT:
66*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
67*7509620bSJens Wiklander 			a = params[n].value.a;
68*7509620bSJens Wiklander 			b = params[n].value.b;
69*7509620bSJens Wiklander 			break;
70*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
71*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
72*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
73*7509620bSJens Wiklander 			a = (vaddr_t)params[n].memref.buffer;
74*7509620bSJens Wiklander 			b = params[n].memref.size;
75*7509620bSJens Wiklander 			break;
76*7509620bSJens Wiklander 		default:
77*7509620bSJens Wiklander 			a = 0;
78*7509620bSJens Wiklander 			b = 0;
79*7509620bSJens Wiklander 		}
80*7509620bSJens Wiklander 		up->vals[n * 2] = a;
81*7509620bSJens Wiklander 		up->vals[n * 2 + 1] = b;
82*7509620bSJens Wiklander 	}
83*7509620bSJens Wiklander }
84*7509620bSJens Wiklander 
85*7509620bSJens Wiklander static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf,
86*7509620bSJens Wiklander 				size_t *tmp_len, void *tmp_va[TEE_NUM_PARAMS])
87e86f1266SJens Wiklander {
88ef305e54SJens Wiklander 	size_t n = 0;
89ef305e54SJens Wiklander 	uint8_t *tb = NULL;
90ef305e54SJens Wiklander 	size_t tbl = 0;
91ef305e54SJens Wiklander 	size_t tmp_align = sizeof(vaddr_t) * 2;
92ef305e54SJens Wiklander 	bool is_tmp_mem[TEE_NUM_PARAMS] = { false };
93ef305e54SJens Wiklander 	void *b = NULL;
94ef305e54SJens Wiklander 	size_t s = 0;
95ef305e54SJens Wiklander 	const uint32_t flags = TEE_MEMORY_ACCESS_READ;
96ef305e54SJens Wiklander 
97ef305e54SJens Wiklander 	/*
98ef305e54SJens Wiklander 	 * If a memory parameter points to TA private memory we need to
99ef305e54SJens Wiklander 	 * allocate a temporary buffer to avoid exposing the memory
100ef305e54SJens Wiklander 	 * directly to the called TA.
101ef305e54SJens Wiklander 	 */
102ef305e54SJens Wiklander 
103ef305e54SJens Wiklander 	*tmp_buf = NULL;
104ef305e54SJens Wiklander 	*tmp_len = 0;
105ef305e54SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
106ef305e54SJens Wiklander 		tmp_va[n] = NULL;
107*7509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
108ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
109ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
110ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
111*7509620bSJens Wiklander 			b = (void *)(vaddr_t)up->vals[n * 2];
112*7509620bSJens Wiklander 			s = up->vals[n * 2 + 1];
113ef305e54SJens Wiklander 			/*
114ef305e54SJens Wiklander 			 * We're only allocating temporary memory if the
115ef305e54SJens Wiklander 			 * buffer is completely within TA memory. If it's
116ef305e54SJens Wiklander 			 * NULL, empty, partially outside or completely
117ef305e54SJens Wiklander 			 * outside TA memory there's nothing more we need
118ef305e54SJens Wiklander 			 * to do here. If there's security/permissions
119ef305e54SJens Wiklander 			 * problem we'll get an error in the
120ef305e54SJens Wiklander 			 * invoke_command/open_session below.
121ef305e54SJens Wiklander 			 */
122ef305e54SJens Wiklander 			if (b && s &&
123ef305e54SJens Wiklander 			    !TEE_CheckMemoryAccessRights(flags, b, s)) {
124ef305e54SJens Wiklander 				is_tmp_mem[n] = true;
125ef305e54SJens Wiklander 				tbl += ROUNDUP(s, tmp_align);
126ef305e54SJens Wiklander 			}
127ef305e54SJens Wiklander 			break;
128ef305e54SJens Wiklander 		default:
129ef305e54SJens Wiklander 			break;
130ef305e54SJens Wiklander 		}
131ef305e54SJens Wiklander 	}
132ef305e54SJens Wiklander 
133ef305e54SJens Wiklander 	if (tbl) {
134ef305e54SJens Wiklander 		tb = tee_map_zi(tbl, TEE_MEMORY_ACCESS_ANY_OWNER);
135ef305e54SJens Wiklander 		if (!tb)
136ef305e54SJens Wiklander 			return TEE_ERROR_OUT_OF_MEMORY;
137ef305e54SJens Wiklander 		*tmp_buf = tb;
138ef305e54SJens Wiklander 		*tmp_len = tbl;
139ef305e54SJens Wiklander 	}
140e86f1266SJens Wiklander 
141e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
142*7509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(up->types, n)) {
143e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
144e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
145ef305e54SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INPUT:
146*7509620bSJens Wiklander 			if (!is_tmp_mem[n])
147*7509620bSJens Wiklander 				break;
148*7509620bSJens Wiklander 			s = up->vals[n * 2 + 1];
149*7509620bSJens Wiklander 			b = (void *)(vaddr_t)up->vals[n * 2];
150ef305e54SJens Wiklander 			tmp_va[n] = tb;
151ef305e54SJens Wiklander 			tb += ROUNDUP(s, tmp_align);
152*7509620bSJens Wiklander 			up->vals[n * 2] = (vaddr_t)tmp_va[n];
153*7509620bSJens Wiklander 			if (TEE_PARAM_TYPE_GET(up->types, n) !=
154ef305e54SJens Wiklander 			    TEE_PARAM_TYPE_MEMREF_OUTPUT)
155*7509620bSJens Wiklander 				memcpy(tmp_va[n], b, s);
156e86f1266SJens Wiklander 			break;
157e86f1266SJens Wiklander 		default:
158e86f1266SJens Wiklander 			break;
159e86f1266SJens Wiklander 		}
160e86f1266SJens Wiklander 	}
161ef305e54SJens Wiklander 
162ef305e54SJens Wiklander 	return TEE_SUCCESS;
163*7509620bSJens Wiklander 
164e86f1266SJens Wiklander }
165e86f1266SJens Wiklander 
166ef305e54SJens Wiklander static void update_out_param(TEE_Param params[TEE_NUM_PARAMS],
167ef305e54SJens Wiklander 			     void *tmp_va[TEE_NUM_PARAMS],
168ef305e54SJens Wiklander 			     const struct utee_params *up)
169e86f1266SJens Wiklander {
170e86f1266SJens Wiklander 	size_t n;
171e86f1266SJens Wiklander 	uint32_t types = up->types;
172e86f1266SJens Wiklander 
173e86f1266SJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
174e86f1266SJens Wiklander 		uintptr_t a = up->vals[n * 2];
175e86f1266SJens Wiklander 		uintptr_t b = up->vals[n * 2 + 1];
176e86f1266SJens Wiklander 
177e86f1266SJens Wiklander 		switch (TEE_PARAM_TYPE_GET(types, n)) {
178e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
179e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
180e86f1266SJens Wiklander 			params[n].value.a = a;
181e86f1266SJens Wiklander 			params[n].value.b = b;
182e86f1266SJens Wiklander 			break;
183e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
184e86f1266SJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
185ef305e54SJens Wiklander 			if (tmp_va[n])
186ef305e54SJens Wiklander 				memcpy(params[n].memref.buffer, tmp_va[n],
187ef305e54SJens Wiklander 				       MIN(b, params[n].memref.size));
188e86f1266SJens Wiklander 			params[n].memref.size = b;
189e86f1266SJens Wiklander 			break;
190e86f1266SJens Wiklander 		default:
191e86f1266SJens Wiklander 			break;
192e86f1266SJens Wiklander 		}
193e86f1266SJens Wiklander 	}
194e86f1266SJens Wiklander }
195e86f1266SJens Wiklander 
196*7509620bSJens Wiklander static void update_out_gp11_param(__GP11_TEE_Param params[TEE_NUM_PARAMS],
197*7509620bSJens Wiklander 				  void *tmp_va[TEE_NUM_PARAMS],
198*7509620bSJens Wiklander 				  const struct utee_params *up)
199*7509620bSJens Wiklander {
200*7509620bSJens Wiklander 	size_t n = 0;
201*7509620bSJens Wiklander 	uint32_t types = up->types;
202*7509620bSJens Wiklander 
203*7509620bSJens Wiklander 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
204*7509620bSJens Wiklander 		uintptr_t a = up->vals[n * 2];
205*7509620bSJens Wiklander 		uintptr_t b = up->vals[n * 2 + 1];
206*7509620bSJens Wiklander 
207*7509620bSJens Wiklander 		switch (TEE_PARAM_TYPE_GET(types, n)) {
208*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
209*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_VALUE_INOUT:
210*7509620bSJens Wiklander 			params[n].value.a = a;
211*7509620bSJens Wiklander 			params[n].value.b = b;
212*7509620bSJens Wiklander 			break;
213*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
214*7509620bSJens Wiklander 		case TEE_PARAM_TYPE_MEMREF_INOUT:
215*7509620bSJens Wiklander 			if (tmp_va[n])
216*7509620bSJens Wiklander 				memcpy(params[n].memref.buffer, tmp_va[n],
217*7509620bSJens Wiklander 				       MIN(b, params[n].memref.size));
218*7509620bSJens Wiklander 			params[n].memref.size = b;
219*7509620bSJens Wiklander 			break;
220*7509620bSJens Wiklander 		default:
221*7509620bSJens Wiklander 			break;
222*7509620bSJens Wiklander 		}
223*7509620bSJens Wiklander 	}
224*7509620bSJens Wiklander }
225*7509620bSJens Wiklander 
226b0104773SPascal Brand TEE_Result TEE_OpenTASession(const TEE_UUID *destination,
227b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
22868540524SIgor Opaniuk 				uint32_t paramTypes,
22968540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
230b0104773SPascal Brand 				TEE_TASessionHandle *session,
231b0104773SPascal Brand 				uint32_t *returnOrigin)
232b0104773SPascal Brand {
233ef305e54SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
234*7509620bSJens Wiklander 	struct utee_params up = { };
235ef305e54SJens Wiklander 	uint32_t s = 0;
236ef305e54SJens Wiklander 	void *tmp_buf = NULL;
237ef305e54SJens Wiklander 	size_t tmp_len = 0;
238ef305e54SJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
239b0104773SPascal Brand 
2406915bbbbSJens Wiklander 	if (paramTypes)
2416915bbbbSJens Wiklander 		__utee_check_inout_annotation(params,
2426915bbbbSJens Wiklander 					      sizeof(TEE_Param) *
2436915bbbbSJens Wiklander 					      TEE_NUM_PARAMS);
2446915bbbbSJens Wiklander 	__utee_check_out_annotation(session, sizeof(*session));
2456915bbbbSJens Wiklander 
246*7509620bSJens Wiklander 	copy_param(&up, paramTypes, params);
247*7509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
248ef305e54SJens Wiklander 	if (res)
249ef305e54SJens Wiklander 		goto out;
2502c028fdeSJerome Forissier 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
251e86f1266SJens Wiklander 				    &up, &s, returnOrigin);
252ef305e54SJens Wiklander 	update_out_param(params, tmp_va, &up);
253ef305e54SJens Wiklander 	if (tmp_buf) {
254ef305e54SJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
255ef305e54SJens Wiklander 
256ef305e54SJens Wiklander 		if (res2)
257ef305e54SJens Wiklander 			TEE_Panic(res2);
258ef305e54SJens Wiklander 	}
259ef305e54SJens Wiklander 
260ef305e54SJens Wiklander out:
261b0104773SPascal Brand 	/*
262b0104773SPascal Brand 	 * Specification says that *session must hold TEE_HANDLE_NULL is
263b0104773SPascal Brand 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
264b0104773SPascal Brand 	 * the syscall fails before out parameters has been updated.
265b0104773SPascal Brand 	 */
266b0104773SPascal Brand 	if (res != TEE_SUCCESS)
267e86f1266SJens Wiklander 		s = TEE_HANDLE_NULL;
268b0104773SPascal Brand 
269e86f1266SJens Wiklander 	*session = (TEE_TASessionHandle)(uintptr_t)s;
270b0104773SPascal Brand 	return res;
271b0104773SPascal Brand }
272b0104773SPascal Brand 
273*7509620bSJens Wiklander TEE_Result __GP11_TEE_OpenTASession(const TEE_UUID *destination,
274*7509620bSJens Wiklander 				    uint32_t cancellationRequestTimeout,
275*7509620bSJens Wiklander 				    uint32_t paramTypes,
276*7509620bSJens Wiklander 				    __GP11_TEE_Param params[TEE_NUM_PARAMS],
277*7509620bSJens Wiklander 				    TEE_TASessionHandle *session,
278*7509620bSJens Wiklander 				    uint32_t *returnOrigin)
279*7509620bSJens Wiklander {
280*7509620bSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
281*7509620bSJens Wiklander 	struct utee_params up = { };
282*7509620bSJens Wiklander 	uint32_t s = 0;
283*7509620bSJens Wiklander 	void *tmp_buf = NULL;
284*7509620bSJens Wiklander 	size_t tmp_len = 0;
285*7509620bSJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
286*7509620bSJens Wiklander 
287*7509620bSJens Wiklander 	if (paramTypes)
288*7509620bSJens Wiklander 		__utee_check_inout_annotation(params,
289*7509620bSJens Wiklander 					      sizeof(__GP11_TEE_Param) *
290*7509620bSJens Wiklander 					      TEE_NUM_PARAMS);
291*7509620bSJens Wiklander 	__utee_check_out_annotation(session, sizeof(*session));
292*7509620bSJens Wiklander 
293*7509620bSJens Wiklander 	copy_gp11_param(&up, paramTypes, params);
294*7509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
295*7509620bSJens Wiklander 	if (res)
296*7509620bSJens Wiklander 		goto out;
297*7509620bSJens Wiklander 	res = _utee_open_ta_session(destination, cancellationRequestTimeout,
298*7509620bSJens Wiklander 				    &up, &s, returnOrigin);
299*7509620bSJens Wiklander 	update_out_gp11_param(params, tmp_va, &up);
300*7509620bSJens Wiklander 	if (tmp_buf) {
301*7509620bSJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
302*7509620bSJens Wiklander 
303*7509620bSJens Wiklander 		if (res2)
304*7509620bSJens Wiklander 			TEE_Panic(res2);
305*7509620bSJens Wiklander 	}
306*7509620bSJens Wiklander 
307*7509620bSJens Wiklander out:
308*7509620bSJens Wiklander 	/*
309*7509620bSJens Wiklander 	 * Specification says that *session must hold TEE_HANDLE_NULL if
310*7509620bSJens Wiklander 	 * TEE_SUCCESS isn't returned. Set it here explicitly in case
311*7509620bSJens Wiklander 	 * the syscall fails before out parameters has been updated.
312*7509620bSJens Wiklander 	 */
313*7509620bSJens Wiklander 	if (res != TEE_SUCCESS)
314*7509620bSJens Wiklander 		s = TEE_HANDLE_NULL;
315*7509620bSJens Wiklander 
316*7509620bSJens Wiklander 	*session = (TEE_TASessionHandle)(uintptr_t)s;
317*7509620bSJens Wiklander 	return res;
318*7509620bSJens Wiklander }
319*7509620bSJens Wiklander 
320b0104773SPascal Brand void TEE_CloseTASession(TEE_TASessionHandle session)
321b0104773SPascal Brand {
322b0104773SPascal Brand 	if (session != TEE_HANDLE_NULL) {
3232c028fdeSJerome Forissier 		TEE_Result res = _utee_close_ta_session((uintptr_t)session);
324e86f1266SJens Wiklander 
325b0104773SPascal Brand 		if (res != TEE_SUCCESS)
326b0104773SPascal Brand 			TEE_Panic(res);
327b0104773SPascal Brand 	}
328b0104773SPascal Brand }
329b0104773SPascal Brand 
330b0104773SPascal Brand TEE_Result TEE_InvokeTACommand(TEE_TASessionHandle session,
331b0104773SPascal Brand 				uint32_t cancellationRequestTimeout,
332b0104773SPascal Brand 				uint32_t commandID, uint32_t paramTypes,
33368540524SIgor Opaniuk 				TEE_Param params[TEE_NUM_PARAMS],
33468540524SIgor Opaniuk 				uint32_t *returnOrigin)
335b0104773SPascal Brand {
336ef305e54SJens Wiklander 	TEE_Result res = TEE_SUCCESS;
337ef305e54SJens Wiklander 	uint32_t ret_origin = TEE_ORIGIN_TEE;
338*7509620bSJens Wiklander 	struct utee_params up = { };
339ef305e54SJens Wiklander 	void *tmp_buf = NULL;
340ef305e54SJens Wiklander 	size_t tmp_len = 0;
341ef305e54SJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
342c15e5835SCedric Chaumont 
3436915bbbbSJens Wiklander 	if (paramTypes)
3446915bbbbSJens Wiklander 		__utee_check_inout_annotation(params,
3456915bbbbSJens Wiklander 					      sizeof(TEE_Param) *
3466915bbbbSJens Wiklander 					      TEE_NUM_PARAMS);
3476915bbbbSJens Wiklander 	if (returnOrigin)
3486915bbbbSJens Wiklander 		__utee_check_out_annotation(returnOrigin,
3496915bbbbSJens Wiklander 					    sizeof(*returnOrigin));
3506915bbbbSJens Wiklander 
351*7509620bSJens Wiklander 	copy_param(&up, paramTypes, params);
352*7509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
353ef305e54SJens Wiklander 	if (res)
354ef305e54SJens Wiklander 		goto out;
3552c028fdeSJerome Forissier 	res = _utee_invoke_ta_command((uintptr_t)session,
356e86f1266SJens Wiklander 				      cancellationRequestTimeout,
357e86f1266SJens Wiklander 				      commandID, &up, &ret_origin);
358ef305e54SJens Wiklander 	update_out_param(params, tmp_va, &up);
359ef305e54SJens Wiklander 	if (tmp_buf) {
360ef305e54SJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
3616709c3eaSCedric Chaumont 
362ef305e54SJens Wiklander 		if (res2)
363ef305e54SJens Wiklander 			TEE_Panic(res2);
364ef305e54SJens Wiklander 	}
365ef305e54SJens Wiklander 
366ef305e54SJens Wiklander out:
3676709c3eaSCedric Chaumont 	if (returnOrigin != NULL)
3686709c3eaSCedric Chaumont 		*returnOrigin = ret_origin;
3696709c3eaSCedric Chaumont 
3706709c3eaSCedric Chaumont 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
3716709c3eaSCedric Chaumont 		return res;
3726709c3eaSCedric Chaumont 
373c15e5835SCedric Chaumont 	if (res != TEE_SUCCESS &&
374c15e5835SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
375c15e5835SCedric Chaumont 	    res != TEE_ERROR_TARGET_DEAD)
376c15e5835SCedric Chaumont 		TEE_Panic(res);
377c15e5835SCedric Chaumont 
378c15e5835SCedric Chaumont 	return res;
379b0104773SPascal Brand }
380b0104773SPascal Brand 
381*7509620bSJens Wiklander TEE_Result __GP11_TEE_InvokeTACommand(TEE_TASessionHandle session,
382*7509620bSJens Wiklander 				      uint32_t cancellationRequestTimeout,
383*7509620bSJens Wiklander 				      uint32_t commandID, uint32_t paramTypes,
384*7509620bSJens Wiklander 				      __GP11_TEE_Param params[TEE_NUM_PARAMS],
385*7509620bSJens Wiklander 				      uint32_t *returnOrigin)
386*7509620bSJens Wiklander {
387*7509620bSJens Wiklander 	TEE_Result res = TEE_SUCCESS;
388*7509620bSJens Wiklander 	uint32_t ret_origin = TEE_ORIGIN_TEE;
389*7509620bSJens Wiklander 	struct utee_params up = { };
390*7509620bSJens Wiklander 	void *tmp_buf = NULL;
391*7509620bSJens Wiklander 	size_t tmp_len = 0;
392*7509620bSJens Wiklander 	void *tmp_va[TEE_NUM_PARAMS] = { NULL };
393*7509620bSJens Wiklander 
394*7509620bSJens Wiklander 	if (paramTypes)
395*7509620bSJens Wiklander 		__utee_check_inout_annotation(params,
396*7509620bSJens Wiklander 					      sizeof(__GP11_TEE_Param) *
397*7509620bSJens Wiklander 					      TEE_NUM_PARAMS);
398*7509620bSJens Wiklander 	if (returnOrigin)
399*7509620bSJens Wiklander 		__utee_check_out_annotation(returnOrigin,
400*7509620bSJens Wiklander 					    sizeof(*returnOrigin));
401*7509620bSJens Wiklander 
402*7509620bSJens Wiklander 	copy_gp11_param(&up, paramTypes, params);
403*7509620bSJens Wiklander 	res = map_tmp_param(&up, &tmp_buf, &tmp_len, tmp_va);
404*7509620bSJens Wiklander 	if (res)
405*7509620bSJens Wiklander 		goto out;
406*7509620bSJens Wiklander 	res = _utee_invoke_ta_command((uintptr_t)session,
407*7509620bSJens Wiklander 				      cancellationRequestTimeout,
408*7509620bSJens Wiklander 				      commandID, &up, &ret_origin);
409*7509620bSJens Wiklander 	update_out_gp11_param(params, tmp_va, &up);
410*7509620bSJens Wiklander 	if (tmp_buf) {
411*7509620bSJens Wiklander 		TEE_Result res2 = tee_unmap(tmp_buf, tmp_len);
412*7509620bSJens Wiklander 
413*7509620bSJens Wiklander 		if (res2)
414*7509620bSJens Wiklander 			TEE_Panic(res2);
415*7509620bSJens Wiklander 	}
416*7509620bSJens Wiklander 
417*7509620bSJens Wiklander out:
418*7509620bSJens Wiklander 	if (returnOrigin)
419*7509620bSJens Wiklander 		*returnOrigin = ret_origin;
420*7509620bSJens Wiklander 
421*7509620bSJens Wiklander 	if (ret_origin == TEE_ORIGIN_TRUSTED_APP)
422*7509620bSJens Wiklander 		return res;
423*7509620bSJens Wiklander 
424*7509620bSJens Wiklander 	if (res != TEE_SUCCESS &&
425*7509620bSJens Wiklander 	    res != TEE_ERROR_OUT_OF_MEMORY &&
426*7509620bSJens Wiklander 	    res != TEE_ERROR_TARGET_DEAD)
427*7509620bSJens Wiklander 		TEE_Panic(res);
428*7509620bSJens Wiklander 
429*7509620bSJens Wiklander 	return res;
430*7509620bSJens Wiklander }
431*7509620bSJens Wiklander 
432b0104773SPascal Brand /* System API - Cancellations */
433b0104773SPascal Brand 
434b0104773SPascal Brand bool TEE_GetCancellationFlag(void)
435b0104773SPascal Brand {
436e86f1266SJens Wiklander 	uint32_t c;
4372c028fdeSJerome Forissier 	TEE_Result res = _utee_get_cancellation_flag(&c);
438e86f1266SJens Wiklander 
439b0104773SPascal Brand 	if (res != TEE_SUCCESS)
440e86f1266SJens Wiklander 		c = 0;
441e86f1266SJens Wiklander 	return !!c;
442b0104773SPascal Brand }
443b0104773SPascal Brand 
444b0104773SPascal Brand bool TEE_UnmaskCancellation(void)
445b0104773SPascal Brand {
446e86f1266SJens Wiklander 	uint32_t old_mask;
4472c028fdeSJerome Forissier 	TEE_Result res = _utee_unmask_cancellation(&old_mask);
448b0104773SPascal Brand 
449b0104773SPascal Brand 	if (res != TEE_SUCCESS)
450b0104773SPascal Brand 		TEE_Panic(res);
451e86f1266SJens Wiklander 	return !!old_mask;
452b0104773SPascal Brand }
453b0104773SPascal Brand 
454b0104773SPascal Brand bool TEE_MaskCancellation(void)
455b0104773SPascal Brand {
456e86f1266SJens Wiklander 	uint32_t old_mask;
4572c028fdeSJerome Forissier 	TEE_Result res = _utee_mask_cancellation(&old_mask);
458b0104773SPascal Brand 
459b0104773SPascal Brand 	if (res != TEE_SUCCESS)
460b0104773SPascal Brand 		TEE_Panic(res);
461e86f1266SJens Wiklander 	return !!old_mask;
462b0104773SPascal Brand }
463b0104773SPascal Brand 
464b0104773SPascal Brand /* System API - Memory Management */
465b0104773SPascal Brand 
466b0104773SPascal Brand TEE_Result TEE_CheckMemoryAccessRights(uint32_t accessFlags, void *buffer,
46779a3c601SCedric Chaumont 				       uint32_t size)
468b0104773SPascal Brand {
469b0104773SPascal Brand 	TEE_Result res;
470b0104773SPascal Brand 
471b0104773SPascal Brand 	if (size == 0)
472b0104773SPascal Brand 		return TEE_SUCCESS;
473b0104773SPascal Brand 
474b0104773SPascal Brand 	/* Check access rights against memory mapping */
4752c028fdeSJerome Forissier 	res = _utee_check_access_rights(accessFlags, buffer, size);
476b0104773SPascal Brand 	if (res != TEE_SUCCESS)
477b0104773SPascal Brand 		goto out;
478b0104773SPascal Brand 
479b0104773SPascal Brand 	/*
480b0104773SPascal Brand 	* Check access rights against input parameters
481b0104773SPascal Brand 	* Previous legacy code was removed and will need to be restored
482b0104773SPascal Brand 	*/
483b0104773SPascal Brand 
484b0104773SPascal Brand 	res = TEE_SUCCESS;
485b0104773SPascal Brand out:
486b0104773SPascal Brand 	return res;
487b0104773SPascal Brand }
488b0104773SPascal Brand 
4898f07fe6fSJerome Forissier void TEE_SetInstanceData(const void *instanceData)
490b0104773SPascal Brand {
491b0104773SPascal Brand 	tee_api_instance_data = instanceData;
492b0104773SPascal Brand }
493b0104773SPascal Brand 
4948f07fe6fSJerome Forissier const void *TEE_GetInstanceData(void)
495b0104773SPascal Brand {
496b0104773SPascal Brand 	return tee_api_instance_data;
497b0104773SPascal Brand }
498b0104773SPascal Brand 
499b0104773SPascal Brand void *TEE_MemMove(void *dest, const void *src, uint32_t size)
500b0104773SPascal Brand {
501b0104773SPascal Brand 	return memmove(dest, src, size);
502b0104773SPascal Brand }
503b0104773SPascal Brand 
504b0104773SPascal Brand int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, uint32_t size)
505b0104773SPascal Brand {
50665551e69SJerome Forissier 	return consttime_memcmp(buffer1, buffer2, size);
507b0104773SPascal Brand }
508b0104773SPascal Brand 
50932c75600SJens Wiklander void TEE_MemFill(void *buff, uint32_t x, uint32_t size)
510b0104773SPascal Brand {
51132c75600SJens Wiklander 	memset(buff, x, size);
512b0104773SPascal Brand }
513b0104773SPascal Brand 
514b0104773SPascal Brand /* Date & Time API */
515b0104773SPascal Brand 
516b0104773SPascal Brand void TEE_GetSystemTime(TEE_Time *time)
517b0104773SPascal Brand {
5182c028fdeSJerome Forissier 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_SYSTEM, time);
519b0104773SPascal Brand 
520b0104773SPascal Brand 	if (res != TEE_SUCCESS)
521b36311adSJerome Forissier 		TEE_Panic(res);
522b0104773SPascal Brand }
523b0104773SPascal Brand 
524b0104773SPascal Brand TEE_Result TEE_Wait(uint32_t timeout)
525b0104773SPascal Brand {
5262c028fdeSJerome Forissier 	TEE_Result res = _utee_wait(timeout);
527b0104773SPascal Brand 
528b0104773SPascal Brand 	if (res != TEE_SUCCESS && res != TEE_ERROR_CANCEL)
529b0104773SPascal Brand 		TEE_Panic(res);
530b0104773SPascal Brand 
531b0104773SPascal Brand 	return res;
532b0104773SPascal Brand }
533b0104773SPascal Brand 
534b0104773SPascal Brand TEE_Result TEE_GetTAPersistentTime(TEE_Time *time)
535b0104773SPascal Brand {
536b64d6909SCedric Chaumont 	TEE_Result res;
537b64d6909SCedric Chaumont 
5382c028fdeSJerome Forissier 	res = _utee_get_time(UTEE_TIME_CAT_TA_PERSISTENT, time);
539b64d6909SCedric Chaumont 
540b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS && res != TEE_ERROR_OVERFLOW) {
541b64d6909SCedric Chaumont 		time->seconds = 0;
542b64d6909SCedric Chaumont 		time->millis = 0;
543b64d6909SCedric Chaumont 	}
544b64d6909SCedric Chaumont 
545b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
546b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NOT_SET &&
547b64d6909SCedric Chaumont 	    res != TEE_ERROR_TIME_NEEDS_RESET &&
548b64d6909SCedric Chaumont 	    res != TEE_ERROR_OVERFLOW &&
549b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY)
550b64d6909SCedric Chaumont 		TEE_Panic(res);
551b64d6909SCedric Chaumont 
552b64d6909SCedric Chaumont 	return res;
553b0104773SPascal Brand }
554b0104773SPascal Brand 
555b0104773SPascal Brand TEE_Result TEE_SetTAPersistentTime(const TEE_Time *time)
556b0104773SPascal Brand {
557b64d6909SCedric Chaumont 	TEE_Result res;
558b64d6909SCedric Chaumont 
5592c028fdeSJerome Forissier 	res = _utee_set_ta_time(time);
560b64d6909SCedric Chaumont 
561b64d6909SCedric Chaumont 	if (res != TEE_SUCCESS &&
562b64d6909SCedric Chaumont 	    res != TEE_ERROR_OUT_OF_MEMORY &&
563b64d6909SCedric Chaumont 	    res != TEE_ERROR_STORAGE_NO_SPACE)
564b64d6909SCedric Chaumont 		TEE_Panic(res);
565b64d6909SCedric Chaumont 
566b64d6909SCedric Chaumont 	return res;
567b0104773SPascal Brand }
568b0104773SPascal Brand 
569b0104773SPascal Brand void TEE_GetREETime(TEE_Time *time)
570b0104773SPascal Brand {
5712c028fdeSJerome Forissier 	TEE_Result res = _utee_get_time(UTEE_TIME_CAT_REE, time);
572b0104773SPascal Brand 
573b0104773SPascal Brand 	if (res != TEE_SUCCESS)
574b36311adSJerome Forissier 		TEE_Panic(res);
575b0104773SPascal Brand }
576b0104773SPascal Brand 
57779a3c601SCedric Chaumont void *TEE_Malloc(uint32_t len, uint32_t hint)
578b0104773SPascal Brand {
579a83ee50aSSadiq Hussain 	if (!len)
580a83ee50aSSadiq Hussain 		return TEE_NULL_SIZED_VA;
581a83ee50aSSadiq Hussain 
58296c1d8c5SJens Wiklander 	if (hint == TEE_MALLOC_FILL_ZERO)
58396c1d8c5SJens Wiklander 		return calloc(1, len);
58496c1d8c5SJens Wiklander 	else if (hint == TEE_USER_MEM_HINT_NO_FILL_ZERO)
58596c1d8c5SJens Wiklander 		return malloc(len);
58696c1d8c5SJens Wiklander 
58796c1d8c5SJens Wiklander 	EMSG("Invalid hint %#" PRIx32, hint);
58896c1d8c5SJens Wiklander 
58996c1d8c5SJens Wiklander 	return NULL;
590b0104773SPascal Brand }
591b0104773SPascal Brand 
592c0ce02edSJens Wiklander void *TEE_Realloc(void *buffer, uint32_t newSize)
593b0104773SPascal Brand {
594a83ee50aSSadiq Hussain 	if (!newSize) {
595a83ee50aSSadiq Hussain 		TEE_Free(buffer);
596a83ee50aSSadiq Hussain 		return TEE_NULL_SIZED_VA;
597a83ee50aSSadiq Hussain 	}
598a83ee50aSSadiq Hussain 
599a83ee50aSSadiq Hussain 	if (buffer == TEE_NULL_SIZED_VA)
600a83ee50aSSadiq Hussain 		return calloc(1, newSize);
601a83ee50aSSadiq Hussain 
60296c1d8c5SJens Wiklander 	return realloc(buffer, newSize);
603b0104773SPascal Brand }
604b0104773SPascal Brand 
605b0104773SPascal Brand void TEE_Free(void *buffer)
606b0104773SPascal Brand {
607a83ee50aSSadiq Hussain 	if (buffer != TEE_NULL_SIZED_VA)
60896c1d8c5SJens Wiklander 		free(buffer);
609b0104773SPascal Brand }
610fa530828SPascal Brand 
611fa530828SPascal Brand /* Cache maintenance support (TA requires the CACHE_MAINTENANCE property) */
612fa530828SPascal Brand TEE_Result TEE_CacheClean(char *buf, size_t len)
613fa530828SPascal Brand {
6142c028fdeSJerome Forissier 	return _utee_cache_operation(buf, len, TEE_CACHECLEAN);
615fa530828SPascal Brand }
616fa530828SPascal Brand TEE_Result TEE_CacheFlush(char *buf, size_t len)
617fa530828SPascal Brand {
6182c028fdeSJerome Forissier 	return _utee_cache_operation(buf, len, TEE_CACHEFLUSH);
619fa530828SPascal Brand }
620fa530828SPascal Brand 
621fa530828SPascal Brand TEE_Result TEE_CacheInvalidate(char *buf, size_t len)
622fa530828SPascal Brand {
6232c028fdeSJerome Forissier 	return _utee_cache_operation(buf, len, TEE_CACHEINVALIDATE);
624fa530828SPascal Brand }
625