11913091 |
1 | // vim:shiftwidth=2:expandtab |
2 | #include <stdio.h> |
3 | #include <string.h> |
4 | #include <sys/types.h> |
5 | #include <sys/stat.h> |
6 | #include <fcntl.h> |
7 | #include <sys/mman.h> |
3d295a9f |
8 | #include <unistd.h> |
dc90c02d |
9 | #include <sys/ioctl.h> |
11913091 |
10 | |
11 | #include "header.h" |
12 | #include "sys_cacheflush.h" |
13 | |
dc90c02d |
14 | #if 0 |
15 | #define strace printf |
16 | #else |
0881206b |
17 | #define strace(...) |
dc90c02d |
18 | #endif |
19 | |
20 | // note: first mask must be always full for search algo |
21 | static const unsigned int sig_mask_all[] = { |
22 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, |
23 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff |
24 | }; |
0881206b |
25 | |
11913091 |
26 | static const unsigned int sig_open[] = { |
27 | 0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900005 |
28 | }; |
dc90c02d |
29 | #define sig_mask_open sig_mask_all |
11913091 |
30 | |
31 | static const unsigned int sig_mmap[] = { |
32 | 0xe92d000f, 0xe1a0000d, 0xef90005a, 0xe28dd010 |
33 | }; |
dc90c02d |
34 | #define sig_mask_mmap sig_mask_all |
11913091 |
35 | |
36 | static const unsigned int sig_mmap_[] = { |
37 | 0xe52d5004, 0xe59d5008, 0xe52d4004, 0xe59d4008, |
38 | 0xe1b0ca05, 0x1a000006, 0xe1a05625, 0xef9000c0 |
39 | }; |
dc90c02d |
40 | #define sig_mask_mmap_ sig_mask_all |
11913091 |
41 | |
3d295a9f |
42 | static const unsigned int sig_read[] = { |
43 | 0xe59fc080, 0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900003 |
44 | }; |
dc90c02d |
45 | #define sig_mask_read sig_mask_all |
3d295a9f |
46 | |
dc90c02d |
47 | static const unsigned int sig_ioctl[] = { |
48 | 0xef900036, 0xe3700a01, 0x312fff1e |
c1ffd5ba |
49 | }; |
dc90c02d |
50 | #define sig_mask_ioctl sig_mask_all |
c1ffd5ba |
51 | |
dc90c02d |
52 | static const unsigned int sig_sigaction[] = { |
53 | 0xe59f300c, 0xe3530000, 0x0a000000, 0xea000000, 0xea000000 |
54 | }; |
55 | static const unsigned int sig_mask_sigaction[] = { |
56 | 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000 |
57 | }; |
58 | |
59 | static const struct dev_fd_t takeover_devs[] = { |
c1ffd5ba |
60 | { "/dev/mem", FAKEDEV_MEM }, |
61 | { "/dev/GPIO", FAKEDEV_GPIO }, |
62 | { "/dev/fb0", FAKEDEV_FB0 }, |
63 | { "/dev/fb/0", FAKEDEV_FB0 }, |
64 | { "/dev/fb1", FAKEDEV_FB1 }, |
65 | { "/dev/fb/1", FAKEDEV_FB1 }, |
66 | { "/dev/mmuhack", FAKEDEV_MMUHACK }, |
67 | }; |
11913091 |
68 | |
69 | static int w_open(const char *pathname, int flags, mode_t mode) |
70 | { |
c1ffd5ba |
71 | int i, ret; |
72 | |
73 | for (i = 0; i < ARRAY_SIZE(takeover_devs); i++) { |
74 | if (strcmp(pathname, takeover_devs[i].name) == 0) { |
75 | ret = takeover_devs[i].fd; |
76 | break; |
77 | } |
78 | } |
79 | |
80 | if (i == ARRAY_SIZE(takeover_devs)) |
3d295a9f |
81 | ret = open(pathname, flags, mode); |
11913091 |
82 | |
dc90c02d |
83 | if (ret >= 0) { |
84 | for (i = 0; emu_interesting_fds[i].name != NULL; i++) { |
85 | if (strcmp(pathname, emu_interesting_fds[i].name) == 0) { |
86 | emu_interesting_fds[i].fd = ret; |
87 | break; |
88 | } |
89 | } |
90 | } |
91 | |
0881206b |
92 | strace("open(%s) = %d\n", pathname, ret); |
11913091 |
93 | return ret; |
94 | } |
95 | |
96 | static void *w_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) |
97 | { |
98 | void *ret; |
dc90c02d |
99 | if (FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) |
100 | ret = emu_do_mmap(length, prot, flags, fd, offset); |
11913091 |
101 | else |
dc90c02d |
102 | ret = mmap(addr, length, prot, flags, fd, offset); |
11913091 |
103 | |
c1ffd5ba |
104 | // threads are using heap before they mmap their stack |
105 | // printf needs valid stack for pthtead/errno |
106 | if (((long)&ret & 0xf0000000) == 0xb0000000) |
107 | strace("mmap(%p, %x, %x, %x, %d, %lx) = %p\n", addr, length, prot, flags, fd, (long)offset, ret); |
11913091 |
108 | return ret; |
109 | } |
110 | #define w_mmap_ w_mmap |
111 | |
dc90c02d |
112 | static ssize_t w_read(int fd, void *buf, size_t count) |
3d295a9f |
113 | { |
114 | ssize_t ret; |
c1ffd5ba |
115 | if (fd != FAKEDEV_GPIO) |
3d295a9f |
116 | return read(fd, buf, count); |
117 | |
118 | ret = emu_read_gpiodev(buf, count); |
dc90c02d |
119 | //strace("read(%d, %p, %d) = %d\n", fd, buf, count, ret); |
3d295a9f |
120 | return ret; |
121 | } |
122 | |
dc90c02d |
123 | static int w_ioctl(int fd, int request, void *argp) |
124 | { |
125 | int ret; |
126 | |
127 | if ((FAKEDEV_MEM <= fd && fd < FAKEDEV_FD_BOUNDARY) || |
128 | fd == emu_interesting_fds[IFD_SOUND].fd) |
129 | ret = emu_do_ioctl(fd, request, argp); |
130 | else |
131 | ret = ioctl(fd, request, argp); |
132 | |
133 | strace("ioctl(%d, %08x, %p) = %d\n", fd, request, argp, ret); |
134 | return ret; |
135 | } |
136 | |
137 | static int w_sigaction(int signum, const void *act, void *oldact) |
138 | { |
139 | strace("sigaction(%d, %p, %p) = %d\n", signum, act, oldact, 0); |
140 | return 0; |
141 | } |
142 | |
143 | #define PATCH(f) { sig_##f, sig_mask_##f, ARRAY_SIZE(sig_##f), w_##f } |
11913091 |
144 | |
145 | static const struct { |
146 | const unsigned int *sig; |
dc90c02d |
147 | const unsigned int *sig_mask; |
11913091 |
148 | size_t sig_cnt; |
149 | void *func; |
150 | } patches[] = { |
151 | PATCH(open), |
152 | PATCH(mmap), |
153 | PATCH(mmap_), // mmap using mmap2 syscall |
3d295a9f |
154 | PATCH(read), |
dc90c02d |
155 | PATCH(ioctl), |
156 | PATCH(sigaction), |
11913091 |
157 | }; |
158 | |
159 | void do_patches(void *ptr, unsigned int size) |
160 | { |
161 | int i, s; |
162 | |
163 | for (i = 0; i < ARRAY_SIZE(patches); i++) { |
164 | const unsigned int *sig = patches[i].sig; |
dc90c02d |
165 | const unsigned int *sig_mask = patches[i].sig_mask; |
11913091 |
166 | unsigned int *seg = (void *)(((long)ptr + 3) & ~3); |
167 | unsigned int *seg_end = seg + size / 4; |
168 | unsigned int sig0 = sig[0]; |
169 | |
170 | for (; seg < seg_end; seg++) { |
171 | if (*seg != sig0) |
172 | continue; |
173 | |
174 | for (s = 1; s < patches[i].sig_cnt; s++) |
dc90c02d |
175 | if ((seg[s] ^ sig[s]) & sig_mask[s]) |
11913091 |
176 | break; |
177 | |
178 | if (s == patches[i].sig_cnt) |
179 | goto found; |
180 | } |
181 | continue; |
182 | |
183 | found: |
dc90c02d |
184 | dbg(" patch #%i @ %08x\n", i, (int)seg); |
11913091 |
185 | seg[0] = 0xe59ff000; // ldr pc, [pc] |
186 | seg[1] = 0; |
187 | seg[2] = (unsigned int)patches[i].func; |
188 | } |
189 | |
190 | sys_cacheflush(ptr, (char *)ptr + size); |
191 | } |
192 | |