1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "egl_wrapper_loader.h"
17
18 #include <dlfcn.h>
19 #include <string>
20
21 #include "directory_ex.h"
22
23 #include "egl_defs.h"
24 #include "wrapper_log.h"
25
26 using namespace OHOS;
27 namespace OHOS {
28 namespace {
29 #if (defined(__aarch64__) || defined(__x86_64__))
30 constexpr const char *VENDOR_LIB_PATH = "/vendor/lib64/chipsetsdk/";
31 constexpr const char *SYSTEM_LIB_PATH = "/system/lib64/";
32 #else
33 constexpr const char *VENDOR_LIB_PATH = "/vendor/lib/chipsetsdk/";
34 constexpr const char *SYSTEM_LIB_PATH = "/system/lib/";
35 #endif
36 constexpr const char *LIB_EGL_NAME = "libEGL_impl.so";
37 constexpr const char *LIB_GLESV1_NAME = "libGLESv1_impl.so";
38 constexpr const char *LIB_GLESV2_NAME = "libGLESv2_impl.so";
39 constexpr const char *LIB_GLESV3_NAME = "libGLESv3_impl.so";
40 }
41
GetInstance()42 EglWrapperLoader& EglWrapperLoader::GetInstance()
43 {
44 static EglWrapperLoader loader;
45 return loader;
46 }
47
~EglWrapperLoader()48 EglWrapperLoader::~EglWrapperLoader()
49 {
50 WLOGD("");
51 }
52
53 using GetProcAddressType = FunctionPointerType (*)(const char *);
LoadEgl(const char * libName,EglHookTable * table)54 bool EglWrapperLoader::LoadEgl(const char* libName, EglHookTable* table)
55 {
56 WLOGD("");
57 std::string path = std::string(VENDOR_LIB_PATH) + std::string(libName);
58 std::string realPath = "";
59 if (!PathToRealPath(path, realPath) ||
60 strncmp(realPath.c_str(), VENDOR_LIB_PATH, strlen(VENDOR_LIB_PATH)) != 0) {
61 WLOGD("Vendor path is invalid or not within vendor directory: %{private}s", path.c_str());
62 dlEglHandle_ = nullptr;
63 } else {
64 dlEglHandle_ = dlopen(realPath.c_str(), RTLD_NOW | RTLD_LOCAL);
65 }
66 if (dlEglHandle_ == nullptr) {
67 path = std::string(SYSTEM_LIB_PATH) + std::string(libName);
68 if (!PathToRealPath(path, realPath) ||
69 strncmp(realPath.c_str(), SYSTEM_LIB_PATH, strlen(SYSTEM_LIB_PATH)) != 0) {
70 WLOGE("System path is invalid or not within system directory: %{private}s", path.c_str());
71 return false;
72 }
73 dlEglHandle_ = dlopen(realPath.c_str(), RTLD_NOW | RTLD_LOCAL);
74 if (dlEglHandle_ == nullptr) {
75 WLOGE("dlopen failed. error: %{public}s.", dlerror());
76 return false;
77 }
78 }
79
80 GetProcAddressType getProcAddr =
81 (GetProcAddressType)dlsym(dlEglHandle_, "eglGetProcAddress");
82 if (getProcAddr == nullptr) {
83 WLOGE("can't find eglGetProcAddress() in EGL driver library.");
84 return false;
85 }
86
87 FunctionPointerType *current = (FunctionPointerType *)table;
88 char const * const *api = gEglApiNames;
89 while (*api) {
90 char const *name = *api;
91 FunctionPointerType func = (FunctionPointerType)dlsym(dlEglHandle_, name);
92 if (func == nullptr) {
93 WLOGD("try to getProcAddr %{public}s.", name);
94 func = getProcAddr(name);
95 if (func == nullptr) {
96 WLOGD("couldn't find the entry-point: %{public}s.", name);
97 }
98 }
99
100 *current++ = func;
101 api++;
102 }
103
104 return true;
105 }
106
LoadGl(const char * libName,char const * const * glName,FunctionPointerType * entry)107 void *EglWrapperLoader::LoadGl(const char *libName, char const * const *glName, FunctionPointerType *entry)
108 {
109 WLOGD("");
110 std::string path = std::string(VENDOR_LIB_PATH) + std::string(libName);
111 std::string realPath = "";
112 void *dlHandle = nullptr;
113 if (!PathToRealPath(path, realPath) ||
114 strncmp(realPath.c_str(), VENDOR_LIB_PATH, strlen(VENDOR_LIB_PATH)) != 0) {
115 WLOGD("Vendor path is invalid or not within vendor directory: %{private}s", path.c_str());
116 } else {
117 dlHandle = dlopen(realPath.c_str(), RTLD_NOW | RTLD_LOCAL);
118 }
119 if (dlHandle == nullptr) {
120 path = std::string(SYSTEM_LIB_PATH) + std::string(libName);
121 if (!PathToRealPath(path, realPath) ||
122 strncmp(realPath.c_str(), SYSTEM_LIB_PATH, strlen(SYSTEM_LIB_PATH)) != 0) {
123 WLOGE("System path is invalid or not within system directory: %{private}s", path.c_str());
124 return nullptr;
125 }
126 dlHandle = dlopen(realPath.c_str(), RTLD_NOW | RTLD_LOCAL);
127 if (dlHandle == nullptr) {
128 WLOGE("dlopen failed. error: %{public}s.", dlerror());
129 return nullptr;
130 }
131 }
132
133 GetProcAddressType getProcAddr =
134 (GetProcAddressType)dlsym(dlEglHandle_, "eglGetProcAddress");
135 if (getProcAddr == nullptr) {
136 WLOGE("can't find eglGetProcAddress() in EGL driver library.");
137 return nullptr;
138 }
139
140 FunctionPointerType *current = entry;
141 char const * const *api = glName;
142 while (*api) {
143 char const *name = *api;
144 FunctionPointerType func = (FunctionPointerType)dlsym(dlHandle, name);
145 if (func == nullptr) {
146 WLOGD("try to getProcAddr %{public}s.", name);
147 func = getProcAddr(name);
148 if (func == nullptr) {
149 WLOGD("couldn't find the entry-point: %{public}s.", name);
150 }
151 }
152 *current++ = func;
153 api++;
154 }
155
156 return dlHandle;
157 }
158
LoadVendorDriver(EglWrapperDispatchTable * table)159 bool EglWrapperLoader::LoadVendorDriver(EglWrapperDispatchTable *table)
160 {
161 WLOGD("EGL");
162 if (!LoadEgl(LIB_EGL_NAME, &table->egl)) {
163 WLOGE("LoadEgl Failed.");
164 return false;
165 }
166
167 WLOGD("GLESV1");
168 dlGlHandle1_ = LoadGl(LIB_GLESV1_NAME, gGlApiNames1, (FunctionPointerType *)&table->gl.table1);
169 if (!dlEglHandle_) {
170 WLOGE("LoadGl GLESV1 Failed.");
171 return false;
172 }
173
174 WLOGD("GLESV2");
175 dlGlHandle2_ = LoadGl(LIB_GLESV2_NAME, gGlApiNames2, (FunctionPointerType *)&table->gl.table2);
176 if (!dlGlHandle2_) {
177 WLOGE("LoadGl GLESV2 Failed.");
178 return false;
179 }
180
181 WLOGD("GLESV3");
182 dlGlHandle3_ = LoadGl(LIB_GLESV3_NAME, gGlApiNames3, (FunctionPointerType *)&table->gl.table3);
183 if (!dlGlHandle3_) {
184 WLOGE("LoadGl GLESV3 Failed.");
185 return false;
186 }
187
188 return true;
189 }
190
Load(EglWrapperDispatchTable * table)191 bool EglWrapperLoader::Load(EglWrapperDispatchTable *table)
192 {
193 WLOGD("");
194 if (table == nullptr) {
195 WLOGE("table is nullptr.");
196 return false;
197 }
198
199 if (table->isLoad) {
200 WLOGI("EglWrapperLoader has been already loaded.");
201 return true;
202 }
203
204 if (!LoadVendorDriver(table)) {
205 WLOGE("LoadVendorDriver Failed.");
206 return false;
207 }
208
209 table->isLoad = true;
210 return true;
211 }
212
Unload(EglWrapperDispatchTable * table)213 bool EglWrapperLoader::Unload(EglWrapperDispatchTable *table)
214 {
215 WLOGD("");
216 if (table == nullptr) {
217 WLOGE("table is nullptr.");
218 return false;
219 }
220 if (!table->isLoad) {
221 WLOGE("EglWrapperLoader is not loaded.");
222 return false;
223 }
224
225 table->isLoad = false;
226
227 if (dlEglHandle_) {
228 dlclose(dlEglHandle_);
229 dlEglHandle_ = nullptr;
230 }
231 if (dlGlHandle1_) {
232 dlclose(dlGlHandle1_);
233 dlGlHandle1_ = nullptr;
234 }
235 if (dlGlHandle2_) {
236 dlclose(dlGlHandle2_);
237 dlGlHandle2_ = nullptr;
238 }
239 if (dlGlHandle3_) {
240 dlclose(dlGlHandle3_);
241 dlGlHandle3_ = nullptr;
242 }
243
244 return true;
245 }
246
GetProcAddrFromDriver(const char * name)247 void *EglWrapperLoader::GetProcAddrFromDriver(const char *name)
248 {
249 void *func = nullptr;
250
251 if (dlEglHandle_) {
252 func = dlsym(dlEglHandle_, name);
253 }
254
255 if (!func && dlGlHandle3_) {
256 func = dlsym(dlGlHandle3_, name);
257 }
258
259 if (!func && dlGlHandle2_) {
260 func = dlsym(dlGlHandle2_, name);
261 }
262
263 if (!func && dlGlHandle1_) {
264 func = dlsym(dlGlHandle1_, name);
265 }
266
267 return func;
268 }
269 } // namespace OHOS
270