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