xref: /optee_os/lib/libdl/dlfcn.c (revision 5b25c76ac40f830867e3d60800120ffd7874e8dc)
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 
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 
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_call_elf_init_fn();
69 	}
70 
71 	hcount++;
72 	h->uuid = uuid;
73 	return (void *)h;
74 err:
75 	free(h);
76 	return NULL;
77 }
78 
79 int dlclose(void *handle)
80 {
81 	free(handle);
82 	hcount--;
83 	if (!hcount && sess != TEE_HANDLE_NULL) {
84 		TEE_CloseTASession(sess);
85 		sess = TEE_HANDLE_NULL;
86 	}
87 	return 0;
88 }
89 
90 void *dlsym(void *handle, const char *symbol)
91 {
92 	TEE_Result res = TEE_ERROR_GENERIC;
93 	TEE_Param params[TEE_NUM_PARAMS] = { };
94 	struct dl_handle *h = handle;
95 	uint32_t param_types = 0;
96 	void *ptr = NULL;
97 
98 	if (!handle || !symbol)
99 		return NULL;
100 
101 	param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
102 				      TEE_PARAM_TYPE_MEMREF_INPUT,
103 				      TEE_PARAM_TYPE_VALUE_OUTPUT,
104 				      TEE_PARAM_TYPE_NONE);
105 
106 	params[0].memref.buffer = &h->uuid;
107 	params[0].memref.size = sizeof(h->uuid);
108 	params[1].memref.buffer = (void *)symbol;
109 	params[1].memref.size = strlen(symbol) + 1;
110 
111 	res = invoke_system_pta(PTA_SYSTEM_DLSYM, param_types, params);
112 	if (!res)
113 		ptr = (void *)(vaddr_t)reg_pair_to_64(params[2].value.a,
114 						      params[2].value.b);
115 
116 	return ptr;
117 }
118 
119