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