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