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