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