refactor dependencies
[ginge.git] / loader / override.c
CommitLineData
7fd42181 1// vim:shiftwidth=2:expandtab
2#include <stdio.h>
3#include <stdlib.h>
4d045184 4#include <stdarg.h>
7fd42181 5#include <string.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <sys/mman.h>
10#include <unistd.h>
11#include <sys/ioctl.h>
12#include <signal.h>
13#include <termios.h>
14
15#include "realfuncs.h"
16#include "header.h"
17
18#if (DBG & 1)
19#define strace printf
20#else
21#define strace(...)
22#endif
23
24#define UNUSED __attribute__((unused))
25
26static const struct dev_fd_t takeover_devs[] = {
27 { "/dev/mem", FAKEDEV_MEM },
28 { "/dev/GPIO", FAKEDEV_GPIO },
29 { "/dev/fb0", FAKEDEV_FB0 },
30 { "/dev/fb/0", FAKEDEV_FB0 },
31 { "/dev/fb1", FAKEDEV_FB1 },
32 { "/dev/fb/1", FAKEDEV_FB1 },
33 { "/dev/mmuhack", FAKEDEV_MMUHACK },
34 { "/dev/tty", -1 }, // XXX hmh..
35 { "/dev/tty0", FAKEDEV_TTY0 },
7000b522 36#ifdef PND
37 { "/dev/input/event*", -1 }, // hide for now, may cause dupe events
38#endif
7fd42181 39};
40
41static int w_open(const char *pathname, int flags, mode_t mode)
42{
43 int i, ret;
44
45 for (i = 0; i < ARRAY_SIZE(takeover_devs); i++) {
7000b522 46 const char *p, *oname;
47 int len;
48
49 oname = takeover_devs[i].name;
50 p = strchr(oname, '*');
51 if (p != NULL)
52 len = p - oname;
53 else
54 len = strlen(oname) + 1;
55
56 if (strncmp(pathname, oname, len) == 0) {
7fd42181 57 ret = takeover_devs[i].fd;
58 break;
59 }
60 }
61
62 if (i == ARRAY_SIZE(takeover_devs))
63 ret = open(pathname, flags, mode);
64
65 if (ret >= 0) {
66 for (i = 0; emu_interesting_fds[i].name != NULL; i++) {
7000b522 67 struct dev_fd_t *eifd = &emu_interesting_fds[i];
68 if (strcmp(pathname, eifd->name) == 0) {
69 eifd->fd = ret;
70 if (eifd->open_cb != NULL)
71 eifd->open_cb(ret);
7fd42181 72 break;
73 }
74 }
75 }
76
77 strace("open(%s) = %d\n", pathname, ret);
78 return ret;
79}
80
81static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
82{
83 void *ret;
84 if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY)
85 ret = emu_do_mmap(length, prot, flags, fd, offset);
86 else
87 ret = mmap(addr, length, prot, flags, fd, offset);
88
89 // threads are using heap before they mmap their stack
90 // printf needs valid stack for pthread/errno
91 if (((long)&ret & 0xf0000000) == 0xb0000000)
92 strace("mmap(%p, %x, %x, %x, %d, %lx) = %p\n", addr, length, prot, flags, fd, (long)offset, ret);
93 return ret;
94}
95#define w_mmap2 w_mmap
96
97static ssize_t w_read(int fd, void *buf, size_t count)
98{
99 ssize_t ret;
100 if (fd == FAKEDEV_GPIO)
101 ret = emu_read_gpiodev(buf, count);
102 else
103 ret = read(fd, buf, count);
104
105 //strace("read(%d, %p, %d) = %d\n", fd, buf, count, ret);
106 return ret;
107}
108
109static int w_ioctl(int fd, int request, void *argp)
110{
111 int ret;
112
113 if ((FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) ||
114 fd == emu_interesting_fds[IFD_SOUND].fd)
115 ret = emu_do_ioctl(fd, request, argp);
116 else
117 ret = ioctl(fd, request, argp);
118
119 strace("ioctl(%d, %08x, %p) = %d\n", fd, request, argp, ret);
120 return ret;
121}
122
123static int w_sigaction(int signum, const void *act, void *oldact)
124{
125 strace("sigaction(%d, %p, %p) = %d\n", signum, act, oldact, 0);
126 return 0;
127}
128
129/* dynamic only */
130static UNUSED int w_tcgetattr(int fd, struct termios *termios_p)
131{
132 int ret;
133 if (fd != FAKEDEV_TTY0)
134 ret = tcgetattr(fd, termios_p);
135 else
136 ret = 0;
137
138 strace("tcgetattr(%d, %p) = %d\n", fd, termios_p, ret);
139 return ret;
140}
141
142static UNUSED int w_tcsetattr(int fd, int optional_actions,
143 const struct termios *termios_p)
144{
145 int ret;
146 if (fd != FAKEDEV_TTY0)
147 ret = tcsetattr(fd, optional_actions, termios_p);
148 else
149 ret = 0;
150
151 strace("tcsetattr(%d, %x, %p) = %d\n", fd, optional_actions, termios_p, ret);
152 return ret;
153}
154
155static UNUSED FILE *w_fopen(const char *path, const char *mode)
156{
157 FILE *ret = emu_do_fopen(path, mode);
158 strace("fopen(%s, %s) = %p\n", path, mode, ret);
159 return ret;
160}
161
162static UNUSED int w_system(const char *command)
163{
164 int ret = emu_do_system(command);
165 strace("system(%s) = %d\n", command, ret);
166 return ret;
167}
168
7000b522 169extern char **environ;
170
db9191ed 171static UNUSED int w_execl(const char *path, const char *arg, ...)
172{
173 // don't allow exec (for now)
174 strace("execl(%s, %s, ...) = ?\n", path, arg);
7000b522 175 exit(1);
db9191ed 176}
177
178static UNUSED int w_execlp(const char *file, const char *arg, ...)
179{
180 strace("execlp(%s, %s, ...) = ?\n", file, arg);
7000b522 181 exit(1);
182}
183
184static UNUSED int w_execle(const char *path, const char *arg, ...)
185{
186 strace("execle(%s, %s, ...) = ?\n", path, arg);
187 exit(1);
188}
189
190static UNUSED int w_execv(const char *path, char *const argv[])
191{
192 strace("execv(%s, %p) = ?\n", path, argv);
193 return emu_do_execve(path, argv, environ);
194}
195
196static UNUSED int w_execvp(const char *file, char *const argv[])
197{
198 strace("execvp(%s, %p) = ?\n", file, argv);
199 return emu_do_execve(file, argv, environ);
db9191ed 200}
201
202// static note: this can't safely return because of the way it's patched in
203// static note2: can't be used, execve hangs?
204static UNUSED int w_execve(const char *filename, char *const argv[],
205 char *const envp[])
206{
207 strace("execve(%s, %p, %p) = ?\n", filename, argv, envp);
7000b522 208 return emu_do_execve(filename, argv, envp);
db9191ed 209}
210
211static int w_chdir(const char *path)
212{
213 int ret;
214 if (path != NULL && strstr(path, "/usr/gp2x") != NULL)
215 ret = 0;
216 else
217 ret = chdir(path);
218 strace("chdir(%s) = %d\n", path, ret);
219 return ret;
220}
221
7fd42181 222#undef open
223#undef fopen
224#undef mmap
225#undef read
226#undef ioctl
227#undef sigaction
228#undef tcgetattr
229#undef tcsetattr
230#undef system
db9191ed 231#undef execl
232#undef execlp
7000b522 233#undef execle
234#undef execv
235#undef execvp
db9191ed 236#undef execve
237#undef chdir
7fd42181 238
239#ifdef DL
240
db9191ed 241#define MAKE_WRAP_SYM_N(sym) \
7fd42181 242 /* alias wrap symbols to real names */ \
db9191ed 243 typeof(sym) sym __attribute__((alias("w_" #sym)))
244
245#define MAKE_WRAP_SYM(sym) \
246 MAKE_WRAP_SYM_N(sym); \
7fd42181 247 /* wrapper to real functions, to be set up on load */ \
248 static typeof(sym) *p_real_##sym
249
4d045184 250// note: update symver too
7fd42181 251MAKE_WRAP_SYM(open);
252MAKE_WRAP_SYM(fopen);
253MAKE_WRAP_SYM(mmap);
254MAKE_WRAP_SYM(read);
255MAKE_WRAP_SYM(ioctl);
256MAKE_WRAP_SYM(sigaction);
257MAKE_WRAP_SYM(tcgetattr);
258MAKE_WRAP_SYM(tcsetattr);
259MAKE_WRAP_SYM(system);
db9191ed 260MAKE_WRAP_SYM_N(execl);
261MAKE_WRAP_SYM_N(execlp);
7000b522 262MAKE_WRAP_SYM_N(execle);
263MAKE_WRAP_SYM_N(execv);
264MAKE_WRAP_SYM_N(execvp);
db9191ed 265MAKE_WRAP_SYM(execve);
266MAKE_WRAP_SYM(chdir);
7fd42181 267typeof(mmap) mmap2 __attribute__((alias("w_mmap")));
268
269#define REAL_FUNC_NP(name) \
270 { #name, (void **)&p_real_##name }
271
272static const struct {
273 const char *name;
274 void **func_ptr;
275} real_funcs_np[] = {
276 REAL_FUNC_NP(open),
277 REAL_FUNC_NP(fopen),
278 REAL_FUNC_NP(mmap),
279 REAL_FUNC_NP(read),
280 REAL_FUNC_NP(ioctl),
281 REAL_FUNC_NP(sigaction),
282 REAL_FUNC_NP(tcgetattr),
283 REAL_FUNC_NP(tcsetattr),
284 REAL_FUNC_NP(system),
db9191ed 285 // exec* - skipped
286 REAL_FUNC_NP(execve),
287 REAL_FUNC_NP(chdir),
7fd42181 288};
289
290#define open p_real_open
291#define fopen p_real_fopen
292#define mmap p_real_mmap
293#define read p_real_read
294#define ioctl p_real_ioctl
295#define sigaction p_real_sigaction
296#define tcgetattr p_real_tcgetattr
297#define tcsetattr p_real_tcsetattr
298#define system p_real_system
db9191ed 299#define execve p_real_execve
300#define chdir p_real_chdir
7fd42181 301
302#undef MAKE_WRAP_SYM
303#undef REAL_FUNC_NP
304
305#endif
306
307// just call real funcs for static, pointer for dynamic
4d045184 308int real_open(const char *pathname, int flags, ...)
7fd42181 309{
4d045184 310 va_list ap;
311 mode_t mode;
312
313 va_start(ap, flags);
314 mode = va_arg(ap, mode_t);
315 va_end(ap);
7fd42181 316 return open(pathname, flags, mode);
317}
318
319FILE *real_fopen(const char *path, const char *mode)
320{
321 return fopen(path, mode);
322}
323
324void *real_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset)
325{
326 return mmap(addr, length, prot, flags, fd, offset);
327}
328
329int real_read(int fd, void *buf, size_t count)
330{
331 return read(fd, buf, count);
332}
333
334int real_ioctl(int d, int request, void *argp)
335{
336 return ioctl(d, request, argp);
337}
338
339int real_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
340{
341 return sigaction(signum, act, oldact);
342}
343
344int real_tcgetattr(int fd, struct termios *termios_p)
345{
346 return tcgetattr(fd, termios_p);
347}
348
349int real_tcsetattr(int fd, int optional_actions,
350 const struct termios *termios_p)
351{
352 return tcsetattr(fd, optional_actions, termios_p);
353}
354
355int real_system(const char *command)
356{
357 return system(command);
358}
db9191ed 359
360// real_exec* is missing intentionally - we don't need them
361
362int real_execve(const char *filename, char *const argv[],
363 char *const envp[])
364{
365 return execve(filename, argv, envp);
366}
367
368int real_chdir(const char *path)
369{
370 return chdir(path);
371}