coreboot-kgpe-d16/util/vgabios/testbios.c
Stefan Reinauer 14e2277962 Since some people disapprove of white space cleanups mixed in regular commits
while others dislike them being extra commits, let's clean them up once and
for all for the existing code. If it's ugly, let it only be ugly once :-)

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Stefan Reinauer <stepan@coresystems.de>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5507 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
2010-04-27 06:56:47 +00:00

394 lines
7.4 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#define die(x) { perror(x); exit(1); }
#define warn(x) { perror(x); }
#include <x86emu/x86emu.h>
#include "helper_exec.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);
unsigned short get_device(char *arg_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 have_devfn = 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_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 = get_device(optarg);
have_devfn = 1;
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 (initialip == 0x0003) {
if ((devfn == 0) || (have_devfn == 0)) {
printf("WARNING! It appears you are trying to run an option ROM.\n");
printf(" (initial ip = 0x0003)\n");
if (have_devfn) {
printf(" However, the device you have specified is 0x00\n");
printf(" It is very unlikely that your device is at this address\n");
printf(" Please check your -d option\n");
}
else {
printf(" Please specify a device with -d\n");
printf(" The default is not likely to work\n");
}
}
}
if (absegname) {
abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
if (!abseg)
die(absegname);
}
current = &p;
X86EMU_setMemBase(biosmem, sizeof(biosmem));
M.abseg = (unsigned long)abseg;
X86EMU_setupPioFuncs(&myfuncs);
ioperm(0, 0x400, 1);
if (iopl(3) < 0) {
warn("iopl failed, continuing anyway");
}
/* 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);
if (devfn) {
printf("Loading ax with BusDevFn = %x\n",devfn);
}
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;
}
unsigned short get_device(char *arg_val)
{
unsigned short devfn=0;
long bus=0,dev=0,fn=0,need_pack=0;
char *tok;
tok = strsep(&arg_val,":");
if (arg_val != NULL) {
bus = strtol(tok,0,16);
need_pack = 1;
}
else {
arg_val = tok;
}
tok = strsep(&arg_val,".");
if (arg_val != NULL) {
dev = strtol(tok,0,16);
fn = strtol(arg_val,0,16);
need_pack = 1;
}
else {
if (need_pack ==1 && (strlen(tok))) {
dev = strtol(tok,0,16);
}
}
if ( need_pack == 1) {
devfn = bus<<8 | (dev<<3) | fn;
}
else {
devfn = strtol(tok, 0, 0);
}
return devfn;
}