xref: /rk3399_rockchip-uboot/lib/optee_clientApi/OpteeClientApiLib.c (revision 396e3049bd88ad9273f7077b1396f0bc5703401a)
1abdd2437Shisping /*
2abdd2437Shisping  * Copyright 2017, Rockchip Electronics Co., Ltd
3abdd2437Shisping  * hisping lin, <hisping.lin@rock-chips.com>
4abdd2437Shisping  *
5abdd2437Shisping  * SPDX-License-Identifier:	GPL-2.0+
6abdd2437Shisping  */
7abdd2437Shisping #include <common.h>
8abdd2437Shisping #include <optee_include/OpteeClientApiLib.h>
9abdd2437Shisping #include <optee_include/OpteeClientMem.h>
1074eb6027SHisping Lin #include <optee_include/OpteeClientRPC.h>
11abdd2437Shisping #include <optee_include/OpteeClientSMC.h>
121f25ada2SHisping Lin #include <optee_include/OpteeClientRkFs.h>
1374eb6027SHisping Lin #include <optee_include/teesmc.h>
1474eb6027SHisping Lin #include <optee_include/teesmc_optee.h>
1574eb6027SHisping Lin #include <optee_include/teesmc_v2.h>
1674eb6027SHisping Lin 
1774eb6027SHisping Lin #define OPTEE_MSG_REVISION_MAJOR        2
1874eb6027SHisping Lin #define OPTEE_MSG_REVISION_MINOR        0
1974eb6027SHisping Lin 
207a349fdcSElon Zhang static bool optee_is_init;
217a349fdcSElon Zhang 
2274eb6027SHisping Lin static bool optee_api_revision_is_compatible(void)
2374eb6027SHisping Lin {
2474eb6027SHisping Lin 	ARM_SMC_ARGS ArmSmcArgs = {0};
2574eb6027SHisping Lin 
2674eb6027SHisping Lin 	ArmSmcArgs.Arg0 = OPTEE_SMC_CALLS_REVISION;
2774eb6027SHisping Lin 
2874eb6027SHisping Lin 	tee_smc_call(&ArmSmcArgs);
2974eb6027SHisping Lin 
3074eb6027SHisping Lin 	if (ArmSmcArgs.Arg0 == OPTEE_MSG_REVISION_MAJOR &&
3174eb6027SHisping Lin 	    ArmSmcArgs.Arg1 >= OPTEE_MSG_REVISION_MINOR) {
3274eb6027SHisping Lin 		printf("optee api revision: %d.%d\n",
3374eb6027SHisping Lin 		       ArmSmcArgs.Arg0, ArmSmcArgs.Arg1);
3474eb6027SHisping Lin 		return true;
3574eb6027SHisping Lin 	} else {
3674eb6027SHisping Lin 		printf("optee check api revision fail: %d.%d\n",
3774eb6027SHisping Lin 		       ArmSmcArgs.Arg0, ArmSmcArgs.Arg1);
3874eb6027SHisping Lin 		return false;
3974eb6027SHisping Lin 	}
4074eb6027SHisping Lin }
41abdd2437Shisping 
42*396e3049SElon Zhang void optee_get_shm_config(phys_addr_t *base, phys_size_t *size)
43*396e3049SElon Zhang {
44*396e3049SElon Zhang 	ARM_SMC_ARGS ArmSmcArgs = {0};
45*396e3049SElon Zhang 
46*396e3049SElon Zhang 	ArmSmcArgs.Arg0 = OPTEE_SMC_GET_SHM_CONFIG_V2;
47*396e3049SElon Zhang 
48*396e3049SElon Zhang 	tee_smc_call(&ArmSmcArgs);
49*396e3049SElon Zhang 
50*396e3049SElon Zhang 	*base = ArmSmcArgs.Arg1;
51*396e3049SElon Zhang 	*size = ArmSmcArgs.Arg2;
52*396e3049SElon Zhang }
53*396e3049SElon Zhang 
54abdd2437Shisping /*
55abdd2437Shisping  * Initlialize the library
56abdd2437Shisping  */
57abdd2437Shisping TEEC_Result OpteeClientApiLibInitialize(void)
58abdd2437Shisping {
59abdd2437Shisping 	TEEC_Result status = TEEC_SUCCESS;
60abdd2437Shisping 
617a349fdcSElon Zhang 	if (optee_is_init)
627a349fdcSElon Zhang 		return TEEC_SUCCESS;
637a349fdcSElon Zhang 
6474eb6027SHisping Lin 	/* check api revision compatibility */
6574eb6027SHisping Lin 	if (!optee_api_revision_is_compatible())
6674eb6027SHisping Lin 		panic("optee api revision is too low");
6774eb6027SHisping Lin 
68f4e1db95SHisping Lin 	status = OpteeClientMemInit();
69f4e1db95SHisping Lin 	if (status != TEEC_SUCCESS) {
70efb93541SHisping Lin 		printf("TEEC: OpteeClientMemInit fail!\n");
71abdd2437Shisping 		return status;
72abdd2437Shisping 	}
73f4e1db95SHisping Lin 	status = OpteeClientRkFsInit();
74f4e1db95SHisping Lin 	if (status != TEEC_SUCCESS) {
75efb93541SHisping Lin 		printf("TEEC: OpteeClientRkFsInit fail!\n");
76f4e1db95SHisping Lin 		return status;
77f4e1db95SHisping Lin 	}
78f4e1db95SHisping Lin 
797a349fdcSElon Zhang 	optee_is_init = true;
807a349fdcSElon Zhang 
81f4e1db95SHisping Lin 	return TEEC_SUCCESS;
82f4e1db95SHisping Lin }
83abdd2437Shisping 
84abdd2437Shisping /*
85abdd2437Shisping  * This function initializes a new TEE Context, connecting this Client
86abdd2437Shisping  * application to the TEE indentified by the name name.
87abdd2437Shisping  *
88abdd2437Shisping  * name == NULL will give the default TEE.
89abdd2437Shisping  *
90abdd2437Shisping  * In this implementation only the default name is supported.
91abdd2437Shisping  * If name != NULL then TEEC_ERROR_ITEM_NOT_FOUND is returned.
92abdd2437Shisping  */
93abdd2437Shisping TEEC_Result TEEC_InitializeContext(const char *name,
94abdd2437Shisping 				TEEC_Context *context)
95abdd2437Shisping {
96abdd2437Shisping 	TEEC_Result teecresult = TEEC_SUCCESS;
97abdd2437Shisping 
98abdd2437Shisping 	debug("TEEC_InitializeContext Enter: name=%s  context=%s  0x%X\n",
99abdd2437Shisping 			name, context->devname, context->fd);
100abdd2437Shisping 
101abdd2437Shisping 	if (context == NULL) {
102abdd2437Shisping 		teecresult = TEEC_ERROR_BAD_PARAMETERS;
103abdd2437Shisping 		goto exit;
104abdd2437Shisping 	}
105abdd2437Shisping 
106abdd2437Shisping 	if (name != NULL) {
107abdd2437Shisping 		teecresult = TEEC_ERROR_ITEM_NOT_FOUND;
108abdd2437Shisping 		goto exit;
109abdd2437Shisping 	}
110abdd2437Shisping 
111abdd2437Shisping 	memset(context, 0, sizeof(*context));
112abdd2437Shisping 
113abdd2437Shisping exit:
114efb93541SHisping Lin 	debug("TEEC_InitializeContext Exit : teecresult=0x%X\n", teecresult);
115abdd2437Shisping 	return teecresult;
116abdd2437Shisping }
117abdd2437Shisping 
118abdd2437Shisping /*
119abdd2437Shisping  * This function destroys an initialized TEE Context, closing the connection
120abdd2437Shisping  * between the Client and the TEE.
121abdd2437Shisping  * The function implementation MUST do nothing if context is NULL
122abdd2437Shisping  *
123abdd2437Shisping  * There is nothing to do here since there is no context state.
124abdd2437Shisping  */
125abdd2437Shisping TEEC_Result TEEC_FinalizeContext(TEEC_Context *context)
126abdd2437Shisping {
1271f25ada2SHisping Lin 	debug("TEEC_FinalizeContext Enter-Exit: context=0x%zu\n",
1281f25ada2SHisping Lin 		(size_t)context);
129abdd2437Shisping 	return TEEC_SUCCESS;
130abdd2437Shisping }
131abdd2437Shisping 
132abdd2437Shisping /*
133abdd2437Shisping  * Allocates or registers shared memory.
134abdd2437Shisping  *
135abdd2437Shisping  * Since EDK2 is configured flat with virtual memory == physical memory
136abdd2437Shisping  * then we don't need to perform any special operations to get physical
137abdd2437Shisping  * contiguous memory.
138abdd2437Shisping  */
139abdd2437Shisping TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
140abdd2437Shisping 			TEEC_SharedMemory *shared_memory)
141abdd2437Shisping {
142abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
143abdd2437Shisping 
1441f25ada2SHisping Lin 	debug("TEEC_AllocateSharedMemory Enter: context=%s 0x%X, shared_memory=0x%zu\n",
145abdd2437Shisping 		context->devname, context->fd, shared_memory->size);
146abdd2437Shisping 
147abdd2437Shisping 	if ((context == NULL) || (shared_memory == NULL)) {
148abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
149abdd2437Shisping 		goto Exit;
150abdd2437Shisping 	}
151abdd2437Shisping 
152abdd2437Shisping 	if (shared_memory->flags != 0) {
153abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
154abdd2437Shisping 		goto Exit;
155abdd2437Shisping 	}
156abdd2437Shisping 
157abdd2437Shisping 	shared_memory->buffer = NULL;
158abdd2437Shisping 	shared_memory->alloc_buffer = 0;
159abdd2437Shisping 
1601f25ada2SHisping Lin 	debug("TEEC_AllocateSharedMemory: size=0x%zu, flags=0x%X\n",
161abdd2437Shisping 			shared_memory->size, shared_memory->flags);
162abdd2437Shisping 
163abdd2437Shisping 	shared_memory->buffer = OpteeClientMemAlloc(shared_memory->size);
164abdd2437Shisping 	if (shared_memory->buffer == NULL) {
165abdd2437Shisping 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
166abdd2437Shisping 		goto Exit;
167abdd2437Shisping 	}
168abdd2437Shisping 
169abdd2437Shisping 	shared_memory->alloc_buffer = shared_memory->buffer;
170abdd2437Shisping 
171abdd2437Shisping Exit:
172abdd2437Shisping 	debug("TEEC_AllocateSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
173abdd2437Shisping 	return TeecResult;
174abdd2437Shisping }
175abdd2437Shisping 
176abdd2437Shisping /*
177abdd2437Shisping  * Releases shared memory.
178abdd2437Shisping  *
179abdd2437Shisping  * The optee_client implementation allows this to be called with a null pointer
180abdd2437Shisping  * and null buffer but we'll assert this is not the case for better debugging.
181abdd2437Shisping  */
182abdd2437Shisping void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory)
183abdd2437Shisping {
1841f25ada2SHisping Lin 	debug("TEEC_ReleaseSharedMemory Enter: shared_memory=0x%zu\n",
185abdd2437Shisping 				shared_memory->size);
186abdd2437Shisping 
187abdd2437Shisping 	if (shared_memory == NULL)
188abdd2437Shisping 		goto Exit;
189abdd2437Shisping 
190abdd2437Shisping 	if (shared_memory->buffer == NULL)
191abdd2437Shisping 		goto Exit;
192abdd2437Shisping 
193abdd2437Shisping 	if (shared_memory->alloc_buffer != 0) {
194abdd2437Shisping 		OpteeClientMemFree(shared_memory->alloc_buffer);
195abdd2437Shisping 		shared_memory->alloc_buffer = 0;
196abdd2437Shisping 	}
197abdd2437Shisping 
198abdd2437Shisping 	shared_memory->buffer = NULL;
199abdd2437Shisping 	shared_memory->size = 0;
200abdd2437Shisping 
201abdd2437Shisping Exit:
202abdd2437Shisping 	return;
203abdd2437Shisping }
204abdd2437Shisping 
205abdd2437Shisping /*
206abdd2437Shisping  * Register shared memory
207abdd2437Shisping  *
208abdd2437Shisping  * If the supplied buffer is compatible we can use it as supplied otherwise
209abdd2437Shisping  * we'll need to allocate a copy buffer for the transfer instead.
210abdd2437Shisping  */
211abdd2437Shisping TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
212abdd2437Shisping 			TEEC_SharedMemory *shared_memory)
213abdd2437Shisping {
214abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
215abdd2437Shisping 
216abdd2437Shisping 	if ((context == NULL) || (shared_memory == NULL)) {
217abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
218abdd2437Shisping 		goto Exit;
219abdd2437Shisping 	}
220abdd2437Shisping 
221abdd2437Shisping 	if (shared_memory->buffer == NULL) {
222abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
223abdd2437Shisping 		goto Exit;
224abdd2437Shisping 	}
225abdd2437Shisping 
226abdd2437Shisping 	shared_memory->alloc_buffer = 0;
227abdd2437Shisping 
228abdd2437Shisping 	phys_addr_t start = (phys_addr_t) shared_memory->buffer;
229abdd2437Shisping 
230abdd2437Shisping 	if ((start % 4096) != 0) {
231abdd2437Shisping 		TEEC_SharedMemory TempSharedMemory;
232abdd2437Shisping 		TempSharedMemory.size  = shared_memory->size;
233abdd2437Shisping 		TempSharedMemory.flags = shared_memory->flags;
234abdd2437Shisping 
235abdd2437Shisping 		TeecResult = TEEC_AllocateSharedMemory
236abdd2437Shisping 			(context, &TempSharedMemory);
237abdd2437Shisping 
238abdd2437Shisping 		if (TeecResult != TEEC_SUCCESS)
239abdd2437Shisping 			goto Exit;
240abdd2437Shisping 
241abdd2437Shisping 		shared_memory->alloc_buffer = TempSharedMemory.alloc_buffer;
242abdd2437Shisping 	}
243abdd2437Shisping 
244abdd2437Shisping Exit:
245abdd2437Shisping 	debug("TEEC_RegisterSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
246abdd2437Shisping 	return TeecResult;
247abdd2437Shisping }
248abdd2437Shisping 
249abdd2437Shisping /*
250abdd2437Shisping  * This function opens a new Session between the Client application and the
251abdd2437Shisping  * specified TEE application.
252abdd2437Shisping  *
253abdd2437Shisping  * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and
254abdd2437Shisping  * operation shall be set to NULL.
255abdd2437Shisping  */
256abdd2437Shisping TEEC_Result TEEC_OpenSession(TEEC_Context *context,
257abdd2437Shisping 			TEEC_Session *session,
258abdd2437Shisping 			const TEEC_UUID *destination,
259abdd2437Shisping 			uint32_t connection_method,
260abdd2437Shisping 			const void *connection_data,
261abdd2437Shisping 			TEEC_Operation *operation,
262abdd2437Shisping 			uint32_t *error_origin)
263abdd2437Shisping {
264abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
265abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
266abdd2437Shisping 
267abdd2437Shisping 	debug("TEEC_OpenSession: session=0x%X, ...\n", session->id);
268abdd2437Shisping 
269abdd2437Shisping 	if ((context == NULL) || (session == NULL) || (destination == NULL)) {
270abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
271abdd2437Shisping 		goto Exit;
272abdd2437Shisping 	}
273abdd2437Shisping 
274abdd2437Shisping 	if (connection_method != TEEC_LOGIN_PUBLIC) {
275abdd2437Shisping 		TeecResult = TEEC_ERROR_NOT_SUPPORTED;
276abdd2437Shisping 		goto Exit;
277abdd2437Shisping 	}
278abdd2437Shisping 
279abdd2437Shisping 	TEEC_Operation TeecNullOperation = {0};
280abdd2437Shisping 	TEEC_Operation *TeecOperation;
281abdd2437Shisping 
282abdd2437Shisping 	if (operation == NULL) {
283abdd2437Shisping 		memset(&TeecNullOperation, 0, sizeof(TEEC_Operation));
284abdd2437Shisping 		TeecOperation = &TeecNullOperation;
285abdd2437Shisping 	} else {
286abdd2437Shisping 		TeecOperation = operation;
287abdd2437Shisping 	}
288abdd2437Shisping 
289abdd2437Shisping 	TeecResult = TEEC_SMC_OpenSession(context, session, destination,
290abdd2437Shisping 				TeecOperation, &TeecErrorOrigin);
291abdd2437Shisping 
292abdd2437Shisping Exit:
293abdd2437Shisping 	if (error_origin != NULL)
294abdd2437Shisping 		*error_origin = TeecErrorOrigin;
295abdd2437Shisping 
296efb93541SHisping Lin 	debug("TEEC_OpenSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
297abdd2437Shisping 				TeecResult, TeecErrorOrigin);
298abdd2437Shisping 	return TeecResult;
299abdd2437Shisping }
300abdd2437Shisping 
301abdd2437Shisping /*
302abdd2437Shisping  * This function closes a session which has been opened with a TEE
303abdd2437Shisping  * application.
304abdd2437Shisping  */
305abdd2437Shisping void TEEC_CloseSession(TEEC_Session *session)
306abdd2437Shisping {
307abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
308abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
309abdd2437Shisping 
310abdd2437Shisping 	debug("TEEC_CloseSession Enter: session=0x%X\n", session->id);
311abdd2437Shisping 
312abdd2437Shisping 	if (session == NULL)
313abdd2437Shisping 		goto Exit;
314abdd2437Shisping 
315abdd2437Shisping 	TeecResult = TEEC_SMC_CloseSession(session, &TeecErrorOrigin);
316abdd2437Shisping 
317abdd2437Shisping Exit:
318efb93541SHisping Lin 	debug("TEEC_CloseSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
319abdd2437Shisping 			TeecResult, TeecErrorOrigin);
320abdd2437Shisping 	return;
321abdd2437Shisping }
322abdd2437Shisping 
323abdd2437Shisping /*
324abdd2437Shisping  * Invokes a TEE command (secure service, sub-PA or whatever).
325abdd2437Shisping  */
326abdd2437Shisping TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
327abdd2437Shisping 				uint32_t cmd_id,
328abdd2437Shisping 				TEEC_Operation *operation,
329abdd2437Shisping 				uint32_t *error_origin)
330abdd2437Shisping {
331abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
332abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
333abdd2437Shisping 
334abdd2437Shisping 	debug("TEEC_InvokeCommand Enter: session=0x%X, cmd_id=0x%X\n",
335abdd2437Shisping 			session->id, cmd_id);
336abdd2437Shisping 
337abdd2437Shisping 	if (session == NULL) {
338abdd2437Shisping 		TeecResult = TEEC_ERROR_BAD_PARAMETERS;
339abdd2437Shisping 		goto Exit;
340abdd2437Shisping 	}
341abdd2437Shisping 
342abdd2437Shisping 	TEEC_Operation TeecNullOperation = {0};
343abdd2437Shisping 	TEEC_Operation *TeecOperation;
344abdd2437Shisping 
345abdd2437Shisping 	if (operation == NULL)
346abdd2437Shisping 		TeecOperation = &TeecNullOperation;
347abdd2437Shisping 	else
348abdd2437Shisping 		TeecOperation = operation;
349abdd2437Shisping 
350abdd2437Shisping 	TeecResult = TEEC_SMC_InvokeCommand(session, cmd_id,
351abdd2437Shisping 			TeecOperation, &TeecErrorOrigin);
352abdd2437Shisping 
353abdd2437Shisping Exit:
354abdd2437Shisping 	if (error_origin != NULL)
355abdd2437Shisping 		*error_origin = TeecErrorOrigin;
356abdd2437Shisping 
357efb93541SHisping Lin 	debug("TEEC_InvokeCommand Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
358abdd2437Shisping 				TeecResult, TeecErrorOrigin);
359abdd2437Shisping 
360abdd2437Shisping 	return TeecResult;
361abdd2437Shisping }
362abdd2437Shisping 
363abdd2437Shisping /*
364abdd2437Shisping  * Request a cancellation of a in-progress operation (best effort)
365abdd2437Shisping  */
366abdd2437Shisping void TEEC_RequestCancellation(TEEC_Operation *operation)
367abdd2437Shisping {
368abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
369abdd2437Shisping 	uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
370abdd2437Shisping 
371abdd2437Shisping 	if (operation == NULL)
372abdd2437Shisping 		goto Exit;
373abdd2437Shisping 
374abdd2437Shisping 	TeecResult = TEEC_SMC_RequestCancellation(operation, &TeecErrorOrigin);
375abdd2437Shisping 
376abdd2437Shisping Exit:
377abdd2437Shisping 	debug("TEEC_RequestCancellation Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
378abdd2437Shisping 			TeecResult, TeecErrorOrigin);
379abdd2437Shisping 
380abdd2437Shisping 	return;
381abdd2437Shisping }
382