added testbios for V2
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1624 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
328
util/vgabios/testbios.c
Normal file
328
util/vgabios/testbios.c
Normal file
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user