summaryrefslogtreecommitdiff
path: root/util/vgabios/testbios.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/vgabios/testbios.c')
-rw-r--r--util/vgabios/testbios.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/util/vgabios/testbios.c b/util/vgabios/testbios.c
new file mode 100644
index 0000000000..891e5d2ad7
--- /dev/null
+++ b/util/vgabios/testbios.c
@@ -0,0 +1,328 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/io.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <getopt.h>
+
+#define die(x) { perror(x); exit(1); }
+
+#include <x86emu.h>
+#include "test.h"
+#include "pci-userspace.h"
+
+void x86emu_dump_xregs(void);
+int int15_handler(void);
+int int16_handler(void);
+int int1A_handler(void);
+#ifndef _PC
+int int42_handler(void);
+#endif
+int intE6_handler(void);
+
+void pushw(u16 val);
+
+extern int teststart, testend;
+
+_ptr p;
+ptr current = 0;
+unsigned char biosmem[1024 * 1024];
+
+int verbose = 0;
+
+
+/* Interrupt multiplexer */
+
+void do_int(int num)
+{
+ int ret = 0;
+
+ printf("int%x vector at %x\n", num, getIntVect(num));
+
+ /* This is a pInt leftover */
+ current->num = num;
+
+ switch (num) {
+#ifndef _PC
+ case 0x10:
+ case 0x42:
+ case 0x6D:
+
+ if (getIntVect(num) == 0xFF065) {
+ ret = int42_handler();
+ }
+ break;
+#endif
+ case 0x15:
+ ret = int15_handler();
+ break;
+ case 0x16:
+ ret = int16_handler();
+ break;
+ case 0x1A:
+ ret = int1A_handler();
+ break;
+ case 0xe6:
+ ret = intE6_handler();
+ break;
+ default:
+ break;
+ }
+
+ if (!ret)
+ ret = run_bios_int(num);
+
+ if (!ret) {
+ printf("\nint%x: not implemented\n", num);
+ x86emu_dump_xregs();
+ }
+}
+
+unsigned char *mapitin(char *file, off_t where, size_t size)
+{
+ void *z;
+
+ int fd = open(file, O_RDWR, 0);
+
+ if (fd < 0)
+ die(file);
+ z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
+ if (z == (void *) -1)
+ die("mmap");
+ close(fd);
+
+ return z;
+
+}
+
+u8 x_inb(u16 port);
+u16 x_inw(u16 port);
+void x_outb(u16 port, u8 val);
+void x_outw(u16 port, u16 val);
+u32 x_inl(u16 port);
+void x_outl(u16 port, u32 val);
+
+
+X86EMU_pioFuncs myfuncs = {
+ x_inb, x_inw, x_inl,
+ x_outb, x_outw, x_outl
+};
+
+
+void usage(char *name)
+{
+ printf
+ ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
+ name);
+}
+
+int main(int argc, char **argv)
+{
+ char *absegname = 0;
+ void *abseg = 0;
+ int i, c, trace = 0;
+ unsigned char *cp;
+ char *filename;
+ size_t size = 0;
+ int base = 0;
+ int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
+ int parse_rom = 0;
+ char *fsegname = 0;
+ unsigned char *fsegptr;
+ unsigned short initialip = 0, initialcs = 0, devfn = 0;
+ X86EMU_intrFuncs intFuncs[256];
+ void X86EMU_setMemBase(void *base, size_t size);
+ void X86EMU_setabseg(void *abseg);
+ void x86emu_dump_xregs(void);
+ int X86EMU_set_debug(int debug);
+ int debugflag = 0;
+
+ const char *optstring = "vh?b:i:c:s:tpd:";
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] = {
+ {"verbose", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {"trace", 0, 0, 't'},
+ {"base", 1, 0, 'b'},
+ {"fseg", 1, 0, 'f'},
+ {"instructionpointer", 1, 0, 'i'},
+ {"codesegment", 1, 0, 'c'},
+ {"absegment", 1, 0, 'a'},
+ {"size", 1, 0, 's'},
+ {"parserom", 0, 0, 'p'},
+ {"device", 1, 0, 'd'},
+ {"debug", 1, 0, 'D'},
+ {0, 0, 0, 0}
+ };
+ c = getopt_long(argc, argv, optstring, long_options, &option_index);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'v':
+ verbose = 1;
+ break;
+ case 'h':
+ case '?':
+ usage(argv[0]);
+ return 0;
+ case 't':
+ trace = 1;
+ break;
+ case 'b':
+ base = strtol(optarg, 0, 0);
+ have_base = 1;
+ break;
+ case 'i':
+ initialip = strtol(optarg, 0, 0);
+ have_ip = 1;
+ break;
+ case 'c':
+ initialcs = strtol(optarg, 0, 0);
+ have_cs = 1;
+ break;
+ case 's':
+ size = strtol(optarg, 0, 0);
+ have_size = 1;
+ break;
+ case 'p':
+ printf("Parsing rom images not implemented.\n");
+ parse_rom = 1;
+ break;
+ case 'f':
+ fsegname = optarg;
+ break;
+ case 'a':
+ absegname = optarg;
+ break;
+ case 'd':
+ devfn = strtol(optarg, 0, 0);
+ break;
+ case 'D':
+ debugflag = strtol(optarg, 0, 0);
+ break;
+ default:
+ printf("Unknown option \n");
+ usage(argv[0]);
+ return 1;
+ }
+ }
+
+ if (optind >= argc) {
+ printf("Filename missing.\n");
+ usage(argv[0]);
+ return 1;
+ }
+
+ while (optind < argc) {
+ printf("running file %s\n", argv[optind]);
+ filename = argv[optind];
+ optind++;
+ /* normally we would do continue, but for
+ * now only one filename is supported.
+ */
+ /* continue; */
+ break;
+ }
+
+ if (!have_size) {
+ printf("No size specified. defaulting to 32k\n");
+ size = 32 * 1024;
+ }
+ if (!have_base) {
+ printf("No base specified. defaulting to 0xc0000\n");
+ base = 0xc0000;
+ }
+ if (!have_cs) {
+ printf("No initial code segment specified. defaulting to 0xc000\n");
+ initialcs = 0xc000;
+ }
+ if (!have_ip) {
+ printf
+ ("No initial instruction pointer specified. defaulting to 0x0003\n");
+ initialip = 0x0003;
+ }
+
+ //printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
+
+ if (absegname) {
+ abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
+ if (!abseg)
+ die(absegname);
+ }
+
+ current = &p;
+ X86EMU_setMemBase(biosmem, sizeof(biosmem));
+ X86EMU_setabseg(abseg);
+ X86EMU_setupPioFuncs(&myfuncs);
+ ioperm(0, 0x400, 1);
+
+ if (iopl(3) < 0)
+ die("iopl");
+
+ /* Emergency sync ;-) */
+ sync();
+ sync();
+
+ /* Setting up interrupt environment.
+ * basically this means initializing PCI and
+ * intXX handlers.
+ */
+ pciInit();
+
+ for (i = 0; i < 256; i++)
+ intFuncs[i] = do_int;
+ X86EMU_setupIntrFuncs(intFuncs);
+ cp = mapitin(filename, (off_t) 0, size);
+
+ current->ax = devfn ? devfn : 0xff;
+ current->dx = 0x80;
+ // current->ip = 0;
+ for (i = 0; i < size; i++)
+ wrb(base + i, cp[i]);
+
+ if (fsegname) {
+ fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
+ for (i = 0; i < 0x10000; i++)
+ wrb(0xf0000 + i, fsegptr[i]);
+ } else {
+ char *date = "01/01/99";
+ for (i = i; date[i]; i++)
+ wrb(0xffff5 + i, date[i]);
+ wrb(0xffff7, '/');
+ wrb(0xffffa, '/');
+ }
+ /* cpu setup */
+ X86_AX = devfn ? devfn : 0xff;
+ X86_DX = 0x80;
+ X86_EIP = initialip;
+ X86_CS = initialcs;
+
+ /* Initialize stack and data segment */
+ X86_SS = 0x0030;
+ X86_DS = 0x0040;
+ X86_SP = 0xfffe;
+ /* We need a sane way to return from bios
+ * execution. A hlt instruction and a pointer
+ * to it, both kept on the stack, will do.
+ */
+ pushw(0xf4f4); /* hlt; hlt */
+ pushw(X86_SS);
+ pushw(X86_SP + 2);
+
+ X86_ES = 0x0000;
+
+ if (trace) {
+ printf("Switching to single step mode.\n");
+ X86EMU_trace_on();
+ }
+ if (debugflag) {
+ X86EMU_set_debug(debugflag);
+ }
+ X86EMU_exec();
+ /* Cleaning up */
+ pciExit();
+
+ return 0;
+}