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