1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2018 Broadcom
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker /**
25*61046927SAndroid Build Coastguard Worker * @file
26*61046927SAndroid Build Coastguard Worker *
27*61046927SAndroid Build Coastguard Worker * Implements wrappers of libc functions to fake having a DRM device that
28*61046927SAndroid Build Coastguard Worker * isn't actually present in the kernel.
29*61046927SAndroid Build Coastguard Worker */
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Worker /* Prevent glibc from defining open64 when we want to alias it. */
32*61046927SAndroid Build Coastguard Worker #undef _FILE_OFFSET_BITS
33*61046927SAndroid Build Coastguard Worker #undef _TIME_BITS
34*61046927SAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE
35*61046927SAndroid Build Coastguard Worker
36*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
37*61046927SAndroid Build Coastguard Worker #include <stdio.h>
38*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
39*61046927SAndroid Build Coastguard Worker #include <string.h>
40*61046927SAndroid Build Coastguard Worker #include <unistd.h>
41*61046927SAndroid Build Coastguard Worker #include <sys/ioctl.h>
42*61046927SAndroid Build Coastguard Worker #include <sys/mman.h>
43*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
44*61046927SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
45*61046927SAndroid Build Coastguard Worker #include <stdarg.h>
46*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
47*61046927SAndroid Build Coastguard Worker #include <dlfcn.h>
48*61046927SAndroid Build Coastguard Worker #include <dirent.h>
49*61046927SAndroid Build Coastguard Worker #include <c11/threads.h>
50*61046927SAndroid Build Coastguard Worker #include <drm-uapi/drm.h>
51*61046927SAndroid Build Coastguard Worker
52*61046927SAndroid Build Coastguard Worker #include "util/anon_file.h"
53*61046927SAndroid Build Coastguard Worker #include "util/set.h"
54*61046927SAndroid Build Coastguard Worker #include "util/simple_mtx.h"
55*61046927SAndroid Build Coastguard Worker #include "util/u_debug.h"
56*61046927SAndroid Build Coastguard Worker #include "drm_shim.h"
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Worker #define REAL_FUNCTION_POINTER(x) __typeof__(x) *real_##x
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Worker static simple_mtx_t shim_lock = SIMPLE_MTX_INITIALIZER;
61*61046927SAndroid Build Coastguard Worker struct set *opendir_set;
62*61046927SAndroid Build Coastguard Worker bool drm_shim_debug;
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker /* If /dev/dri doesn't exist, we'll need an arbitrary pointer that wouldn't be
65*61046927SAndroid Build Coastguard Worker * returned by any other opendir() call so we can return just our fake node.
66*61046927SAndroid Build Coastguard Worker */
67*61046927SAndroid Build Coastguard Worker DIR *fake_dev_dri = (void *)&opendir_set;
68*61046927SAndroid Build Coastguard Worker
69*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(access);
70*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(close);
71*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(closedir);
72*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(dup);
73*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(fcntl);
74*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(fopen);
75*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(ioctl);
76*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(mmap);
77*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(mmap64);
78*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(open);
79*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(opendir);
80*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(readdir);
81*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(readdir64);
82*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(readlink);
83*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(realpath);
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker #define HAS_XSTAT __GLIBC__ == 2 && __GLIBC_MINOR__ < 33
86*61046927SAndroid Build Coastguard Worker
87*61046927SAndroid Build Coastguard Worker #if HAS_XSTAT
88*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(__xstat);
89*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(__xstat64);
90*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(__fxstat);
91*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(__fxstat64);
92*61046927SAndroid Build Coastguard Worker #else
93*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(stat);
94*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(stat64);
95*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(fstat);
96*61046927SAndroid Build Coastguard Worker REAL_FUNCTION_POINTER(fstat64);
97*61046927SAndroid Build Coastguard Worker #endif
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker static char render_node_dir[] = "/dev/dri/";
100*61046927SAndroid Build Coastguard Worker /* Full path of /dev/dri/renderD* */
101*61046927SAndroid Build Coastguard Worker static char *render_node_path;
102*61046927SAndroid Build Coastguard Worker /* renderD* */
103*61046927SAndroid Build Coastguard Worker static char *render_node_dirent_name;
104*61046927SAndroid Build Coastguard Worker /* /sys/dev/char/major: */
105*61046927SAndroid Build Coastguard Worker static int drm_device_path_len;
106*61046927SAndroid Build Coastguard Worker static char *drm_device_path;
107*61046927SAndroid Build Coastguard Worker /* /sys/dev/char/major:minor/device */
108*61046927SAndroid Build Coastguard Worker static int device_path_len;
109*61046927SAndroid Build Coastguard Worker static char *device_path;
110*61046927SAndroid Build Coastguard Worker /* /sys/dev/char/major:minor/device/subsystem */
111*61046927SAndroid Build Coastguard Worker static char *subsystem_path;
112*61046927SAndroid Build Coastguard Worker int render_node_minor = -1;
113*61046927SAndroid Build Coastguard Worker
114*61046927SAndroid Build Coastguard Worker struct file_override {
115*61046927SAndroid Build Coastguard Worker const char *path;
116*61046927SAndroid Build Coastguard Worker char *contents;
117*61046927SAndroid Build Coastguard Worker };
118*61046927SAndroid Build Coastguard Worker static struct file_override file_overrides[10];
119*61046927SAndroid Build Coastguard Worker static int file_overrides_count;
120*61046927SAndroid Build Coastguard Worker extern bool drm_shim_driver_prefers_first_render_node;
121*61046927SAndroid Build Coastguard Worker
122*61046927SAndroid Build Coastguard Worker static int
nfvasprintf(char ** restrict strp,const char * restrict fmt,va_list ap)123*61046927SAndroid Build Coastguard Worker nfvasprintf(char **restrict strp, const char *restrict fmt, va_list ap)
124*61046927SAndroid Build Coastguard Worker {
125*61046927SAndroid Build Coastguard Worker int ret = vasprintf(strp, fmt, ap);
126*61046927SAndroid Build Coastguard Worker assert(ret >= 0);
127*61046927SAndroid Build Coastguard Worker return ret;
128*61046927SAndroid Build Coastguard Worker }
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker static int
nfasprintf(char ** restrict strp,const char * restrict fmt,...)131*61046927SAndroid Build Coastguard Worker nfasprintf(char **restrict strp, const char *restrict fmt, ...)
132*61046927SAndroid Build Coastguard Worker {
133*61046927SAndroid Build Coastguard Worker va_list ap;
134*61046927SAndroid Build Coastguard Worker va_start(ap, fmt);
135*61046927SAndroid Build Coastguard Worker int ret = nfvasprintf(strp, fmt, ap);
136*61046927SAndroid Build Coastguard Worker va_end(ap);
137*61046927SAndroid Build Coastguard Worker return ret;
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker
140*61046927SAndroid Build Coastguard Worker /* Pick the minor and filename for our shimmed render node. This can be
141*61046927SAndroid Build Coastguard Worker * either a new one that didn't exist on the system, or if the driver wants,
142*61046927SAndroid Build Coastguard Worker * it can replace the first render node.
143*61046927SAndroid Build Coastguard Worker */
144*61046927SAndroid Build Coastguard Worker static void
get_dri_render_node_minor(void)145*61046927SAndroid Build Coastguard Worker get_dri_render_node_minor(void)
146*61046927SAndroid Build Coastguard Worker {
147*61046927SAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) {
148*61046927SAndroid Build Coastguard Worker UNUSED int minor = 128 + i;
149*61046927SAndroid Build Coastguard Worker nfasprintf(&render_node_dirent_name, "renderD%d", minor);
150*61046927SAndroid Build Coastguard Worker nfasprintf(&render_node_path, "/dev/dri/%s",
151*61046927SAndroid Build Coastguard Worker render_node_dirent_name);
152*61046927SAndroid Build Coastguard Worker struct stat st;
153*61046927SAndroid Build Coastguard Worker if (drm_shim_driver_prefers_first_render_node ||
154*61046927SAndroid Build Coastguard Worker stat(render_node_path, &st) == -1) {
155*61046927SAndroid Build Coastguard Worker
156*61046927SAndroid Build Coastguard Worker render_node_minor = minor;
157*61046927SAndroid Build Coastguard Worker return;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker }
160*61046927SAndroid Build Coastguard Worker
161*61046927SAndroid Build Coastguard Worker fprintf(stderr, "Couldn't find a spare render node slot\n");
162*61046927SAndroid Build Coastguard Worker }
163*61046927SAndroid Build Coastguard Worker
get_function_pointer(const char * name)164*61046927SAndroid Build Coastguard Worker static void *get_function_pointer(const char *name)
165*61046927SAndroid Build Coastguard Worker {
166*61046927SAndroid Build Coastguard Worker void *func = dlsym(RTLD_NEXT, name);
167*61046927SAndroid Build Coastguard Worker if (!func) {
168*61046927SAndroid Build Coastguard Worker fprintf(stderr, "Failed to resolve %s\n", name);
169*61046927SAndroid Build Coastguard Worker abort();
170*61046927SAndroid Build Coastguard Worker }
171*61046927SAndroid Build Coastguard Worker return func;
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker #define GET_FUNCTION_POINTER(x) real_##x = get_function_pointer(#x)
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker void
drm_shim_override_file(const char * contents,const char * path_format,...)177*61046927SAndroid Build Coastguard Worker drm_shim_override_file(const char *contents, const char *path_format, ...)
178*61046927SAndroid Build Coastguard Worker {
179*61046927SAndroid Build Coastguard Worker assert(file_overrides_count < ARRAY_SIZE(file_overrides));
180*61046927SAndroid Build Coastguard Worker
181*61046927SAndroid Build Coastguard Worker char *path;
182*61046927SAndroid Build Coastguard Worker va_list ap;
183*61046927SAndroid Build Coastguard Worker va_start(ap, path_format);
184*61046927SAndroid Build Coastguard Worker nfvasprintf(&path, path_format, ap);
185*61046927SAndroid Build Coastguard Worker va_end(ap);
186*61046927SAndroid Build Coastguard Worker
187*61046927SAndroid Build Coastguard Worker struct file_override *override = &file_overrides[file_overrides_count++];
188*61046927SAndroid Build Coastguard Worker override->path = path;
189*61046927SAndroid Build Coastguard Worker override->contents = strdup(contents);
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker
192*61046927SAndroid Build Coastguard Worker static void
destroy_shim(void)193*61046927SAndroid Build Coastguard Worker destroy_shim(void)
194*61046927SAndroid Build Coastguard Worker {
195*61046927SAndroid Build Coastguard Worker _mesa_set_destroy(opendir_set, NULL);
196*61046927SAndroid Build Coastguard Worker free(render_node_path);
197*61046927SAndroid Build Coastguard Worker free(render_node_dirent_name);
198*61046927SAndroid Build Coastguard Worker free(subsystem_path);
199*61046927SAndroid Build Coastguard Worker }
200*61046927SAndroid Build Coastguard Worker
201*61046927SAndroid Build Coastguard Worker /* Initialization, which will be called from the first general library call
202*61046927SAndroid Build Coastguard Worker * that might need to be wrapped with the shim.
203*61046927SAndroid Build Coastguard Worker */
204*61046927SAndroid Build Coastguard Worker static void
init_shim(void)205*61046927SAndroid Build Coastguard Worker init_shim(void)
206*61046927SAndroid Build Coastguard Worker {
207*61046927SAndroid Build Coastguard Worker static bool inited = false;
208*61046927SAndroid Build Coastguard Worker drm_shim_debug = debug_get_bool_option("DRM_SHIM_DEBUG", false);
209*61046927SAndroid Build Coastguard Worker
210*61046927SAndroid Build Coastguard Worker /* We can't lock this, because we recurse during initialization. */
211*61046927SAndroid Build Coastguard Worker if (inited)
212*61046927SAndroid Build Coastguard Worker return;
213*61046927SAndroid Build Coastguard Worker
214*61046927SAndroid Build Coastguard Worker /* This comes first (and we're locked), to make sure we don't recurse
215*61046927SAndroid Build Coastguard Worker * during initialization.
216*61046927SAndroid Build Coastguard Worker */
217*61046927SAndroid Build Coastguard Worker inited = true;
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker opendir_set = _mesa_set_create(NULL,
220*61046927SAndroid Build Coastguard Worker _mesa_hash_string,
221*61046927SAndroid Build Coastguard Worker _mesa_key_string_equal);
222*61046927SAndroid Build Coastguard Worker
223*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(access);
224*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(close);
225*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(closedir);
226*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(dup);
227*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(fcntl);
228*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(fopen);
229*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(ioctl);
230*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(mmap);
231*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(mmap64);
232*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(open);
233*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(opendir);
234*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(readdir);
235*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(readdir64);
236*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(readlink);
237*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(realpath);
238*61046927SAndroid Build Coastguard Worker
239*61046927SAndroid Build Coastguard Worker #if HAS_XSTAT
240*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(__xstat);
241*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(__xstat64);
242*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(__fxstat);
243*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(__fxstat64);
244*61046927SAndroid Build Coastguard Worker #else
245*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(stat);
246*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(stat64);
247*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(fstat);
248*61046927SAndroid Build Coastguard Worker GET_FUNCTION_POINTER(fstat64);
249*61046927SAndroid Build Coastguard Worker #endif
250*61046927SAndroid Build Coastguard Worker
251*61046927SAndroid Build Coastguard Worker get_dri_render_node_minor();
252*61046927SAndroid Build Coastguard Worker
253*61046927SAndroid Build Coastguard Worker if (drm_shim_debug) {
254*61046927SAndroid Build Coastguard Worker fprintf(stderr, "Initializing DRM shim on %s\n",
255*61046927SAndroid Build Coastguard Worker render_node_path);
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker drm_device_path_len =
259*61046927SAndroid Build Coastguard Worker nfasprintf(&drm_device_path, "/sys/dev/char/%d:", DRM_MAJOR);
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker device_path_len =
262*61046927SAndroid Build Coastguard Worker nfasprintf(&device_path,
263*61046927SAndroid Build Coastguard Worker "/sys/dev/char/%d:%d/device",
264*61046927SAndroid Build Coastguard Worker DRM_MAJOR, render_node_minor);
265*61046927SAndroid Build Coastguard Worker
266*61046927SAndroid Build Coastguard Worker nfasprintf(&subsystem_path,
267*61046927SAndroid Build Coastguard Worker "/sys/dev/char/%d:%d/device/subsystem",
268*61046927SAndroid Build Coastguard Worker DRM_MAJOR, render_node_minor);
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker drm_shim_device_init();
271*61046927SAndroid Build Coastguard Worker
272*61046927SAndroid Build Coastguard Worker atexit(destroy_shim);
273*61046927SAndroid Build Coastguard Worker }
274*61046927SAndroid Build Coastguard Worker
hide_drm_device_path(const char * path)275*61046927SAndroid Build Coastguard Worker static bool hide_drm_device_path(const char *path)
276*61046927SAndroid Build Coastguard Worker {
277*61046927SAndroid Build Coastguard Worker if (render_node_minor == -1)
278*61046927SAndroid Build Coastguard Worker return false;
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker /* If the path looks like our fake render node device, then don't hide it.
281*61046927SAndroid Build Coastguard Worker */
282*61046927SAndroid Build Coastguard Worker if (strncmp(path, device_path, device_path_len) == 0 ||
283*61046927SAndroid Build Coastguard Worker strcmp(path, render_node_path) == 0)
284*61046927SAndroid Build Coastguard Worker return false;
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker /* String starts with /sys/dev/char/226: but is not the fake render node.
287*61046927SAndroid Build Coastguard Worker * We want to hide all other drm devices for the shim.
288*61046927SAndroid Build Coastguard Worker */
289*61046927SAndroid Build Coastguard Worker if (strncmp(path, drm_device_path, drm_device_path_len) == 0)
290*61046927SAndroid Build Coastguard Worker return true;
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker /* String starts with /dev/dri/ but is not the fake render node. We want to
293*61046927SAndroid Build Coastguard Worker * hide all other drm devices for the shim.
294*61046927SAndroid Build Coastguard Worker */
295*61046927SAndroid Build Coastguard Worker if (strncmp(path, render_node_dir, sizeof(render_node_dir) - 1) == 0)
296*61046927SAndroid Build Coastguard Worker return true;
297*61046927SAndroid Build Coastguard Worker
298*61046927SAndroid Build Coastguard Worker return false;
299*61046927SAndroid Build Coastguard Worker }
300*61046927SAndroid Build Coastguard Worker
file_override_open(const char * path)301*61046927SAndroid Build Coastguard Worker static int file_override_open(const char *path)
302*61046927SAndroid Build Coastguard Worker {
303*61046927SAndroid Build Coastguard Worker for (int i = 0; i < file_overrides_count; i++) {
304*61046927SAndroid Build Coastguard Worker if (strcmp(file_overrides[i].path, path) == 0) {
305*61046927SAndroid Build Coastguard Worker int fd = os_create_anonymous_file(0, "shim file");
306*61046927SAndroid Build Coastguard Worker write(fd, file_overrides[i].contents,
307*61046927SAndroid Build Coastguard Worker strlen(file_overrides[i].contents));
308*61046927SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_SET);
309*61046927SAndroid Build Coastguard Worker return fd;
310*61046927SAndroid Build Coastguard Worker }
311*61046927SAndroid Build Coastguard Worker }
312*61046927SAndroid Build Coastguard Worker
313*61046927SAndroid Build Coastguard Worker return -1;
314*61046927SAndroid Build Coastguard Worker }
315*61046927SAndroid Build Coastguard Worker
316*61046927SAndroid Build Coastguard Worker /* Override libdrm's reading of various sysfs files for device enumeration. */
fopen(const char * path,const char * mode)317*61046927SAndroid Build Coastguard Worker PUBLIC FILE *fopen(const char *path, const char *mode)
318*61046927SAndroid Build Coastguard Worker {
319*61046927SAndroid Build Coastguard Worker init_shim();
320*61046927SAndroid Build Coastguard Worker
321*61046927SAndroid Build Coastguard Worker int fd = file_override_open(path);
322*61046927SAndroid Build Coastguard Worker if (fd >= 0)
323*61046927SAndroid Build Coastguard Worker return fdopen(fd, "r");
324*61046927SAndroid Build Coastguard Worker
325*61046927SAndroid Build Coastguard Worker return real_fopen(path, mode);
326*61046927SAndroid Build Coastguard Worker }
327*61046927SAndroid Build Coastguard Worker PUBLIC FILE *fopen64(const char *path, const char *mode)
328*61046927SAndroid Build Coastguard Worker __attribute__((alias("fopen")));
329*61046927SAndroid Build Coastguard Worker
330*61046927SAndroid Build Coastguard Worker /* Intercepts access(render_node_path) to trick drmGetMinorType */
access(const char * path,int mode)331*61046927SAndroid Build Coastguard Worker PUBLIC int access(const char *path, int mode)
332*61046927SAndroid Build Coastguard Worker {
333*61046927SAndroid Build Coastguard Worker init_shim();
334*61046927SAndroid Build Coastguard Worker
335*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
336*61046927SAndroid Build Coastguard Worker errno = ENOENT;
337*61046927SAndroid Build Coastguard Worker return -1;
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker if (strcmp(path, render_node_path) != 0)
341*61046927SAndroid Build Coastguard Worker return real_access(path, mode);
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker return 0;
344*61046927SAndroid Build Coastguard Worker }
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker /* Intercepts open(render_node_path) to redirect it to the simulator. */
open(const char * path,int flags,...)347*61046927SAndroid Build Coastguard Worker PUBLIC int open(const char *path, int flags, ...)
348*61046927SAndroid Build Coastguard Worker {
349*61046927SAndroid Build Coastguard Worker init_shim();
350*61046927SAndroid Build Coastguard Worker
351*61046927SAndroid Build Coastguard Worker va_list ap;
352*61046927SAndroid Build Coastguard Worker va_start(ap, flags);
353*61046927SAndroid Build Coastguard Worker mode_t mode = va_arg(ap, mode_t);
354*61046927SAndroid Build Coastguard Worker va_end(ap);
355*61046927SAndroid Build Coastguard Worker
356*61046927SAndroid Build Coastguard Worker int fd = file_override_open(path);
357*61046927SAndroid Build Coastguard Worker if (fd >= 0)
358*61046927SAndroid Build Coastguard Worker return fd;
359*61046927SAndroid Build Coastguard Worker
360*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
361*61046927SAndroid Build Coastguard Worker errno = ENOENT;
362*61046927SAndroid Build Coastguard Worker return -1;
363*61046927SAndroid Build Coastguard Worker }
364*61046927SAndroid Build Coastguard Worker
365*61046927SAndroid Build Coastguard Worker if (strcmp(path, render_node_path) != 0)
366*61046927SAndroid Build Coastguard Worker return real_open(path, flags, mode);
367*61046927SAndroid Build Coastguard Worker
368*61046927SAndroid Build Coastguard Worker fd = real_open("/dev/null", O_RDWR, 0);
369*61046927SAndroid Build Coastguard Worker
370*61046927SAndroid Build Coastguard Worker drm_shim_fd_register(fd, NULL);
371*61046927SAndroid Build Coastguard Worker
372*61046927SAndroid Build Coastguard Worker return fd;
373*61046927SAndroid Build Coastguard Worker }
374*61046927SAndroid Build Coastguard Worker PUBLIC int open64(const char*, int, ...) __attribute__((alias("open")));
375*61046927SAndroid Build Coastguard Worker
376*61046927SAndroid Build Coastguard Worker /* __open64_2 isn't declared unless _FORTIFY_SOURCE is defined. */
377*61046927SAndroid Build Coastguard Worker PUBLIC int __open64_2(const char *path, int flags);
__open64_2(const char * path,int flags)378*61046927SAndroid Build Coastguard Worker PUBLIC int __open64_2(const char *path, int flags)
379*61046927SAndroid Build Coastguard Worker {
380*61046927SAndroid Build Coastguard Worker return open(path, flags, 0);
381*61046927SAndroid Build Coastguard Worker }
382*61046927SAndroid Build Coastguard Worker
close(int fd)383*61046927SAndroid Build Coastguard Worker PUBLIC int close(int fd)
384*61046927SAndroid Build Coastguard Worker {
385*61046927SAndroid Build Coastguard Worker init_shim();
386*61046927SAndroid Build Coastguard Worker
387*61046927SAndroid Build Coastguard Worker drm_shim_fd_unregister(fd);
388*61046927SAndroid Build Coastguard Worker
389*61046927SAndroid Build Coastguard Worker return real_close(fd);
390*61046927SAndroid Build Coastguard Worker }
391*61046927SAndroid Build Coastguard Worker
392*61046927SAndroid Build Coastguard Worker #if HAS_XSTAT
393*61046927SAndroid Build Coastguard Worker /* Fakes stat to return character device stuff for our fake render node. */
__xstat(int ver,const char * path,struct stat * st)394*61046927SAndroid Build Coastguard Worker PUBLIC int __xstat(int ver, const char *path, struct stat *st)
395*61046927SAndroid Build Coastguard Worker {
396*61046927SAndroid Build Coastguard Worker init_shim();
397*61046927SAndroid Build Coastguard Worker
398*61046927SAndroid Build Coastguard Worker /* Note: call real stat if we're in the process of probing for a free
399*61046927SAndroid Build Coastguard Worker * render node!
400*61046927SAndroid Build Coastguard Worker */
401*61046927SAndroid Build Coastguard Worker if (render_node_minor == -1)
402*61046927SAndroid Build Coastguard Worker return real___xstat(ver, path, st);
403*61046927SAndroid Build Coastguard Worker
404*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
405*61046927SAndroid Build Coastguard Worker errno = ENOENT;
406*61046927SAndroid Build Coastguard Worker return -1;
407*61046927SAndroid Build Coastguard Worker }
408*61046927SAndroid Build Coastguard Worker
409*61046927SAndroid Build Coastguard Worker /* Fool libdrm's probe of whether the /sys dir for this char dev is
410*61046927SAndroid Build Coastguard Worker * there.
411*61046927SAndroid Build Coastguard Worker */
412*61046927SAndroid Build Coastguard Worker char *sys_dev_drm_dir;
413*61046927SAndroid Build Coastguard Worker nfasprintf(&sys_dev_drm_dir,
414*61046927SAndroid Build Coastguard Worker "/sys/dev/char/%d:%d/device/drm",
415*61046927SAndroid Build Coastguard Worker DRM_MAJOR, render_node_minor);
416*61046927SAndroid Build Coastguard Worker if (strcmp(path, sys_dev_drm_dir) == 0) {
417*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
418*61046927SAndroid Build Coastguard Worker return 0;
419*61046927SAndroid Build Coastguard Worker }
420*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
421*61046927SAndroid Build Coastguard Worker
422*61046927SAndroid Build Coastguard Worker if (strcmp(path, render_node_path) != 0)
423*61046927SAndroid Build Coastguard Worker return real___xstat(ver, path, st);
424*61046927SAndroid Build Coastguard Worker
425*61046927SAndroid Build Coastguard Worker memset(st, 0, sizeof(*st));
426*61046927SAndroid Build Coastguard Worker st->st_rdev = makedev(DRM_MAJOR, render_node_minor);
427*61046927SAndroid Build Coastguard Worker st->st_mode = S_IFCHR;
428*61046927SAndroid Build Coastguard Worker
429*61046927SAndroid Build Coastguard Worker return 0;
430*61046927SAndroid Build Coastguard Worker }
431*61046927SAndroid Build Coastguard Worker
432*61046927SAndroid Build Coastguard Worker /* Fakes stat to return character device stuff for our fake render node. */
__xstat64(int ver,const char * path,struct stat64 * st)433*61046927SAndroid Build Coastguard Worker PUBLIC int __xstat64(int ver, const char *path, struct stat64 *st)
434*61046927SAndroid Build Coastguard Worker {
435*61046927SAndroid Build Coastguard Worker init_shim();
436*61046927SAndroid Build Coastguard Worker
437*61046927SAndroid Build Coastguard Worker /* Note: call real stat if we're in the process of probing for a free
438*61046927SAndroid Build Coastguard Worker * render node!
439*61046927SAndroid Build Coastguard Worker */
440*61046927SAndroid Build Coastguard Worker if (render_node_minor == -1)
441*61046927SAndroid Build Coastguard Worker return real___xstat64(ver, path, st);
442*61046927SAndroid Build Coastguard Worker
443*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
444*61046927SAndroid Build Coastguard Worker errno = ENOENT;
445*61046927SAndroid Build Coastguard Worker return -1;
446*61046927SAndroid Build Coastguard Worker }
447*61046927SAndroid Build Coastguard Worker
448*61046927SAndroid Build Coastguard Worker /* Fool libdrm's probe of whether the /sys dir for this char dev is
449*61046927SAndroid Build Coastguard Worker * there.
450*61046927SAndroid Build Coastguard Worker */
451*61046927SAndroid Build Coastguard Worker char *sys_dev_drm_dir;
452*61046927SAndroid Build Coastguard Worker nfasprintf(&sys_dev_drm_dir,
453*61046927SAndroid Build Coastguard Worker "/sys/dev/char/%d:%d/device/drm",
454*61046927SAndroid Build Coastguard Worker DRM_MAJOR, render_node_minor);
455*61046927SAndroid Build Coastguard Worker if (strcmp(path, sys_dev_drm_dir) == 0) {
456*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
457*61046927SAndroid Build Coastguard Worker return 0;
458*61046927SAndroid Build Coastguard Worker }
459*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
460*61046927SAndroid Build Coastguard Worker
461*61046927SAndroid Build Coastguard Worker if (strcmp(path, render_node_path) != 0)
462*61046927SAndroid Build Coastguard Worker return real___xstat64(ver, path, st);
463*61046927SAndroid Build Coastguard Worker
464*61046927SAndroid Build Coastguard Worker memset(st, 0, sizeof(*st));
465*61046927SAndroid Build Coastguard Worker st->st_rdev = makedev(DRM_MAJOR, render_node_minor);
466*61046927SAndroid Build Coastguard Worker st->st_mode = S_IFCHR;
467*61046927SAndroid Build Coastguard Worker
468*61046927SAndroid Build Coastguard Worker return 0;
469*61046927SAndroid Build Coastguard Worker }
470*61046927SAndroid Build Coastguard Worker
471*61046927SAndroid Build Coastguard Worker /* Fakes fstat to return character device stuff for our fake render node. */
__fxstat(int ver,int fd,struct stat * st)472*61046927SAndroid Build Coastguard Worker PUBLIC int __fxstat(int ver, int fd, struct stat *st)
473*61046927SAndroid Build Coastguard Worker {
474*61046927SAndroid Build Coastguard Worker init_shim();
475*61046927SAndroid Build Coastguard Worker
476*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
477*61046927SAndroid Build Coastguard Worker
478*61046927SAndroid Build Coastguard Worker if (!shim_fd)
479*61046927SAndroid Build Coastguard Worker return real___fxstat(ver, fd, st);
480*61046927SAndroid Build Coastguard Worker
481*61046927SAndroid Build Coastguard Worker memset(st, 0, sizeof(*st));
482*61046927SAndroid Build Coastguard Worker st->st_rdev = makedev(DRM_MAJOR, render_node_minor);
483*61046927SAndroid Build Coastguard Worker st->st_mode = S_IFCHR;
484*61046927SAndroid Build Coastguard Worker
485*61046927SAndroid Build Coastguard Worker return 0;
486*61046927SAndroid Build Coastguard Worker }
487*61046927SAndroid Build Coastguard Worker
__fxstat64(int ver,int fd,struct stat64 * st)488*61046927SAndroid Build Coastguard Worker PUBLIC int __fxstat64(int ver, int fd, struct stat64 *st)
489*61046927SAndroid Build Coastguard Worker {
490*61046927SAndroid Build Coastguard Worker init_shim();
491*61046927SAndroid Build Coastguard Worker
492*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
493*61046927SAndroid Build Coastguard Worker
494*61046927SAndroid Build Coastguard Worker if (!shim_fd)
495*61046927SAndroid Build Coastguard Worker return real___fxstat64(ver, fd, st);
496*61046927SAndroid Build Coastguard Worker
497*61046927SAndroid Build Coastguard Worker memset(st, 0, sizeof(*st));
498*61046927SAndroid Build Coastguard Worker st->st_rdev = makedev(DRM_MAJOR, render_node_minor);
499*61046927SAndroid Build Coastguard Worker st->st_mode = S_IFCHR;
500*61046927SAndroid Build Coastguard Worker
501*61046927SAndroid Build Coastguard Worker return 0;
502*61046927SAndroid Build Coastguard Worker }
503*61046927SAndroid Build Coastguard Worker
504*61046927SAndroid Build Coastguard Worker #else
505*61046927SAndroid Build Coastguard Worker
stat(const char * path,struct stat * stat_buf)506*61046927SAndroid Build Coastguard Worker PUBLIC int stat(const char* path, struct stat* stat_buf)
507*61046927SAndroid Build Coastguard Worker {
508*61046927SAndroid Build Coastguard Worker init_shim();
509*61046927SAndroid Build Coastguard Worker
510*61046927SAndroid Build Coastguard Worker /* Note: call real stat if we're in the process of probing for a free
511*61046927SAndroid Build Coastguard Worker * render node!
512*61046927SAndroid Build Coastguard Worker */
513*61046927SAndroid Build Coastguard Worker if (render_node_minor == -1)
514*61046927SAndroid Build Coastguard Worker return real_stat(path, stat_buf);
515*61046927SAndroid Build Coastguard Worker
516*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
517*61046927SAndroid Build Coastguard Worker errno = ENOENT;
518*61046927SAndroid Build Coastguard Worker return -1;
519*61046927SAndroid Build Coastguard Worker }
520*61046927SAndroid Build Coastguard Worker
521*61046927SAndroid Build Coastguard Worker /* Fool libdrm's probe of whether the /sys dir for this char dev is
522*61046927SAndroid Build Coastguard Worker * there.
523*61046927SAndroid Build Coastguard Worker */
524*61046927SAndroid Build Coastguard Worker char *sys_dev_drm_dir;
525*61046927SAndroid Build Coastguard Worker nfasprintf(&sys_dev_drm_dir,
526*61046927SAndroid Build Coastguard Worker "/sys/dev/char/%d:%d/device/drm",
527*61046927SAndroid Build Coastguard Worker DRM_MAJOR, render_node_minor);
528*61046927SAndroid Build Coastguard Worker if (strcmp(path, sys_dev_drm_dir) == 0) {
529*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
530*61046927SAndroid Build Coastguard Worker return 0;
531*61046927SAndroid Build Coastguard Worker }
532*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
533*61046927SAndroid Build Coastguard Worker
534*61046927SAndroid Build Coastguard Worker if (strcmp(path, render_node_path) != 0)
535*61046927SAndroid Build Coastguard Worker return real_stat(path, stat_buf);
536*61046927SAndroid Build Coastguard Worker
537*61046927SAndroid Build Coastguard Worker memset(stat_buf, 0, sizeof(*stat_buf));
538*61046927SAndroid Build Coastguard Worker stat_buf->st_rdev = makedev(DRM_MAJOR, render_node_minor);
539*61046927SAndroid Build Coastguard Worker stat_buf->st_mode = S_IFCHR;
540*61046927SAndroid Build Coastguard Worker
541*61046927SAndroid Build Coastguard Worker return 0;
542*61046927SAndroid Build Coastguard Worker }
543*61046927SAndroid Build Coastguard Worker
stat64(const char * path,struct stat64 * stat_buf)544*61046927SAndroid Build Coastguard Worker PUBLIC int stat64(const char* path, struct stat64* stat_buf)
545*61046927SAndroid Build Coastguard Worker {
546*61046927SAndroid Build Coastguard Worker init_shim();
547*61046927SAndroid Build Coastguard Worker
548*61046927SAndroid Build Coastguard Worker /* Note: call real stat if we're in the process of probing for a free
549*61046927SAndroid Build Coastguard Worker * render node!
550*61046927SAndroid Build Coastguard Worker */
551*61046927SAndroid Build Coastguard Worker if (render_node_minor == -1)
552*61046927SAndroid Build Coastguard Worker return real_stat64(path, stat_buf);
553*61046927SAndroid Build Coastguard Worker
554*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
555*61046927SAndroid Build Coastguard Worker errno = ENOENT;
556*61046927SAndroid Build Coastguard Worker return -1;
557*61046927SAndroid Build Coastguard Worker }
558*61046927SAndroid Build Coastguard Worker
559*61046927SAndroid Build Coastguard Worker /* Fool libdrm's probe of whether the /sys dir for this char dev is
560*61046927SAndroid Build Coastguard Worker * there.
561*61046927SAndroid Build Coastguard Worker */
562*61046927SAndroid Build Coastguard Worker char *sys_dev_drm_dir;
563*61046927SAndroid Build Coastguard Worker nfasprintf(&sys_dev_drm_dir,
564*61046927SAndroid Build Coastguard Worker "/sys/dev/char/%d:%d/device/drm",
565*61046927SAndroid Build Coastguard Worker DRM_MAJOR, render_node_minor);
566*61046927SAndroid Build Coastguard Worker if (strcmp(path, sys_dev_drm_dir) == 0) {
567*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
568*61046927SAndroid Build Coastguard Worker return 0;
569*61046927SAndroid Build Coastguard Worker }
570*61046927SAndroid Build Coastguard Worker free(sys_dev_drm_dir);
571*61046927SAndroid Build Coastguard Worker
572*61046927SAndroid Build Coastguard Worker if (strcmp(path, render_node_path) != 0)
573*61046927SAndroid Build Coastguard Worker return real_stat64(path, stat_buf);
574*61046927SAndroid Build Coastguard Worker
575*61046927SAndroid Build Coastguard Worker memset(stat_buf, 0, sizeof(*stat_buf));
576*61046927SAndroid Build Coastguard Worker stat_buf->st_rdev = makedev(DRM_MAJOR, render_node_minor);
577*61046927SAndroid Build Coastguard Worker stat_buf->st_mode = S_IFCHR;
578*61046927SAndroid Build Coastguard Worker
579*61046927SAndroid Build Coastguard Worker return 0;
580*61046927SAndroid Build Coastguard Worker }
581*61046927SAndroid Build Coastguard Worker
fstat(int fd,struct stat * stat_buf)582*61046927SAndroid Build Coastguard Worker PUBLIC int fstat(int fd, struct stat* stat_buf)
583*61046927SAndroid Build Coastguard Worker {
584*61046927SAndroid Build Coastguard Worker init_shim();
585*61046927SAndroid Build Coastguard Worker
586*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
587*61046927SAndroid Build Coastguard Worker
588*61046927SAndroid Build Coastguard Worker if (!shim_fd)
589*61046927SAndroid Build Coastguard Worker return real_fstat(fd, stat_buf);
590*61046927SAndroid Build Coastguard Worker
591*61046927SAndroid Build Coastguard Worker memset(stat_buf, 0, sizeof(*stat_buf));
592*61046927SAndroid Build Coastguard Worker stat_buf->st_rdev = makedev(DRM_MAJOR, render_node_minor);
593*61046927SAndroid Build Coastguard Worker stat_buf->st_mode = S_IFCHR;
594*61046927SAndroid Build Coastguard Worker
595*61046927SAndroid Build Coastguard Worker return 0;
596*61046927SAndroid Build Coastguard Worker }
597*61046927SAndroid Build Coastguard Worker
fstat64(int fd,struct stat64 * stat_buf)598*61046927SAndroid Build Coastguard Worker PUBLIC int fstat64(int fd, struct stat64* stat_buf)
599*61046927SAndroid Build Coastguard Worker {
600*61046927SAndroid Build Coastguard Worker init_shim();
601*61046927SAndroid Build Coastguard Worker
602*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
603*61046927SAndroid Build Coastguard Worker
604*61046927SAndroid Build Coastguard Worker if (!shim_fd)
605*61046927SAndroid Build Coastguard Worker return real_fstat64(fd, stat_buf);
606*61046927SAndroid Build Coastguard Worker
607*61046927SAndroid Build Coastguard Worker memset(stat_buf, 0, sizeof(*stat_buf));
608*61046927SAndroid Build Coastguard Worker stat_buf->st_rdev = makedev(DRM_MAJOR, render_node_minor);
609*61046927SAndroid Build Coastguard Worker stat_buf->st_mode = S_IFCHR;
610*61046927SAndroid Build Coastguard Worker
611*61046927SAndroid Build Coastguard Worker return 0;
612*61046927SAndroid Build Coastguard Worker }
613*61046927SAndroid Build Coastguard Worker #endif
614*61046927SAndroid Build Coastguard Worker
615*61046927SAndroid Build Coastguard Worker /* Tracks if the opendir was on /dev/dri. */
616*61046927SAndroid Build Coastguard Worker PUBLIC DIR *
opendir(const char * name)617*61046927SAndroid Build Coastguard Worker opendir(const char *name)
618*61046927SAndroid Build Coastguard Worker {
619*61046927SAndroid Build Coastguard Worker init_shim();
620*61046927SAndroid Build Coastguard Worker
621*61046927SAndroid Build Coastguard Worker DIR *dir = real_opendir(name);
622*61046927SAndroid Build Coastguard Worker if (strcmp(name, "/dev/dri") == 0) {
623*61046927SAndroid Build Coastguard Worker if (!dir) {
624*61046927SAndroid Build Coastguard Worker /* If /dev/dri didn't exist, we still want to be able to return our
625*61046927SAndroid Build Coastguard Worker * fake /dev/dri/render* even though we probably can't
626*61046927SAndroid Build Coastguard Worker * mkdir("/dev/dri"). Return a fake DIR pointer for that.
627*61046927SAndroid Build Coastguard Worker */
628*61046927SAndroid Build Coastguard Worker dir = fake_dev_dri;
629*61046927SAndroid Build Coastguard Worker }
630*61046927SAndroid Build Coastguard Worker
631*61046927SAndroid Build Coastguard Worker simple_mtx_lock(&shim_lock);
632*61046927SAndroid Build Coastguard Worker _mesa_set_add(opendir_set, dir);
633*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&shim_lock);
634*61046927SAndroid Build Coastguard Worker }
635*61046927SAndroid Build Coastguard Worker
636*61046927SAndroid Build Coastguard Worker return dir;
637*61046927SAndroid Build Coastguard Worker }
638*61046927SAndroid Build Coastguard Worker
639*61046927SAndroid Build Coastguard Worker /* If we're looking at /dev/dri, add our render node to the list
640*61046927SAndroid Build Coastguard Worker * before the real entries in the directory.
641*61046927SAndroid Build Coastguard Worker */
642*61046927SAndroid Build Coastguard Worker PUBLIC struct dirent *
readdir(DIR * dir)643*61046927SAndroid Build Coastguard Worker readdir(DIR *dir)
644*61046927SAndroid Build Coastguard Worker {
645*61046927SAndroid Build Coastguard Worker init_shim();
646*61046927SAndroid Build Coastguard Worker
647*61046927SAndroid Build Coastguard Worker struct dirent *ent = NULL;
648*61046927SAndroid Build Coastguard Worker
649*61046927SAndroid Build Coastguard Worker static struct dirent render_node_dirent = { 0 };
650*61046927SAndroid Build Coastguard Worker
651*61046927SAndroid Build Coastguard Worker simple_mtx_lock(&shim_lock);
652*61046927SAndroid Build Coastguard Worker if (_mesa_set_search(opendir_set, dir)) {
653*61046927SAndroid Build Coastguard Worker strcpy(render_node_dirent.d_name,
654*61046927SAndroid Build Coastguard Worker render_node_dirent_name);
655*61046927SAndroid Build Coastguard Worker render_node_dirent.d_type = DT_CHR;
656*61046927SAndroid Build Coastguard Worker ent = &render_node_dirent;
657*61046927SAndroid Build Coastguard Worker _mesa_set_remove_key(opendir_set, dir);
658*61046927SAndroid Build Coastguard Worker }
659*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&shim_lock);
660*61046927SAndroid Build Coastguard Worker
661*61046927SAndroid Build Coastguard Worker if (!ent && dir != fake_dev_dri)
662*61046927SAndroid Build Coastguard Worker ent = real_readdir(dir);
663*61046927SAndroid Build Coastguard Worker
664*61046927SAndroid Build Coastguard Worker return ent;
665*61046927SAndroid Build Coastguard Worker }
666*61046927SAndroid Build Coastguard Worker
667*61046927SAndroid Build Coastguard Worker /* If we're looking at /dev/dri, add our render node to the list
668*61046927SAndroid Build Coastguard Worker * before the real entries in the directory.
669*61046927SAndroid Build Coastguard Worker */
670*61046927SAndroid Build Coastguard Worker PUBLIC struct dirent64 *
readdir64(DIR * dir)671*61046927SAndroid Build Coastguard Worker readdir64(DIR *dir)
672*61046927SAndroid Build Coastguard Worker {
673*61046927SAndroid Build Coastguard Worker init_shim();
674*61046927SAndroid Build Coastguard Worker
675*61046927SAndroid Build Coastguard Worker struct dirent64 *ent = NULL;
676*61046927SAndroid Build Coastguard Worker
677*61046927SAndroid Build Coastguard Worker static struct dirent64 render_node_dirent = { 0 };
678*61046927SAndroid Build Coastguard Worker
679*61046927SAndroid Build Coastguard Worker simple_mtx_lock(&shim_lock);
680*61046927SAndroid Build Coastguard Worker if (_mesa_set_search(opendir_set, dir)) {
681*61046927SAndroid Build Coastguard Worker strcpy(render_node_dirent.d_name,
682*61046927SAndroid Build Coastguard Worker render_node_dirent_name);
683*61046927SAndroid Build Coastguard Worker render_node_dirent.d_type = DT_CHR;
684*61046927SAndroid Build Coastguard Worker ent = &render_node_dirent;
685*61046927SAndroid Build Coastguard Worker _mesa_set_remove_key(opendir_set, dir);
686*61046927SAndroid Build Coastguard Worker }
687*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&shim_lock);
688*61046927SAndroid Build Coastguard Worker
689*61046927SAndroid Build Coastguard Worker if (!ent && dir != fake_dev_dri)
690*61046927SAndroid Build Coastguard Worker ent = real_readdir64(dir);
691*61046927SAndroid Build Coastguard Worker
692*61046927SAndroid Build Coastguard Worker return ent;
693*61046927SAndroid Build Coastguard Worker }
694*61046927SAndroid Build Coastguard Worker
695*61046927SAndroid Build Coastguard Worker /* Cleans up tracking of opendir("/dev/dri") */
696*61046927SAndroid Build Coastguard Worker PUBLIC int
closedir(DIR * dir)697*61046927SAndroid Build Coastguard Worker closedir(DIR *dir)
698*61046927SAndroid Build Coastguard Worker {
699*61046927SAndroid Build Coastguard Worker init_shim();
700*61046927SAndroid Build Coastguard Worker
701*61046927SAndroid Build Coastguard Worker simple_mtx_lock(&shim_lock);
702*61046927SAndroid Build Coastguard Worker _mesa_set_remove_key(opendir_set, dir);
703*61046927SAndroid Build Coastguard Worker simple_mtx_unlock(&shim_lock);
704*61046927SAndroid Build Coastguard Worker
705*61046927SAndroid Build Coastguard Worker if (dir != fake_dev_dri)
706*61046927SAndroid Build Coastguard Worker return real_closedir(dir);
707*61046927SAndroid Build Coastguard Worker else
708*61046927SAndroid Build Coastguard Worker return 0;
709*61046927SAndroid Build Coastguard Worker }
710*61046927SAndroid Build Coastguard Worker
711*61046927SAndroid Build Coastguard Worker /* Handles libdrm's readlink to figure out what kind of device we have. */
712*61046927SAndroid Build Coastguard Worker PUBLIC ssize_t
readlink(const char * path,char * buf,size_t size)713*61046927SAndroid Build Coastguard Worker readlink(const char *path, char *buf, size_t size)
714*61046927SAndroid Build Coastguard Worker {
715*61046927SAndroid Build Coastguard Worker init_shim();
716*61046927SAndroid Build Coastguard Worker
717*61046927SAndroid Build Coastguard Worker if (hide_drm_device_path(path)) {
718*61046927SAndroid Build Coastguard Worker errno = ENOENT;
719*61046927SAndroid Build Coastguard Worker return -1;
720*61046927SAndroid Build Coastguard Worker }
721*61046927SAndroid Build Coastguard Worker
722*61046927SAndroid Build Coastguard Worker if (strcmp(path, subsystem_path) != 0)
723*61046927SAndroid Build Coastguard Worker return real_readlink(path, buf, size);
724*61046927SAndroid Build Coastguard Worker
725*61046927SAndroid Build Coastguard Worker static const struct {
726*61046927SAndroid Build Coastguard Worker const char *name;
727*61046927SAndroid Build Coastguard Worker int bus_type;
728*61046927SAndroid Build Coastguard Worker } bus_types[] = {
729*61046927SAndroid Build Coastguard Worker { "/pci", DRM_BUS_PCI },
730*61046927SAndroid Build Coastguard Worker { "/usb", DRM_BUS_USB },
731*61046927SAndroid Build Coastguard Worker { "/platform", DRM_BUS_PLATFORM },
732*61046927SAndroid Build Coastguard Worker { "/spi", DRM_BUS_PLATFORM },
733*61046927SAndroid Build Coastguard Worker { "/host1x", DRM_BUS_HOST1X },
734*61046927SAndroid Build Coastguard Worker };
735*61046927SAndroid Build Coastguard Worker
736*61046927SAndroid Build Coastguard Worker for (uint32_t i = 0; i < ARRAY_SIZE(bus_types); i++) {
737*61046927SAndroid Build Coastguard Worker if (bus_types[i].bus_type != shim_device.bus_type)
738*61046927SAndroid Build Coastguard Worker continue;
739*61046927SAndroid Build Coastguard Worker
740*61046927SAndroid Build Coastguard Worker strncpy(buf, bus_types[i].name, size);
741*61046927SAndroid Build Coastguard Worker buf[size - 1] = 0;
742*61046927SAndroid Build Coastguard Worker break;
743*61046927SAndroid Build Coastguard Worker }
744*61046927SAndroid Build Coastguard Worker
745*61046927SAndroid Build Coastguard Worker return strlen(buf) + 1;
746*61046927SAndroid Build Coastguard Worker }
747*61046927SAndroid Build Coastguard Worker
748*61046927SAndroid Build Coastguard Worker #if __USE_FORTIFY_LEVEL > 0 && !defined _CLANG_FORTIFY_DISABLE
749*61046927SAndroid Build Coastguard Worker /* Identical to readlink, but with buffer overflow check */
750*61046927SAndroid Build Coastguard Worker PUBLIC ssize_t
__readlink_chk(const char * path,char * buf,size_t size,size_t buflen)751*61046927SAndroid Build Coastguard Worker __readlink_chk(const char *path, char *buf, size_t size, size_t buflen)
752*61046927SAndroid Build Coastguard Worker {
753*61046927SAndroid Build Coastguard Worker if (size > buflen)
754*61046927SAndroid Build Coastguard Worker abort();
755*61046927SAndroid Build Coastguard Worker return readlink(path, buf, size);
756*61046927SAndroid Build Coastguard Worker }
757*61046927SAndroid Build Coastguard Worker #endif
758*61046927SAndroid Build Coastguard Worker
759*61046927SAndroid Build Coastguard Worker /* Handles libdrm's realpath to figure out what kind of device we have. */
760*61046927SAndroid Build Coastguard Worker PUBLIC char *
realpath(const char * path,char * resolved_path)761*61046927SAndroid Build Coastguard Worker realpath(const char *path, char *resolved_path)
762*61046927SAndroid Build Coastguard Worker {
763*61046927SAndroid Build Coastguard Worker init_shim();
764*61046927SAndroid Build Coastguard Worker
765*61046927SAndroid Build Coastguard Worker if (strcmp(path, device_path) != 0)
766*61046927SAndroid Build Coastguard Worker return real_realpath(path, resolved_path);
767*61046927SAndroid Build Coastguard Worker
768*61046927SAndroid Build Coastguard Worker strcpy(resolved_path, path);
769*61046927SAndroid Build Coastguard Worker
770*61046927SAndroid Build Coastguard Worker return resolved_path;
771*61046927SAndroid Build Coastguard Worker }
772*61046927SAndroid Build Coastguard Worker
773*61046927SAndroid Build Coastguard Worker /* Main entrypoint to DRM drivers: the ioctl syscall. We send all ioctls on
774*61046927SAndroid Build Coastguard Worker * our DRM fd to drm_shim_ioctl().
775*61046927SAndroid Build Coastguard Worker */
776*61046927SAndroid Build Coastguard Worker PUBLIC int
ioctl(int fd,unsigned long request,...)777*61046927SAndroid Build Coastguard Worker ioctl(int fd, unsigned long request, ...)
778*61046927SAndroid Build Coastguard Worker {
779*61046927SAndroid Build Coastguard Worker init_shim();
780*61046927SAndroid Build Coastguard Worker
781*61046927SAndroid Build Coastguard Worker va_list ap;
782*61046927SAndroid Build Coastguard Worker va_start(ap, request);
783*61046927SAndroid Build Coastguard Worker void *arg = va_arg(ap, void *);
784*61046927SAndroid Build Coastguard Worker va_end(ap);
785*61046927SAndroid Build Coastguard Worker
786*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
787*61046927SAndroid Build Coastguard Worker if (!shim_fd)
788*61046927SAndroid Build Coastguard Worker return real_ioctl(fd, request, arg);
789*61046927SAndroid Build Coastguard Worker
790*61046927SAndroid Build Coastguard Worker return drm_shim_ioctl(fd, request, arg);
791*61046927SAndroid Build Coastguard Worker }
792*61046927SAndroid Build Coastguard Worker
793*61046927SAndroid Build Coastguard Worker /* Gallium uses this to dup the incoming fd on gbm screen creation */
794*61046927SAndroid Build Coastguard Worker PUBLIC int
fcntl(int fd,int cmd,...)795*61046927SAndroid Build Coastguard Worker fcntl(int fd, int cmd, ...)
796*61046927SAndroid Build Coastguard Worker {
797*61046927SAndroid Build Coastguard Worker init_shim();
798*61046927SAndroid Build Coastguard Worker
799*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
800*61046927SAndroid Build Coastguard Worker
801*61046927SAndroid Build Coastguard Worker va_list ap;
802*61046927SAndroid Build Coastguard Worker va_start(ap, cmd);
803*61046927SAndroid Build Coastguard Worker void *arg = va_arg(ap, void *);
804*61046927SAndroid Build Coastguard Worker va_end(ap);
805*61046927SAndroid Build Coastguard Worker
806*61046927SAndroid Build Coastguard Worker int ret = real_fcntl(fd, cmd, arg);
807*61046927SAndroid Build Coastguard Worker
808*61046927SAndroid Build Coastguard Worker if (shim_fd && (cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC))
809*61046927SAndroid Build Coastguard Worker drm_shim_fd_register(ret, shim_fd);
810*61046927SAndroid Build Coastguard Worker
811*61046927SAndroid Build Coastguard Worker return ret;
812*61046927SAndroid Build Coastguard Worker }
813*61046927SAndroid Build Coastguard Worker PUBLIC int fcntl64(int, int, ...)
814*61046927SAndroid Build Coastguard Worker __attribute__((alias("fcntl")));
815*61046927SAndroid Build Coastguard Worker
816*61046927SAndroid Build Coastguard Worker /* I wrote this when trying to fix gallium screen creation, leaving it around
817*61046927SAndroid Build Coastguard Worker * since it's probably good to have.
818*61046927SAndroid Build Coastguard Worker */
819*61046927SAndroid Build Coastguard Worker PUBLIC int
dup(int fd)820*61046927SAndroid Build Coastguard Worker dup(int fd)
821*61046927SAndroid Build Coastguard Worker {
822*61046927SAndroid Build Coastguard Worker init_shim();
823*61046927SAndroid Build Coastguard Worker
824*61046927SAndroid Build Coastguard Worker int ret = real_dup(fd);
825*61046927SAndroid Build Coastguard Worker
826*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
827*61046927SAndroid Build Coastguard Worker if (shim_fd && ret >= 0)
828*61046927SAndroid Build Coastguard Worker drm_shim_fd_register(ret, shim_fd);
829*61046927SAndroid Build Coastguard Worker
830*61046927SAndroid Build Coastguard Worker return ret;
831*61046927SAndroid Build Coastguard Worker }
832*61046927SAndroid Build Coastguard Worker
833*61046927SAndroid Build Coastguard Worker PUBLIC void *
mmap(void * addr,size_t length,int prot,int flags,int fd,off_t offset)834*61046927SAndroid Build Coastguard Worker mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
835*61046927SAndroid Build Coastguard Worker {
836*61046927SAndroid Build Coastguard Worker init_shim();
837*61046927SAndroid Build Coastguard Worker
838*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
839*61046927SAndroid Build Coastguard Worker if (shim_fd)
840*61046927SAndroid Build Coastguard Worker return drm_shim_mmap(shim_fd, length, prot, flags, fd, offset);
841*61046927SAndroid Build Coastguard Worker
842*61046927SAndroid Build Coastguard Worker return real_mmap(addr, length, prot, flags, fd, offset);
843*61046927SAndroid Build Coastguard Worker }
844*61046927SAndroid Build Coastguard Worker
845*61046927SAndroid Build Coastguard Worker PUBLIC void *
mmap64(void * addr,size_t length,int prot,int flags,int fd,off64_t offset)846*61046927SAndroid Build Coastguard Worker mmap64(void* addr, size_t length, int prot, int flags, int fd, off64_t offset)
847*61046927SAndroid Build Coastguard Worker {
848*61046927SAndroid Build Coastguard Worker init_shim();
849*61046927SAndroid Build Coastguard Worker
850*61046927SAndroid Build Coastguard Worker struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
851*61046927SAndroid Build Coastguard Worker if (shim_fd)
852*61046927SAndroid Build Coastguard Worker return drm_shim_mmap(shim_fd, length, prot, flags, fd, offset);
853*61046927SAndroid Build Coastguard Worker
854*61046927SAndroid Build Coastguard Worker return real_mmap64(addr, length, prot, flags, fd, offset);
855*61046927SAndroid Build Coastguard Worker }
856