blob: 2646a29ffd542da61ff06764c2e65d6a658520c9 [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>
Richard Smithff8c08e2006-04-23 19:16:09 +00008#include <string.h>
Li-Ta Lo81521262004-07-08 17:18:27 +00009
10#define die(x) { perror(x); exit(1); }
Ronald G. Minnich284c27f2004-11-28 04:39:45 +000011#define warn(x) { perror(x); }
Li-Ta Lo81521262004-07-08 17:18:27 +000012
Stefan Reinauer86051f92010-03-23 15:53:38 +000013#include <x86emu/x86emu.h>
Luc Verhaegene6e899d2009-05-27 11:39:16 +000014#include "helper_exec.h"
Li-Ta Lo81521262004-07-08 17:18:27 +000015#include "test.h"
16#include "pci-userspace.h"
17
18void x86emu_dump_xregs(void);
19int int15_handler(void);
20int int16_handler(void);
21int int1A_handler(void);
22#ifndef _PC
23int int42_handler(void);
24#endif
25int intE6_handler(void);
26
27void pushw(u16 val);
28
Richard Smithff8c08e2006-04-23 19:16:09 +000029unsigned short get_device(char *arg_val);
30
Li-Ta Lo81521262004-07-08 17:18:27 +000031extern int teststart, testend;
32
33_ptr p;
34ptr current = 0;
35unsigned char biosmem[1024 * 1024];
36
37int verbose = 0;
38
39
40/* Interrupt multiplexer */
41
42void do_int(int num)
43{
44 int ret = 0;
45
46 printf("int%x vector at %x\n", num, getIntVect(num));
47
48 /* This is a pInt leftover */
49 current->num = num;
50
51 switch (num) {
52#ifndef _PC
53 case 0x10:
54 case 0x42:
55 case 0x6D:
56
57 if (getIntVect(num) == 0xFF065) {
58 ret = int42_handler();
59 }
60 break;
61#endif
62 case 0x15:
63 ret = int15_handler();
64 break;
65 case 0x16:
66 ret = int16_handler();
67 break;
68 case 0x1A:
69 ret = int1A_handler();
70 break;
71 case 0xe6:
72 ret = intE6_handler();
73 break;
74 default:
75 break;
76 }
77
78 if (!ret)
79 ret = run_bios_int(num);
80
81 if (!ret) {
82 printf("\nint%x: not implemented\n", num);
Li-Ta Lo8b0356c2005-01-11 03:18:39 +000083 //x86emu_dump_xregs();
Li-Ta Lo81521262004-07-08 17:18:27 +000084 }
85}
86
87unsigned char *mapitin(char *file, off_t where, size_t size)
88{
89 void *z;
90
91 int fd = open(file, O_RDWR, 0);
92
93 if (fd < 0)
94 die(file);
95 z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
96 if (z == (void *) -1)
97 die("mmap");
98 close(fd);
99
100 return z;
101
102}
103
104u8 x_inb(u16 port);
105u16 x_inw(u16 port);
106void x_outb(u16 port, u8 val);
107void x_outw(u16 port, u16 val);
108u32 x_inl(u16 port);
109void x_outl(u16 port, u32 val);
110
111
112X86EMU_pioFuncs myfuncs = {
113 x_inb, x_inw, x_inl,
114 x_outb, x_outw, x_outl
115};
116
117
118void usage(char *name)
119{
120 printf
121 ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
122 name);
123}
124
125int main(int argc, char **argv)
126{
127 char *absegname = 0;
128 void *abseg = 0;
129 int i, c, trace = 0;
130 unsigned char *cp;
131 char *filename;
132 size_t size = 0;
133 int base = 0;
134 int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
Richard Smithff8c08e2006-04-23 19:16:09 +0000135 int have_devfn = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000136 int parse_rom = 0;
137 char *fsegname = 0;
138 unsigned char *fsegptr;
139 unsigned short initialip = 0, initialcs = 0, devfn = 0;
140 X86EMU_intrFuncs intFuncs[256];
141 void X86EMU_setMemBase(void *base, size_t size);
Li-Ta Lo81521262004-07-08 17:18:27 +0000142 void x86emu_dump_xregs(void);
143 int X86EMU_set_debug(int debug);
144 int debugflag = 0;
145
146 const char *optstring = "vh?b:i:c:s:tpd:";
147 while (1) {
148 int option_index = 0;
149 static struct option long_options[] = {
150 {"verbose", 0, 0, 'v'},
151 {"help", 0, 0, 'h'},
152 {"trace", 0, 0, 't'},
153 {"base", 1, 0, 'b'},
154 {"fseg", 1, 0, 'f'},
155 {"instructionpointer", 1, 0, 'i'},
156 {"codesegment", 1, 0, 'c'},
157 {"absegment", 1, 0, 'a'},
158 {"size", 1, 0, 's'},
159 {"parserom", 0, 0, 'p'},
160 {"device", 1, 0, 'd'},
161 {"debug", 1, 0, 'D'},
162 {0, 0, 0, 0}
163 };
164 c = getopt_long(argc, argv, optstring, long_options, &option_index);
165 if (c == -1)
166 break;
167 switch (c) {
168 case 'v':
169 verbose = 1;
170 break;
171 case 'h':
172 case '?':
173 usage(argv[0]);
174 return 0;
175 case 't':
176 trace = 1;
177 break;
178 case 'b':
179 base = strtol(optarg, 0, 0);
180 have_base = 1;
181 break;
182 case 'i':
183 initialip = strtol(optarg, 0, 0);
184 have_ip = 1;
185 break;
186 case 'c':
187 initialcs = strtol(optarg, 0, 0);
188 have_cs = 1;
189 break;
190 case 's':
191 size = strtol(optarg, 0, 0);
192 have_size = 1;
193 break;
194 case 'p':
195 printf("Parsing rom images not implemented.\n");
196 parse_rom = 1;
197 break;
198 case 'f':
199 fsegname = optarg;
200 break;
201 case 'a':
202 absegname = optarg;
203 break;
204 case 'd':
Richard Smithff8c08e2006-04-23 19:16:09 +0000205 devfn = get_device(optarg);
206 have_devfn = 1;
Li-Ta Lo81521262004-07-08 17:18:27 +0000207 break;
208 case 'D':
209 debugflag = strtol(optarg, 0, 0);
210 break;
211 default:
212 printf("Unknown option \n");
213 usage(argv[0]);
214 return 1;
215 }
216 }
217
218 if (optind >= argc) {
219 printf("Filename missing.\n");
220 usage(argv[0]);
221 return 1;
222 }
223
224 while (optind < argc) {
225 printf("running file %s\n", argv[optind]);
226 filename = argv[optind];
227 optind++;
228 /* normally we would do continue, but for
229 * now only one filename is supported.
230 */
231 /* continue; */
232 break;
233 }
234
235 if (!have_size) {
236 printf("No size specified. defaulting to 32k\n");
237 size = 32 * 1024;
238 }
239 if (!have_base) {
240 printf("No base specified. defaulting to 0xc0000\n");
241 base = 0xc0000;
242 }
243 if (!have_cs) {
244 printf("No initial code segment specified. defaulting to 0xc000\n");
245 initialcs = 0xc000;
246 }
247 if (!have_ip) {
248 printf
249 ("No initial instruction pointer specified. defaulting to 0x0003\n");
250 initialip = 0x0003;
251 }
252
253 //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
254
Richard Smithff8c08e2006-04-23 19:16:09 +0000255 if (initialip == 0x0003) {
256 if ((devfn == 0) || (have_devfn == 0)) {
257 printf("WARNING! It appears you are trying to run an option ROM.\n");
258 printf(" (initial ip = 0x0003)\n");
259 if (have_devfn) {
260 printf(" However, the device you have specified is 0x00\n");
261 printf(" It is very unlikely that your device is at this address\n");
262 printf(" Please check your -d option\n");
263 }
264 else {
265 printf(" Please specify a device with -d\n");
266 printf(" The default is not likely to work\n");
267 }
268 }
269 }
270
Li-Ta Lo81521262004-07-08 17:18:27 +0000271 if (absegname) {
272 abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
273 if (!abseg)
274 die(absegname);
275 }
276
277 current = &p;
278 X86EMU_setMemBase(biosmem, sizeof(biosmem));
Stefan Reinauer86051f92010-03-23 15:53:38 +0000279 M.abseg = (unsigned long)abseg;
Li-Ta Lo81521262004-07-08 17:18:27 +0000280 X86EMU_setupPioFuncs(&myfuncs);
281 ioperm(0, 0x400, 1);
282
Ronald G. Minnich284c27f2004-11-28 04:39:45 +0000283 if (iopl(3) < 0) {
284 warn("iopl failed, continuing anyway");
285 }
Li-Ta Lo81521262004-07-08 17:18:27 +0000286
287 /* Emergency sync ;-) */
288 sync();
289 sync();
290
291 /* Setting up interrupt environment.
292 * basically this means initializing PCI and
293 * intXX handlers.
294 */
295 pciInit();
296
297 for (i = 0; i < 256; i++)
298 intFuncs[i] = do_int;
299 X86EMU_setupIntrFuncs(intFuncs);
300 cp = mapitin(filename, (off_t) 0, size);
301
Richard Smithff8c08e2006-04-23 19:16:09 +0000302 if (devfn) {
303 printf("Loading ax with BusDevFn = %x\n",devfn);
304 }
305
Li-Ta Lo81521262004-07-08 17:18:27 +0000306 current->ax = devfn ? devfn : 0xff;
307 current->dx = 0x80;
308 // current->ip = 0;
309 for (i = 0; i < size; i++)
310 wrb(base + i, cp[i]);
311
312 if (fsegname) {
313 fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
314 for (i = 0; i < 0x10000; i++)
315 wrb(0xf0000 + i, fsegptr[i]);
316 } else {
317 char *date = "01/01/99";
318 for (i = i; date[i]; i++)
319 wrb(0xffff5 + i, date[i]);
320 wrb(0xffff7, '/');
321 wrb(0xffffa, '/');
322 }
323 /* cpu setup */
324 X86_AX = devfn ? devfn : 0xff;
325 X86_DX = 0x80;
326 X86_EIP = initialip;
327 X86_CS = initialcs;
328
329 /* Initialize stack and data segment */
330 X86_SS = 0x0030;
331 X86_DS = 0x0040;
332 X86_SP = 0xfffe;
333 /* We need a sane way to return from bios
334 * execution. A hlt instruction and a pointer
335 * to it, both kept on the stack, will do.
336 */
337 pushw(0xf4f4); /* hlt; hlt */
338 pushw(X86_SS);
339 pushw(X86_SP + 2);
340
341 X86_ES = 0x0000;
342
343 if (trace) {
344 printf("Switching to single step mode.\n");
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000345 //X86EMU_trace_on();
Li-Ta Lo81521262004-07-08 17:18:27 +0000346 }
347 if (debugflag) {
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000348 //X86EMU_set_debug(debugflag);
Li-Ta Lo81521262004-07-08 17:18:27 +0000349 }
350 X86EMU_exec();
351 /* Cleaning up */
352 pciExit();
353
354 return 0;
355}
Richard Smithff8c08e2006-04-23 19:16:09 +0000356
357unsigned short get_device(char *arg_val)
358{
359 unsigned short devfn=0;
360 long bus=0,dev=0,fn=0,need_pack=0;
361 char *tok;
362
363 tok = strsep(&arg_val,":");
364 if (arg_val != NULL) {
365 bus = strtol(tok,0,16);
366 need_pack = 1;
367 }
368 else {
369 arg_val = tok;
370 }
371
372 tok = strsep(&arg_val,".");
373 if (arg_val != NULL) {
374 dev = strtol(tok,0,16);
375 fn = strtol(arg_val,0,16);
376 need_pack = 1;
377 }
378 else {
379 if (need_pack ==1 && (strlen(tok))) {
380 dev = strtol(tok,0,16);
381 }
382 }
383
384 if ( need_pack == 1) {
385 devfn = bus<<8 | (dev<<3) | fn;
386 }
387 else {
388 devfn = strtol(tok, 0, 0);
389 }
390
391
392 return devfn;
393}
394