blob: d66c857bbff5b889ab2c15679f145b1a26f4b42d [file] [log] [blame]
Patrick Georgi7333a112020-05-08 20:48:04 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer05082732015-10-21 13:00:41 -07002
Li-Ta Lo81521262004-07-08 17:18:27 +00003#include <stdio.h>
4#include <stdlib.h>
5#include <unistd.h>
6#include <sys/io.h>
7#include <sys/mman.h>
8#include <fcntl.h>
9#include <getopt.h>
Richard Smithff8c08e2006-04-23 19:16:09 +000010#include <string.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070011#include <stdarg.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070012#include <stdtypes.h>
Li-Ta Lo81521262004-07-08 17:18:27 +000013#define die(x) { perror(x); exit(1); }
Ronald G. Minnich284c27f2004-11-28 04:39:45 +000014#define warn(x) { perror(x); }
Li-Ta Lo81521262004-07-08 17:18:27 +000015
Stefan Reinauer86051f92010-03-23 15:53:38 +000016#include <x86emu/x86emu.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070017#include <console/console.h>
Stefan Reinauer05082732015-10-21 13:00:41 -070018#include <arch/byteorder.h>
19#include "device.h"
20
Stefan Reinauer850e7d42015-09-28 13:12:04 -070021#include "testbios.h"
Li-Ta Lo81521262004-07-08 17:18:27 +000022#include "pci-userspace.h"
Stefan Reinauer850e7d42015-09-28 13:12:04 -070023int X86EMU_set_debug(int debug);
Stefan Reinauer05082732015-10-21 13:00:41 -070024
25biosemu_device_t bios_device;
Richard Smithff8c08e2006-04-23 19:16:09 +000026
Li-Ta Lo81521262004-07-08 17:18:27 +000027extern int teststart, testend;
28
Stefan Reinauer05082732015-10-21 13:00:41 -070029#define BIOSMEM_SIZE (1024 * 1024)
30unsigned char biosmem[BIOSMEM_SIZE];
Li-Ta Lo81521262004-07-08 17:18:27 +000031
32int verbose = 0;
33
Stefan Reinauer850e7d42015-09-28 13:12:04 -070034static unsigned char *mapitin(char *file, off_t where, size_t size)
Li-Ta Lo81521262004-07-08 17:18:27 +000035{
36 void *z;
37
38 int fd = open(file, O_RDWR, 0);
39
40 if (fd < 0)
41 die(file);
42 z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
43 if (z == (void *) -1)
44 die("mmap");
45 close(fd);
46
47 return z;
Li-Ta Lo81521262004-07-08 17:18:27 +000048}
49
Stefan Reinauer05082732015-10-21 13:00:41 -070050static unsigned short get_device(char *arg_val)
51{
52 unsigned short devfn=0;
53 long bus=0,dev=0,fn=0,need_pack=0;
54 char *tok;
Li-Ta Lo81521262004-07-08 17:18:27 +000055
Stefan Reinauer05082732015-10-21 13:00:41 -070056 tok = strsep(&arg_val,":");
57 if (arg_val != NULL) {
58 bus = strtol(tok,0,16);
59 need_pack = 1;
60 }
61 else {
62 arg_val = tok;
63 }
64
65 tok = strsep(&arg_val,".");
66 if (arg_val != NULL) {
67 dev = strtol(tok,0,16);
68 fn = strtol(arg_val,0,16);
69 need_pack = 1;
70 }
71 else {
72 if (need_pack ==1 && (strlen(tok))) {
73 dev = strtol(tok,0,16);
74 }
75 }
76
77 if ( need_pack == 1) {
78 devfn = bus<<8 | (dev<<3) | fn;
79 }
80 else {
81 devfn = strtol(tok, 0, 0);
82 }
83
84 return devfn;
85}
86
87int printk(int msg_level, const char *fmt, ...)
88{
89 va_list args;
90 int i;
91
Stefan Reinauere2804c12017-07-20 00:53:53 +020092 putchar('<');
93 putchar('0' + msg_level);
94 putchar('>');
95 putchar(' ');
Stefan Reinauer05082732015-10-21 13:00:41 -070096 va_start(args, fmt);
97 i = vprintf(fmt, args);
98 va_end(args);
99
100 return i;
101}
Li-Ta Lo81521262004-07-08 17:18:27 +0000102
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700103static void usage(char *name)
Li-Ta Lo81521262004-07-08 17:18:27 +0000104{
105 printf
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200106 ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] "
107 "<filename> ...\n", name);
Li-Ta Lo81521262004-07-08 17:18:27 +0000108}
109
Stefan Reinauer05082732015-10-21 13:00:41 -0700110/* main entry into YABEL biosemu, arguments are:
111 * *biosmem = pointer to virtual memory
112 * biosmem_size = size of the virtual memory
113 * *dev = pointer to the device to be initialised
114 * rom_addr = address of the OptionROM to be executed, if this is = 0, YABEL
115 * will look for an ExpansionROM BAR and use the code from there.
116 */
117u32
118biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long
119 rom_addr);
120
121
Li-Ta Lo81521262004-07-08 17:18:27 +0000122int main(int argc, char **argv)
123{
Stefan Reinauer05082732015-10-21 13:00:41 -0700124 int ret;
Elyes HAOUAS1d3fde42018-06-05 08:41:29 +0200125 char *absegname = NULL;
126 void *abseg = NULL;
Stefan Reinauer05082732015-10-21 13:00:41 -0700127 int c, trace = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000128 unsigned char *cp;
129 char *filename;
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700130 ssize_t size = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000131 int base = 0;
132 int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
Richard Smithff8c08e2006-04-23 19:16:09 +0000133 int have_devfn = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000134 int parse_rom = 0;
Stefan Reinauer05082732015-10-21 13:00:41 -0700135 //char *fsegname = 0;
136 //unsigned char *fsegptr;
Li-Ta Lo81521262004-07-08 17:18:27 +0000137 unsigned short initialip = 0, initialcs = 0, devfn = 0;
Stefan Reinauer05082732015-10-21 13:00:41 -0700138 //X86EMU_intrFuncs intFuncs[256];
Li-Ta Lo81521262004-07-08 17:18:27 +0000139 int debugflag = 0;
Stefan Reinauer05082732015-10-21 13:00:41 -0700140 struct device *dev;
Li-Ta Lo81521262004-07-08 17:18:27 +0000141
Stefan Reinauer05082732015-10-21 13:00:41 -0700142 //const char *optstring = "vh?b:i:c:s:tpd:";
Li-Ta Lo81521262004-07-08 17:18:27 +0000143 const char *optstring = "vh?b:i:c:s:tpd:";
144 while (1) {
145 int option_index = 0;
146 static struct option long_options[] = {
147 {"verbose", 0, 0, 'v'},
148 {"help", 0, 0, 'h'},
149 {"trace", 0, 0, 't'},
150 {"base", 1, 0, 'b'},
Stefan Reinauer05082732015-10-21 13:00:41 -0700151 //{"fseg", 1, 0, 'f'},
Li-Ta Lo81521262004-07-08 17:18:27 +0000152 {"instructionpointer", 1, 0, 'i'},
153 {"codesegment", 1, 0, 'c'},
154 {"absegment", 1, 0, 'a'},
155 {"size", 1, 0, 's'},
156 {"parserom", 0, 0, 'p'},
157 {"device", 1, 0, 'd'},
158 {"debug", 1, 0, 'D'},
159 {0, 0, 0, 0}
160 };
161 c = getopt_long(argc, argv, optstring, long_options, &option_index);
162 if (c == -1)
163 break;
164 switch (c) {
165 case 'v':
166 verbose = 1;
167 break;
168 case 'h':
169 case '?':
170 usage(argv[0]);
171 return 0;
172 case 't':
173 trace = 1;
174 break;
Stefan Reinauer05082732015-10-21 13:00:41 -0700175 //case 'b':
176 // base = strtol(optarg, 0, 0);
177 // have_base = 1;
178 // break;
Li-Ta Lo81521262004-07-08 17:18:27 +0000179 case 'i':
180 initialip = strtol(optarg, 0, 0);
181 have_ip = 1;
182 break;
183 case 'c':
184 initialcs = strtol(optarg, 0, 0);
185 have_cs = 1;
186 break;
187 case 's':
188 size = strtol(optarg, 0, 0);
189 have_size = 1;
190 break;
191 case 'p':
Li-Ta Lo81521262004-07-08 17:18:27 +0000192 parse_rom = 1;
193 break;
Stefan Reinauer05082732015-10-21 13:00:41 -0700194 // case 'f':
195 // fsegname = optarg;
196 // break;
Li-Ta Lo81521262004-07-08 17:18:27 +0000197 case 'a':
198 absegname = optarg;
199 break;
200 case 'd':
Richard Smithff8c08e2006-04-23 19:16:09 +0000201 devfn = get_device(optarg);
202 have_devfn = 1;
Li-Ta Lo81521262004-07-08 17:18:27 +0000203 break;
204 case 'D':
205 debugflag = strtol(optarg, 0, 0);
206 break;
207 default:
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200208 printf("Unknown option\n");
Li-Ta Lo81521262004-07-08 17:18:27 +0000209 usage(argv[0]);
210 return 1;
211 }
212 }
213
214 if (optind >= argc) {
215 printf("Filename missing.\n");
216 usage(argv[0]);
217 return 1;
218 }
219
220 while (optind < argc) {
221 printf("running file %s\n", argv[optind]);
222 filename = argv[optind];
223 optind++;
224 /* normally we would do continue, but for
225 * now only one filename is supported.
226 */
227 /* continue; */
228 break;
229 }
230
231 if (!have_size) {
232 printf("No size specified. defaulting to 32k\n");
233 size = 32 * 1024;
234 }
235 if (!have_base) {
236 printf("No base specified. defaulting to 0xc0000\n");
237 base = 0xc0000;
238 }
Stefan Reinauer05082732015-10-21 13:00:41 -0700239 //if (!have_cs) {
240 // printf("No initial code segment specified. defaulting to 0xc000\n");
241 // initialcs = 0xc000;
242 //}
Li-Ta Lo81521262004-07-08 17:18:27 +0000243 if (!have_ip) {
244 printf
245 ("No initial instruction pointer specified. defaulting to 0x0003\n");
246 initialip = 0x0003;
247 }
248
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700249 if (parse_rom)
250 printf("Parsing rom images not implemented.\n");
251
Li-Ta Lo81521262004-07-08 17:18:27 +0000252 //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
Stefan Reinauer05082732015-10-21 13:00:41 -0700253#if 0
Richard Smithff8c08e2006-04-23 19:16:09 +0000254 if (initialip == 0x0003) {
255 if ((devfn == 0) || (have_devfn == 0)) {
256 printf("WARNING! It appears you are trying to run an option ROM.\n");
257 printf(" (initial ip = 0x0003)\n");
258 if (have_devfn) {
259 printf(" However, the device you have specified is 0x00\n");
260 printf(" It is very unlikely that your device is at this address\n");
261 printf(" Please check your -d option\n");
262 }
263 else {
264 printf(" Please specify a device with -d\n");
265 printf(" The default is not likely to work\n");
266 }
267 }
268 }
Stefan Reinauer05082732015-10-21 13:00:41 -0700269#endif
Stefan Reinauer14e22772010-04-27 06:56:47 +0000270
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
Li-Ta Lo81521262004-07-08 17:18:27 +0000277 ioperm(0, 0x400, 1);
278
Ronald G. Minnich284c27f2004-11-28 04:39:45 +0000279 if (iopl(3) < 0) {
280 warn("iopl failed, continuing anyway");
281 }
Li-Ta Lo81521262004-07-08 17:18:27 +0000282
283 /* Emergency sync ;-) */
284 sync();
285 sync();
286
287 /* Setting up interrupt environment.
288 * basically this means initializing PCI and
289 * intXX handlers.
290 */
Stefan Reinauer05082732015-10-21 13:00:41 -0700291 pci_initialize();
Li-Ta Lo81521262004-07-08 17:18:27 +0000292
Stefan Reinauer05082732015-10-21 13:00:41 -0700293#if 0
Li-Ta Lo81521262004-07-08 17:18:27 +0000294 for (i = 0; i < 256; i++)
295 intFuncs[i] = do_int;
296 X86EMU_setupIntrFuncs(intFuncs);
Stefan Reinauer05082732015-10-21 13:00:41 -0700297#endif
Li-Ta Lo81521262004-07-08 17:18:27 +0000298 cp = mapitin(filename, (off_t) 0, size);
299
Richard Smithff8c08e2006-04-23 19:16:09 +0000300 if (devfn) {
301 printf("Loading ax with BusDevFn = %x\n",devfn);
302 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000303
Stefan Reinauer05082732015-10-21 13:00:41 -0700304#if 0
Li-Ta Lo81521262004-07-08 17:18:27 +0000305 current->ax = devfn ? devfn : 0xff;
306 current->dx = 0x80;
307 // current->ip = 0;
308 for (i = 0; i < size; i++)
309 wrb(base + i, cp[i]);
310
311 if (fsegname) {
312 fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
313 for (i = 0; i < 0x10000; i++)
314 wrb(0xf0000 + i, fsegptr[i]);
315 } else {
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700316 const char *date = "01/01/99";
Li-Ta Lo81521262004-07-08 17:18:27 +0000317 for (i = i; date[i]; i++)
318 wrb(0xffff5 + i, date[i]);
319 wrb(0xffff7, '/');
320 wrb(0xffffa, '/');
321 }
322 /* cpu setup */
323 X86_AX = devfn ? devfn : 0xff;
324 X86_DX = 0x80;
325 X86_EIP = initialip;
326 X86_CS = initialcs;
327
328 /* Initialize stack and data segment */
329 X86_SS = 0x0030;
330 X86_DS = 0x0040;
331 X86_SP = 0xfffe;
332 /* We need a sane way to return from bios
333 * execution. A hlt instruction and a pointer
334 * to it, both kept on the stack, will do.
335 */
336 pushw(0xf4f4); /* hlt; hlt */
337 pushw(X86_SS);
338 pushw(X86_SP + 2);
339
340 X86_ES = 0x0000;
Stefan Reinauer05082732015-10-21 13:00:41 -0700341#endif
Li-Ta Lo81521262004-07-08 17:18:27 +0000342
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) {
Stefan Reinauer05082732015-10-21 13:00:41 -0700348 printf("Enable Debug = %x.\n",debugflag);
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000349 //X86EMU_set_debug(debugflag);
Li-Ta Lo81521262004-07-08 17:18:27 +0000350 }
Stefan Reinauer05082732015-10-21 13:00:41 -0700351#if 0
Li-Ta Lo81521262004-07-08 17:18:27 +0000352 X86EMU_exec();
Stefan Reinauer05082732015-10-21 13:00:41 -0700353#endif
354
355 ret = biosemu(biosmem, BIOSMEM_SIZE, dev, base);
356
357#if 0
358 current = &p;
359 X86EMU_setMemBase(biosmem, sizeof(biosmem));
360 M.abseg = (unsigned long)abseg;
361 X86EMU_setupPioFuncs(&myfuncs);
362#endif
363
Li-Ta Lo81521262004-07-08 17:18:27 +0000364 /* Cleaning up */
Stefan Reinauer05082732015-10-21 13:00:41 -0700365 pci_exit();
Li-Ta Lo81521262004-07-08 17:18:27 +0000366
367 return 0;
368}