1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2019 Linaro limited
4 */
5
6 #include <ctype.h>
7 #include <dlfcn.h>
8 #include <pta_system.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <tee_api.h>
12 #include <tee_internal_api_extensions.h>
13 #include <user_ta_header.h>
14
15 static TEE_TASessionHandle sess = TEE_HANDLE_NULL;
16 static size_t hcount;
17
invoke_system_pta(uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])18 static TEE_Result invoke_system_pta(uint32_t cmd_id, uint32_t param_types,
19 TEE_Param params[TEE_NUM_PARAMS])
20 {
21 const TEE_UUID core_uuid = PTA_SYSTEM_UUID;
22 TEE_Result res = TEE_ERROR_GENERIC;
23
24 if (sess == TEE_HANDLE_NULL) {
25 res = TEE_OpenTASession(&core_uuid, TEE_TIMEOUT_INFINITE,
26 0, NULL, &sess, NULL);
27 if (res)
28 return res;
29 }
30 return TEE_InvokeTACommand(sess, TEE_TIMEOUT_INFINITE,
31 cmd_id, param_types, params, NULL);
32 }
33
34 struct dl_handle {
35 TEE_UUID uuid;
36 };
37
dlopen(const char * filename,int flags)38 void *dlopen(const char *filename, int flags)
39 {
40 TEE_Param params[TEE_NUM_PARAMS] = { };
41 struct dl_handle *h = NULL;
42 uint32_t param_types = 0;
43 TEE_Result res = TEE_ERROR_GENERIC;
44 TEE_UUID uuid = { };
45
46 h = malloc(sizeof(*h));
47 if (!h)
48 return NULL;
49
50 if (filename) {
51 res = tee_uuid_from_str(&uuid, filename);
52 if (res)
53 goto err;
54
55 param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
56 TEE_PARAM_TYPE_VALUE_INPUT,
57 TEE_PARAM_TYPE_NONE,
58 TEE_PARAM_TYPE_NONE);
59
60 params[0].memref.buffer = (void *)&uuid;
61 params[0].memref.size = sizeof(uuid);
62 params[1].value.a = flags;
63
64 res = invoke_system_pta(PTA_SYSTEM_DLOPEN, param_types, params);
65 if (res)
66 goto err;
67
68 __utee_tcb_init();
69 __utee_call_elf_init_fn();
70 }
71
72 hcount++;
73 h->uuid = uuid;
74 return (void *)h;
75 err:
76 free(h);
77 return NULL;
78 }
79
dlclose(void * handle)80 int dlclose(void *handle)
81 {
82 free(handle);
83 hcount--;
84 if (!hcount && sess != TEE_HANDLE_NULL) {
85 TEE_CloseTASession(sess);
86 sess = TEE_HANDLE_NULL;
87 }
88 return 0;
89 }
90
dlsym(void * handle,const char * symbol)91 void *dlsym(void *handle, const char *symbol)
92 {
93 TEE_Result res = TEE_ERROR_GENERIC;
94 TEE_Param params[TEE_NUM_PARAMS] = { };
95 struct dl_handle *h = handle;
96 uint32_t param_types = 0;
97 void *ptr = NULL;
98
99 if (!handle || !symbol)
100 return NULL;
101
102 param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
103 TEE_PARAM_TYPE_MEMREF_INPUT,
104 TEE_PARAM_TYPE_VALUE_OUTPUT,
105 TEE_PARAM_TYPE_NONE);
106
107 params[0].memref.buffer = &h->uuid;
108 params[0].memref.size = sizeof(h->uuid);
109 params[1].memref.buffer = (void *)symbol;
110 params[1].memref.size = strlen(symbol) + 1;
111
112 res = invoke_system_pta(PTA_SYSTEM_DLSYM, param_types, params);
113 if (!res)
114 ptr = (void *)(vaddr_t)reg_pair_to_64(params[2].value.a,
115 params[2].value.b);
116
117 return ptr;
118 }
119
120