blob: de537b8fcd2f74fee05093481eb2ea973b155356 [file] [log] [blame]
Stefan Reinauer05082732015-10-21 13:00:41 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2016 Google Inc
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
Li-Ta Lo81521262004-07-08 17:18:27 +000016#include <stdio.h>
17#include <stdlib.h>
18#include <unistd.h>
19#include <sys/io.h>
20#include <sys/mman.h>
21#include <fcntl.h>
22#include <getopt.h>
Richard Smithff8c08e2006-04-23 19:16:09 +000023#include <string.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070024#include <stdarg.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070025#include <stdtypes.h>
Li-Ta Lo81521262004-07-08 17:18:27 +000026#define die(x) { perror(x); exit(1); }
Ronald G. Minnich284c27f2004-11-28 04:39:45 +000027#define warn(x) { perror(x); }
Li-Ta Lo81521262004-07-08 17:18:27 +000028
Stefan Reinauer86051f92010-03-23 15:53:38 +000029#include <x86emu/x86emu.h>
Stefan Reinauer850e7d42015-09-28 13:12:04 -070030#include <console/console.h>
Stefan Reinauer05082732015-10-21 13:00:41 -070031#include <arch/byteorder.h>
32#include "device.h"
33
Stefan Reinauer850e7d42015-09-28 13:12:04 -070034#include "testbios.h"
Li-Ta Lo81521262004-07-08 17:18:27 +000035#include "pci-userspace.h"
Stefan Reinauer850e7d42015-09-28 13:12:04 -070036int X86EMU_set_debug(int debug);
Stefan Reinauer05082732015-10-21 13:00:41 -070037
38biosemu_device_t bios_device;
Richard Smithff8c08e2006-04-23 19:16:09 +000039
Li-Ta Lo81521262004-07-08 17:18:27 +000040extern int teststart, testend;
41
Stefan Reinauer05082732015-10-21 13:00:41 -070042#define BIOSMEM_SIZE (1024 * 1024)
43unsigned char biosmem[BIOSMEM_SIZE];
Li-Ta Lo81521262004-07-08 17:18:27 +000044
45int verbose = 0;
46
Stefan Reinauer850e7d42015-09-28 13:12:04 -070047static unsigned char *mapitin(char *file, off_t where, size_t size)
Li-Ta Lo81521262004-07-08 17:18:27 +000048{
49 void *z;
50
51 int fd = open(file, O_RDWR, 0);
52
53 if (fd < 0)
54 die(file);
55 z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
56 if (z == (void *) -1)
57 die("mmap");
58 close(fd);
59
60 return z;
Li-Ta Lo81521262004-07-08 17:18:27 +000061}
62
Stefan Reinauer05082732015-10-21 13:00:41 -070063static unsigned short get_device(char *arg_val)
64{
65 unsigned short devfn=0;
66 long bus=0,dev=0,fn=0,need_pack=0;
67 char *tok;
Li-Ta Lo81521262004-07-08 17:18:27 +000068
Stefan Reinauer05082732015-10-21 13:00:41 -070069 tok = strsep(&arg_val,":");
70 if (arg_val != NULL) {
71 bus = strtol(tok,0,16);
72 need_pack = 1;
73 }
74 else {
75 arg_val = tok;
76 }
77
78 tok = strsep(&arg_val,".");
79 if (arg_val != NULL) {
80 dev = strtol(tok,0,16);
81 fn = strtol(arg_val,0,16);
82 need_pack = 1;
83 }
84 else {
85 if (need_pack ==1 && (strlen(tok))) {
86 dev = strtol(tok,0,16);
87 }
88 }
89
90 if ( need_pack == 1) {
91 devfn = bus<<8 | (dev<<3) | fn;
92 }
93 else {
94 devfn = strtol(tok, 0, 0);
95 }
96
97 return devfn;
98}
99
100int printk(int msg_level, const char *fmt, ...)
101{
102 va_list args;
103 int i;
104
Stefan Reinauere2804c12017-07-20 00:53:53 +0200105 putchar('<');
106 putchar('0' + msg_level);
107 putchar('>');
108 putchar(' ');
Stefan Reinauer05082732015-10-21 13:00:41 -0700109 va_start(args, fmt);
110 i = vprintf(fmt, args);
111 va_end(args);
112
113 return i;
114}
Li-Ta Lo81521262004-07-08 17:18:27 +0000115
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700116static void usage(char *name)
Li-Ta Lo81521262004-07-08 17:18:27 +0000117{
118 printf
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200119 ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] "
120 "<filename> ...\n", name);
Li-Ta Lo81521262004-07-08 17:18:27 +0000121}
122
Stefan Reinauer05082732015-10-21 13:00:41 -0700123/* main entry into YABEL biosemu, arguments are:
124 * *biosmem = pointer to virtual memory
125 * biosmem_size = size of the virtual memory
126 * *dev = pointer to the device to be initialised
127 * rom_addr = address of the OptionROM to be executed, if this is = 0, YABEL
128 * will look for an ExpansionROM BAR and use the code from there.
129 */
130u32
131biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long
132 rom_addr);
133
134
Li-Ta Lo81521262004-07-08 17:18:27 +0000135int main(int argc, char **argv)
136{
Stefan Reinauer05082732015-10-21 13:00:41 -0700137 int ret;
Elyes HAOUAS1d3fde42018-06-05 08:41:29 +0200138 char *absegname = NULL;
139 void *abseg = NULL;
Stefan Reinauer05082732015-10-21 13:00:41 -0700140 int c, trace = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000141 unsigned char *cp;
142 char *filename;
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700143 ssize_t size = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000144 int base = 0;
145 int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
Richard Smithff8c08e2006-04-23 19:16:09 +0000146 int have_devfn = 0;
Li-Ta Lo81521262004-07-08 17:18:27 +0000147 int parse_rom = 0;
Stefan Reinauer05082732015-10-21 13:00:41 -0700148 //char *fsegname = 0;
149 //unsigned char *fsegptr;
Li-Ta Lo81521262004-07-08 17:18:27 +0000150 unsigned short initialip = 0, initialcs = 0, devfn = 0;
Stefan Reinauer05082732015-10-21 13:00:41 -0700151 //X86EMU_intrFuncs intFuncs[256];
Li-Ta Lo81521262004-07-08 17:18:27 +0000152 int debugflag = 0;
Stefan Reinauer05082732015-10-21 13:00:41 -0700153 struct device *dev;
Li-Ta Lo81521262004-07-08 17:18:27 +0000154
Stefan Reinauer05082732015-10-21 13:00:41 -0700155 //const char *optstring = "vh?b:i:c:s:tpd:";
Li-Ta Lo81521262004-07-08 17:18:27 +0000156 const char *optstring = "vh?b:i:c:s:tpd:";
157 while (1) {
158 int option_index = 0;
159 static struct option long_options[] = {
160 {"verbose", 0, 0, 'v'},
161 {"help", 0, 0, 'h'},
162 {"trace", 0, 0, 't'},
163 {"base", 1, 0, 'b'},
Stefan Reinauer05082732015-10-21 13:00:41 -0700164 //{"fseg", 1, 0, 'f'},
Li-Ta Lo81521262004-07-08 17:18:27 +0000165 {"instructionpointer", 1, 0, 'i'},
166 {"codesegment", 1, 0, 'c'},
167 {"absegment", 1, 0, 'a'},
168 {"size", 1, 0, 's'},
169 {"parserom", 0, 0, 'p'},
170 {"device", 1, 0, 'd'},
171 {"debug", 1, 0, 'D'},
172 {0, 0, 0, 0}
173 };
174 c = getopt_long(argc, argv, optstring, long_options, &option_index);
175 if (c == -1)
176 break;
177 switch (c) {
178 case 'v':
179 verbose = 1;
180 break;
181 case 'h':
182 case '?':
183 usage(argv[0]);
184 return 0;
185 case 't':
186 trace = 1;
187 break;
Stefan Reinauer05082732015-10-21 13:00:41 -0700188 //case 'b':
189 // base = strtol(optarg, 0, 0);
190 // have_base = 1;
191 // break;
Li-Ta Lo81521262004-07-08 17:18:27 +0000192 case 'i':
193 initialip = strtol(optarg, 0, 0);
194 have_ip = 1;
195 break;
196 case 'c':
197 initialcs = strtol(optarg, 0, 0);
198 have_cs = 1;
199 break;
200 case 's':
201 size = strtol(optarg, 0, 0);
202 have_size = 1;
203 break;
204 case 'p':
Li-Ta Lo81521262004-07-08 17:18:27 +0000205 parse_rom = 1;
206 break;
Stefan Reinauer05082732015-10-21 13:00:41 -0700207 // case 'f':
208 // fsegname = optarg;
209 // break;
Li-Ta Lo81521262004-07-08 17:18:27 +0000210 case 'a':
211 absegname = optarg;
212 break;
213 case 'd':
Richard Smithff8c08e2006-04-23 19:16:09 +0000214 devfn = get_device(optarg);
215 have_devfn = 1;
Li-Ta Lo81521262004-07-08 17:18:27 +0000216 break;
217 case 'D':
218 debugflag = strtol(optarg, 0, 0);
219 break;
220 default:
Elyes HAOUASb0f19882018-06-09 11:59:00 +0200221 printf("Unknown option\n");
Li-Ta Lo81521262004-07-08 17:18:27 +0000222 usage(argv[0]);
223 return 1;
224 }
225 }
226
227 if (optind >= argc) {
228 printf("Filename missing.\n");
229 usage(argv[0]);
230 return 1;
231 }
232
233 while (optind < argc) {
234 printf("running file %s\n", argv[optind]);
235 filename = argv[optind];
236 optind++;
237 /* normally we would do continue, but for
238 * now only one filename is supported.
239 */
240 /* continue; */
241 break;
242 }
243
244 if (!have_size) {
245 printf("No size specified. defaulting to 32k\n");
246 size = 32 * 1024;
247 }
248 if (!have_base) {
249 printf("No base specified. defaulting to 0xc0000\n");
250 base = 0xc0000;
251 }
Stefan Reinauer05082732015-10-21 13:00:41 -0700252 //if (!have_cs) {
253 // printf("No initial code segment specified. defaulting to 0xc000\n");
254 // initialcs = 0xc000;
255 //}
Li-Ta Lo81521262004-07-08 17:18:27 +0000256 if (!have_ip) {
257 printf
258 ("No initial instruction pointer specified. defaulting to 0x0003\n");
259 initialip = 0x0003;
260 }
261
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700262 if (parse_rom)
263 printf("Parsing rom images not implemented.\n");
264
Li-Ta Lo81521262004-07-08 17:18:27 +0000265 //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
Stefan Reinauer05082732015-10-21 13:00:41 -0700266#if 0
Richard Smithff8c08e2006-04-23 19:16:09 +0000267 if (initialip == 0x0003) {
268 if ((devfn == 0) || (have_devfn == 0)) {
269 printf("WARNING! It appears you are trying to run an option ROM.\n");
270 printf(" (initial ip = 0x0003)\n");
271 if (have_devfn) {
272 printf(" However, the device you have specified is 0x00\n");
273 printf(" It is very unlikely that your device is at this address\n");
274 printf(" Please check your -d option\n");
275 }
276 else {
277 printf(" Please specify a device with -d\n");
278 printf(" The default is not likely to work\n");
279 }
280 }
281 }
Stefan Reinauer05082732015-10-21 13:00:41 -0700282#endif
Stefan Reinauer14e22772010-04-27 06:56:47 +0000283
Li-Ta Lo81521262004-07-08 17:18:27 +0000284 if (absegname) {
285 abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
286 if (!abseg)
287 die(absegname);
288 }
289
Li-Ta Lo81521262004-07-08 17:18:27 +0000290 ioperm(0, 0x400, 1);
291
Ronald G. Minnich284c27f2004-11-28 04:39:45 +0000292 if (iopl(3) < 0) {
293 warn("iopl failed, continuing anyway");
294 }
Li-Ta Lo81521262004-07-08 17:18:27 +0000295
296 /* Emergency sync ;-) */
297 sync();
298 sync();
299
300 /* Setting up interrupt environment.
301 * basically this means initializing PCI and
302 * intXX handlers.
303 */
Stefan Reinauer05082732015-10-21 13:00:41 -0700304 pci_initialize();
Li-Ta Lo81521262004-07-08 17:18:27 +0000305
Stefan Reinauer05082732015-10-21 13:00:41 -0700306#if 0
Li-Ta Lo81521262004-07-08 17:18:27 +0000307 for (i = 0; i < 256; i++)
308 intFuncs[i] = do_int;
309 X86EMU_setupIntrFuncs(intFuncs);
Stefan Reinauer05082732015-10-21 13:00:41 -0700310#endif
Li-Ta Lo81521262004-07-08 17:18:27 +0000311 cp = mapitin(filename, (off_t) 0, size);
312
Richard Smithff8c08e2006-04-23 19:16:09 +0000313 if (devfn) {
314 printf("Loading ax with BusDevFn = %x\n",devfn);
315 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000316
Stefan Reinauer05082732015-10-21 13:00:41 -0700317#if 0
Li-Ta Lo81521262004-07-08 17:18:27 +0000318 current->ax = devfn ? devfn : 0xff;
319 current->dx = 0x80;
320 // current->ip = 0;
321 for (i = 0; i < size; i++)
322 wrb(base + i, cp[i]);
323
324 if (fsegname) {
325 fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
326 for (i = 0; i < 0x10000; i++)
327 wrb(0xf0000 + i, fsegptr[i]);
328 } else {
Stefan Reinauer850e7d42015-09-28 13:12:04 -0700329 const char *date = "01/01/99";
Li-Ta Lo81521262004-07-08 17:18:27 +0000330 for (i = i; date[i]; i++)
331 wrb(0xffff5 + i, date[i]);
332 wrb(0xffff7, '/');
333 wrb(0xffffa, '/');
334 }
335 /* cpu setup */
336 X86_AX = devfn ? devfn : 0xff;
337 X86_DX = 0x80;
338 X86_EIP = initialip;
339 X86_CS = initialcs;
340
341 /* Initialize stack and data segment */
342 X86_SS = 0x0030;
343 X86_DS = 0x0040;
344 X86_SP = 0xfffe;
345 /* We need a sane way to return from bios
346 * execution. A hlt instruction and a pointer
347 * to it, both kept on the stack, will do.
348 */
349 pushw(0xf4f4); /* hlt; hlt */
350 pushw(X86_SS);
351 pushw(X86_SP + 2);
352
353 X86_ES = 0x0000;
Stefan Reinauer05082732015-10-21 13:00:41 -0700354#endif
Li-Ta Lo81521262004-07-08 17:18:27 +0000355
356 if (trace) {
357 printf("Switching to single step mode.\n");
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000358 //X86EMU_trace_on();
Li-Ta Lo81521262004-07-08 17:18:27 +0000359 }
360 if (debugflag) {
Stefan Reinauer05082732015-10-21 13:00:41 -0700361 printf("Enable Debug = %x.\n",debugflag);
Li-Ta Lo8b0356c2005-01-11 03:18:39 +0000362 //X86EMU_set_debug(debugflag);
Li-Ta Lo81521262004-07-08 17:18:27 +0000363 }
Stefan Reinauer05082732015-10-21 13:00:41 -0700364#if 0
Li-Ta Lo81521262004-07-08 17:18:27 +0000365 X86EMU_exec();
Stefan Reinauer05082732015-10-21 13:00:41 -0700366#endif
367
368 ret = biosemu(biosmem, BIOSMEM_SIZE, dev, base);
369
370#if 0
371 current = &p;
372 X86EMU_setMemBase(biosmem, sizeof(biosmem));
373 M.abseg = (unsigned long)abseg;
374 X86EMU_setupPioFuncs(&myfuncs);
375#endif
376
Li-Ta Lo81521262004-07-08 17:18:27 +0000377 /* Cleaning up */
Stefan Reinauer05082732015-10-21 13:00:41 -0700378 pci_exit();
Li-Ta Lo81521262004-07-08 17:18:27 +0000379
380 return 0;
381}