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