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