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