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