coreboot-kgpe-d16/util/vgabios/testbios.c
Stefan Reinauer e2804c14a4 util/vgabios: Don't call redefined printk in printk
A few pieces of coreboot code (like the video bios emulator) are
imported from other code bases, and hence might call printf. In
order to see the output, we redefine printf to printk. However,
when we are re-importing this code in a userspace utility, we might
call printk instead of printf if we're not careful.
A good fix for this would be to not call printf in coreboot ever.
As a short term fix to keep testbios from segfaulting, we just
don't call printf from printk, so we don't cause our own stack to
overflow.

Change-Id: I789075422dd8c5f8069d576fa7baf4176f6caf55
Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-on: https://review.coreboot.org/20658
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Martin Roth <martinroth@google.com>
2017-07-21 15:45:41 +00:00

381 lines
7.8 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright (C) 2016 Google Inc
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#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>
#include <stdarg.h>
#include <stdtypes.h>
#define die(x) { perror(x); exit(1); }
#define warn(x) { perror(x); }
#include <x86emu/x86emu.h>
#include <console/console.h>
#include <arch/byteorder.h>
#include "device.h"
#include "testbios.h"
#include "pci-userspace.h"
int X86EMU_set_debug(int debug);
biosemu_device_t bios_device;
extern int teststart, testend;
#define BIOSMEM_SIZE (1024 * 1024)
unsigned char biosmem[BIOSMEM_SIZE];
int verbose = 0;
static 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;
}
static 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;
}
int printk(int msg_level, const char *fmt, ...)
{
va_list args;
int i;
putchar('<');
putchar('0' + msg_level);
putchar('>');
putchar(' ');
va_start(args, fmt);
i = vprintf(fmt, args);
va_end(args);
return i;
}
static void usage(char *name)
{
printf
("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] <filename> ... \n",
name);
}
/* main entry into YABEL biosemu, arguments are:
* *biosmem = pointer to virtual memory
* biosmem_size = size of the virtual memory
* *dev = pointer to the device to be initialised
* rom_addr = address of the OptionROM to be executed, if this is = 0, YABEL
* will look for an ExpansionROM BAR and use the code from there.
*/
u32
biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long
rom_addr);
int main(int argc, char **argv)
{
int ret;
char *absegname = 0;
void *abseg = 0;
int c, trace = 0;
unsigned char *cp;
char *filename;
ssize_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];
int debugflag = 0;
struct device *dev;
//const char *optstring = "vh?b:i:c:s:tpd:";
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':
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;
}
if (parse_rom)
printf("Parsing rom images not implemented.\n");
//printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
#if 0
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");
}
}
}
#endif
if (absegname) {
abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
if (!abseg)
die(absegname);
}
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.
*/
pci_initialize();
#if 0
for (i = 0; i < 256; i++)
intFuncs[i] = do_int;
X86EMU_setupIntrFuncs(intFuncs);
#endif
cp = mapitin(filename, (off_t) 0, size);
if (devfn) {
printf("Loading ax with BusDevFn = %x\n",devfn);
}
#if 0
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 {
const 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;
#endif
if (trace) {
printf("Switching to single step mode.\n");
//X86EMU_trace_on();
}
if (debugflag) {
printf("Enable Debug = %x.\n",debugflag);
//X86EMU_set_debug(debugflag);
}
#if 0
X86EMU_exec();
#endif
ret = biosemu(biosmem, BIOSMEM_SIZE, dev, base);
#if 0
current = &p;
X86EMU_setMemBase(biosmem, sizeof(biosmem));
M.abseg = (unsigned long)abseg;
X86EMU_setupPioFuncs(&myfuncs);
#endif
/* Cleaning up */
pci_exit();
return 0;
}