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