xref: /optee_os/core/tee/tee_svc.c (revision b01047730e77127c23a36591643eeb8bb0487d68)
1*b0104773SPascal Brand /*
2*b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
3*b0104773SPascal Brand  * All rights reserved.
4*b0104773SPascal Brand  *
5*b0104773SPascal Brand  * Redistribution and use in source and binary forms, with or without
6*b0104773SPascal Brand  * modification, are permitted provided that the following conditions are met:
7*b0104773SPascal Brand  *
8*b0104773SPascal Brand  * 1. Redistributions of source code must retain the above copyright notice,
9*b0104773SPascal Brand  * this list of conditions and the following disclaimer.
10*b0104773SPascal Brand  *
11*b0104773SPascal Brand  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*b0104773SPascal Brand  * this list of conditions and the following disclaimer in the documentation
13*b0104773SPascal Brand  * and/or other materials provided with the distribution.
14*b0104773SPascal Brand  *
15*b0104773SPascal Brand  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*b0104773SPascal Brand  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*b0104773SPascal Brand  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*b0104773SPascal Brand  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*b0104773SPascal Brand  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*b0104773SPascal Brand  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*b0104773SPascal Brand  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*b0104773SPascal Brand  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*b0104773SPascal Brand  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*b0104773SPascal Brand  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*b0104773SPascal Brand  * POSSIBILITY OF SUCH DAMAGE.
26*b0104773SPascal Brand  */
27*b0104773SPascal Brand #include <kernel/tee_common_otp.h>
28*b0104773SPascal Brand #include <kernel/tee_common.h>
29*b0104773SPascal Brand #include <kernel/tee_compat.h>
30*b0104773SPascal Brand #include <tee_api_types.h>
31*b0104773SPascal Brand #include <kernel/tee_ta_manager.h>
32*b0104773SPascal Brand #include <utee_types.h>
33*b0104773SPascal Brand #include <tee/tee_svc.h>
34*b0104773SPascal Brand #include <mm/tee_mmu.h>
35*b0104773SPascal Brand #include <mm/tee_mm.h>
36*b0104773SPascal Brand #include <kernel/tee_rpc.h>
37*b0104773SPascal Brand #include <kernel/tee_rpc_types.h>
38*b0104773SPascal Brand #include <kernel/tee_time.h>
39*b0104773SPascal Brand 
40*b0104773SPascal Brand #include <user_ta_header.h>
41*b0104773SPascal Brand #include <kernel/tee_core_trace.h>
42*b0104773SPascal Brand #include <kernel/tee_kta_trace.h>
43*b0104773SPascal Brand #include <kernel/chip_services.h>
44*b0104773SPascal Brand #include <tee/tee_hash.h>
45*b0104773SPascal Brand #include <tee_ltc_wrapper.h>
46*b0104773SPascal Brand 
47*b0104773SPascal Brand 
48*b0104773SPascal Brand void tee_svc_sys_log(const void *buf, size_t len)
49*b0104773SPascal Brand {
50*b0104773SPascal Brand 	char *kbuf;
51*b0104773SPascal Brand 
52*b0104773SPascal Brand 	if (len == 0)
53*b0104773SPascal Brand 		return;
54*b0104773SPascal Brand 
55*b0104773SPascal Brand 	kbuf = malloc(len);
56*b0104773SPascal Brand 	if (kbuf == NULL)
57*b0104773SPascal Brand 		return;
58*b0104773SPascal Brand 
59*b0104773SPascal Brand 	/* log as Info/Raw traces */
60*b0104773SPascal Brand 	if (tee_svc_copy_from_user(NULL, kbuf, buf, len) == TEE_SUCCESS)
61*b0104773SPascal Brand 		ATAMSG_RAW("%s", kbuf);
62*b0104773SPascal Brand 
63*b0104773SPascal Brand 	free(kbuf);
64*b0104773SPascal Brand }
65*b0104773SPascal Brand 
66*b0104773SPascal Brand void tee_svc_sys_panic(uint32_t code)
67*b0104773SPascal Brand {
68*b0104773SPascal Brand 	struct tee_ta_session *sess;
69*b0104773SPascal Brand 
70*b0104773SPascal Brand 	if (tee_ta_get_current_session(&sess) == TEE_SUCCESS) {
71*b0104773SPascal Brand 		EMSG("Set session 0x%x to panicked", sess);
72*b0104773SPascal Brand 		sess->ctx->panicked = 1;
73*b0104773SPascal Brand 		sess->ctx->panic_code = code;
74*b0104773SPascal Brand 
75*b0104773SPascal Brand 		{
76*b0104773SPascal Brand 			/*
77*b0104773SPascal Brand 			 * Force panicking. This memory error will be trapped by
78*b0104773SPascal Brand 			 * the error exception handler myErrorHandler()
79*b0104773SPascal Brand 			 */
80*b0104773SPascal Brand 			EMSG("Following 'DTLB exception in bundle'");
81*b0104773SPascal Brand 			EMSG("   is generated with code %d", code);
82*b0104773SPascal Brand 			int *p = 0;
83*b0104773SPascal Brand 			*p = 1;
84*b0104773SPascal Brand 		}
85*b0104773SPascal Brand 	} else {
86*b0104773SPascal Brand 		DMSG("Panic called from unknown TA");
87*b0104773SPascal Brand 	}
88*b0104773SPascal Brand }
89*b0104773SPascal Brand 
90*b0104773SPascal Brand uint32_t tee_svc_sys_dummy(uint32_t *a)
91*b0104773SPascal Brand {
92*b0104773SPascal Brand 	DMSG("tee_svc_sys_dummy: a 0x%x", (unsigned int)a);
93*b0104773SPascal Brand 	return 0;
94*b0104773SPascal Brand }
95*b0104773SPascal Brand 
96*b0104773SPascal Brand uint32_t tee_svc_sys_dummy_7args(uint32_t a1, uint32_t a2, uint32_t a3,
97*b0104773SPascal Brand 				 uint32_t a4, uint32_t a5, uint32_t a6,
98*b0104773SPascal Brand 				 uint32_t a7)
99*b0104773SPascal Brand {
100*b0104773SPascal Brand 	DMSG("tee_svc_sys_dummy_7args: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, %x, %x\n",
101*b0104773SPascal Brand 	     a1, a2, a3, a4, a5, a6, a7);
102*b0104773SPascal Brand 	return 0;
103*b0104773SPascal Brand }
104*b0104773SPascal Brand 
105*b0104773SPascal Brand uint32_t tee_svc_sys_nocall(void)
106*b0104773SPascal Brand {
107*b0104773SPascal Brand 	DMSG("No syscall");
108*b0104773SPascal Brand 	return 0x1;
109*b0104773SPascal Brand }
110*b0104773SPascal Brand 
111*b0104773SPascal Brand TEE_Result tee_svc_sys_get_property(uint32_t prop, tee_uaddr_t buf, size_t blen)
112*b0104773SPascal Brand {
113*b0104773SPascal Brand 	static const char api_vers[] = "1.0";
114*b0104773SPascal Brand 	static const char descr[] = "Version N.N";
115*b0104773SPascal Brand 	/*
116*b0104773SPascal Brand 	 * Value 100 means:
117*b0104773SPascal Brand 	 * System time based on REE-controlled timers. Can be tampered by the
118*b0104773SPascal Brand 	 * REE.  The implementation must still guarantee that the system time
119*b0104773SPascal Brand 	 * is monotonous, i.e., successive calls to TEE_GetSystemTime must
120*b0104773SPascal Brand 	 * return increasing values of the system time.
121*b0104773SPascal Brand 	 */
122*b0104773SPascal Brand 	static const uint32_t sys_time_prot_lvl = 100;
123*b0104773SPascal Brand 	static const uint32_t ta_time_prot_lvl = 100;
124*b0104773SPascal Brand 	struct tee_ta_session *sess;
125*b0104773SPascal Brand 	TEE_Result res;
126*b0104773SPascal Brand 
127*b0104773SPascal Brand 	res = tee_ta_get_current_session(&sess);
128*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
129*b0104773SPascal Brand 		return res;
130*b0104773SPascal Brand 
131*b0104773SPascal Brand 	switch (prop) {
132*b0104773SPascal Brand 	case UTEE_PROP_TEE_API_VERSION:
133*b0104773SPascal Brand 		if (blen < sizeof(api_vers))
134*b0104773SPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
135*b0104773SPascal Brand 		return tee_svc_copy_to_user(sess, (void *)buf, api_vers,
136*b0104773SPascal Brand 					    sizeof(api_vers));
137*b0104773SPascal Brand 
138*b0104773SPascal Brand 	case UTEE_PROP_TEE_DESCR:
139*b0104773SPascal Brand 		if (blen < sizeof(descr))
140*b0104773SPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
141*b0104773SPascal Brand 		return tee_svc_copy_to_user(sess, (void *)buf, descr,
142*b0104773SPascal Brand 					    sizeof(descr));
143*b0104773SPascal Brand 
144*b0104773SPascal Brand 	case UTEE_PROP_TEE_DEV_ID:
145*b0104773SPascal Brand 		{
146*b0104773SPascal Brand 			TEE_UUID uuid;
147*b0104773SPascal Brand 			const size_t nslen = 4;
148*b0104773SPascal Brand 			uint8_t data[4 +
149*b0104773SPascal Brand 				     FVR_DIE_ID_NUM_REGS * sizeof(uint32_t)] = {
150*b0104773SPascal Brand 			    'S', 'T', 'E', 'E' };
151*b0104773SPascal Brand 
152*b0104773SPascal Brand 			if (blen < sizeof(uuid))
153*b0104773SPascal Brand 				return TEE_ERROR_SHORT_BUFFER;
154*b0104773SPascal Brand 
155*b0104773SPascal Brand 			if (tee_otp_get_die_id
156*b0104773SPascal Brand 					(data + nslen, sizeof(data) - nslen))
157*b0104773SPascal Brand 				return TEE_ERROR_BAD_STATE;
158*b0104773SPascal Brand 
159*b0104773SPascal Brand 			res = tee_hash_createdigest(
160*b0104773SPascal Brand 					TEE_ALG_SHA256,
161*b0104773SPascal Brand 					data, sizeof(data),
162*b0104773SPascal Brand 					(uint8_t *)&uuid, sizeof(uuid));
163*b0104773SPascal Brand 			if (res != TEE_SUCCESS)
164*b0104773SPascal Brand 				return TEE_ERROR_BAD_STATE;
165*b0104773SPascal Brand 
166*b0104773SPascal Brand 			/*
167*b0104773SPascal Brand 			 * Changes the random value into and UUID as specifiec
168*b0104773SPascal Brand 			 * in RFC 4122. The magic values are from the example
169*b0104773SPascal Brand 			 * code in the RFC.
170*b0104773SPascal Brand 			 *
171*b0104773SPascal Brand 			 * TEE_UUID is defined slightly different from the RFC,
172*b0104773SPascal Brand 			 * but close enough for our purpose.
173*b0104773SPascal Brand 			 */
174*b0104773SPascal Brand 
175*b0104773SPascal Brand 			uuid.timeHiAndVersion &= 0x0fff;
176*b0104773SPascal Brand 			uuid.timeHiAndVersion |= 5 << 12;
177*b0104773SPascal Brand 
178*b0104773SPascal Brand 			/* uuid.clock_seq_hi_and_reserved in the RFC */
179*b0104773SPascal Brand 			uuid.clockSeqAndNode[0] &= 0x3f;
180*b0104773SPascal Brand 			uuid.clockSeqAndNode[0] |= 0x80;
181*b0104773SPascal Brand 
182*b0104773SPascal Brand 			return tee_svc_copy_to_user(sess, (void *)buf, &uuid,
183*b0104773SPascal Brand 						    sizeof(TEE_UUID));
184*b0104773SPascal Brand 		}
185*b0104773SPascal Brand 
186*b0104773SPascal Brand 	case UTEE_PROP_TEE_SYS_TIME_PROT_LEVEL:
187*b0104773SPascal Brand 		if (blen < sizeof(sys_time_prot_lvl))
188*b0104773SPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
189*b0104773SPascal Brand 		return tee_svc_copy_to_user(sess, (void *)buf,
190*b0104773SPascal Brand 					    &sys_time_prot_lvl,
191*b0104773SPascal Brand 					    sizeof(sys_time_prot_lvl));
192*b0104773SPascal Brand 
193*b0104773SPascal Brand 	case UTEE_PROP_TEE_TA_TIME_PROT_LEVEL:
194*b0104773SPascal Brand 		if (blen < sizeof(ta_time_prot_lvl))
195*b0104773SPascal Brand 			return TEE_ERROR_SHORT_BUFFER;
196*b0104773SPascal Brand 		return tee_svc_copy_to_user(sess, (void *)buf,
197*b0104773SPascal Brand 					    &ta_time_prot_lvl,
198*b0104773SPascal Brand 					    sizeof(ta_time_prot_lvl));
199*b0104773SPascal Brand 
200*b0104773SPascal Brand 	case UTEE_PROP_TEE_ARITH_MAX_BIG_INT_SIZE:
201*b0104773SPascal Brand 		{
202*b0104773SPascal Brand 			uint32_t v = LTC_MAX_BITS_PER_VARIABLE / 2;
203*b0104773SPascal Brand 
204*b0104773SPascal Brand 			if (blen < sizeof(v))
205*b0104773SPascal Brand 				return TEE_ERROR_SHORT_BUFFER;
206*b0104773SPascal Brand 
207*b0104773SPascal Brand 			return tee_svc_copy_to_user(sess, (void *)buf, &v,
208*b0104773SPascal Brand 						    sizeof(v));
209*b0104773SPascal Brand 		}
210*b0104773SPascal Brand 
211*b0104773SPascal Brand 	case UTEE_PROP_CLIENT_ID:
212*b0104773SPascal Brand 		{
213*b0104773SPascal Brand 			if (blen < sizeof(TEE_Identity))
214*b0104773SPascal Brand 				return TEE_ERROR_SHORT_BUFFER;
215*b0104773SPascal Brand 
216*b0104773SPascal Brand 			return tee_svc_copy_to_user(sess, (void *)buf,
217*b0104773SPascal Brand 						    &sess->clnt_id,
218*b0104773SPascal Brand 						    sizeof(TEE_Identity));
219*b0104773SPascal Brand 		}
220*b0104773SPascal Brand 	case UTEE_PROP_TA_APP_ID:
221*b0104773SPascal Brand 		{
222*b0104773SPascal Brand 			if (blen < sizeof(TEE_UUID))
223*b0104773SPascal Brand 				return TEE_ERROR_SHORT_BUFFER;
224*b0104773SPascal Brand 
225*b0104773SPascal Brand 			return tee_svc_copy_to_user(sess, (void *)buf,
226*b0104773SPascal Brand 						    &sess->ctx->head->uuid,
227*b0104773SPascal Brand 						    sizeof(TEE_UUID));
228*b0104773SPascal Brand 		}
229*b0104773SPascal Brand 
230*b0104773SPascal Brand 	default:
231*b0104773SPascal Brand 		break;
232*b0104773SPascal Brand 	}
233*b0104773SPascal Brand 	return TEE_ERROR_NOT_IMPLEMENTED;
234*b0104773SPascal Brand }
235*b0104773SPascal Brand 
236*b0104773SPascal Brand /*
237*b0104773SPascal Brand  * TA invokes some TA with parameter.
238*b0104773SPascal Brand  * If some parameters are memory references:
239*b0104773SPascal Brand  * - either the memref is inside TA private RAM: TA is not allowed to expose
240*b0104773SPascal Brand  *   its private RAM: use a temporary memory buffer and copy the data.
241*b0104773SPascal Brand  * - or the memref is not in the TA private RAM:
242*b0104773SPascal Brand  *   - if the memref was mapped to the TA, TA is allowed to expose it.
243*b0104773SPascal Brand  *   - if so, converts memref virtual address into a physical address.
244*b0104773SPascal Brand  */
245*b0104773SPascal Brand static TEE_Result tee_svc_copy_param(struct tee_ta_session *sess,
246*b0104773SPascal Brand 				     struct tee_ta_session *called_sess,
247*b0104773SPascal Brand 				     uint32_t param_types,
248*b0104773SPascal Brand 				     TEE_Param params[TEE_NUM_PARAMS],
249*b0104773SPascal Brand 				     struct tee_ta_param *param,
250*b0104773SPascal Brand 				     tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS],
251*b0104773SPascal Brand 				     tee_mm_entry_t **mm)
252*b0104773SPascal Brand {
253*b0104773SPascal Brand 	size_t n;
254*b0104773SPascal Brand 	TEE_Result res;
255*b0104773SPascal Brand 	size_t req_mem = 0;
256*b0104773SPascal Brand 	size_t s;
257*b0104773SPascal Brand 	uint8_t *dst = 0;
258*b0104773SPascal Brand 	tee_paddr_t dst_pa, src_pa = 0;
259*b0104773SPascal Brand 	bool ta_private_memref[TEE_NUM_PARAMS];
260*b0104773SPascal Brand 
261*b0104773SPascal Brand 	param->types = param_types;
262*b0104773SPascal Brand 	if (params == NULL) {
263*b0104773SPascal Brand 		if (param->types != 0)
264*b0104773SPascal Brand 			return TEE_ERROR_BAD_PARAMETERS;
265*b0104773SPascal Brand 		memset(param->params, 0, sizeof(param->params));
266*b0104773SPascal Brand 	} else {
267*b0104773SPascal Brand 		tee_svc_copy_from_user(sess, param->params, params,
268*b0104773SPascal Brand 				       sizeof(param->params));
269*b0104773SPascal Brand 	}
270*b0104773SPascal Brand 
271*b0104773SPascal Brand 	if ((called_sess != NULL) &&
272*b0104773SPascal Brand 		(called_sess->ctx->static_ta == NULL) &&
273*b0104773SPascal Brand 		(called_sess->ctx->flags & TA_FLAG_USER_MODE) == 0) {
274*b0104773SPascal Brand 		/*
275*b0104773SPascal Brand 		 * kernel TA, borrow the mapping of the calling
276*b0104773SPascal Brand 		 * during this call.
277*b0104773SPascal Brand 		 */
278*b0104773SPascal Brand 		called_sess->calling_sess = sess;
279*b0104773SPascal Brand 		return TEE_SUCCESS;
280*b0104773SPascal Brand 	}
281*b0104773SPascal Brand 
282*b0104773SPascal Brand 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
283*b0104773SPascal Brand 
284*b0104773SPascal Brand 		ta_private_memref[n] = false;
285*b0104773SPascal Brand 
286*b0104773SPascal Brand 		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
287*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_INPUT:
288*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
289*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_INOUT:
290*b0104773SPascal Brand 			if (param->params[n].memref.buffer == NULL) {
291*b0104773SPascal Brand 				if (param->params[n].memref.size != 0)
292*b0104773SPascal Brand 					return TEE_ERROR_BAD_PARAMETERS;
293*b0104773SPascal Brand 				break;
294*b0104773SPascal Brand 			}
295*b0104773SPascal Brand 			/* uTA cannot expose its private memory */
296*b0104773SPascal Brand 			if (tee_mmu_is_vbuf_inside_ta_private(sess->ctx,
297*b0104773SPascal Brand 				    (uintptr_t)param->params[n].memref.buffer,
298*b0104773SPascal Brand 				    param->params[n].memref.size)) {
299*b0104773SPascal Brand 
300*b0104773SPascal Brand 				s = TEE_ROUNDUP(param->params[n].memref.size,
301*b0104773SPascal Brand 						sizeof(uint32_t));
302*b0104773SPascal Brand 				/* Check overflow */
303*b0104773SPascal Brand 				if (req_mem + s < req_mem)
304*b0104773SPascal Brand 					return TEE_ERROR_BAD_PARAMETERS;
305*b0104773SPascal Brand 				req_mem += s;
306*b0104773SPascal Brand 				ta_private_memref[n] = true;
307*b0104773SPascal Brand 				break;
308*b0104773SPascal Brand 			}
309*b0104773SPascal Brand 			if (!tee_mmu_is_vbuf_outside_ta_private(sess->ctx,
310*b0104773SPascal Brand 				    (uintptr_t)param->params[n].memref.buffer,
311*b0104773SPascal Brand 				    param->params[n].memref.size))
312*b0104773SPascal Brand 				return TEE_ERROR_BAD_PARAMETERS;
313*b0104773SPascal Brand 
314*b0104773SPascal Brand 			if (tee_mmu_user_va2pa(sess->ctx,
315*b0104773SPascal Brand 					(void *)param->params[n].memref.buffer,
316*b0104773SPascal Brand 					(void **)&src_pa) != TEE_SUCCESS)
317*b0104773SPascal Brand 				return TEE_ERROR_BAD_PARAMETERS;
318*b0104773SPascal Brand 
319*b0104773SPascal Brand 			param->param_attr[n] = tee_mmu_user_get_cache_attr(
320*b0104773SPascal Brand 				sess->ctx,
321*b0104773SPascal Brand 				(void *)param->params[n].memref.buffer);
322*b0104773SPascal Brand 
323*b0104773SPascal Brand 			param->params[n].memref.buffer = (void *)src_pa;
324*b0104773SPascal Brand 			break;
325*b0104773SPascal Brand 
326*b0104773SPascal Brand 		default:
327*b0104773SPascal Brand 			break;
328*b0104773SPascal Brand 		}
329*b0104773SPascal Brand 	}
330*b0104773SPascal Brand 
331*b0104773SPascal Brand 	if (req_mem == 0)
332*b0104773SPascal Brand 		return TEE_SUCCESS;
333*b0104773SPascal Brand 
334*b0104773SPascal Brand 	/* Allocate section in secure DDR */
335*b0104773SPascal Brand 	*mm = tee_mm_alloc(&tee_mm_sec_ddr, req_mem);
336*b0104773SPascal Brand 	if (*mm == NULL) {
337*b0104773SPascal Brand 		DMSG("tee_mm_alloc TEE_ERROR_GENERIC");
338*b0104773SPascal Brand 		return TEE_ERROR_GENERIC;
339*b0104773SPascal Brand 	}
340*b0104773SPascal Brand 
341*b0104773SPascal Brand 	/* Get the virtual address for the section in secure DDR */
342*b0104773SPascal Brand 	res = tee_mmu_kmap(tee_mm_get_smem(*mm), req_mem, &dst);
343*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
344*b0104773SPascal Brand 		return res;
345*b0104773SPascal Brand 	dst_pa = tee_mm_get_smem(*mm);
346*b0104773SPascal Brand 
347*b0104773SPascal Brand 	for (n = 0; n < 4; n++) {
348*b0104773SPascal Brand 
349*b0104773SPascal Brand 		if (ta_private_memref[n] == false)
350*b0104773SPascal Brand 			continue;
351*b0104773SPascal Brand 
352*b0104773SPascal Brand 		s = TEE_ROUNDUP(param->params[n].memref.size, sizeof(uint32_t));
353*b0104773SPascal Brand 
354*b0104773SPascal Brand 		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
355*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_INPUT:
356*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_INOUT:
357*b0104773SPascal Brand 			if (param->params[n].memref.buffer != NULL) {
358*b0104773SPascal Brand 				res = tee_svc_copy_from_user(sess, dst,
359*b0104773SPascal Brand 							     param->params[n].
360*b0104773SPascal Brand 							     memref.buffer,
361*b0104773SPascal Brand 							     param->params[n].
362*b0104773SPascal Brand 							     memref.size);
363*b0104773SPascal Brand 				if (res != TEE_SUCCESS)
364*b0104773SPascal Brand 					return res;
365*b0104773SPascal Brand 
366*b0104773SPascal Brand 				param->param_attr[n] =
367*b0104773SPascal Brand 					tee_mmu_kmap_get_cache_attr(dst);
368*b0104773SPascal Brand 				param->params[n].memref.buffer = (void *)dst_pa;
369*b0104773SPascal Brand 				tmp_buf_pa[n] = dst_pa;
370*b0104773SPascal Brand 				dst += s;
371*b0104773SPascal Brand 				dst_pa += s;
372*b0104773SPascal Brand 			}
373*b0104773SPascal Brand 			break;
374*b0104773SPascal Brand 
375*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
376*b0104773SPascal Brand 			if (param->params[n].memref.buffer != NULL) {
377*b0104773SPascal Brand 				param->param_attr[n] =
378*b0104773SPascal Brand 					tee_mmu_kmap_get_cache_attr(dst);
379*b0104773SPascal Brand 				param->params[n].memref.buffer = (void *)dst_pa;
380*b0104773SPascal Brand 				tmp_buf_pa[n] = dst_pa;
381*b0104773SPascal Brand 				dst += s;
382*b0104773SPascal Brand 				dst_pa += s;
383*b0104773SPascal Brand 			}
384*b0104773SPascal Brand 			break;
385*b0104773SPascal Brand 
386*b0104773SPascal Brand 		default:
387*b0104773SPascal Brand 			continue;
388*b0104773SPascal Brand 		}
389*b0104773SPascal Brand 	}
390*b0104773SPascal Brand 
391*b0104773SPascal Brand 	tee_mmu_kunmap(dst, req_mem);
392*b0104773SPascal Brand 
393*b0104773SPascal Brand 	return TEE_SUCCESS;
394*b0104773SPascal Brand }
395*b0104773SPascal Brand 
396*b0104773SPascal Brand /*
397*b0104773SPascal Brand  * Back from execution of service: update parameters passed from TA:
398*b0104773SPascal Brand  * If some parameters were memory references:
399*b0104773SPascal Brand  * - either the memref was temporary: copy back data and update size
400*b0104773SPascal Brand  * - or it was the original TA memref: update only the size value.
401*b0104773SPascal Brand  */
402*b0104773SPascal Brand static TEE_Result tee_svc_update_out_param(
403*b0104773SPascal Brand 		struct tee_ta_session *sess,
404*b0104773SPascal Brand 		struct tee_ta_session *called_sess,
405*b0104773SPascal Brand 		struct tee_ta_param *param,
406*b0104773SPascal Brand 		tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS],
407*b0104773SPascal Brand 		TEE_Param params[TEE_NUM_PARAMS])
408*b0104773SPascal Brand {
409*b0104773SPascal Brand 	size_t n;
410*b0104773SPascal Brand 	bool have_private_mem_map = (called_sess == NULL) ||
411*b0104773SPascal Brand 		(called_sess->ctx->static_ta != NULL) ||
412*b0104773SPascal Brand 		((called_sess->ctx->flags & TA_FLAG_USER_MODE) != 0);
413*b0104773SPascal Brand 
414*b0104773SPascal Brand 	tee_ta_set_current_session(sess);
415*b0104773SPascal Brand 
416*b0104773SPascal Brand 	for (n = 0; n < TEE_NUM_PARAMS; n++) {
417*b0104773SPascal Brand 		switch (TEE_PARAM_TYPE_GET(param->types, n)) {
418*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_OUTPUT:
419*b0104773SPascal Brand 		case TEE_PARAM_TYPE_MEMREF_INOUT:
420*b0104773SPascal Brand 
421*b0104773SPascal Brand 			/* outside TA private => memref is valid, update size */
422*b0104773SPascal Brand 			if (!tee_mmu_is_vbuf_inside_ta_private(sess->ctx,
423*b0104773SPascal Brand 					(uintptr_t)params[n].memref.buffer,
424*b0104773SPascal Brand 					param->params[n].memref.size)) {
425*b0104773SPascal Brand 				params[n].memref.size =
426*b0104773SPascal Brand 					param->params[n].memref.size;
427*b0104773SPascal Brand 				break;
428*b0104773SPascal Brand 			}
429*b0104773SPascal Brand 
430*b0104773SPascal Brand 			/*
431*b0104773SPascal Brand 			 * If we called a kernel TA the parameters are in shared
432*b0104773SPascal Brand 			 * memory and no copy is needed.
433*b0104773SPascal Brand 			 */
434*b0104773SPascal Brand 			if (have_private_mem_map &&
435*b0104773SPascal Brand 			    param->params[n].memref.size <=
436*b0104773SPascal Brand 			    params[n].memref.size) {
437*b0104773SPascal Brand 				uint8_t *src = 0;
438*b0104773SPascal Brand 				TEE_Result res;
439*b0104773SPascal Brand 
440*b0104773SPascal Brand 				/* FIXME: TA_RAM is already mapped ! */
441*b0104773SPascal Brand 				res = tee_mmu_kmap(tmp_buf_pa[n],
442*b0104773SPascal Brand 					param->params[n].memref.size, &src);
443*b0104773SPascal Brand 				if (res != TEE_SUCCESS)
444*b0104773SPascal Brand 					return TEE_ERROR_GENERIC;
445*b0104773SPascal Brand 
446*b0104773SPascal Brand 				res = tee_svc_copy_to_user(sess,
447*b0104773SPascal Brand 							 params[n].memref.
448*b0104773SPascal Brand 							 buffer, src,
449*b0104773SPascal Brand 							 param->params[n].
450*b0104773SPascal Brand 							 memref.size);
451*b0104773SPascal Brand 				if (res != TEE_SUCCESS)
452*b0104773SPascal Brand 					return res;
453*b0104773SPascal Brand 				tee_mmu_kunmap(src,
454*b0104773SPascal Brand 					       param->params[n].memref.size);
455*b0104773SPascal Brand 
456*b0104773SPascal Brand 			}
457*b0104773SPascal Brand 			params[n].memref.size = param->params[n].memref.size;
458*b0104773SPascal Brand 			break;
459*b0104773SPascal Brand 
460*b0104773SPascal Brand 		case TEE_PARAM_TYPE_VALUE_OUTPUT:
461*b0104773SPascal Brand 		case TEE_PARAM_TYPE_VALUE_INOUT:
462*b0104773SPascal Brand 			params[n].value = param->params[n].value;
463*b0104773SPascal Brand 			break;
464*b0104773SPascal Brand 
465*b0104773SPascal Brand 		default:
466*b0104773SPascal Brand 			continue;
467*b0104773SPascal Brand 		}
468*b0104773SPascal Brand 	}
469*b0104773SPascal Brand 
470*b0104773SPascal Brand 	return TEE_SUCCESS;
471*b0104773SPascal Brand }
472*b0104773SPascal Brand 
473*b0104773SPascal Brand /* Called when a TA calls an OpenSession on another TA */
474*b0104773SPascal Brand TEE_Result tee_svc_open_ta_session(const TEE_UUID *dest,
475*b0104773SPascal Brand 				   uint32_t cancel_req_to, uint32_t param_types,
476*b0104773SPascal Brand 				   TEE_Param params[4],
477*b0104773SPascal Brand 				   TEE_TASessionHandle *ta_sess,
478*b0104773SPascal Brand 				   uint32_t *ret_orig)
479*b0104773SPascal Brand {
480*b0104773SPascal Brand 	TEE_Result res;
481*b0104773SPascal Brand 	uint32_t ret_o = TEE_ORIGIN_TEE;
482*b0104773SPascal Brand 	struct tee_ta_session *s = NULL;
483*b0104773SPascal Brand 	struct tee_ta_session *sess;
484*b0104773SPascal Brand 	tee_mm_entry_t *mm_param = NULL;
485*b0104773SPascal Brand 
486*b0104773SPascal Brand 	TEE_UUID *uuid = malloc(sizeof(TEE_UUID));
487*b0104773SPascal Brand 	struct tee_ta_param *param = malloc(sizeof(struct tee_ta_param));
488*b0104773SPascal Brand 	TEE_Identity *clnt_id = malloc(sizeof(TEE_Identity));
489*b0104773SPascal Brand 	tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS];
490*b0104773SPascal Brand 
491*b0104773SPascal Brand 	if (uuid == NULL || param == NULL || clnt_id == NULL) {
492*b0104773SPascal Brand 		res = TEE_ERROR_OUT_OF_MEMORY;
493*b0104773SPascal Brand 		goto out_free_only;
494*b0104773SPascal Brand 	}
495*b0104773SPascal Brand 
496*b0104773SPascal Brand 	memset(param, 0, sizeof(struct tee_ta_param));
497*b0104773SPascal Brand 
498*b0104773SPascal Brand 	res = tee_ta_get_current_session(&sess);
499*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
500*b0104773SPascal Brand 		goto out_free_only;
501*b0104773SPascal Brand 
502*b0104773SPascal Brand 	res = tee_svc_copy_from_user(sess, uuid, dest, sizeof(TEE_UUID));
503*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
504*b0104773SPascal Brand 		goto function_exit;
505*b0104773SPascal Brand 
506*b0104773SPascal Brand 	clnt_id->login = TEE_LOGIN_TRUSTED_APP;
507*b0104773SPascal Brand 	memcpy(&clnt_id->uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID));
508*b0104773SPascal Brand 
509*b0104773SPascal Brand 	res = tee_svc_copy_param(sess, NULL, param_types, params, param,
510*b0104773SPascal Brand 				 tmp_buf_pa, &mm_param);
511*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
512*b0104773SPascal Brand 		goto function_exit;
513*b0104773SPascal Brand 
514*b0104773SPascal Brand 	/*
515*b0104773SPascal Brand 	 * Find session of a multi session TA or a static TA
516*b0104773SPascal Brand 	 * In such a case, there is no need to ask the supplicant for the TA
517*b0104773SPascal Brand 	 * code
518*b0104773SPascal Brand 	 */
519*b0104773SPascal Brand 	res = tee_ta_open_session(&ret_o, &s, &sess->ctx->open_sessions, uuid,
520*b0104773SPascal Brand 				  NULL, clnt_id, cancel_req_to, param);
521*b0104773SPascal Brand 
522*b0104773SPascal Brand 	if (ret_o != TEE_ORIGIN_TEE || res != TEE_ERROR_ITEM_NOT_FOUND)
523*b0104773SPascal Brand 		goto function_exit;
524*b0104773SPascal Brand 
525*b0104773SPascal Brand 	if (ret_o == TEE_ORIGIN_TEE && res == TEE_ERROR_ITEM_NOT_FOUND) {
526*b0104773SPascal Brand 		kta_signed_header_t *ta = NULL;
527*b0104773SPascal Brand 		struct tee_ta_nwumap lp;
528*b0104773SPascal Brand 
529*b0104773SPascal Brand 		tee_mmu_set_ctx(NULL);
530*b0104773SPascal Brand 
531*b0104773SPascal Brand 		/* Load TA */
532*b0104773SPascal Brand 		res = tee_ta_rpc_load(uuid, &ta, &lp, &ret_o);
533*b0104773SPascal Brand 		if (res != TEE_SUCCESS) {
534*b0104773SPascal Brand 			tee_mmu_set_ctx(sess->ctx);
535*b0104773SPascal Brand 			goto function_exit;
536*b0104773SPascal Brand 		}
537*b0104773SPascal Brand 
538*b0104773SPascal Brand 		res = tee_ta_open_session(&ret_o, &s, &sess->ctx->open_sessions,
539*b0104773SPascal Brand 					  uuid, ta, clnt_id, cancel_req_to,
540*b0104773SPascal Brand 					  param);
541*b0104773SPascal Brand 		tee_mmu_set_ctx(sess->ctx);
542*b0104773SPascal Brand 		if (res != TEE_SUCCESS)
543*b0104773SPascal Brand 			goto function_exit;
544*b0104773SPascal Brand 
545*b0104773SPascal Brand 		s->ctx->nwumap = lp;
546*b0104773SPascal Brand 	}
547*b0104773SPascal Brand 
548*b0104773SPascal Brand 	res = tee_svc_update_out_param(sess, NULL, param, tmp_buf_pa, params);
549*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
550*b0104773SPascal Brand 		goto function_exit;
551*b0104773SPascal Brand 
552*b0104773SPascal Brand function_exit:
553*b0104773SPascal Brand 	tee_ta_set_current_session(sess);
554*b0104773SPascal Brand 
555*b0104773SPascal Brand 	if (mm_param != NULL) {
556*b0104773SPascal Brand 		TEE_Result res2;
557*b0104773SPascal Brand 		void *va = 0;
558*b0104773SPascal Brand 
559*b0104773SPascal Brand 		res2 =
560*b0104773SPascal Brand 		    tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va);
561*b0104773SPascal Brand 		if (res2 == TEE_SUCCESS)
562*b0104773SPascal Brand 			tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param));
563*b0104773SPascal Brand 	}
564*b0104773SPascal Brand 	tee_mm_free(mm_param);
565*b0104773SPascal Brand 	tee_svc_copy_to_user(sess, ta_sess, &s, sizeof(s));
566*b0104773SPascal Brand 	tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o));
567*b0104773SPascal Brand 
568*b0104773SPascal Brand out_free_only:
569*b0104773SPascal Brand 	free(param);
570*b0104773SPascal Brand 	free(uuid);
571*b0104773SPascal Brand 	free(clnt_id);
572*b0104773SPascal Brand 	return res;
573*b0104773SPascal Brand }
574*b0104773SPascal Brand 
575*b0104773SPascal Brand TEE_Result tee_svc_close_ta_session(TEE_TASessionHandle ta_sess)
576*b0104773SPascal Brand {
577*b0104773SPascal Brand 	TEE_Result res;
578*b0104773SPascal Brand 	struct tee_ta_session *sess;
579*b0104773SPascal Brand 
580*b0104773SPascal Brand 	res = tee_ta_get_current_session(&sess);
581*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
582*b0104773SPascal Brand 		return res;
583*b0104773SPascal Brand 
584*b0104773SPascal Brand 	tee_ta_set_current_session(NULL);
585*b0104773SPascal Brand 
586*b0104773SPascal Brand 	res =
587*b0104773SPascal Brand 	    tee_ta_close_session((uint32_t)ta_sess, &sess->ctx->open_sessions);
588*b0104773SPascal Brand 	tee_ta_set_current_session(sess);
589*b0104773SPascal Brand 	return res;
590*b0104773SPascal Brand }
591*b0104773SPascal Brand 
592*b0104773SPascal Brand TEE_Result tee_svc_invoke_ta_command(TEE_TASessionHandle ta_sess,
593*b0104773SPascal Brand 				     uint32_t cancel_req_to, uint32_t cmd_id,
594*b0104773SPascal Brand 				     uint32_t param_types, TEE_Param params[4],
595*b0104773SPascal Brand 				     uint32_t *ret_orig)
596*b0104773SPascal Brand {
597*b0104773SPascal Brand 	TEE_Result res;
598*b0104773SPascal Brand 	uint32_t ret_o = TEE_ORIGIN_TEE;
599*b0104773SPascal Brand 	struct tee_ta_param param = { 0 };
600*b0104773SPascal Brand 	TEE_Identity clnt_id;
601*b0104773SPascal Brand 	struct tee_ta_session *sess;
602*b0104773SPascal Brand 	struct tee_ta_session *called_sess = (struct tee_ta_session *)ta_sess;
603*b0104773SPascal Brand 	tee_mm_entry_t *mm_param = NULL;
604*b0104773SPascal Brand 	tee_paddr_t tmp_buf_pa[TEE_NUM_PARAMS];
605*b0104773SPascal Brand 
606*b0104773SPascal Brand 	res = tee_ta_get_current_session(&sess);
607*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
608*b0104773SPascal Brand 		return res;
609*b0104773SPascal Brand 
610*b0104773SPascal Brand 	res =
611*b0104773SPascal Brand 	    tee_ta_verify_session_pointer(called_sess,
612*b0104773SPascal Brand 					  &sess->ctx->open_sessions);
613*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
614*b0104773SPascal Brand 		return res;
615*b0104773SPascal Brand 
616*b0104773SPascal Brand 	res = tee_svc_copy_param(sess, called_sess, param_types, params,
617*b0104773SPascal Brand 				 &param, tmp_buf_pa, &mm_param);
618*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
619*b0104773SPascal Brand 		goto function_exit;
620*b0104773SPascal Brand 
621*b0104773SPascal Brand 	res =
622*b0104773SPascal Brand 	    tee_ta_invoke_command(&ret_o, called_sess, &clnt_id, cancel_req_to,
623*b0104773SPascal Brand 				  cmd_id, &param);
624*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
625*b0104773SPascal Brand 		goto function_exit;
626*b0104773SPascal Brand 
627*b0104773SPascal Brand 	res = tee_svc_update_out_param(sess, called_sess, &param, tmp_buf_pa,
628*b0104773SPascal Brand 				       params);
629*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
630*b0104773SPascal Brand 		goto function_exit;
631*b0104773SPascal Brand 
632*b0104773SPascal Brand function_exit:
633*b0104773SPascal Brand 	tee_ta_set_current_session(sess);
634*b0104773SPascal Brand 	called_sess->calling_sess = NULL; /* clear eventual borrowed mapping */
635*b0104773SPascal Brand 
636*b0104773SPascal Brand 	if (mm_param != NULL) {
637*b0104773SPascal Brand 		TEE_Result res2;
638*b0104773SPascal Brand 		void *va = 0;
639*b0104773SPascal Brand 
640*b0104773SPascal Brand 		res2 =
641*b0104773SPascal Brand 		    tee_mmu_kmap_pa2va((void *)tee_mm_get_smem(mm_param), &va);
642*b0104773SPascal Brand 		if (res2 == TEE_SUCCESS)
643*b0104773SPascal Brand 			tee_mmu_kunmap(va, tee_mm_get_bytes(mm_param));
644*b0104773SPascal Brand 	}
645*b0104773SPascal Brand 	tee_mm_free(mm_param);
646*b0104773SPascal Brand 	if (ret_orig)
647*b0104773SPascal Brand 		tee_svc_copy_to_user(sess, ret_orig, &ret_o, sizeof(ret_o));
648*b0104773SPascal Brand 	return res;
649*b0104773SPascal Brand }
650*b0104773SPascal Brand 
651*b0104773SPascal Brand TEE_Result tee_svc_check_access_rights(uint32_t flags, const void *buf,
652*b0104773SPascal Brand 				       size_t len)
653*b0104773SPascal Brand {
654*b0104773SPascal Brand 	TEE_Result res;
655*b0104773SPascal Brand 	struct tee_ta_session *s;
656*b0104773SPascal Brand 
657*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
658*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
659*b0104773SPascal Brand 		return res;
660*b0104773SPascal Brand 
661*b0104773SPascal Brand 	return tee_mmu_check_access_rights(s->ctx, flags, (tee_uaddr_t)buf,
662*b0104773SPascal Brand 					   len);
663*b0104773SPascal Brand }
664*b0104773SPascal Brand 
665*b0104773SPascal Brand TEE_Result tee_svc_copy_from_user(struct tee_ta_session *sess, void *kaddr,
666*b0104773SPascal Brand 				  const void *uaddr, size_t len)
667*b0104773SPascal Brand {
668*b0104773SPascal Brand 	TEE_Result res;
669*b0104773SPascal Brand 	struct tee_ta_session *s;
670*b0104773SPascal Brand 
671*b0104773SPascal Brand 	if (sess == NULL) {
672*b0104773SPascal Brand 		res = tee_ta_get_current_session(&s);
673*b0104773SPascal Brand 		if (res != TEE_SUCCESS)
674*b0104773SPascal Brand 			return res;
675*b0104773SPascal Brand 	} else {
676*b0104773SPascal Brand 		s = sess;
677*b0104773SPascal Brand 		tee_ta_set_current_session(s);
678*b0104773SPascal Brand 	}
679*b0104773SPascal Brand 	res =
680*b0104773SPascal Brand 	    tee_mmu_check_access_rights(s->ctx,
681*b0104773SPascal Brand 					TEE_MEMORY_ACCESS_READ |
682*b0104773SPascal Brand 					TEE_MEMORY_ACCESS_ANY_OWNER,
683*b0104773SPascal Brand 					(tee_uaddr_t)uaddr, len);
684*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
685*b0104773SPascal Brand 		return res;
686*b0104773SPascal Brand 
687*b0104773SPascal Brand 	memcpy(kaddr, uaddr, len);
688*b0104773SPascal Brand 	return TEE_SUCCESS;
689*b0104773SPascal Brand }
690*b0104773SPascal Brand 
691*b0104773SPascal Brand TEE_Result tee_svc_copy_to_user(struct tee_ta_session *sess, void *uaddr,
692*b0104773SPascal Brand 				const void *kaddr, size_t len)
693*b0104773SPascal Brand {
694*b0104773SPascal Brand 	TEE_Result res;
695*b0104773SPascal Brand 	struct tee_ta_session *s;
696*b0104773SPascal Brand 
697*b0104773SPascal Brand 	if (sess == NULL) {
698*b0104773SPascal Brand 		res = tee_ta_get_current_session(&s);
699*b0104773SPascal Brand 		if (res != TEE_SUCCESS)
700*b0104773SPascal Brand 			return res;
701*b0104773SPascal Brand 	} else {
702*b0104773SPascal Brand 		s = sess;
703*b0104773SPascal Brand 		tee_ta_set_current_session(s);
704*b0104773SPascal Brand 	}
705*b0104773SPascal Brand 
706*b0104773SPascal Brand 	res =
707*b0104773SPascal Brand 	    tee_mmu_check_access_rights(s->ctx,
708*b0104773SPascal Brand 					TEE_MEMORY_ACCESS_WRITE |
709*b0104773SPascal Brand 					TEE_MEMORY_ACCESS_ANY_OWNER,
710*b0104773SPascal Brand 					(tee_uaddr_t)uaddr, len);
711*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
712*b0104773SPascal Brand 		return res;
713*b0104773SPascal Brand 
714*b0104773SPascal Brand 	memcpy(uaddr, kaddr, len);
715*b0104773SPascal Brand 	return TEE_SUCCESS;
716*b0104773SPascal Brand }
717*b0104773SPascal Brand 
718*b0104773SPascal Brand static bool session_is_cancelled(struct tee_ta_session *s, TEE_Time *curr_time)
719*b0104773SPascal Brand {
720*b0104773SPascal Brand 	TEE_Time current_time;
721*b0104773SPascal Brand 
722*b0104773SPascal Brand 	if (s->cancel_mask)
723*b0104773SPascal Brand 		return false;
724*b0104773SPascal Brand 
725*b0104773SPascal Brand 	if (s->cancel)
726*b0104773SPascal Brand 		return true;
727*b0104773SPascal Brand 
728*b0104773SPascal Brand 	if (s->cancel_time.seconds == UINT32_MAX)
729*b0104773SPascal Brand 		return false;
730*b0104773SPascal Brand 
731*b0104773SPascal Brand 	if (curr_time != NULL)
732*b0104773SPascal Brand 		current_time = *curr_time;
733*b0104773SPascal Brand 	else if (tee_time_get_sys_time(&current_time) != TEE_SUCCESS)
734*b0104773SPascal Brand 		return false;
735*b0104773SPascal Brand 
736*b0104773SPascal Brand 	if (current_time.seconds > s->cancel_time.seconds ||
737*b0104773SPascal Brand 	    (current_time.seconds == s->cancel_time.seconds &&
738*b0104773SPascal Brand 	     current_time.millis >= s->cancel_time.millis)) {
739*b0104773SPascal Brand 		return true;
740*b0104773SPascal Brand 	}
741*b0104773SPascal Brand 
742*b0104773SPascal Brand 	return false;
743*b0104773SPascal Brand }
744*b0104773SPascal Brand 
745*b0104773SPascal Brand TEE_Result tee_svc_get_cancellation_flag(bool *cancel)
746*b0104773SPascal Brand {
747*b0104773SPascal Brand 	TEE_Result res;
748*b0104773SPascal Brand 	struct tee_ta_session *s = NULL;
749*b0104773SPascal Brand 	bool c;
750*b0104773SPascal Brand 
751*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
752*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
753*b0104773SPascal Brand 		return res;
754*b0104773SPascal Brand 
755*b0104773SPascal Brand 	c = session_is_cancelled(s, NULL);
756*b0104773SPascal Brand 
757*b0104773SPascal Brand 	return tee_svc_copy_to_user(s, cancel, &c, sizeof(c));
758*b0104773SPascal Brand }
759*b0104773SPascal Brand 
760*b0104773SPascal Brand TEE_Result tee_svc_unmask_cancellation(bool *old_mask)
761*b0104773SPascal Brand {
762*b0104773SPascal Brand 	TEE_Result res;
763*b0104773SPascal Brand 	struct tee_ta_session *s = NULL;
764*b0104773SPascal Brand 	bool m;
765*b0104773SPascal Brand 
766*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
767*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
768*b0104773SPascal Brand 		return res;
769*b0104773SPascal Brand 
770*b0104773SPascal Brand 	m = s->cancel_mask;
771*b0104773SPascal Brand 	s->cancel_mask = false;
772*b0104773SPascal Brand 	return tee_svc_copy_to_user(s, old_mask, &m, sizeof(m));
773*b0104773SPascal Brand }
774*b0104773SPascal Brand 
775*b0104773SPascal Brand TEE_Result tee_svc_mask_cancellation(bool *old_mask)
776*b0104773SPascal Brand {
777*b0104773SPascal Brand 	TEE_Result res;
778*b0104773SPascal Brand 	struct tee_ta_session *s = NULL;
779*b0104773SPascal Brand 	bool m;
780*b0104773SPascal Brand 
781*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
782*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
783*b0104773SPascal Brand 		return res;
784*b0104773SPascal Brand 
785*b0104773SPascal Brand 	m = s->cancel_mask;
786*b0104773SPascal Brand 	s->cancel_mask = true;
787*b0104773SPascal Brand 	return tee_svc_copy_to_user(s, old_mask, &m, sizeof(m));
788*b0104773SPascal Brand }
789*b0104773SPascal Brand 
790*b0104773SPascal Brand TEE_Result tee_svc_wait(uint32_t timeout)
791*b0104773SPascal Brand {
792*b0104773SPascal Brand 	TEE_Result res = TEE_SUCCESS;
793*b0104773SPascal Brand 	uint32_t mytime = 0;
794*b0104773SPascal Brand 	struct tee_ta_session *s;
795*b0104773SPascal Brand 	TEE_Time base_time;
796*b0104773SPascal Brand 	TEE_Time current_time;
797*b0104773SPascal Brand 
798*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
799*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
800*b0104773SPascal Brand 		return res;
801*b0104773SPascal Brand 
802*b0104773SPascal Brand 	res = tee_time_get_sys_time(&base_time);
803*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
804*b0104773SPascal Brand 		return res;
805*b0104773SPascal Brand 
806*b0104773SPascal Brand 	while (true) {
807*b0104773SPascal Brand 		res = tee_time_get_sys_time(&current_time);
808*b0104773SPascal Brand 		if (res != TEE_SUCCESS)
809*b0104773SPascal Brand 			return res;
810*b0104773SPascal Brand 
811*b0104773SPascal Brand 		if (session_is_cancelled(s, &current_time))
812*b0104773SPascal Brand 			return TEE_ERROR_CANCEL;
813*b0104773SPascal Brand 
814*b0104773SPascal Brand 		mytime = (current_time.seconds - base_time.seconds) * 1000 +
815*b0104773SPascal Brand 		    (int)current_time.millis - (int)base_time.millis;
816*b0104773SPascal Brand 		if (mytime >= timeout)
817*b0104773SPascal Brand 			return TEE_SUCCESS;
818*b0104773SPascal Brand 
819*b0104773SPascal Brand 		tee_wait_specific(timeout - mytime);
820*b0104773SPascal Brand 	}
821*b0104773SPascal Brand 
822*b0104773SPascal Brand 	return res;
823*b0104773SPascal Brand }
824*b0104773SPascal Brand 
825*b0104773SPascal Brand TEE_Result tee_svc_get_time(enum utee_time_category cat, TEE_Time *mytime)
826*b0104773SPascal Brand {
827*b0104773SPascal Brand 	TEE_Result res, res2;
828*b0104773SPascal Brand 	struct tee_ta_session *s = NULL;
829*b0104773SPascal Brand 	TEE_Time t;
830*b0104773SPascal Brand 
831*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
832*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
833*b0104773SPascal Brand 		return res;
834*b0104773SPascal Brand 
835*b0104773SPascal Brand 	switch (cat) {
836*b0104773SPascal Brand 	case UTEE_TIME_CAT_SYSTEM:
837*b0104773SPascal Brand 		res = tee_time_get_sys_time(&t);
838*b0104773SPascal Brand 		break;
839*b0104773SPascal Brand 	case UTEE_TIME_CAT_TA_PERSISTENT:
840*b0104773SPascal Brand 		res =
841*b0104773SPascal Brand 		    tee_time_get_ta_time((const void *)&s->ctx->head->uuid, &t);
842*b0104773SPascal Brand 		break;
843*b0104773SPascal Brand 	case UTEE_TIME_CAT_REE:
844*b0104773SPascal Brand 		res = tee_time_get_ree_time(&t);
845*b0104773SPascal Brand 		break;
846*b0104773SPascal Brand 	default:
847*b0104773SPascal Brand 		res = TEE_ERROR_BAD_PARAMETERS;
848*b0104773SPascal Brand 		break;
849*b0104773SPascal Brand 	}
850*b0104773SPascal Brand 
851*b0104773SPascal Brand 	if (res == TEE_SUCCESS || res == TEE_ERROR_OVERFLOW) {
852*b0104773SPascal Brand 		res2 = tee_svc_copy_to_user(s, mytime, &t, sizeof(t));
853*b0104773SPascal Brand 		if (res2 != TEE_SUCCESS)
854*b0104773SPascal Brand 			res = res2;
855*b0104773SPascal Brand 	}
856*b0104773SPascal Brand 
857*b0104773SPascal Brand 	return res;
858*b0104773SPascal Brand }
859*b0104773SPascal Brand 
860*b0104773SPascal Brand TEE_Result tee_svc_set_ta_time(const TEE_Time *mytime)
861*b0104773SPascal Brand {
862*b0104773SPascal Brand 	TEE_Result res;
863*b0104773SPascal Brand 	struct tee_ta_session *s = NULL;
864*b0104773SPascal Brand 	TEE_Time t;
865*b0104773SPascal Brand 
866*b0104773SPascal Brand 	res = tee_ta_get_current_session(&s);
867*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
868*b0104773SPascal Brand 		return res;
869*b0104773SPascal Brand 
870*b0104773SPascal Brand 	res = tee_svc_copy_from_user(s, &t, mytime, sizeof(t));
871*b0104773SPascal Brand 	if (res != TEE_SUCCESS)
872*b0104773SPascal Brand 		return res;
873*b0104773SPascal Brand 
874*b0104773SPascal Brand 	return tee_time_set_ta_time((const void *)&s->ctx->head->uuid, &t);
875*b0104773SPascal Brand }
876