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 2274eb6027SHisping Lin static bool optee_api_revision_is_compatible(void) 2374eb6027SHisping Lin { 2474eb6027SHisping Lin ARM_SMC_ARGS ArmSmcArgs = {0}; 2574eb6027SHisping Lin 2674eb6027SHisping Lin ArmSmcArgs.Arg0 = OPTEE_SMC_CALLS_REVISION; 2774eb6027SHisping Lin 2874eb6027SHisping Lin tee_smc_call(&ArmSmcArgs); 2974eb6027SHisping Lin 3074eb6027SHisping Lin if (ArmSmcArgs.Arg0 == OPTEE_MSG_REVISION_MAJOR && 3174eb6027SHisping Lin ArmSmcArgs.Arg1 >= OPTEE_MSG_REVISION_MINOR) { 3274eb6027SHisping Lin printf("optee api revision: %d.%d\n", 3374eb6027SHisping Lin ArmSmcArgs.Arg0, ArmSmcArgs.Arg1); 3474eb6027SHisping Lin return true; 3574eb6027SHisping Lin } else { 3674eb6027SHisping Lin printf("optee check api revision fail: %d.%d\n", 3774eb6027SHisping Lin ArmSmcArgs.Arg0, ArmSmcArgs.Arg1); 3874eb6027SHisping Lin return false; 3974eb6027SHisping Lin } 4074eb6027SHisping Lin } 41abdd2437Shisping 42*396e3049SElon Zhang void optee_get_shm_config(phys_addr_t *base, phys_size_t *size) 43*396e3049SElon Zhang { 44*396e3049SElon Zhang ARM_SMC_ARGS ArmSmcArgs = {0}; 45*396e3049SElon Zhang 46*396e3049SElon Zhang ArmSmcArgs.Arg0 = OPTEE_SMC_GET_SHM_CONFIG_V2; 47*396e3049SElon Zhang 48*396e3049SElon Zhang tee_smc_call(&ArmSmcArgs); 49*396e3049SElon Zhang 50*396e3049SElon Zhang *base = ArmSmcArgs.Arg1; 51*396e3049SElon Zhang *size = ArmSmcArgs.Arg2; 52*396e3049SElon Zhang } 53*396e3049SElon Zhang 54abdd2437Shisping /* 55abdd2437Shisping * Initlialize the library 56abdd2437Shisping */ 57abdd2437Shisping TEEC_Result OpteeClientApiLibInitialize(void) 58abdd2437Shisping { 59abdd2437Shisping TEEC_Result status = TEEC_SUCCESS; 60abdd2437Shisping 617a349fdcSElon Zhang if (optee_is_init) 627a349fdcSElon Zhang return TEEC_SUCCESS; 637a349fdcSElon Zhang 6474eb6027SHisping Lin /* check api revision compatibility */ 6574eb6027SHisping Lin if (!optee_api_revision_is_compatible()) 6674eb6027SHisping Lin panic("optee api revision is too low"); 6774eb6027SHisping Lin 68f4e1db95SHisping Lin status = OpteeClientMemInit(); 69f4e1db95SHisping Lin if (status != TEEC_SUCCESS) { 70efb93541SHisping Lin printf("TEEC: OpteeClientMemInit fail!\n"); 71abdd2437Shisping return status; 72abdd2437Shisping } 73f4e1db95SHisping Lin status = OpteeClientRkFsInit(); 74f4e1db95SHisping Lin if (status != TEEC_SUCCESS) { 75efb93541SHisping Lin printf("TEEC: OpteeClientRkFsInit fail!\n"); 76f4e1db95SHisping Lin return status; 77f4e1db95SHisping Lin } 78f4e1db95SHisping Lin 797a349fdcSElon Zhang optee_is_init = true; 807a349fdcSElon Zhang 81f4e1db95SHisping Lin return TEEC_SUCCESS; 82f4e1db95SHisping Lin } 83abdd2437Shisping 84abdd2437Shisping /* 85abdd2437Shisping * This function initializes a new TEE Context, connecting this Client 86abdd2437Shisping * application to the TEE indentified by the name name. 87abdd2437Shisping * 88abdd2437Shisping * name == NULL will give the default TEE. 89abdd2437Shisping * 90abdd2437Shisping * In this implementation only the default name is supported. 91abdd2437Shisping * If name != NULL then TEEC_ERROR_ITEM_NOT_FOUND is returned. 92abdd2437Shisping */ 93abdd2437Shisping TEEC_Result TEEC_InitializeContext(const char *name, 94abdd2437Shisping TEEC_Context *context) 95abdd2437Shisping { 96abdd2437Shisping TEEC_Result teecresult = TEEC_SUCCESS; 97abdd2437Shisping 98abdd2437Shisping debug("TEEC_InitializeContext Enter: name=%s context=%s 0x%X\n", 99abdd2437Shisping name, context->devname, context->fd); 100abdd2437Shisping 101abdd2437Shisping if (context == NULL) { 102abdd2437Shisping teecresult = TEEC_ERROR_BAD_PARAMETERS; 103abdd2437Shisping goto exit; 104abdd2437Shisping } 105abdd2437Shisping 106abdd2437Shisping if (name != NULL) { 107abdd2437Shisping teecresult = TEEC_ERROR_ITEM_NOT_FOUND; 108abdd2437Shisping goto exit; 109abdd2437Shisping } 110abdd2437Shisping 111abdd2437Shisping memset(context, 0, sizeof(*context)); 112abdd2437Shisping 113abdd2437Shisping exit: 114efb93541SHisping Lin debug("TEEC_InitializeContext Exit : teecresult=0x%X\n", teecresult); 115abdd2437Shisping return teecresult; 116abdd2437Shisping } 117abdd2437Shisping 118abdd2437Shisping /* 119abdd2437Shisping * This function destroys an initialized TEE Context, closing the connection 120abdd2437Shisping * between the Client and the TEE. 121abdd2437Shisping * The function implementation MUST do nothing if context is NULL 122abdd2437Shisping * 123abdd2437Shisping * There is nothing to do here since there is no context state. 124abdd2437Shisping */ 125abdd2437Shisping TEEC_Result TEEC_FinalizeContext(TEEC_Context *context) 126abdd2437Shisping { 1271f25ada2SHisping Lin debug("TEEC_FinalizeContext Enter-Exit: context=0x%zu\n", 1281f25ada2SHisping Lin (size_t)context); 129abdd2437Shisping return TEEC_SUCCESS; 130abdd2437Shisping } 131abdd2437Shisping 132abdd2437Shisping /* 133abdd2437Shisping * Allocates or registers shared memory. 134abdd2437Shisping * 135abdd2437Shisping * Since EDK2 is configured flat with virtual memory == physical memory 136abdd2437Shisping * then we don't need to perform any special operations to get physical 137abdd2437Shisping * contiguous memory. 138abdd2437Shisping */ 139abdd2437Shisping TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *context, 140abdd2437Shisping TEEC_SharedMemory *shared_memory) 141abdd2437Shisping { 142abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS; 143abdd2437Shisping 1441f25ada2SHisping Lin debug("TEEC_AllocateSharedMemory Enter: context=%s 0x%X, shared_memory=0x%zu\n", 145abdd2437Shisping context->devname, context->fd, shared_memory->size); 146abdd2437Shisping 147abdd2437Shisping if ((context == NULL) || (shared_memory == NULL)) { 148abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS; 149abdd2437Shisping goto Exit; 150abdd2437Shisping } 151abdd2437Shisping 152abdd2437Shisping if (shared_memory->flags != 0) { 153abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS; 154abdd2437Shisping goto Exit; 155abdd2437Shisping } 156abdd2437Shisping 157abdd2437Shisping shared_memory->buffer = NULL; 158abdd2437Shisping shared_memory->alloc_buffer = 0; 159abdd2437Shisping 1601f25ada2SHisping Lin debug("TEEC_AllocateSharedMemory: size=0x%zu, flags=0x%X\n", 161abdd2437Shisping shared_memory->size, shared_memory->flags); 162abdd2437Shisping 163abdd2437Shisping shared_memory->buffer = OpteeClientMemAlloc(shared_memory->size); 164abdd2437Shisping if (shared_memory->buffer == NULL) { 165abdd2437Shisping TeecResult = TEEC_ERROR_OUT_OF_MEMORY; 166abdd2437Shisping goto Exit; 167abdd2437Shisping } 168abdd2437Shisping 169abdd2437Shisping shared_memory->alloc_buffer = shared_memory->buffer; 170abdd2437Shisping 171abdd2437Shisping Exit: 172abdd2437Shisping debug("TEEC_AllocateSharedMemory Exit : TeecResult=0x%X\n", TeecResult); 173abdd2437Shisping return TeecResult; 174abdd2437Shisping } 175abdd2437Shisping 176abdd2437Shisping /* 177abdd2437Shisping * Releases shared memory. 178abdd2437Shisping * 179abdd2437Shisping * The optee_client implementation allows this to be called with a null pointer 180abdd2437Shisping * and null buffer but we'll assert this is not the case for better debugging. 181abdd2437Shisping */ 182abdd2437Shisping void TEEC_ReleaseSharedMemory(TEEC_SharedMemory *shared_memory) 183abdd2437Shisping { 1841f25ada2SHisping Lin debug("TEEC_ReleaseSharedMemory Enter: shared_memory=0x%zu\n", 185abdd2437Shisping shared_memory->size); 186abdd2437Shisping 187abdd2437Shisping if (shared_memory == NULL) 188abdd2437Shisping goto Exit; 189abdd2437Shisping 190abdd2437Shisping if (shared_memory->buffer == NULL) 191abdd2437Shisping goto Exit; 192abdd2437Shisping 193abdd2437Shisping if (shared_memory->alloc_buffer != 0) { 194abdd2437Shisping OpteeClientMemFree(shared_memory->alloc_buffer); 195abdd2437Shisping shared_memory->alloc_buffer = 0; 196abdd2437Shisping } 197abdd2437Shisping 198abdd2437Shisping shared_memory->buffer = NULL; 199abdd2437Shisping shared_memory->size = 0; 200abdd2437Shisping 201abdd2437Shisping Exit: 202abdd2437Shisping return; 203abdd2437Shisping } 204abdd2437Shisping 205abdd2437Shisping /* 206abdd2437Shisping * Register shared memory 207abdd2437Shisping * 208abdd2437Shisping * If the supplied buffer is compatible we can use it as supplied otherwise 209abdd2437Shisping * we'll need to allocate a copy buffer for the transfer instead. 210abdd2437Shisping */ 211abdd2437Shisping TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *context, 212abdd2437Shisping TEEC_SharedMemory *shared_memory) 213abdd2437Shisping { 214abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS; 215abdd2437Shisping 216abdd2437Shisping if ((context == NULL) || (shared_memory == NULL)) { 217abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS; 218abdd2437Shisping goto Exit; 219abdd2437Shisping } 220abdd2437Shisping 221abdd2437Shisping if (shared_memory->buffer == NULL) { 222abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS; 223abdd2437Shisping goto Exit; 224abdd2437Shisping } 225abdd2437Shisping 226abdd2437Shisping shared_memory->alloc_buffer = 0; 227abdd2437Shisping 228abdd2437Shisping phys_addr_t start = (phys_addr_t) shared_memory->buffer; 229abdd2437Shisping 230abdd2437Shisping if ((start % 4096) != 0) { 231abdd2437Shisping TEEC_SharedMemory TempSharedMemory; 232abdd2437Shisping TempSharedMemory.size = shared_memory->size; 233abdd2437Shisping TempSharedMemory.flags = shared_memory->flags; 234abdd2437Shisping 235abdd2437Shisping TeecResult = TEEC_AllocateSharedMemory 236abdd2437Shisping (context, &TempSharedMemory); 237abdd2437Shisping 238abdd2437Shisping if (TeecResult != TEEC_SUCCESS) 239abdd2437Shisping goto Exit; 240abdd2437Shisping 241abdd2437Shisping shared_memory->alloc_buffer = TempSharedMemory.alloc_buffer; 242abdd2437Shisping } 243abdd2437Shisping 244abdd2437Shisping Exit: 245abdd2437Shisping debug("TEEC_RegisterSharedMemory Exit : TeecResult=0x%X\n", TeecResult); 246abdd2437Shisping return TeecResult; 247abdd2437Shisping } 248abdd2437Shisping 249abdd2437Shisping /* 250abdd2437Shisping * This function opens a new Session between the Client application and the 251abdd2437Shisping * specified TEE application. 252abdd2437Shisping * 253abdd2437Shisping * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and 254abdd2437Shisping * operation shall be set to NULL. 255abdd2437Shisping */ 256abdd2437Shisping TEEC_Result TEEC_OpenSession(TEEC_Context *context, 257abdd2437Shisping TEEC_Session *session, 258abdd2437Shisping const TEEC_UUID *destination, 259abdd2437Shisping uint32_t connection_method, 260abdd2437Shisping const void *connection_data, 261abdd2437Shisping TEEC_Operation *operation, 262abdd2437Shisping uint32_t *error_origin) 263abdd2437Shisping { 264abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS; 265abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API; 266abdd2437Shisping 267abdd2437Shisping debug("TEEC_OpenSession: session=0x%X, ...\n", session->id); 268abdd2437Shisping 269abdd2437Shisping if ((context == NULL) || (session == NULL) || (destination == NULL)) { 270abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS; 271abdd2437Shisping goto Exit; 272abdd2437Shisping } 273abdd2437Shisping 274abdd2437Shisping if (connection_method != TEEC_LOGIN_PUBLIC) { 275abdd2437Shisping TeecResult = TEEC_ERROR_NOT_SUPPORTED; 276abdd2437Shisping goto Exit; 277abdd2437Shisping } 278abdd2437Shisping 279abdd2437Shisping TEEC_Operation TeecNullOperation = {0}; 280abdd2437Shisping TEEC_Operation *TeecOperation; 281abdd2437Shisping 282abdd2437Shisping if (operation == NULL) { 283abdd2437Shisping memset(&TeecNullOperation, 0, sizeof(TEEC_Operation)); 284abdd2437Shisping TeecOperation = &TeecNullOperation; 285abdd2437Shisping } else { 286abdd2437Shisping TeecOperation = operation; 287abdd2437Shisping } 288abdd2437Shisping 289abdd2437Shisping TeecResult = TEEC_SMC_OpenSession(context, session, destination, 290abdd2437Shisping TeecOperation, &TeecErrorOrigin); 291abdd2437Shisping 292abdd2437Shisping Exit: 293abdd2437Shisping if (error_origin != NULL) 294abdd2437Shisping *error_origin = TeecErrorOrigin; 295abdd2437Shisping 296efb93541SHisping Lin debug("TEEC_OpenSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n", 297abdd2437Shisping TeecResult, TeecErrorOrigin); 298abdd2437Shisping return TeecResult; 299abdd2437Shisping } 300abdd2437Shisping 301abdd2437Shisping /* 302abdd2437Shisping * This function closes a session which has been opened with a TEE 303abdd2437Shisping * application. 304abdd2437Shisping */ 305abdd2437Shisping void TEEC_CloseSession(TEEC_Session *session) 306abdd2437Shisping { 307abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS; 308abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API; 309abdd2437Shisping 310abdd2437Shisping debug("TEEC_CloseSession Enter: session=0x%X\n", session->id); 311abdd2437Shisping 312abdd2437Shisping if (session == NULL) 313abdd2437Shisping goto Exit; 314abdd2437Shisping 315abdd2437Shisping TeecResult = TEEC_SMC_CloseSession(session, &TeecErrorOrigin); 316abdd2437Shisping 317abdd2437Shisping Exit: 318efb93541SHisping Lin debug("TEEC_CloseSession Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n", 319abdd2437Shisping TeecResult, TeecErrorOrigin); 320abdd2437Shisping return; 321abdd2437Shisping } 322abdd2437Shisping 323abdd2437Shisping /* 324abdd2437Shisping * Invokes a TEE command (secure service, sub-PA or whatever). 325abdd2437Shisping */ 326abdd2437Shisping TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, 327abdd2437Shisping uint32_t cmd_id, 328abdd2437Shisping TEEC_Operation *operation, 329abdd2437Shisping uint32_t *error_origin) 330abdd2437Shisping { 331abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS; 332abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API; 333abdd2437Shisping 334abdd2437Shisping debug("TEEC_InvokeCommand Enter: session=0x%X, cmd_id=0x%X\n", 335abdd2437Shisping session->id, cmd_id); 336abdd2437Shisping 337abdd2437Shisping if (session == NULL) { 338abdd2437Shisping TeecResult = TEEC_ERROR_BAD_PARAMETERS; 339abdd2437Shisping goto Exit; 340abdd2437Shisping } 341abdd2437Shisping 342abdd2437Shisping TEEC_Operation TeecNullOperation = {0}; 343abdd2437Shisping TEEC_Operation *TeecOperation; 344abdd2437Shisping 345abdd2437Shisping if (operation == NULL) 346abdd2437Shisping TeecOperation = &TeecNullOperation; 347abdd2437Shisping else 348abdd2437Shisping TeecOperation = operation; 349abdd2437Shisping 350abdd2437Shisping TeecResult = TEEC_SMC_InvokeCommand(session, cmd_id, 351abdd2437Shisping TeecOperation, &TeecErrorOrigin); 352abdd2437Shisping 353abdd2437Shisping Exit: 354abdd2437Shisping if (error_origin != NULL) 355abdd2437Shisping *error_origin = TeecErrorOrigin; 356abdd2437Shisping 357efb93541SHisping Lin debug("TEEC_InvokeCommand Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n", 358abdd2437Shisping TeecResult, TeecErrorOrigin); 359abdd2437Shisping 360abdd2437Shisping return TeecResult; 361abdd2437Shisping } 362abdd2437Shisping 363abdd2437Shisping /* 364abdd2437Shisping * Request a cancellation of a in-progress operation (best effort) 365abdd2437Shisping */ 366abdd2437Shisping void TEEC_RequestCancellation(TEEC_Operation *operation) 367abdd2437Shisping { 368abdd2437Shisping TEEC_Result TeecResult = TEEC_SUCCESS; 369abdd2437Shisping uint32_t TeecErrorOrigin = TEEC_ORIGIN_API; 370abdd2437Shisping 371abdd2437Shisping if (operation == NULL) 372abdd2437Shisping goto Exit; 373abdd2437Shisping 374abdd2437Shisping TeecResult = TEEC_SMC_RequestCancellation(operation, &TeecErrorOrigin); 375abdd2437Shisping 376abdd2437Shisping Exit: 377abdd2437Shisping debug("TEEC_RequestCancellation Exit : TeecResult=0x%X, TeecErrorOrigin=0x%X\n", 378abdd2437Shisping TeecResult, TeecErrorOrigin); 379abdd2437Shisping 380abdd2437Shisping return; 381abdd2437Shisping } 382