blob: 8c9783f07ee9634f19af01572e829bb539fe84e4 [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>
Stefan Reinauer850e7d42015-09-28 13:12:04 -07009#include <stdarg.h>
Li-Ta Lo81521262004-07-08 17:18:27 +000010
Stefan Reinauer850e7d42015-09-28 13:12:04 -070011#include <stdtypes.h>
Li-Ta Lo81521262004-07-08 17:18:27 +000012#define die(x) { perror(x); exit(1); }
Ronald G. Minnich284c27f2004-11-28 04:39:45 +000013#define warn(x) { perror(x); }
Li-Ta Lo81521262004-07-08 17:18:27 +000014
Stefan Reinauer86051f92010-03-23 15:53:38 +000015#include <x86emu/x86emu.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070016#include <console/console.h>
Luc Verhaegene6e899d2009-05-27 11:39:16 +000017#include "helper_exec.h"
Stefan Reinauer850e7d42015-09-28 13:12:04 -070018#include "testbios.h"
Li-Ta Lo81521262004-07-08 17:18:27 +000019#include "pci-userspace.h"
Stefan Reinauer850e7d42015-09-28 13:12:04 -070020int X86EMU_set_debug(int debug);
Richard Smithff8c08e2006-04-23 19:16:09 +000021unsigned short get_device(char *arg_val);
22
Li-Ta Lo81521262004-07-08 17:18:27 +000023extern int teststart, testend;
24
25_ptr p;
26ptr current = 0;
27unsigned char biosmem[1024 * 1024];
28
29int verbose = 0;
30
31
32/* Interrupt multiplexer */
33
Stefan Reinauer850e7d42015-09-28 13:12:04 -070034static void do_int(int num)
Li-Ta Lo81521262004-07-08 17:18:27 +000035{
36 int ret = 0;
37
38 printf("int%x vector at %x\n", num, getIntVect(num));
39
40 /* This is a pInt leftover */
41 current->num = num;
42
43 switch (num) {
44#ifndef _PC
45 case 0x10:
46 case 0x42:
47 case 0x6D:
48
49 if (getIntVect(num) == 0xFF065) {
50 ret = int42_handler();
51 }
52 break;
53#endif
54 case 0x15:
55 ret = int15_handler();
56 break;
57 case 0x16:
58 ret = int16_handler();
59 break;
60 case 0x1A:
61 ret = int1A_handler();
62 break;
63 case 0xe6:
64 ret = intE6_handler();
65 break;
66 default:
67 break;
68 }
69
70 if (!ret)
71 ret = run_bios_int(num);
72
73 if (!ret) {
74 printf("\nint%x: not implemented\n", num);
Li-Ta Lo8b0356c2005-01-11 03:18:39 +000075 //x86emu_dump_xregs();
Li-Ta Lo81521262004-07-08 17:18:27 +000076 }
77}
78
Stefan Reinauer850e7d42015-09-28 13:12:04 -070079static unsigned char *mapitin(char *file, off_t where, size_t size)
Li-Ta Lo81521262004-07-08 17:18:27 +000080{
81 void *z;
82
83 int fd = open(file, O_RDWR, 0);
84
85 if (fd < 0)
86 die(file);
87 z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
88 if (z == (void *) -1)
89 die("mmap");
90 close(fd);
91
92 return z;
93
94}
95
Li-Ta Lo81521262004-07-08 17:18:27 +000096X86EMU_pioFuncs myfuncs = {
97 x_inb, x_inw, x_inl,
98 x_outb, x_outw, x_outl
99};
100
101
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700102static void usage(char *name)
Li-Ta Lo81521262004-07-08 17:18:27 +0000103{
104 printf
105 ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
106 name);
107}
108
109int main(int argc, char **argv)
110{
111 char *absegname = 0;
112 void *abseg = 0;
113 int i, c, trace = 0;
114 unsigned char *cp;
115 char *filename;
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700116 ssize_t size = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000117 int base = 0;
118 int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
Richard Smithff8c08e2006-04-23 19:16:09 +0000119 int have_devfn = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000120 int parse_rom = 0;
121 char *fsegname = 0;
122 unsigned char *fsegptr;
123 unsigned short initialip = 0, initialcs = 0, devfn = 0;
124 X86EMU_intrFuncs intFuncs[256];
Li-Ta Lo81521262004-07-08 17:18:27 +0000125 int debugflag = 0;
126
127 const char *optstring = "vh?b:i:c:s:tpd:";
128 while (1) {
129 int option_index = 0;
130 static struct option long_options[] = {
131 {"verbose", 0, 0, 'v'},
132 {"help", 0, 0, 'h'},
133 {"trace", 0, 0, 't'},
134 {"base", 1, 0, 'b'},
135 {"fseg", 1, 0, 'f'},
136 {"instructionpointer", 1, 0, 'i'},
137 {"codesegment", 1, 0, 'c'},
138 {"absegment", 1, 0, 'a'},
139 {"size", 1, 0, 's'},
140 {"parserom", 0, 0, 'p'},
141 {"device", 1, 0, 'd'},
142 {"debug", 1, 0, 'D'},
143 {0, 0, 0, 0}
144 };
145 c = getopt_long(argc, argv, optstring, long_options, &option_index);
146 if (c == -1)
147 break;
148 switch (c) {
149 case 'v':
150 verbose = 1;
151 break;
152 case 'h':
153 case '?':
154 usage(argv[0]);
155 return 0;
156 case 't':
157 trace = 1;
158 break;
159 case 'b':
160 base = strtol(optarg, 0, 0);
161 have_base = 1;
162 break;
163 case 'i':
164 initialip = strtol(optarg, 0, 0);
165 have_ip = 1;
166 break;
167 case 'c':
168 initialcs = strtol(optarg, 0, 0);
169 have_cs = 1;
170 break;
171 case 's':
172 size = strtol(optarg, 0, 0);
173 have_size = 1;
174 break;
175 case 'p':
Li-Ta Lo81521262004-07-08 17:18:27 +0000176 parse_rom = 1;
177 break;
178 case 'f':
179 fsegname = optarg;
180 break;
181 case 'a':
182 absegname = optarg;
183 break;
184 case 'd':
Richard Smithff8c08e2006-04-23 19:16:09 +0000185 devfn = get_device(optarg);
186 have_devfn = 1;
Li-Ta Lo81521262004-07-08 17:18:27 +0000187 break;
188 case 'D':
189 debugflag = strtol(optarg, 0, 0);
190 break;
191 default:
192 printf("Unknown option \n");
193 usage(argv[0]);
194 return 1;
195 }
196 }
197
198 if (optind >= argc) {
199 printf("Filename missing.\n");
200 usage(argv[0]);
201 return 1;
202 }
203
204 while (optind < argc) {
205 printf("running file %s\n", argv[optind]);
206 filename = argv[optind];
207 optind++;
208 /* normally we would do continue, but for
209 * now only one filename is supported.
210 */
211 /* continue; */
212 break;
213 }
214
215 if (!have_size) {
216 printf("No size specified. defaulting to 32k\n");
217 size = 32 * 1024;
218 }
219 if (!have_base) {
220 printf("No base specified. defaulting to 0xc0000\n");
221 base = 0xc0000;
222 }
223 if (!have_cs) {
224 printf("No initial code segment specified. defaulting to 0xc000\n");
225 initialcs = 0xc000;
226 }
227 if (!have_ip) {
228 printf
229 ("No initial instruction pointer specified. defaulting to 0x0003\n");
230 initialip = 0x0003;
231 }
232
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700233 if (parse_rom)
234 printf("Parsing rom images not implemented.\n");
235
Li-Ta Lo81521262004-07-08 17:18:27 +0000236 //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
237
Richard Smithff8c08e2006-04-23 19:16:09 +0000238 if (initialip == 0x0003) {
239 if ((devfn == 0) || (have_devfn == 0)) {
240 printf("WARNING! It appears you are trying to run an option ROM.\n");
241 printf(" (initial ip = 0x0003)\n");
242 if (have_devfn) {
243 printf(" However, the device you have specified is 0x00\n");
244 printf(" It is very unlikely that your device is at this address\n");
245 printf(" Please check your -d option\n");
246 }
247 else {
248 printf(" Please specify a device with -d\n");
249 printf(" The default is not likely to work\n");
250 }
251 }
252 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000253
Li-Ta Lo81521262004-07-08 17:18:27 +0000254 if (absegname) {
255 abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
256 if (!abseg)
257 die(absegname);
258 }
259
260 current = &p;
261 X86EMU_setMemBase(biosmem, sizeof(biosmem));
Stefan Reinauer86051f92010-03-23 15:53:38 +0000262 M.abseg = (unsigned long)abseg;
Li-Ta Lo81521262004-07-08 17:18:27 +0000263 X86EMU_setupPioFuncs(&myfuncs);
264 ioperm(0, 0x400, 1);
265
Ronald G. Minnich284c27f2004-11-28 04:39:45 +0000266 if (iopl(3) < 0) {
267 warn("iopl failed, continuing anyway");
268 }
Li-Ta Lo81521262004-07-08 17:18:27 +0000269
270 /* Emergency sync ;-) */
271 sync();
272 sync();
273
274 /* Setting up interrupt environment.
275 * basically this means initializing PCI and
276 * intXX handlers.
277 */
278 pciInit();
279
280 for (i = 0; i < 256; i++)
281 intFuncs[i] = do_int;
282 X86EMU_setupIntrFuncs(intFuncs);
283 cp = mapitin(filename, (off_t) 0, size);
284
Richard Smithff8c08e2006-04-23 19:16:09 +0000285 if (devfn) {
286 printf("Loading ax with BusDevFn = %x\n",devfn);
287 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000288
Li-Ta Lo81521262004-07-08 17:18:27 +0000289 current->ax = devfn ? devfn : 0xff;
290 current->dx = 0x80;
291 // current->ip = 0;
292 for (i = 0; i < size; i++)
293 wrb(base + i, cp[i]);
294
295 if (fsegname) {
296 fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
297 for (i = 0; i < 0x10000; i++)
298 wrb(0xf0000 + i, fsegptr[i]);
299 } else {
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700300 const char *date = "01/01/99";
Li-Ta Lo81521262004-07-08 17:18:27 +0000301 for (i = i; date[i]; i++)
302 wrb(0xffff5 + i, date[i]);
303 wrb(0xffff7, '/');
304 wrb(0xffffa, '/');
305 }
306 /* cpu setup */
307 X86_AX = devfn ? devfn : 0xff;
308 X86_DX = 0x80;
309 X86_EIP = initialip;
310 X86_CS = initialcs;
311
312 /* Initialize stack and data segment */
313 X86_SS = 0x0030;
314 X86_DS = 0x0040;
315 X86_SP = 0xfffe;
316 /* We need a sane way to return from bios
317 * execution. A hlt instruction and a pointer
318 * to it, both kept on the stack, will do.
319 */
320 pushw(0xf4f4); /* hlt; hlt */
321 pushw(X86_SS);
322 pushw(X86_SP + 2);
323
324 X86_ES = 0x0000;
325
326 if (trace) {
327 printf("Switching to single step mode.\n");
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000328 //X86EMU_trace_on();
Li-Ta Lo81521262004-07-08 17:18:27 +0000329 }
330 if (debugflag) {
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000331 //X86EMU_set_debug(debugflag);
Li-Ta Lo81521262004-07-08 17:18:27 +0000332 }
333 X86EMU_exec();
334 /* Cleaning up */
335 pciExit();
336
337 return 0;
338}
Richard Smithff8c08e2006-04-23 19:16:09 +0000339
340unsigned short get_device(char *arg_val)
341{
342 unsigned short devfn=0;
343 long bus=0,dev=0,fn=0,need_pack=0;
344 char *tok;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000345
Richard Smithff8c08e2006-04-23 19:16:09 +0000346 tok = strsep(&arg_val,":");
347 if (arg_val != NULL) {
348 bus = strtol(tok,0,16);
349 need_pack = 1;
350 }
351 else {
352 arg_val = tok;
353 }
354
355 tok = strsep(&arg_val,".");
356 if (arg_val != NULL) {
357 dev = strtol(tok,0,16);
358 fn = strtol(arg_val,0,16);
359 need_pack = 1;
360 }
361 else {
362 if (need_pack ==1 && (strlen(tok))) {
Stefan Reinauer14e22772010-04-27 06:56:47 +0000363 dev = strtol(tok,0,16);
Richard Smithff8c08e2006-04-23 19:16:09 +0000364 }
365 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000366
Richard Smithff8c08e2006-04-23 19:16:09 +0000367 if ( need_pack == 1) {
368 devfn = bus<<8 | (dev<<3) | fn;
369 }
370 else {
371 devfn = strtol(tok, 0, 0);
372 }
373
374
375 return devfn;
376}
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700377
378int printk(int msg_level, const char *fmt, ...)
379{
380 va_list args;
381 int i;
382
383 printf ("<%d> ", msg_level);
384 va_start(args, fmt);
385 i = vprintf(fmt, args);
386 va_end(args);
387
388 return i;
389}