xref: /rk3399_rockchip-uboot/lib/optee_clientApi/OpteeClientApiLib.c (revision abdd24375050db7ce121b48477cc332d6c8c40f6)
1*abdd2437Shisping /*
2*abdd2437Shisping  * Copyright 2017, Rockchip Electronics Co., Ltd
3*abdd2437Shisping  * hisping lin, <hisping.lin@rock-chips.com>
4*abdd2437Shisping  *
5*abdd2437Shisping  * SPDX-License-Identifier:	GPL-2.0+
6*abdd2437Shisping  */
7*abdd2437Shisping #include <common.h>
8*abdd2437Shisping #include <optee_include/OpteeClientApiLib.h>
9*abdd2437Shisping #include <optee_include/OpteeClientMem.h>
10*abdd2437Shisping #include <optee_include/OpteeClientSMC.h>
11*abdd2437Shisping 
12*abdd2437Shisping /*
13*abdd2437Shisping  * Initlialize the library
14*abdd2437Shisping  */
15*abdd2437Shisping TEEC_Result OpteeClientApiLibInitialize(void)
16*abdd2437Shisping {
17*abdd2437Shisping 	TEEC_Result status = TEEC_SUCCESS;
18*abdd2437Shisping 
19*abdd2437Shisping 	OpteeClientMemInit();
20*abdd2437Shisping 
21*abdd2437Shisping 	return status;
22*abdd2437Shisping }
23*abdd2437Shisping 
24*abdd2437Shisping /*
25*abdd2437Shisping  * This function initializes a new TEE Context, connecting this Client
26*abdd2437Shisping  * application to the TEE indentified by the name name.
27*abdd2437Shisping  *
28*abdd2437Shisping  * name == NULL will give the default TEE.
29*abdd2437Shisping  *
30*abdd2437Shisping  * In this implementation only the default name is supported.
31*abdd2437Shisping  * If name != NULL then TEEC_ERROR_ITEM_NOT_FOUND is returned.
32*abdd2437Shisping  */
33*abdd2437Shisping TEEC_Result TEEC_InitializeContext(const char *name,
34*abdd2437Shisping 				TEEC_Context *context)
35*abdd2437Shisping {
36*abdd2437Shisping 	TEEC_Result teecresult = TEEC_SUCCESS;
37*abdd2437Shisping 
38*abdd2437Shisping 	debug("TEEC_InitializeContext Enter: name=%s  context=%s  0x%X\n",
39*abdd2437Shisping 			name, context->devname, context->fd);
40*abdd2437Shisping 
41*abdd2437Shisping 	if (context == NULL) {
42*abdd2437Shisping 		teecresult = TEEC_ERROR_BAD_PARAMETERS;
43*abdd2437Shisping 		goto exit;
44*abdd2437Shisping 	}
45*abdd2437Shisping 
46*abdd2437Shisping 	if (name != NULL) {
47*abdd2437Shisping 		teecresult = TEEC_ERROR_ITEM_NOT_FOUND;
48*abdd2437Shisping 		goto exit;
49*abdd2437Shisping 	}
50*abdd2437Shisping 
51*abdd2437Shisping 	memset(context, 0, sizeof(*context));
52*abdd2437Shisping 
53*abdd2437Shisping exit:
54*abdd2437Shisping 	debug("TEEC_InitializeContext Exit : teecresult=0x%X\n\n", teecresult);
55*abdd2437Shisping 	return teecresult;
56*abdd2437Shisping }
57*abdd2437Shisping 
58*abdd2437Shisping /*
59*abdd2437Shisping  * This function destroys an initialized TEE Context, closing the connection
60*abdd2437Shisping  * between the Client and the TEE.
61*abdd2437Shisping  * The function implementation MUST do nothing if context is NULL
62*abdd2437Shisping  *
63*abdd2437Shisping  * There is nothing to do here since there is no context state.
64*abdd2437Shisping  */
65*abdd2437Shisping TEEC_Result TEEC_FinalizeContext(TEEC_Context *context)
66*abdd2437Shisping {
67*abdd2437Shisping 	debug("TEEC_FinalizeContext Enter-Exit: context=0x%X\n",
68*abdd2437Shisping 		(unsigned int)context);
69*abdd2437Shisping 	return TEEC_SUCCESS;
70*abdd2437Shisping }
71*abdd2437Shisping 
72*abdd2437Shisping /*
73*abdd2437Shisping  * Allocates or registers shared memory.
74*abdd2437Shisping  *
75*abdd2437Shisping  * Since EDK2 is configured flat with virtual memory == physical memory
76*abdd2437Shisping  * then we don't need to perform any special operations to get physical
77*abdd2437Shisping  * contiguous memory.
78*abdd2437Shisping  */
79*abdd2437Shisping TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
80*abdd2437Shisping 			TEEC_SharedMemory *shared_memory)
81*abdd2437Shisping {
82*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
83*abdd2437Shisping 
84*abdd2437Shisping 	debug("TEEC_AllocateSharedMemory Enter: context=%s 0x%X, shared_memory=0x%X\n",
85*abdd2437Shisping 		context->devname, context->fd, shared_memory->size);
86*abdd2437Shisping 
87*abdd2437Shisping 	if ((context == NULL) || (shared_memory == NULL)) {
88*abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
89*abdd2437Shisping 		goto Exit;
90*abdd2437Shisping 	}
91*abdd2437Shisping 
92*abdd2437Shisping 	if (shared_memory->flags != 0) {
93*abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
94*abdd2437Shisping 		goto Exit;
95*abdd2437Shisping 	}
96*abdd2437Shisping 
97*abdd2437Shisping 	shared_memory->buffer = NULL;
98*abdd2437Shisping 	shared_memory->alloc_buffer = 0;
99*abdd2437Shisping 
100*abdd2437Shisping 	debug("TEEC_AllocateSharedMemory: size=0x%X, flags=0x%X\n",
101*abdd2437Shisping 			shared_memory->size, shared_memory->flags);
102*abdd2437Shisping 
103*abdd2437Shisping 	shared_memory->buffer = OpteeClientMemAlloc(shared_memory->size);
104*abdd2437Shisping 	if (shared_memory->buffer == NULL) {
105*abdd2437Shisping 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
106*abdd2437Shisping 		goto Exit;
107*abdd2437Shisping 	}
108*abdd2437Shisping 
109*abdd2437Shisping 	shared_memory->alloc_buffer = shared_memory->buffer;
110*abdd2437Shisping 
111*abdd2437Shisping Exit:
112*abdd2437Shisping 	debug("TEEC_AllocateSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
113*abdd2437Shisping 	return TeecResult;
114*abdd2437Shisping }
115*abdd2437Shisping 
116*abdd2437Shisping /*
117*abdd2437Shisping  * Releases shared memory.
118*abdd2437Shisping  *
119*abdd2437Shisping  * The optee_client implementation allows this to be called with a null pointer
120*abdd2437Shisping  * and null buffer but we'll assert this is not the case for better debugging.
121*abdd2437Shisping  */
122*abdd2437Shisping void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory)
123*abdd2437Shisping {
124*abdd2437Shisping 	debug("TEEC_ReleaseSharedMemory Enter: shared_memory=0x%X\n",
125*abdd2437Shisping 				shared_memory->size);
126*abdd2437Shisping 
127*abdd2437Shisping 	if (shared_memory == NULL)
128*abdd2437Shisping 		goto Exit;
129*abdd2437Shisping 
130*abdd2437Shisping 	if (shared_memory->buffer == NULL)
131*abdd2437Shisping 		goto Exit;
132*abdd2437Shisping 
133*abdd2437Shisping 	if (shared_memory->alloc_buffer != 0) {
134*abdd2437Shisping 		OpteeClientMemFree(shared_memory->alloc_buffer);
135*abdd2437Shisping 		shared_memory->alloc_buffer = 0;
136*abdd2437Shisping 	}
137*abdd2437Shisping 
138*abdd2437Shisping 	shared_memory->buffer = NULL;
139*abdd2437Shisping 	shared_memory->size = 0;
140*abdd2437Shisping 
141*abdd2437Shisping Exit:
142*abdd2437Shisping 	return;
143*abdd2437Shisping }
144*abdd2437Shisping 
145*abdd2437Shisping /*
146*abdd2437Shisping  * Register shared memory
147*abdd2437Shisping  *
148*abdd2437Shisping  * If the supplied buffer is compatible we can use it as supplied otherwise
149*abdd2437Shisping  * we'll need to allocate a copy buffer for the transfer instead.
150*abdd2437Shisping  */
151*abdd2437Shisping TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
152*abdd2437Shisping 			TEEC_SharedMemory *shared_memory)
153*abdd2437Shisping {
154*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
155*abdd2437Shisping 
156*abdd2437Shisping 	if ((context == NULL) || (shared_memory == NULL)) {
157*abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
158*abdd2437Shisping 		goto Exit;
159*abdd2437Shisping 	}
160*abdd2437Shisping 
161*abdd2437Shisping 	if (shared_memory->buffer == NULL) {
162*abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
163*abdd2437Shisping 		goto Exit;
164*abdd2437Shisping 	}
165*abdd2437Shisping 
166*abdd2437Shisping 	shared_memory->alloc_buffer = 0;
167*abdd2437Shisping 
168*abdd2437Shisping 	phys_addr_t start = (phys_addr_t) shared_memory->buffer;
169*abdd2437Shisping 
170*abdd2437Shisping 	if ((start % 4096) != 0) {
171*abdd2437Shisping 		TEEC_SharedMemory TempSharedMemory;
172*abdd2437Shisping 		TempSharedMemory.size  = shared_memory->size;
173*abdd2437Shisping 		TempSharedMemory.flags = shared_memory->flags;
174*abdd2437Shisping 
175*abdd2437Shisping 		TeecResult = TEEC_AllocateSharedMemory
176*abdd2437Shisping 			(context, &TempSharedMemory);
177*abdd2437Shisping 
178*abdd2437Shisping 		if (TeecResult != TEEC_SUCCESS)
179*abdd2437Shisping 			goto Exit;
180*abdd2437Shisping 
181*abdd2437Shisping 		shared_memory->alloc_buffer = TempSharedMemory.alloc_buffer;
182*abdd2437Shisping 	}
183*abdd2437Shisping 
184*abdd2437Shisping Exit:
185*abdd2437Shisping 	debug("TEEC_RegisterSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
186*abdd2437Shisping 	return TeecResult;
187*abdd2437Shisping }
188*abdd2437Shisping 
189*abdd2437Shisping /*
190*abdd2437Shisping  * This function opens a new Session between the Client application and the
191*abdd2437Shisping  * specified TEE application.
192*abdd2437Shisping  *
193*abdd2437Shisping  * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and
194*abdd2437Shisping  * operation shall be set to NULL.
195*abdd2437Shisping  */
196*abdd2437Shisping TEEC_Result TEEC_OpenSession(TEEC_Context *context,
197*abdd2437Shisping 			TEEC_Session *session,
198*abdd2437Shisping 			const TEEC_UUID *destination,
199*abdd2437Shisping 			uint32_t connection_method,
200*abdd2437Shisping 			const void *connection_data,
201*abdd2437Shisping 			TEEC_Operation *operation,
202*abdd2437Shisping 			uint32_t *error_origin)
203*abdd2437Shisping {
204*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
205*abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
206*abdd2437Shisping 
207*abdd2437Shisping 	debug("TEEC_OpenSession: session=0x%X, ...\n", session->id);
208*abdd2437Shisping 
209*abdd2437Shisping 	if ((context == NULL) || (session == NULL) || (destination == NULL)) {
210*abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
211*abdd2437Shisping 		goto Exit;
212*abdd2437Shisping 	}
213*abdd2437Shisping 
214*abdd2437Shisping 	if (connection_method != TEEC_LOGIN_PUBLIC) {
215*abdd2437Shisping 		TeecResult = TEEC_ERROR_NOT_SUPPORTED;
216*abdd2437Shisping 		goto Exit;
217*abdd2437Shisping 	}
218*abdd2437Shisping 
219*abdd2437Shisping 	TEEC_Operation TeecNullOperation = {0};
220*abdd2437Shisping 	TEEC_Operation *TeecOperation;
221*abdd2437Shisping 
222*abdd2437Shisping 	if (operation == NULL) {
223*abdd2437Shisping 		memset(&TeecNullOperation, 0, sizeof(TEEC_Operation));
224*abdd2437Shisping 		TeecOperation = &TeecNullOperation;
225*abdd2437Shisping 	} else {
226*abdd2437Shisping 		TeecOperation = operation;
227*abdd2437Shisping 	}
228*abdd2437Shisping 
229*abdd2437Shisping 	TeecResult = TEEC_SMC_OpenSession(context, session, destination,
230*abdd2437Shisping 				TeecOperation, &TeecErrorOrigin);
231*abdd2437Shisping 
232*abdd2437Shisping Exit:
233*abdd2437Shisping 	if (error_origin != NULL)
234*abdd2437Shisping 		*error_origin = TeecErrorOrigin;
235*abdd2437Shisping 
236*abdd2437Shisping 	debug("TEEC_OpenSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n\n",
237*abdd2437Shisping 				TeecResult, TeecErrorOrigin);
238*abdd2437Shisping 	return TeecResult;
239*abdd2437Shisping }
240*abdd2437Shisping 
241*abdd2437Shisping /*
242*abdd2437Shisping  * This function closes a session which has been opened with a TEE
243*abdd2437Shisping  * application.
244*abdd2437Shisping  */
245*abdd2437Shisping void TEEC_CloseSession(TEEC_Session *session)
246*abdd2437Shisping {
247*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
248*abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
249*abdd2437Shisping 
250*abdd2437Shisping 	debug("TEEC_CloseSession Enter: session=0x%X\n", session->id);
251*abdd2437Shisping 
252*abdd2437Shisping 	if (session == NULL)
253*abdd2437Shisping 		goto Exit;
254*abdd2437Shisping 
255*abdd2437Shisping 	TeecResult = TEEC_SMC_CloseSession(session, &TeecErrorOrigin);
256*abdd2437Shisping 
257*abdd2437Shisping Exit:
258*abdd2437Shisping 	debug("TEEC_CloseSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n\n",
259*abdd2437Shisping 			TeecResult, TeecErrorOrigin);
260*abdd2437Shisping 	return;
261*abdd2437Shisping }
262*abdd2437Shisping 
263*abdd2437Shisping /*
264*abdd2437Shisping  * Invokes a TEE command (secure service, sub-PA or whatever).
265*abdd2437Shisping  */
266*abdd2437Shisping TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
267*abdd2437Shisping 				uint32_t cmd_id,
268*abdd2437Shisping 				TEEC_Operation *operation,
269*abdd2437Shisping 				uint32_t *error_origin)
270*abdd2437Shisping {
271*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
272*abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
273*abdd2437Shisping 
274*abdd2437Shisping 	debug("TEEC_InvokeCommand Enter: session=0x%X, cmd_id=0x%X\n",
275*abdd2437Shisping 			session->id, cmd_id);
276*abdd2437Shisping 
277*abdd2437Shisping 	if (session == NULL) {
278*abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
279*abdd2437Shisping 		goto Exit;
280*abdd2437Shisping 	}
281*abdd2437Shisping 
282*abdd2437Shisping 	TEEC_Operation TeecNullOperation = {0};
283*abdd2437Shisping 	TEEC_Operation *TeecOperation;
284*abdd2437Shisping 
285*abdd2437Shisping 	if (operation == NULL)
286*abdd2437Shisping 		TeecOperation = &TeecNullOperation;
287*abdd2437Shisping 	else
288*abdd2437Shisping 		TeecOperation = operation;
289*abdd2437Shisping 
290*abdd2437Shisping 	TeecResult = TEEC_SMC_InvokeCommand(session, cmd_id,
291*abdd2437Shisping 			TeecOperation, &TeecErrorOrigin);
292*abdd2437Shisping 
293*abdd2437Shisping Exit:
294*abdd2437Shisping 	if (error_origin != NULL)
295*abdd2437Shisping 		*error_origin = TeecErrorOrigin;
296*abdd2437Shisping 
297*abdd2437Shisping 	debug("TEEC_InvokeCommand Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n\n",
298*abdd2437Shisping 				TeecResult, TeecErrorOrigin);
299*abdd2437Shisping 
300*abdd2437Shisping 	return TeecResult;
301*abdd2437Shisping }
302*abdd2437Shisping 
303*abdd2437Shisping /*
304*abdd2437Shisping  * Request a cancellation of a in-progress operation (best effort)
305*abdd2437Shisping  */
306*abdd2437Shisping void TEEC_RequestCancellation(TEEC_Operation *operation)
307*abdd2437Shisping {
308*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
309*abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
310*abdd2437Shisping 
311*abdd2437Shisping 	if (operation == NULL)
312*abdd2437Shisping 		goto Exit;
313*abdd2437Shisping 
314*abdd2437Shisping 	TeecResult = TEEC_SMC_RequestCancellation(operation, &TeecErrorOrigin);
315*abdd2437Shisping 
316*abdd2437Shisping Exit:
317*abdd2437Shisping 	debug("TEEC_RequestCancellation Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
318*abdd2437Shisping 			TeecResult, TeecErrorOrigin);
319*abdd2437Shisping 
320*abdd2437Shisping 	return;
321*abdd2437Shisping }
322