blob: 9ffdd068e5b5a881a09eabb0e188ac74ac97e888 [file] [log] [blame]
Li-Ta Lo81521262004-07-08 17:18:27 +00001#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <sys/io.h>
5#include <sys/mman.h>
6#include <fcntl.h>
7#include <getopt.h>
8
9#define die(x) { perror(x); exit(1); }
Ronald G. Minnich284c27f2004-11-28 04:39:45 +000010#define warn(x) { perror(x); }
Li-Ta Lo81521262004-07-08 17:18:27 +000011
12#include <x86emu.h>
13#include "test.h"
14#include "pci-userspace.h"
15
16void x86emu_dump_xregs(void);
17int int15_handler(void);
18int int16_handler(void);
19int int1A_handler(void);
20#ifndef _PC
21int int42_handler(void);
22#endif
23int intE6_handler(void);
24
25void pushw(u16 val);
26
27extern int teststart, testend;
28
29_ptr p;
30ptr current = 0;
31unsigned char biosmem[1024 * 1024];
32
33int verbose = 0;
34
35
36/* Interrupt multiplexer */
37
38void do_int(int num)
39{
40 int ret = 0;
41
42 printf("int%x vector at %x\n", num, getIntVect(num));
43
44 /* This is a pInt leftover */
45 current->num = num;
46
47 switch (num) {
48#ifndef _PC
49 case 0x10:
50 case 0x42:
51 case 0x6D:
52
53 if (getIntVect(num) == 0xFF065) {
54 ret = int42_handler();
55 }
56 break;
57#endif
58 case 0x15:
59 ret = int15_handler();
60 break;
61 case 0x16:
62 ret = int16_handler();
63 break;
64 case 0x1A:
65 ret = int1A_handler();
66 break;
67 case 0xe6:
68 ret = intE6_handler();
69 break;
70 default:
71 break;
72 }
73
74 if (!ret)
75 ret = run_bios_int(num);
76
77 if (!ret) {
78 printf("\nint%x: not implemented\n", num);
Li-Ta Lo8b0356c2005-01-11 03:18:39 +000079 //x86emu_dump_xregs();
Li-Ta Lo81521262004-07-08 17:18:27 +000080 }
81}
82
83unsigned char *mapitin(char *file, off_t where, size_t size)
84{
85 void *z;
86
87 int fd = open(file, O_RDWR, 0);
88
89 if (fd < 0)
90 die(file);
91 z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
92 if (z == (void *) -1)
93 die("mmap");
94 close(fd);
95
96 return z;
97
98}
99
100u8 x_inb(u16 port);
101u16 x_inw(u16 port);
102void x_outb(u16 port, u8 val);
103void x_outw(u16 port, u16 val);
104u32 x_inl(u16 port);
105void x_outl(u16 port, u32 val);
106
107
108X86EMU_pioFuncs myfuncs = {
109 x_inb, x_inw, x_inl,
110 x_outb, x_outw, x_outl
111};
112
113
114void usage(char *name)
115{
116 printf
117 ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
118 name);
119}
120
121int main(int argc, char **argv)
122{
123 char *absegname = 0;
124 void *abseg = 0;
125 int i, c, trace = 0;
126 unsigned char *cp;
127 char *filename;
128 size_t size = 0;
129 int base = 0;
130 int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
131 int parse_rom = 0;
132 char *fsegname = 0;
133 unsigned char *fsegptr;
134 unsigned short initialip = 0, initialcs = 0, devfn = 0;
135 X86EMU_intrFuncs intFuncs[256];
136 void X86EMU_setMemBase(void *base, size_t size);
137 void X86EMU_setabseg(void *abseg);
138 void x86emu_dump_xregs(void);
139 int X86EMU_set_debug(int debug);
140 int debugflag = 0;
141
142 const char *optstring = "vh?b:i:c:s:tpd:";
143 while (1) {
144 int option_index = 0;
145 static struct option long_options[] = {
146 {"verbose", 0, 0, 'v'},
147 {"help", 0, 0, 'h'},
148 {"trace", 0, 0, 't'},
149 {"base", 1, 0, 'b'},
150 {"fseg", 1, 0, 'f'},
151 {"instructionpointer", 1, 0, 'i'},
152 {"codesegment", 1, 0, 'c'},
153 {"absegment", 1, 0, 'a'},
154 {"size", 1, 0, 's'},
155 {"parserom", 0, 0, 'p'},
156 {"device", 1, 0, 'd'},
157 {"debug", 1, 0, 'D'},
158 {0, 0, 0, 0}
159 };
160 c = getopt_long(argc, argv, optstring, long_options, &option_index);
161 if (c == -1)
162 break;
163 switch (c) {
164 case 'v':
165 verbose = 1;
166 break;
167 case 'h':
168 case '?':
169 usage(argv[0]);
170 return 0;
171 case 't':
172 trace = 1;
173 break;
174 case 'b':
175 base = strtol(optarg, 0, 0);
176 have_base = 1;
177 break;
178 case 'i':
179 initialip = strtol(optarg, 0, 0);
180 have_ip = 1;
181 break;
182 case 'c':
183 initialcs = strtol(optarg, 0, 0);
184 have_cs = 1;
185 break;
186 case 's':
187 size = strtol(optarg, 0, 0);
188 have_size = 1;
189 break;
190 case 'p':
191 printf("Parsing rom images not implemented.\n");
192 parse_rom = 1;
193 break;
194 case 'f':
195 fsegname = optarg;
196 break;
197 case 'a':
198 absegname = optarg;
199 break;
200 case 'd':
201 devfn = strtol(optarg, 0, 0);
202 break;
203 case 'D':
204 debugflag = strtol(optarg, 0, 0);
205 break;
206 default:
207 printf("Unknown option \n");
208 usage(argv[0]);
209 return 1;
210 }
211 }
212
213 if (optind >= argc) {
214 printf("Filename missing.\n");
215 usage(argv[0]);
216 return 1;
217 }
218
219 while (optind < argc) {
220 printf("running file %s\n", argv[optind]);
221 filename = argv[optind];
222 optind++;
223 /* normally we would do continue, but for
224 * now only one filename is supported.
225 */
226 /* continue; */
227 break;
228 }
229
230 if (!have_size) {
231 printf("No size specified. defaulting to 32k\n");
232 size = 32 * 1024;
233 }
234 if (!have_base) {
235 printf("No base specified. defaulting to 0xc0000\n");
236 base = 0xc0000;
237 }
238 if (!have_cs) {
239 printf("No initial code segment specified. defaulting to 0xc000\n");
240 initialcs = 0xc000;
241 }
242 if (!have_ip) {
243 printf
244 ("No initial instruction pointer specified. defaulting to 0x0003\n");
245 initialip = 0x0003;
246 }
247
248 //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
249
250 if (absegname) {
251 abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
252 if (!abseg)
253 die(absegname);
254 }
255
256 current = &p;
257 X86EMU_setMemBase(biosmem, sizeof(biosmem));
258 X86EMU_setabseg(abseg);
259 X86EMU_setupPioFuncs(&myfuncs);
260 ioperm(0, 0x400, 1);
261
Ronald G. Minnich284c27f2004-11-28 04:39:45 +0000262 if (iopl(3) < 0) {
263 warn("iopl failed, continuing anyway");
264 }
Li-Ta Lo81521262004-07-08 17:18:27 +0000265
266 /* Emergency sync ;-) */
267 sync();
268 sync();
269
270 /* Setting up interrupt environment.
271 * basically this means initializing PCI and
272 * intXX handlers.
273 */
274 pciInit();
275
276 for (i = 0; i < 256; i++)
277 intFuncs[i] = do_int;
278 X86EMU_setupIntrFuncs(intFuncs);
279 cp = mapitin(filename, (off_t) 0, size);
280
281 current->ax = devfn ? devfn : 0xff;
282 current->dx = 0x80;
283 // current->ip = 0;
284 for (i = 0; i < size; i++)
285 wrb(base + i, cp[i]);
286
287 if (fsegname) {
288 fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
289 for (i = 0; i < 0x10000; i++)
290 wrb(0xf0000 + i, fsegptr[i]);
291 } else {
292 char *date = "01/01/99";
293 for (i = i; date[i]; i++)
294 wrb(0xffff5 + i, date[i]);
295 wrb(0xffff7, '/');
296 wrb(0xffffa, '/');
297 }
298 /* cpu setup */
299 X86_AX = devfn ? devfn : 0xff;
300 X86_DX = 0x80;
301 X86_EIP = initialip;
302 X86_CS = initialcs;
303
304 /* Initialize stack and data segment */
305 X86_SS = 0x0030;
306 X86_DS = 0x0040;
307 X86_SP = 0xfffe;
308 /* We need a sane way to return from bios
309 * execution. A hlt instruction and a pointer
310 * to it, both kept on the stack, will do.
311 */
312 pushw(0xf4f4); /* hlt; hlt */
313 pushw(X86_SS);
314 pushw(X86_SP + 2);
315
316 X86_ES = 0x0000;
317
318 if (trace) {
319 printf("Switching to single step mode.\n");
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000320 //X86EMU_trace_on();
Li-Ta Lo81521262004-07-08 17:18:27 +0000321 }
322 if (debugflag) {
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000323 //X86EMU_set_debug(debugflag);
Li-Ta Lo81521262004-07-08 17:18:27 +0000324 }
325 X86EMU_exec();
326 /* Cleaning up */
327 pciExit();
328
329 return 0;
330}