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