1 /* SPDX-License-Identifier: GPL-2.0-only */
13 #define die(x) { perror(x); exit(1); }
14 #define warn(x) { perror(x); }
16 #include <x86emu/x86emu.h>
17 #include <console/console.h>
18 #include <arch/byteorder.h>
22 #include "pci-userspace.h"
23 int X86EMU_set_debug(int debug
);
25 biosemu_device_t bios_device
;
27 extern int teststart
, testend
;
29 #define BIOSMEM_SIZE (1024 * 1024)
30 unsigned char biosmem
[BIOSMEM_SIZE
];
34 static unsigned char *mapitin(char *file
, off_t where
, size_t size
)
38 int fd
= open(file
, O_RDWR
, 0);
42 z
= mmap(0, size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, where
);
50 static unsigned short get_device(char *arg_val
)
52 unsigned short devfn
=0;
53 long bus
=0,dev
=0,fn
=0,need_pack
=0;
56 tok
= strsep(&arg_val
,":");
57 if (arg_val
!= NULL
) {
58 bus
= strtol(tok
,0,16);
65 tok
= strsep(&arg_val
,".");
66 if (arg_val
!= NULL
) {
67 dev
= strtol(tok
,0,16);
68 fn
= strtol(arg_val
,0,16);
72 if (need_pack
==1 && (strlen(tok
))) {
73 dev
= strtol(tok
,0,16);
77 if ( need_pack
== 1) {
78 devfn
= bus
<<8 | (dev
<<3) | fn
;
81 devfn
= strtol(tok
, 0, 0);
87 int printk(int msg_level
, const char *fmt
, ...)
93 putchar('0' + msg_level
);
97 i
= vprintf(fmt
, args
);
103 static void usage(char *name
)
106 ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] "
107 "<filename> ...\n", name
);
110 /* 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.
118 biosemu(u8
*biosmem
, u32 biosmem_size
, struct device
* dev
, unsigned long
122 int main(int argc
, char **argv
)
125 char *absegname
= NULL
;
132 int have_size
= 0, have_base
= 0, have_ip
= 0, have_cs
= 0;
135 //char *fsegname = 0;
136 //unsigned char *fsegptr;
137 unsigned short initialip
= 0, initialcs
= 0, devfn
= 0;
138 //X86EMU_intrFuncs intFuncs[256];
142 //const char *optstring = "vh?b:i:c:s:tpd:";
143 const char *optstring
= "vh?b:i:c:s:tpd:";
145 int option_index
= 0;
146 static struct option long_options
[] = {
147 {"verbose", 0, 0, 'v'},
149 {"trace", 0, 0, 't'},
151 //{"fseg", 1, 0, 'f'},
152 {"instructionpointer", 1, 0, 'i'},
153 {"codesegment", 1, 0, 'c'},
154 {"absegment", 1, 0, 'a'},
156 {"parserom", 0, 0, 'p'},
157 {"device", 1, 0, 'd'},
158 {"debug", 1, 0, 'D'},
161 c
= getopt_long(argc
, argv
, optstring
, long_options
, &option_index
);
176 // base = strtol(optarg, 0, 0);
180 initialip
= strtol(optarg
, 0, 0);
184 initialcs
= strtol(optarg
, 0, 0);
188 size
= strtol(optarg
, 0, 0);
195 // fsegname = optarg;
201 devfn
= get_device(optarg
);
205 debugflag
= strtol(optarg
, 0, 0);
208 printf("Unknown option\n");
214 if (optind
>= argc
) {
215 printf("Filename missing.\n");
220 while (optind
< argc
) {
221 printf("running file %s\n", argv
[optind
]);
222 filename
= argv
[optind
];
224 /* normally we would do continue, but for
225 * now only one filename is supported.
232 printf("No size specified. defaulting to 32k\n");
236 printf("No base specified. defaulting to 0xc0000\n");
240 // printf("No initial code segment specified. defaulting to 0xc000\n");
241 // initialcs = 0xc000;
245 ("No initial instruction pointer specified. defaulting to 0x0003\n");
250 printf("Parsing rom images not implemented.\n");
252 //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
254 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");
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");
264 printf(" Please specify a device with -d\n");
265 printf(" The default is not likely to work\n");
272 abseg
= mapitin(absegname
, (off_t
) 0xa0000, 0x20000);
280 warn("iopl failed, continuing anyway");
283 /* Emergency sync ;-) */
287 /* Setting up interrupt environment.
288 * basically this means initializing PCI and
294 for (i
= 0; i
< 256; i
++)
295 intFuncs
[i
] = do_int
;
296 X86EMU_setupIntrFuncs(intFuncs
);
298 cp
= mapitin(filename
, (off_t
) 0, size
);
301 printf("Loading ax with BusDevFn = %x\n",devfn
);
305 current
->ax
= devfn
? devfn
: 0xff;
308 for (i
= 0; i
< size
; i
++)
309 wrb(base
+ i
, cp
[i
]);
312 fsegptr
= mapitin(fsegname
, (off_t
) 0, 0x10000);
313 for (i
= 0; i
< 0x10000; i
++)
314 wrb(0xf0000 + i
, fsegptr
[i
]);
316 const char *date
= "01/01/99";
317 for (i
= i
; date
[i
]; i
++)
318 wrb(0xffff5 + i
, date
[i
]);
323 X86_AX
= devfn
? devfn
: 0xff;
328 /* Initialize stack and data segment */
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.
336 pushw(0xf4f4); /* hlt; hlt */
344 printf("Switching to single step mode.\n");
348 printf("Enable Debug = %x.\n",debugflag
);
349 //X86EMU_set_debug(debugflag);
355 ret
= biosemu(biosmem
, BIOSMEM_SIZE
, dev
, base
);
359 X86EMU_setMemBase(biosmem
, sizeof(biosmem
));
360 M
.abseg
= (unsigned long)abseg
;
361 X86EMU_setupPioFuncs(&myfuncs
);