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