diff options
Diffstat (limited to 'util/vgabios/testbios.c')
-rw-r--r-- | util/vgabios/testbios.c | 328 |
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; +} |