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