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