xref: /OK3568_Linux_fs/u-boot/lib/optee_clientApi/OpteeClientApiLib.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2017, Rockchip Electronics Co., Ltd
3*4882a593Smuzhiyun  * hisping lin, <hisping.lin@rock-chips.com>
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <optee_include/OpteeClientApiLib.h>
9*4882a593Smuzhiyun #include <optee_include/OpteeClientMem.h>
10*4882a593Smuzhiyun #include <optee_include/OpteeClientRPC.h>
11*4882a593Smuzhiyun #include <optee_include/OpteeClientSMC.h>
12*4882a593Smuzhiyun #include <optee_include/OpteeClientRkFs.h>
13*4882a593Smuzhiyun #include <optee_include/teesmc.h>
14*4882a593Smuzhiyun #include <optee_include/teesmc_optee.h>
15*4882a593Smuzhiyun #include <optee_include/teesmc_v2.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define OPTEE_MSG_REVISION_MAJOR        2
18*4882a593Smuzhiyun #define OPTEE_MSG_REVISION_MINOR        0
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun static bool optee_is_init;
21*4882a593Smuzhiyun 
optee_vm_create(uint32_t client_id)22*4882a593Smuzhiyun static bool optee_vm_create(uint32_t client_id)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun 	ARM_SMC_ARGS ArmSmcArgs = {0};
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun 	ArmSmcArgs.Arg0 = OPTEE_SMC_VM_CREATED;
27*4882a593Smuzhiyun 	ArmSmcArgs.Arg1 = client_id;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	tee_smc_call(&ArmSmcArgs);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	if (ArmSmcArgs.Arg0 != 0)
32*4882a593Smuzhiyun 		return false;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	return true;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun 
optee_vm_destroyed(uint32_t client_id)37*4882a593Smuzhiyun static bool optee_vm_destroyed(uint32_t client_id)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	ARM_SMC_ARGS ArmSmcArgs = {0};
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	ArmSmcArgs.Arg0 = OPTEE_SMC_VM_DESTROYED;
42*4882a593Smuzhiyun 	ArmSmcArgs.Arg1 = client_id;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	tee_smc_call(&ArmSmcArgs);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (ArmSmcArgs.Arg0 != 0)
47*4882a593Smuzhiyun 		return false;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	return true;
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
optee_exchange_capabilities(uint32_t * sec_caps)52*4882a593Smuzhiyun static bool optee_exchange_capabilities(uint32_t *sec_caps)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	ARM_SMC_ARGS ArmSmcArgs = {0};
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	ArmSmcArgs.Arg0 = OPTEE_SMC_EXCHANGE_CAPABILITIES;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	tee_smc_call(&ArmSmcArgs);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	if (ArmSmcArgs.Arg0 != 0)
61*4882a593Smuzhiyun 		return false;
62*4882a593Smuzhiyun 	*sec_caps = ArmSmcArgs.Arg1;
63*4882a593Smuzhiyun 	return true;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
optee_api_revision_is_compatible(void)66*4882a593Smuzhiyun static bool optee_api_revision_is_compatible(void)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	ARM_SMC_ARGS ArmSmcArgs = {0};
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	ArmSmcArgs.Arg0 = OPTEE_SMC_CALLS_REVISION;
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	tee_smc_call(&ArmSmcArgs);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	if (ArmSmcArgs.Arg0 == OPTEE_MSG_REVISION_MAJOR &&
75*4882a593Smuzhiyun 	    ArmSmcArgs.Arg1 >= OPTEE_MSG_REVISION_MINOR) {
76*4882a593Smuzhiyun 		printf("optee api revision: %d.%d\n",
77*4882a593Smuzhiyun 		       ArmSmcArgs.Arg0, ArmSmcArgs.Arg1);
78*4882a593Smuzhiyun 		return true;
79*4882a593Smuzhiyun 	} else {
80*4882a593Smuzhiyun 		printf("optee check api revision fail: %d.%d\n",
81*4882a593Smuzhiyun 		       ArmSmcArgs.Arg0, ArmSmcArgs.Arg1);
82*4882a593Smuzhiyun 		return false;
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
optee_get_shm_config(phys_addr_t * base,phys_size_t * size)86*4882a593Smuzhiyun void optee_get_shm_config(phys_addr_t *base, phys_size_t *size)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	ARM_SMC_ARGS ArmSmcArgs = {0};
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	ArmSmcArgs.Arg0 = OPTEE_SMC_GET_SHM_CONFIG_V2;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	tee_smc_call(&ArmSmcArgs);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	*base = ArmSmcArgs.Arg1;
95*4882a593Smuzhiyun 	*size = ArmSmcArgs.Arg2;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun /*
99*4882a593Smuzhiyun  * Initlialize the library
100*4882a593Smuzhiyun  */
OpteeClientApiLibInitialize(void)101*4882a593Smuzhiyun TEEC_Result OpteeClientApiLibInitialize(void)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	TEEC_Result status = TEEC_SUCCESS;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	if (optee_is_init)
106*4882a593Smuzhiyun 		return TEEC_SUCCESS;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	/* check api revision compatibility */
109*4882a593Smuzhiyun 	if (!optee_api_revision_is_compatible())
110*4882a593Smuzhiyun 		panic("optee api revision is too low");
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	status = OpteeClientMemInit();
113*4882a593Smuzhiyun 	if (status != TEEC_SUCCESS) {
114*4882a593Smuzhiyun 		printf("TEEC: OpteeClientMemInit fail!\n");
115*4882a593Smuzhiyun 		return status;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 	status = OpteeClientRkFsInit();
118*4882a593Smuzhiyun 	if (status != TEEC_SUCCESS) {
119*4882a593Smuzhiyun 		printf("TEEC: OpteeClientRkFsInit fail!\n");
120*4882a593Smuzhiyun 		return status;
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	optee_is_init = true;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	return TEEC_SUCCESS;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun /*
129*4882a593Smuzhiyun  * This function initializes a new TEE Context, connecting this Client
130*4882a593Smuzhiyun  * application to the TEE indentified by the name name.
131*4882a593Smuzhiyun  *
132*4882a593Smuzhiyun  * name == NULL will give the default TEE.
133*4882a593Smuzhiyun  *
134*4882a593Smuzhiyun  * In this implementation only the default name is supported.
135*4882a593Smuzhiyun  * If name != NULL then TEEC_ERROR_ITEM_NOT_FOUND is returned.
136*4882a593Smuzhiyun  */
TEEC_InitializeContext(const char * name,TEEC_Context * context)137*4882a593Smuzhiyun TEEC_Result TEEC_InitializeContext(const char *name,
138*4882a593Smuzhiyun 				TEEC_Context *context)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	TEEC_Result teecresult = TEEC_SUCCESS;
141*4882a593Smuzhiyun 	uint32_t sec_caps = 0;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	debug("TEEC_InitializeContext Enter: name=%s  context=%s  0x%X\n",
144*4882a593Smuzhiyun 			name, context->devname, context->fd);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (context == NULL) {
148*4882a593Smuzhiyun 		teecresult = TEEC_ERROR_BAD_PARAMETERS;
149*4882a593Smuzhiyun 		goto exit;
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (name != NULL) {
153*4882a593Smuzhiyun 		teecresult = TEEC_ERROR_ITEM_NOT_FOUND;
154*4882a593Smuzhiyun 		goto exit;
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	memset(context, 0, sizeof(*context));
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	/* get optee capabilities */
160*4882a593Smuzhiyun 	if (!optee_exchange_capabilities(&sec_caps))
161*4882a593Smuzhiyun 		panic("optee exchange capabilities fail!");
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	/* optee vm create */
164*4882a593Smuzhiyun 	if (sec_caps & OPTEE_SMC_SEC_CAP_VIRTUALIZATION) {
165*4882a593Smuzhiyun 		if (!optee_vm_create(0))
166*4882a593Smuzhiyun 			panic("optee vm create fail!");
167*4882a593Smuzhiyun 	}
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun exit:
170*4882a593Smuzhiyun 	debug("TEEC_InitializeContext Exit : teecresult=0x%X\n", teecresult);
171*4882a593Smuzhiyun 	return teecresult;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun /*
175*4882a593Smuzhiyun  * This function destroys an initialized TEE Context, closing the connection
176*4882a593Smuzhiyun  * between the Client and the TEE.
177*4882a593Smuzhiyun  * The function implementation MUST do nothing if context is NULL
178*4882a593Smuzhiyun  *
179*4882a593Smuzhiyun  * There is nothing to do here since there is no context state.
180*4882a593Smuzhiyun  */
TEEC_FinalizeContext(TEEC_Context * context)181*4882a593Smuzhiyun TEEC_Result TEEC_FinalizeContext(TEEC_Context *context)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	uint32_t sec_caps = 0;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	/* get optee capabilities */
186*4882a593Smuzhiyun 	if (!optee_exchange_capabilities(&sec_caps))
187*4882a593Smuzhiyun 		panic("optee exchange capabilities fail!");
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	/* optee vm destroyed */
190*4882a593Smuzhiyun 	if (sec_caps & OPTEE_SMC_SEC_CAP_VIRTUALIZATION) {
191*4882a593Smuzhiyun 		if (!optee_vm_destroyed(0))
192*4882a593Smuzhiyun 			panic("optee vm destroyed fail!");
193*4882a593Smuzhiyun 	}
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	debug("TEEC_FinalizeContext Enter-Exit: context=0x%zu\n",
196*4882a593Smuzhiyun 		(size_t)context);
197*4882a593Smuzhiyun 	return TEEC_SUCCESS;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /*
201*4882a593Smuzhiyun  * Allocates or registers shared memory.
202*4882a593Smuzhiyun  *
203*4882a593Smuzhiyun  * Since EDK2 is configured flat with virtual memory == physical memory
204*4882a593Smuzhiyun  * then we don't need to perform any special operations to get physical
205*4882a593Smuzhiyun  * contiguous memory.
206*4882a593Smuzhiyun  */
TEEC_AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * shared_memory)207*4882a593Smuzhiyun TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
208*4882a593Smuzhiyun 			TEEC_SharedMemory *shared_memory)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	TEEC_Result TeecResult = TEEC_SUCCESS;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	debug("TEEC_AllocateSharedMemory Enter: context=%s 0x%X, shared_memory=0x%zu\n",
213*4882a593Smuzhiyun 		context->devname, context->fd, shared_memory->size);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	if ((context == NULL) || (shared_memory == NULL)) {
216*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
217*4882a593Smuzhiyun 		goto Exit;
218*4882a593Smuzhiyun 	}
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	if (shared_memory->flags != 0) {
221*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
222*4882a593Smuzhiyun 		goto Exit;
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	shared_memory->buffer = NULL;
226*4882a593Smuzhiyun 	shared_memory->alloc_buffer = 0;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	debug("TEEC_AllocateSharedMemory: size=0x%zu, flags=0x%X\n",
229*4882a593Smuzhiyun 			shared_memory->size, shared_memory->flags);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	shared_memory->buffer = OpteeClientMemAlloc(shared_memory->size);
232*4882a593Smuzhiyun 	if (shared_memory->buffer == NULL) {
233*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
234*4882a593Smuzhiyun 		goto Exit;
235*4882a593Smuzhiyun 	}
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	shared_memory->alloc_buffer = shared_memory->buffer;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun Exit:
240*4882a593Smuzhiyun 	debug("TEEC_AllocateSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
241*4882a593Smuzhiyun 	return TeecResult;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun /*
245*4882a593Smuzhiyun  * Releases shared memory.
246*4882a593Smuzhiyun  *
247*4882a593Smuzhiyun  * The optee_client implementation allows this to be called with a null pointer
248*4882a593Smuzhiyun  * and null buffer but we'll assert this is not the case for better debugging.
249*4882a593Smuzhiyun  */
TEEC_ReleaseSharedMemory(TEEC_SharedMemory * shared_memory)250*4882a593Smuzhiyun void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	debug("TEEC_ReleaseSharedMemory Enter: shared_memory=0x%zu\n",
253*4882a593Smuzhiyun 				shared_memory->size);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	if (shared_memory == NULL)
256*4882a593Smuzhiyun 		goto Exit;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	if (shared_memory->buffer == NULL)
259*4882a593Smuzhiyun 		goto Exit;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	if (shared_memory->alloc_buffer != 0) {
262*4882a593Smuzhiyun 		OpteeClientMemFree(shared_memory->alloc_buffer);
263*4882a593Smuzhiyun 		shared_memory->alloc_buffer = 0;
264*4882a593Smuzhiyun 	}
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	shared_memory->buffer = NULL;
267*4882a593Smuzhiyun 	shared_memory->size = 0;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun Exit:
270*4882a593Smuzhiyun 	return;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun /*
274*4882a593Smuzhiyun  * Register shared memory
275*4882a593Smuzhiyun  *
276*4882a593Smuzhiyun  * If the supplied buffer is compatible we can use it as supplied otherwise
277*4882a593Smuzhiyun  * we'll need to allocate a copy buffer for the transfer instead.
278*4882a593Smuzhiyun  */
TEEC_RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * shared_memory)279*4882a593Smuzhiyun TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
280*4882a593Smuzhiyun 			TEEC_SharedMemory *shared_memory)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	TEEC_Result TeecResult = TEEC_SUCCESS;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	if ((context == NULL) || (shared_memory == NULL)) {
285*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
286*4882a593Smuzhiyun 		goto Exit;
287*4882a593Smuzhiyun 	}
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	if (shared_memory->buffer == NULL) {
290*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
291*4882a593Smuzhiyun 		goto Exit;
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	shared_memory->alloc_buffer = 0;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	phys_addr_t start = (phys_addr_t) shared_memory->buffer;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	if ((start % 4096) != 0) {
299*4882a593Smuzhiyun 		TEEC_SharedMemory TempSharedMemory;
300*4882a593Smuzhiyun 		TempSharedMemory.size  = shared_memory->size;
301*4882a593Smuzhiyun 		TempSharedMemory.flags = shared_memory->flags;
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 		TeecResult = TEEC_AllocateSharedMemory
304*4882a593Smuzhiyun 			(context, &TempSharedMemory);
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 		if (TeecResult != TEEC_SUCCESS)
307*4882a593Smuzhiyun 			goto Exit;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 		shared_memory->alloc_buffer = TempSharedMemory.alloc_buffer;
310*4882a593Smuzhiyun 	}
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun Exit:
313*4882a593Smuzhiyun 	debug("TEEC_RegisterSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
314*4882a593Smuzhiyun 	return TeecResult;
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun /*
318*4882a593Smuzhiyun  * This function opens a new Session between the Client application and the
319*4882a593Smuzhiyun  * specified TEE application.
320*4882a593Smuzhiyun  *
321*4882a593Smuzhiyun  * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and
322*4882a593Smuzhiyun  * operation shall be set to NULL.
323*4882a593Smuzhiyun  */
TEEC_OpenSession(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connection_method,const void * connection_data,TEEC_Operation * operation,uint32_t * error_origin)324*4882a593Smuzhiyun TEEC_Result TEEC_OpenSession(TEEC_Context *context,
325*4882a593Smuzhiyun 			TEEC_Session *session,
326*4882a593Smuzhiyun 			const TEEC_UUID *destination,
327*4882a593Smuzhiyun 			uint32_t connection_method,
328*4882a593Smuzhiyun 			const void *connection_data,
329*4882a593Smuzhiyun 			TEEC_Operation *operation,
330*4882a593Smuzhiyun 			uint32_t *error_origin)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun 	TEEC_Result TeecResult = TEEC_SUCCESS;
333*4882a593Smuzhiyun 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	debug("TEEC_OpenSession: session=0x%X, ...\n", session->id);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if ((context == NULL) || (session == NULL) || (destination == NULL)) {
338*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
339*4882a593Smuzhiyun 		goto Exit;
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	if (connection_method != TEEC_LOGIN_PUBLIC) {
343*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_NOT_SUPPORTED;
344*4882a593Smuzhiyun 		goto Exit;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	TEEC_Operation TeecNullOperation = {0};
348*4882a593Smuzhiyun 	TEEC_Operation *TeecOperation;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	if (operation == NULL) {
351*4882a593Smuzhiyun 		memset(&TeecNullOperation, 0, sizeof(TEEC_Operation));
352*4882a593Smuzhiyun 		TeecOperation = &TeecNullOperation;
353*4882a593Smuzhiyun 	} else {
354*4882a593Smuzhiyun 		TeecOperation = operation;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	TeecResult = TEEC_SMC_OpenSession(context, session, destination,
358*4882a593Smuzhiyun 				TeecOperation, &TeecErrorOrigin);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun Exit:
361*4882a593Smuzhiyun 	if (error_origin != NULL)
362*4882a593Smuzhiyun 		*error_origin = TeecErrorOrigin;
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	debug("TEEC_OpenSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
365*4882a593Smuzhiyun 				TeecResult, TeecErrorOrigin);
366*4882a593Smuzhiyun 	return TeecResult;
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun /*
370*4882a593Smuzhiyun  * This function closes a session which has been opened with a TEE
371*4882a593Smuzhiyun  * application.
372*4882a593Smuzhiyun  */
TEEC_CloseSession(TEEC_Session * session)373*4882a593Smuzhiyun void TEEC_CloseSession(TEEC_Session *session)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	TEEC_Result TeecResult = TEEC_SUCCESS;
376*4882a593Smuzhiyun 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 	debug("TEEC_CloseSession Enter: session=0x%X\n", session->id);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	if (session == NULL)
381*4882a593Smuzhiyun 		goto Exit;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	TeecResult = TEEC_SMC_CloseSession(session, &TeecErrorOrigin);
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun Exit:
386*4882a593Smuzhiyun 	debug("TEEC_CloseSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
387*4882a593Smuzhiyun 			TeecResult, TeecErrorOrigin);
388*4882a593Smuzhiyun 	return;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun /*
392*4882a593Smuzhiyun  * Invokes a TEE command (secure service, sub-PA or whatever).
393*4882a593Smuzhiyun  */
TEEC_InvokeCommand(TEEC_Session * session,uint32_t cmd_id,TEEC_Operation * operation,uint32_t * error_origin)394*4882a593Smuzhiyun TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
395*4882a593Smuzhiyun 				uint32_t cmd_id,
396*4882a593Smuzhiyun 				TEEC_Operation *operation,
397*4882a593Smuzhiyun 				uint32_t *error_origin)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	TEEC_Result TeecResult = TEEC_SUCCESS;
400*4882a593Smuzhiyun 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	debug("TEEC_InvokeCommand Enter: session=0x%X, cmd_id=0x%X\n",
403*4882a593Smuzhiyun 			session->id, cmd_id);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	if (session == NULL) {
406*4882a593Smuzhiyun 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
407*4882a593Smuzhiyun 		goto Exit;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	TEEC_Operation TeecNullOperation = {0};
411*4882a593Smuzhiyun 	TEEC_Operation *TeecOperation;
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun 	if (operation == NULL)
414*4882a593Smuzhiyun 		TeecOperation = &TeecNullOperation;
415*4882a593Smuzhiyun 	else
416*4882a593Smuzhiyun 		TeecOperation = operation;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 	TeecResult = TEEC_SMC_InvokeCommand(session, cmd_id,
419*4882a593Smuzhiyun 			TeecOperation, &TeecErrorOrigin);
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun Exit:
422*4882a593Smuzhiyun 	if (error_origin != NULL)
423*4882a593Smuzhiyun 		*error_origin = TeecErrorOrigin;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	debug("TEEC_InvokeCommand Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
426*4882a593Smuzhiyun 				TeecResult, TeecErrorOrigin);
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	return TeecResult;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun /*
432*4882a593Smuzhiyun  * Request a cancellation of a in-progress operation (best effort)
433*4882a593Smuzhiyun  */
TEEC_RequestCancellation(TEEC_Operation * operation)434*4882a593Smuzhiyun void TEEC_RequestCancellation(TEEC_Operation *operation)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun 	TEEC_Result TeecResult = TEEC_SUCCESS;
437*4882a593Smuzhiyun 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	if (operation == NULL)
440*4882a593Smuzhiyun 		goto Exit;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun 	TeecResult = TEEC_SMC_RequestCancellation(operation, &TeecErrorOrigin);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun Exit:
445*4882a593Smuzhiyun 	debug("TEEC_RequestCancellation Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
446*4882a593Smuzhiyun 			TeecResult, TeecErrorOrigin);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	return;
449*4882a593Smuzhiyun }
450