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>
1074eb6027SHisping Lin #include <optee_include/OpteeClientRPC.h>
11abdd2437Shisping #include <optee_include/OpteeClientSMC.h>
121f25ada2SHisping Lin #include <optee_include/OpteeClientRkFs.h>
1374eb6027SHisping Lin #include <optee_include/teesmc.h>
1474eb6027SHisping Lin #include <optee_include/teesmc_optee.h>
1574eb6027SHisping Lin #include <optee_include/teesmc_v2.h>
1674eb6027SHisping Lin
1774eb6027SHisping Lin #define OPTEE_MSG_REVISION_MAJOR 2
1874eb6027SHisping Lin #define OPTEE_MSG_REVISION_MINOR 0
1974eb6027SHisping Lin
207a349fdcSElon Zhang static bool optee_is_init;
217a349fdcSElon Zhang
optee_vm_create(uint32_t client_id)22*1d30eaa5SHisping Lin static bool optee_vm_create(uint32_t client_id)
23*1d30eaa5SHisping Lin {
24*1d30eaa5SHisping Lin ARM_SMC_ARGS ArmSmcArgs = {0};
25*1d30eaa5SHisping Lin
26*1d30eaa5SHisping Lin ArmSmcArgs.Arg0 = OPTEE_SMC_VM_CREATED;
27*1d30eaa5SHisping Lin ArmSmcArgs.Arg1 = client_id;
28*1d30eaa5SHisping Lin
29*1d30eaa5SHisping Lin tee_smc_call(&ArmSmcArgs);
30*1d30eaa5SHisping Lin
31*1d30eaa5SHisping Lin if (ArmSmcArgs.Arg0 != 0)
32*1d30eaa5SHisping Lin return false;
33*1d30eaa5SHisping Lin
34*1d30eaa5SHisping Lin return true;
35*1d30eaa5SHisping Lin }
36*1d30eaa5SHisping Lin
optee_vm_destroyed(uint32_t client_id)37*1d30eaa5SHisping Lin static bool optee_vm_destroyed(uint32_t client_id)
38*1d30eaa5SHisping Lin {
39*1d30eaa5SHisping Lin ARM_SMC_ARGS ArmSmcArgs = {0};
40*1d30eaa5SHisping Lin
41*1d30eaa5SHisping Lin ArmSmcArgs.Arg0 = OPTEE_SMC_VM_DESTROYED;
42*1d30eaa5SHisping Lin ArmSmcArgs.Arg1 = client_id;
43*1d30eaa5SHisping Lin
44*1d30eaa5SHisping Lin tee_smc_call(&ArmSmcArgs);
45*1d30eaa5SHisping Lin
46*1d30eaa5SHisping Lin if (ArmSmcArgs.Arg0 != 0)
47*1d30eaa5SHisping Lin return false;
48*1d30eaa5SHisping Lin
49*1d30eaa5SHisping Lin return true;
50*1d30eaa5SHisping Lin }
51*1d30eaa5SHisping Lin
optee_exchange_capabilities(uint32_t * sec_caps)52*1d30eaa5SHisping Lin static bool optee_exchange_capabilities(uint32_t *sec_caps)
53*1d30eaa5SHisping Lin {
54*1d30eaa5SHisping Lin ARM_SMC_ARGS ArmSmcArgs = {0};
55*1d30eaa5SHisping Lin
56*1d30eaa5SHisping Lin ArmSmcArgs.Arg0 = OPTEE_SMC_EXCHANGE_CAPABILITIES;
57*1d30eaa5SHisping Lin
58*1d30eaa5SHisping Lin tee_smc_call(&ArmSmcArgs);
59*1d30eaa5SHisping Lin
60*1d30eaa5SHisping Lin if (ArmSmcArgs.Arg0 != 0)
61*1d30eaa5SHisping Lin return false;
62*1d30eaa5SHisping Lin *sec_caps = ArmSmcArgs.Arg1;
63*1d30eaa5SHisping Lin return true;
64*1d30eaa5SHisping Lin }
65*1d30eaa5SHisping Lin
optee_api_revision_is_compatible(void)6674eb6027SHisping Lin static bool optee_api_revision_is_compatible(void)
6774eb6027SHisping Lin {
6874eb6027SHisping Lin ARM_SMC_ARGS ArmSmcArgs = {0};
6974eb6027SHisping Lin
7074eb6027SHisping Lin ArmSmcArgs.Arg0 = OPTEE_SMC_CALLS_REVISION;
7174eb6027SHisping Lin
7274eb6027SHisping Lin tee_smc_call(&ArmSmcArgs);
7374eb6027SHisping Lin
7474eb6027SHisping Lin if (ArmSmcArgs.Arg0 == OPTEE_MSG_REVISION_MAJOR &&
7574eb6027SHisping Lin ArmSmcArgs.Arg1 >= OPTEE_MSG_REVISION_MINOR) {
7674eb6027SHisping Lin printf("optee api revision: %d.%d\n",
7774eb6027SHisping Lin ArmSmcArgs.Arg0, ArmSmcArgs.Arg1);
7874eb6027SHisping Lin return true;
7974eb6027SHisping Lin } else {
8074eb6027SHisping Lin printf("optee check api revision fail: %d.%d\n",
8174eb6027SHisping Lin ArmSmcArgs.Arg0, ArmSmcArgs.Arg1);
8274eb6027SHisping Lin return false;
8374eb6027SHisping Lin }
8474eb6027SHisping Lin }
85abdd2437Shisping
optee_get_shm_config(phys_addr_t * base,phys_size_t * size)86396e3049SElon Zhang void optee_get_shm_config(phys_addr_t *base, phys_size_t *size)
87396e3049SElon Zhang {
88396e3049SElon Zhang ARM_SMC_ARGS ArmSmcArgs = {0};
89396e3049SElon Zhang
90396e3049SElon Zhang ArmSmcArgs.Arg0 = OPTEE_SMC_GET_SHM_CONFIG_V2;
91396e3049SElon Zhang
92396e3049SElon Zhang tee_smc_call(&ArmSmcArgs);
93396e3049SElon Zhang
94396e3049SElon Zhang *base = ArmSmcArgs.Arg1;
95396e3049SElon Zhang *size = ArmSmcArgs.Arg2;
96396e3049SElon Zhang }
97396e3049SElon Zhang
98abdd2437Shisping /*
99abdd2437Shisping * Initlialize the library
100abdd2437Shisping */
OpteeClientApiLibInitialize(void)101abdd2437Shisping TEEC_Result OpteeClientApiLibInitialize(void)
102abdd2437Shisping {
103abdd2437Shisping TEEC_Result status = TEEC_SUCCESS;
104abdd2437Shisping
1057a349fdcSElon Zhang if (optee_is_init)
1067a349fdcSElon Zhang return TEEC_SUCCESS;
1077a349fdcSElon Zhang
10874eb6027SHisping Lin /* check api revision compatibility */
10974eb6027SHisping Lin if (!optee_api_revision_is_compatible())
11074eb6027SHisping Lin panic("optee api revision is too low");
11174eb6027SHisping Lin
112f4e1db95SHisping Lin status = OpteeClientMemInit();
113f4e1db95SHisping Lin if (status != TEEC_SUCCESS) {
114efb93541SHisping Lin printf("TEEC: OpteeClientMemInit fail!\n");
115abdd2437Shisping return status;
116abdd2437Shisping }
117f4e1db95SHisping Lin status = OpteeClientRkFsInit();
118f4e1db95SHisping Lin if (status != TEEC_SUCCESS) {
119efb93541SHisping Lin printf("TEEC: OpteeClientRkFsInit fail!\n");
120f4e1db95SHisping Lin return status;
121f4e1db95SHisping Lin }
122f4e1db95SHisping Lin
1237a349fdcSElon Zhang optee_is_init = true;
1247a349fdcSElon Zhang
125f4e1db95SHisping Lin return TEEC_SUCCESS;
126f4e1db95SHisping Lin }
127abdd2437Shisping
128abdd2437Shisping /*
129abdd2437Shisping * This function initializes a new TEE Context, connecting this Client
130abdd2437Shisping * application to the TEE indentified by the name name.
131abdd2437Shisping *
132abdd2437Shisping * name == NULL will give the default TEE.
133abdd2437Shisping *
134abdd2437Shisping * In this implementation only the default name is supported.
135abdd2437Shisping * If name != NULL then TEEC_ERROR_ITEM_NOT_FOUND is returned.
136abdd2437Shisping */
TEEC_InitializeContext(const char * name,TEEC_Context * context)137abdd2437Shisping TEEC_Result TEEC_InitializeContext(const char *name,
138abdd2437Shisping TEEC_Context *context)
139abdd2437Shisping {
140abdd2437Shisping TEEC_Result teecresult = TEEC_SUCCESS;
141*1d30eaa5SHisping Lin uint32_t sec_caps = 0;
142abdd2437Shisping
143abdd2437Shisping debug("TEEC_InitializeContext Enter: name=%s context=%s 0x%X\n",
144abdd2437Shisping name, context->devname, context->fd);
145abdd2437Shisping
146*1d30eaa5SHisping Lin
147abdd2437Shisping if (context == NULL) {
148abdd2437Shisping teecresult = TEEC_ERROR_BAD_PARAMETERS;
149abdd2437Shisping goto exit;
150abdd2437Shisping }
151abdd2437Shisping
152abdd2437Shisping if (name != NULL) {
153abdd2437Shisping teecresult = TEEC_ERROR_ITEM_NOT_FOUND;
154abdd2437Shisping goto exit;
155abdd2437Shisping }
156abdd2437Shisping
157abdd2437Shisping memset(context, 0, sizeof(*context));
158abdd2437Shisping
159*1d30eaa5SHisping Lin /* get optee capabilities */
160*1d30eaa5SHisping Lin if (!optee_exchange_capabilities(&sec_caps))
161*1d30eaa5SHisping Lin panic("optee exchange capabilities fail!");
162*1d30eaa5SHisping Lin
163*1d30eaa5SHisping Lin /* optee vm create */
164*1d30eaa5SHisping Lin if (sec_caps & OPTEE_SMC_SEC_CAP_VIRTUALIZATION) {
165*1d30eaa5SHisping Lin if (!optee_vm_create(0))
166*1d30eaa5SHisping Lin panic("optee vm create fail!");
167*1d30eaa5SHisping Lin }
168*1d30eaa5SHisping Lin
169abdd2437Shisping exit:
170efb93541SHisping Lin debug("TEEC_InitializeContext Exit : teecresult=0x%X\n", teecresult);
171abdd2437Shisping return teecresult;
172abdd2437Shisping }
173abdd2437Shisping
174abdd2437Shisping /*
175abdd2437Shisping * This function destroys an initialized TEE Context, closing the connection
176abdd2437Shisping * between the Client and the TEE.
177abdd2437Shisping * The function implementation MUST do nothing if context is NULL
178abdd2437Shisping *
179abdd2437Shisping * There is nothing to do here since there is no context state.
180abdd2437Shisping */
TEEC_FinalizeContext(TEEC_Context * context)181abdd2437Shisping TEEC_Result TEEC_FinalizeContext(TEEC_Context *context)
182abdd2437Shisping {
183*1d30eaa5SHisping Lin uint32_t sec_caps = 0;
184*1d30eaa5SHisping Lin
185*1d30eaa5SHisping Lin /* get optee capabilities */
186*1d30eaa5SHisping Lin if (!optee_exchange_capabilities(&sec_caps))
187*1d30eaa5SHisping Lin panic("optee exchange capabilities fail!");
188*1d30eaa5SHisping Lin
189*1d30eaa5SHisping Lin /* optee vm destroyed */
190*1d30eaa5SHisping Lin if (sec_caps & OPTEE_SMC_SEC_CAP_VIRTUALIZATION) {
191*1d30eaa5SHisping Lin if (!optee_vm_destroyed(0))
192*1d30eaa5SHisping Lin panic("optee vm destroyed fail!");
193*1d30eaa5SHisping Lin }
194*1d30eaa5SHisping Lin
1951f25ada2SHisping Lin debug("TEEC_FinalizeContext Enter-Exit: context=0x%zu\n",
1961f25ada2SHisping Lin (size_t)context);
197abdd2437Shisping return TEEC_SUCCESS;
198abdd2437Shisping }
199abdd2437Shisping
200abdd2437Shisping /*
201abdd2437Shisping * Allocates or registers shared memory.
202abdd2437Shisping *
203abdd2437Shisping * Since EDK2 is configured flat with virtual memory == physical memory
204abdd2437Shisping * then we don't need to perform any special operations to get physical
205abdd2437Shisping * contiguous memory.
206abdd2437Shisping */
TEEC_AllocateSharedMemory(TEEC_Context * context,TEEC_SharedMemory * shared_memory)207abdd2437Shisping TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context,
208abdd2437Shisping TEEC_SharedMemory *shared_memory)
209abdd2437Shisping {
210abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS;
211abdd2437Shisping
2121f25ada2SHisping Lin debug("TEEC_AllocateSharedMemory Enter: context=%s 0x%X, shared_memory=0x%zu\n",
213abdd2437Shisping context->devname, context->fd, shared_memory->size);
214abdd2437Shisping
215abdd2437Shisping if ((context == NULL) || (shared_memory == NULL)) {
216abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS;
217abdd2437Shisping goto Exit;
218abdd2437Shisping }
219abdd2437Shisping
220abdd2437Shisping if (shared_memory->flags != 0) {
221abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS;
222abdd2437Shisping goto Exit;
223abdd2437Shisping }
224abdd2437Shisping
225abdd2437Shisping shared_memory->buffer = NULL;
226abdd2437Shisping shared_memory->alloc_buffer = 0;
227abdd2437Shisping
2281f25ada2SHisping Lin debug("TEEC_AllocateSharedMemory: size=0x%zu, flags=0x%X\n",
229abdd2437Shisping shared_memory->size, shared_memory->flags);
230abdd2437Shisping
231abdd2437Shisping shared_memory->buffer = OpteeClientMemAlloc(shared_memory->size);
232abdd2437Shisping if (shared_memory->buffer == NULL) {
233abdd2437Shisping TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
234abdd2437Shisping goto Exit;
235abdd2437Shisping }
236abdd2437Shisping
237abdd2437Shisping shared_memory->alloc_buffer = shared_memory->buffer;
238abdd2437Shisping
239abdd2437Shisping Exit:
240abdd2437Shisping debug("TEEC_AllocateSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
241abdd2437Shisping return TeecResult;
242abdd2437Shisping }
243abdd2437Shisping
244abdd2437Shisping /*
245abdd2437Shisping * Releases shared memory.
246abdd2437Shisping *
247abdd2437Shisping * The optee_client implementation allows this to be called with a null pointer
248abdd2437Shisping * and null buffer but we'll assert this is not the case for better debugging.
249abdd2437Shisping */
TEEC_ReleaseSharedMemory(TEEC_SharedMemory * shared_memory)250abdd2437Shisping void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory)
251abdd2437Shisping {
2521f25ada2SHisping Lin debug("TEEC_ReleaseSharedMemory Enter: shared_memory=0x%zu\n",
253abdd2437Shisping shared_memory->size);
254abdd2437Shisping
255abdd2437Shisping if (shared_memory == NULL)
256abdd2437Shisping goto Exit;
257abdd2437Shisping
258abdd2437Shisping if (shared_memory->buffer == NULL)
259abdd2437Shisping goto Exit;
260abdd2437Shisping
261abdd2437Shisping if (shared_memory->alloc_buffer != 0) {
262abdd2437Shisping OpteeClientMemFree(shared_memory->alloc_buffer);
263abdd2437Shisping shared_memory->alloc_buffer = 0;
264abdd2437Shisping }
265abdd2437Shisping
266abdd2437Shisping shared_memory->buffer = NULL;
267abdd2437Shisping shared_memory->size = 0;
268abdd2437Shisping
269abdd2437Shisping Exit:
270abdd2437Shisping return;
271abdd2437Shisping }
272abdd2437Shisping
273abdd2437Shisping /*
274abdd2437Shisping * Register shared memory
275abdd2437Shisping *
276abdd2437Shisping * If the supplied buffer is compatible we can use it as supplied otherwise
277abdd2437Shisping * we'll need to allocate a copy buffer for the transfer instead.
278abdd2437Shisping */
TEEC_RegisterSharedMemory(TEEC_Context * context,TEEC_SharedMemory * shared_memory)279abdd2437Shisping TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context,
280abdd2437Shisping TEEC_SharedMemory *shared_memory)
281abdd2437Shisping {
282abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS;
283abdd2437Shisping
284abdd2437Shisping if ((context == NULL) || (shared_memory == NULL)) {
285abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS;
286abdd2437Shisping goto Exit;
287abdd2437Shisping }
288abdd2437Shisping
289abdd2437Shisping if (shared_memory->buffer == NULL) {
290abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS;
291abdd2437Shisping goto Exit;
292abdd2437Shisping }
293abdd2437Shisping
294abdd2437Shisping shared_memory->alloc_buffer = 0;
295abdd2437Shisping
296abdd2437Shisping phys_addr_t start = (phys_addr_t) shared_memory->buffer;
297abdd2437Shisping
298abdd2437Shisping if ((start % 4096) != 0) {
299abdd2437Shisping TEEC_SharedMemory TempSharedMemory;
300abdd2437Shisping TempSharedMemory.size = shared_memory->size;
301abdd2437Shisping TempSharedMemory.flags = shared_memory->flags;
302abdd2437Shisping
303abdd2437Shisping TeecResult = TEEC_AllocateSharedMemory
304abdd2437Shisping (context, &TempSharedMemory);
305abdd2437Shisping
306abdd2437Shisping if (TeecResult != TEEC_SUCCESS)
307abdd2437Shisping goto Exit;
308abdd2437Shisping
309abdd2437Shisping shared_memory->alloc_buffer = TempSharedMemory.alloc_buffer;
310abdd2437Shisping }
311abdd2437Shisping
312abdd2437Shisping Exit:
313abdd2437Shisping debug("TEEC_RegisterSharedMemory Exit : TeecResult=0x%X\n", TeecResult);
314abdd2437Shisping return TeecResult;
315abdd2437Shisping }
316abdd2437Shisping
317abdd2437Shisping /*
318abdd2437Shisping * This function opens a new Session between the Client application and the
319abdd2437Shisping * specified TEE application.
320abdd2437Shisping *
321abdd2437Shisping * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and
322abdd2437Shisping * operation shall be set to NULL.
323abdd2437Shisping */
TEEC_OpenSession(TEEC_Context * context,TEEC_Session * session,const TEEC_UUID * destination,uint32_t connection_method,const void * connection_data,TEEC_Operation * operation,uint32_t * error_origin)324abdd2437Shisping TEEC_Result TEEC_OpenSession(TEEC_Context *context,
325abdd2437Shisping TEEC_Session *session,
326abdd2437Shisping const TEEC_UUID *destination,
327abdd2437Shisping uint32_t connection_method,
328abdd2437Shisping const void *connection_data,
329abdd2437Shisping TEEC_Operation *operation,
330abdd2437Shisping uint32_t *error_origin)
331abdd2437Shisping {
332abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS;
333abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
334abdd2437Shisping
335abdd2437Shisping debug("TEEC_OpenSession: session=0x%X, ...\n", session->id);
336abdd2437Shisping
337abdd2437Shisping if ((context == NULL) || (session == NULL) || (destination == NULL)) {
338abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS;
339abdd2437Shisping goto Exit;
340abdd2437Shisping }
341abdd2437Shisping
342abdd2437Shisping if (connection_method != TEEC_LOGIN_PUBLIC) {
343abdd2437Shisping TeecResult = TEEC_ERROR_NOT_SUPPORTED;
344abdd2437Shisping goto Exit;
345abdd2437Shisping }
346abdd2437Shisping
347abdd2437Shisping TEEC_Operation TeecNullOperation = {0};
348abdd2437Shisping TEEC_Operation *TeecOperation;
349abdd2437Shisping
350abdd2437Shisping if (operation == NULL) {
351abdd2437Shisping memset(&TeecNullOperation, 0, sizeof(TEEC_Operation));
352abdd2437Shisping TeecOperation = &TeecNullOperation;
353abdd2437Shisping } else {
354abdd2437Shisping TeecOperation = operation;
355abdd2437Shisping }
356abdd2437Shisping
357abdd2437Shisping TeecResult = TEEC_SMC_OpenSession(context, session, destination,
358abdd2437Shisping TeecOperation, &TeecErrorOrigin);
359abdd2437Shisping
360abdd2437Shisping Exit:
361abdd2437Shisping if (error_origin != NULL)
362abdd2437Shisping *error_origin = TeecErrorOrigin;
363abdd2437Shisping
364efb93541SHisping Lin debug("TEEC_OpenSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
365abdd2437Shisping TeecResult, TeecErrorOrigin);
366abdd2437Shisping return TeecResult;
367abdd2437Shisping }
368abdd2437Shisping
369abdd2437Shisping /*
370abdd2437Shisping * This function closes a session which has been opened with a TEE
371abdd2437Shisping * application.
372abdd2437Shisping */
TEEC_CloseSession(TEEC_Session * session)373abdd2437Shisping void TEEC_CloseSession(TEEC_Session *session)
374abdd2437Shisping {
375abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS;
376abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
377abdd2437Shisping
378abdd2437Shisping debug("TEEC_CloseSession Enter: session=0x%X\n", session->id);
379abdd2437Shisping
380abdd2437Shisping if (session == NULL)
381abdd2437Shisping goto Exit;
382abdd2437Shisping
383abdd2437Shisping TeecResult = TEEC_SMC_CloseSession(session, &TeecErrorOrigin);
384abdd2437Shisping
385abdd2437Shisping Exit:
386efb93541SHisping Lin debug("TEEC_CloseSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
387abdd2437Shisping TeecResult, TeecErrorOrigin);
388abdd2437Shisping return;
389abdd2437Shisping }
390abdd2437Shisping
391abdd2437Shisping /*
392abdd2437Shisping * Invokes a TEE command (secure service, sub-PA or whatever).
393abdd2437Shisping */
TEEC_InvokeCommand(TEEC_Session * session,uint32_t cmd_id,TEEC_Operation * operation,uint32_t * error_origin)394abdd2437Shisping TEEC_Result TEEC_InvokeCommand(TEEC_Session *session,
395abdd2437Shisping uint32_t cmd_id,
396abdd2437Shisping TEEC_Operation *operation,
397abdd2437Shisping uint32_t *error_origin)
398abdd2437Shisping {
399abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS;
400abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
401abdd2437Shisping
402abdd2437Shisping debug("TEEC_InvokeCommand Enter: session=0x%X, cmd_id=0x%X\n",
403abdd2437Shisping session->id, cmd_id);
404abdd2437Shisping
405abdd2437Shisping if (session == NULL) {
406abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS;
407abdd2437Shisping goto Exit;
408abdd2437Shisping }
409abdd2437Shisping
410abdd2437Shisping TEEC_Operation TeecNullOperation = {0};
411abdd2437Shisping TEEC_Operation *TeecOperation;
412abdd2437Shisping
413abdd2437Shisping if (operation == NULL)
414abdd2437Shisping TeecOperation = &TeecNullOperation;
415abdd2437Shisping else
416abdd2437Shisping TeecOperation = operation;
417abdd2437Shisping
418abdd2437Shisping TeecResult = TEEC_SMC_InvokeCommand(session, cmd_id,
419abdd2437Shisping TeecOperation, &TeecErrorOrigin);
420abdd2437Shisping
421abdd2437Shisping Exit:
422abdd2437Shisping if (error_origin != NULL)
423abdd2437Shisping *error_origin = TeecErrorOrigin;
424abdd2437Shisping
425efb93541SHisping Lin debug("TEEC_InvokeCommand Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
426abdd2437Shisping TeecResult, TeecErrorOrigin);
427abdd2437Shisping
428abdd2437Shisping return TeecResult;
429abdd2437Shisping }
430abdd2437Shisping
431abdd2437Shisping /*
432abdd2437Shisping * Request a cancellation of a in-progress operation (best effort)
433abdd2437Shisping */
TEEC_RequestCancellation(TEEC_Operation * operation)434abdd2437Shisping void TEEC_RequestCancellation(TEEC_Operation *operation)
435abdd2437Shisping {
436abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS;
437abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API;
438abdd2437Shisping
439abdd2437Shisping if (operation == NULL)
440abdd2437Shisping goto Exit;
441abdd2437Shisping
442abdd2437Shisping TeecResult = TEEC_SMC_RequestCancellation(operation, &TeecErrorOrigin);
443abdd2437Shisping
444abdd2437Shisping Exit:
445abdd2437Shisping debug("TEEC_RequestCancellation Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n",
446abdd2437Shisping TeecResult, TeecErrorOrigin);
447abdd2437Shisping
448abdd2437Shisping return;
449abdd2437Shisping }
450