Redo testbios utility to use all of YABEL

Drop buggy duplicate implementation of intXX handlers
and provide enough glue to use all of YABEL.

Change-Id: I2db77a56a2a991cb84876456dcbb3a843a0d9754
Signed-off-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-on: https://review.coreboot.org/12117
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Tested-by: build bot (Jenkins)
This commit is contained in:
Stefan Reinauer 2015-10-21 13:00:41 -07:00 committed by Stefan Reinauer
parent eb960f1af9
commit 05082737a9
20 changed files with 906 additions and 1656 deletions

View File

@ -1,3 +1,18 @@
##
## 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.
##
#
# NOTE: You need to add your libpci.a version to CFLAGS below if
# pci-userspace.c does not build.
@ -7,33 +22,55 @@
#
TOP ?= ../..
OUT ?= build
CC ?= gcc
CFLAGS ?= -O2 -g -fomit-frame-pointer
CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wmissing-prototypes
CFLAGS += -Wwrite-strings -Wredundant-decls -Wstrict-aliasing -Wshadow -Wextra
CFLAGS += -Wno-unused-but-set-variable
# TODO check host architecture
CBCFLAGS = -DCONFIG_ARCH_X86=1 -Wno-sign-compare -Wno-unused-but-set-variable -Wno-unused-parameter
CBCFLAGS = -Wno-sign-compare -Wno-unused-parameter -Wno-format
INCLUDES = -Iinclude -I$(TOP)/src/device/oprom/include/
CBINCLUDES = -I$(TOP)/src --include include/stdtypes.h
CBINCLUDES += --include $(TOP)/src/commonlib/include/commonlib/loglevel.h
CBINCLUDES += -include stdio.h
INCLUDES = -Iinclude -I$(OUT)/include
INCLUDES += -I$(TOP)/src/device/oprom/include/
INCLUDES += -I$(TOP)/src/device/oprom/yabel
INCLUDES += -include $(TOP)/src/commonlib/include/commonlib/loglevel.h
INCLUDES += -include stdtypes.h -include pci-userspace.h
INCLUDES += -include $(TOP)/src/include/kconfig.h
SOURCE = int10.c int15.c int16.c int1a.c inte6.c testbios.c
SOURCE += helper_exec.c helper_mem.c pci-userspace.c
CBINCLUDES = -I$(TOP)/src -include include/stdtypes.h -include $(TOP)/src/include/endian.h
CBINCLUDES += -include stdio.h -include sys/io.h
X86EMU = sys.c decode.c ops.c ops2.c prim_ops.c fpu.c debug.c
X86EMU_DIR = $(TOP)/src/device/oprom/x86emu
SOURCE = testbios.c
SOURCE += pci-userspace.c
SOURCE += device.c
X86EMU = x86emu/sys.c x86emu/decode.c x86emu/ops.c x86emu/ops2.c
X86EMU += x86emu/prim_ops.c x86emu/fpu.c x86emu/debug.c
X86EMU += yabel/interrupt.c
X86EMU += yabel/mem.c
X86EMU += yabel/io.c
X86EMU += yabel/pmm.c
X86EMU += yabel/biosemu.c
X86EMU += yabel/debug.c
#X86EMU += yabel/device.c # For now we need a local copy :-(
X86EMU_DIR = $(TOP)/src/device/oprom
X86EMU_SOURCE = $(addprefix $(X86EMU_DIR)/, $(X86EMU))
OBJECTS:=$(SOURCE:.c=.o) $(X86EMU:.c=.o)
OBJECTS:=$(addprefix $(OUT)/,$(SOURCE:.c=.o)) $(addprefix $(OUT)/, $(X86EMU:.c=.o))
LIBS=-lpci
all: dep testbios
$(OBJECTS): includes
testbios: $(OBJECTS)
printf " LINK $(notdir $@)\n"
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
@ -42,21 +79,37 @@ dep: $(SOURCE) $(X86EMU_SOURCE) Makefile
$(CC) $(CFLAGS) $(INCLUDES) -MM $(SOURCE) > .dependencies
$(CC) $(CFLAGS) $(INCLUDES) $(CBCFLAGS) $(CBINCLUDES) -MM $(X86EMU_SOURCE) >> .dependencies
# Make all the dummy include files (that are in reality
# covered by all the -include statements above)
includes:
mkdir -p $(OUT)/include/device
mkdir -p $(OUT)/include/arch
touch $(OUT)/include/device/device.h
touch $(OUT)/include/device/pci.h
touch $(OUT)/include/device/pci_ops.h
touch $(OUT)/include/device/resource.h
touch $(OUT)/include/arch/io.h
touch $(OUT)/include/timer.h
touch $(OUT)/include/types.h
clean:
rm -f *.o *~ testbios
rm -f $(OBJECTS) *~ testbios
rm -rf $(OUT)
distclean: clean
rm -f .dependencies
%.o: $(X86EMU_DIR)/%.c
$(OUT)/%.o: $(X86EMU_DIR)/%.c
printf " CC (x86emu) $(notdir $<)\n"
mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(CBCFLAGS) $(INCLUDES) $(CBINCLUDES) -c -o $@ $<
%.o: %.c
$(OUT)/%.o: %.c
printf " CC $(notdir $<)\n"
mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
.PHONY: all clean distclean
.PHONY: all includes clean distclean
.SILENT:
-include .dependencies

482
util/vgabios/device.c Normal file
View File

@ -0,0 +1,482 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
* All rights reserved.
* This program and the accompanying materials
* are made available under the terms of the BSD License
* which accompanies this distribution, and is available at
* http://www.opensource.org/licenses/bsd-license.php
*
* Contributors:
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdtypes.h>
#include <arch/byteorder.h>
#include "device.h"
#include "compat/rtas.h"
#include <string.h>
#include "debug.h"
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ops.h>
#include <device/resource.h>
/* the device we are working with... */
biosemu_device_t bios_device;
//max. 6 BARs and 1 Exp.ROM plus CfgSpace and 3 legacy ranges, plus 2 "special" memory ranges
translate_address_t translate_address_array[13];
u8 taa_last_entry;
typedef struct {
u8 info;
u8 bus;
u8 devfn;
u8 cfg_space_offset;
u64 address;
u64 size;
} __attribute__ ((__packed__)) assigned_address_t;
#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
/* coreboot version */
static void
biosemu_dev_get_addr_info(void)
{
#if 0
int taa_index = 0;
struct resource *r;
u8 bus = bios_device.dev->bus->secondary;
u16 devfn = bios_device.dev->path.pci.devfn;
bios_device.bus = bus;
bios_device.devfn = devfn;
DEBUG_PRINTF("bus: %x, devfn: %x\n", bus, devfn);
for (r = bios_device.dev->resource_list; r; r = r->next) {
translate_address_array[taa_index].info = r->flags;
translate_address_array[taa_index].bus = bus;
translate_address_array[taa_index].devfn = devfn;
translate_address_array[taa_index].cfg_space_offset =
r->index;
translate_address_array[taa_index].address = r->base;
translate_address_array[taa_index].size = r->size;
/* don't translate addresses... all addresses are 1:1 */
translate_address_array[taa_index].address_offset = 0;
taa_index++;
}
/* Expansion ROM */
translate_address_array[taa_index].info = IORESOURCE_MEM | IORESOURCE_READONLY;
translate_address_array[taa_index].bus = bus;
translate_address_array[taa_index].devfn = devfn;
translate_address_array[taa_index].cfg_space_offset = 0x30;
translate_address_array[taa_index].address = bios_device.img_addr;
translate_address_array[taa_index].size = 0; /* TODO: do we need the size? */
/* don't translate addresses... all addresses are 1:1 */
translate_address_array[taa_index].address_offset = 0;
taa_index++;
/* legacy ranges if its a VGA card... */
if ((bios_device.dev->class & 0xFF0000) == 0x030000) {
DEBUG_PRINTF("%s: VGA device found, adding legacy resources... \n", __func__);
/* I/O 0x3B0-0x3BB */
translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_IO;
translate_address_array[taa_index].bus = bus;
translate_address_array[taa_index].devfn = devfn;
translate_address_array[taa_index].cfg_space_offset = 0;
translate_address_array[taa_index].address = 0x3b0;
translate_address_array[taa_index].size = 0xc;
/* don't translate addresses... all addresses are 1:1 */
translate_address_array[taa_index].address_offset = 0;
taa_index++;
/* I/O 0x3C0-0x3DF */
translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_IO;
translate_address_array[taa_index].bus = bus;
translate_address_array[taa_index].devfn = devfn;
translate_address_array[taa_index].cfg_space_offset = 0;
translate_address_array[taa_index].address = 0x3c0;
translate_address_array[taa_index].size = 0x20;
/* don't translate addresses... all addresses are 1:1 */
translate_address_array[taa_index].address_offset = 0;
taa_index++;
/* Mem 0xA0000-0xBFFFF */
translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_MEM;
translate_address_array[taa_index].bus = bus;
translate_address_array[taa_index].devfn = devfn;
translate_address_array[taa_index].cfg_space_offset = 0;
translate_address_array[taa_index].address = 0xa0000;
translate_address_array[taa_index].size = 0x20000;
/* don't translate addresses... all addresses are 1:1 */
translate_address_array[taa_index].address_offset = 0;
taa_index++;
}
// store last entry index of translate_address_array
taa_last_entry = taa_index - 1;
#if CONFIG_X86EMU_DEBUG
//dump translate_address_array
printf("translate_address_array: \n");
translate_address_t ta;
int i;
for (i = 0; i <= taa_last_entry; i++) {
ta = translate_address_array[i];
printf
("%d: info: %08lx bus: %02x devfn: %02x cfg_space_offset: %02x\n\taddr: %016llx\n\toffs: %016llx\n\tsize: %016llx\n",
i, ta.info, ta.bus, ta.devfn, ta.cfg_space_offset,
ta.address, ta.address_offset, ta.size);
}
#endif
#endif
}
#else
// use translate_address_dev and get_puid from net-snk's net_support.c
void translate_address_dev(u64 *, phandle_t);
u64 get_puid(phandle_t node);
// scan all addresses assigned to the device ("assigned-addresses" and "reg")
// store in translate_address_array for faster translation using dev_translate_address
void
biosemu_dev_get_addr_info(void)
{
// get bus/dev/fn from assigned-addresses
int32_t len;
//max. 6 BARs and 1 Exp.ROM plus CfgSpace and 3 legacy ranges
assigned_address_t buf[11];
len =
of_getprop(bios_device.phandle, "assigned-addresses", buf,
sizeof(buf));
bios_device.bus = buf[0].bus;
bios_device.devfn = buf[0].devfn;
DEBUG_PRINTF("bus: %x, devfn: %x\n", bios_device.bus,
bios_device.devfn);
//store address translations for all assigned-addresses and regs in
//translate_address_array for faster translation later on...
int i = 0;
// index to insert data into translate_address_array
int taa_index = 0;
u64 address_offset;
for (i = 0; i < (len / sizeof(assigned_address_t)); i++, taa_index++) {
//copy all info stored in assigned-addresses
translate_address_array[taa_index].info = buf[i].info;
translate_address_array[taa_index].bus = buf[i].bus;
translate_address_array[taa_index].devfn = buf[i].devfn;
translate_address_array[taa_index].cfg_space_offset =
buf[i].cfg_space_offset;
translate_address_array[taa_index].address = buf[i].address;
translate_address_array[taa_index].size = buf[i].size;
// translate first address and store it as address_offset
address_offset = buf[i].address;
translate_address_dev(&address_offset, bios_device.phandle);
translate_address_array[taa_index].address_offset =
address_offset - buf[i].address;
}
//get "reg" property
len = of_getprop(bios_device.phandle, "reg", buf, sizeof(buf));
for (i = 0; i < (len / sizeof(assigned_address_t)); i++) {
if ((buf[i].size == 0) || (buf[i].cfg_space_offset != 0)) {
// we don't care for ranges with size 0 and
// BARs and Expansion ROM must be in assigned-addresses... so in reg
// we only look for those without config space offset set...
// i.e. the legacy ranges
continue;
}
//copy all info stored in assigned-addresses
translate_address_array[taa_index].info = buf[i].info;
translate_address_array[taa_index].bus = buf[i].bus;
translate_address_array[taa_index].devfn = buf[i].devfn;
translate_address_array[taa_index].cfg_space_offset =
buf[i].cfg_space_offset;
translate_address_array[taa_index].address = buf[i].address;
translate_address_array[taa_index].size = buf[i].size;
// translate first address and store it as address_offset
address_offset = buf[i].address;
translate_address_dev(&address_offset, bios_device.phandle);
translate_address_array[taa_index].address_offset =
address_offset - buf[i].address;
taa_index++;
}
// store last entry index of translate_address_array
taa_last_entry = taa_index - 1;
#if CONFIG_X86EMU_DEBUG
//dump translate_address_array
printf("translate_address_array: \n");
translate_address_t ta;
for (i = 0; i <= taa_last_entry; i++) {
ta = translate_address_array[i];
printf
("%d: %02x%02x%02x%02x\n\taddr: %016llx\n\toffs: %016llx\n\tsize: %016llx\n",
i, ta.info, ta.bus, ta.devfn, ta.cfg_space_offset,
ta.address, ta.address_offset, ta.size);
}
#endif
}
#endif
// "special memory" is a hack to make some parts of memory fall through to real memory
// (ie. no translation). Necessary if option ROMs attempt DMA there, map registers or
// do similarly crazy things.
void
biosemu_add_special_memory(u32 start, u32 size)
{
#if 0
int taa_index = ++taa_last_entry;
translate_address_array[taa_index].info = IORESOURCE_FIXED | IORESOURCE_MEM;
translate_address_array[taa_index].bus = 0;
translate_address_array[taa_index].devfn = 0;
translate_address_array[taa_index].cfg_space_offset = 0;
translate_address_array[taa_index].address = start;
translate_address_array[taa_index].size = size;
/* don't translate addresses... all addresses are 1:1 */
translate_address_array[taa_index].address_offset = 0;
#endif
printf("TODO: Add special memory handler for %x[%x]\n", start, size);
}
#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
// to simulate accesses to legacy VGA Memory (0xA0000-0xBFFFF)
// we look for the first prefetchable memory BAR, if no prefetchable BAR found,
// we use the first memory BAR
// dev_translate_addr will translate accesses to the legacy VGA Memory into the found vmem BAR
static void
biosemu_dev_find_vmem_addr(void)
{
int i = 0;
translate_address_t ta;
s8 tai_np = -1, tai_p = -1; // translate_address_array index for non-prefetchable and prefetchable memory
//search backwards to find first entry
for (i = taa_last_entry; i >= 0; i--) {
ta = translate_address_array[i];
if ((ta.cfg_space_offset >= 0x10)
&& (ta.cfg_space_offset <= 0x24)) {
//only BARs
if ((ta.info & 0x03) >= 0x02) {
//32/64bit memory
tai_np = i;
if ((ta.info & 0x40) != 0) {
// prefetchable
tai_p = i;
}
}
}
}
if (tai_p != -1) {
ta = translate_address_array[tai_p];
bios_device.vmem_addr = ta.address;
bios_device.vmem_size = ta.size;
DEBUG_PRINTF
("%s: Found prefetchable Virtual Legacy Memory BAR: %llx, size: %llx\n",
__func__, bios_device.vmem_addr,
bios_device.vmem_size);
} else if (tai_np != -1) {
ta = translate_address_array[tai_np];
bios_device.vmem_addr = ta.address;
bios_device.vmem_size = ta.size;
DEBUG_PRINTF
("%s: Found non-prefetchable Virtual Legacy Memory BAR: %llx, size: %llx",
__func__, bios_device.vmem_addr,
bios_device.vmem_size);
}
// disable vmem
//bios_device.vmem_size = 0;
}
void
biosemu_dev_get_puid(void)
{
// get puid
bios_device.puid = get_puid(bios_device.phandle);
DEBUG_PRINTF("puid: 0x%llx\n", bios_device.puid);
}
#endif
static void
biosemu_dev_get_device_vendor_id(void)
{
u32 pci_config_0;
#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_config_0 = pci_read_config32(bios_device.dev, 0x0);
#else
pci_config_0 =
rtas_pci_config_read(bios_device.puid, 4, bios_device.bus,
bios_device.devfn, 0x0);
#endif
bios_device.pci_device_id =
(u16) ((pci_config_0 & 0xFFFF0000) >> 16);
bios_device.pci_vendor_id = (u16) (pci_config_0 & 0x0000FFFF);
DEBUG_PRINTF("PCI Device ID: %04x, PCI Vendor ID: %x\n",
bios_device.pci_device_id, bios_device.pci_vendor_id);
}
/* Check whether the device has a valid Expansion ROM and search the PCI Data
* Structure and any Expansion ROM Header (using dev_scan_exp_header()) for
* needed information. If the rom_addr parameter is != 0, it is the address of
* the Expansion ROM image and will be used, if it is == 0, the Expansion ROM
* BAR address will be used.
*/
u8
biosemu_dev_check_exprom(unsigned long rom_base_addr)
{
#if 0
int i = 0;
translate_address_t ta;
u16 pci_ds_offset;
pci_data_struct_t pci_ds;
if (rom_base_addr == 0) {
// check for ExpROM Address (Offset 30) in taa
for (i = 0; i <= taa_last_entry; i++) {
ta = translate_address_array[i];
if (ta.cfg_space_offset == 0x30) {
//translated address
rom_base_addr = ta.address + ta.address_offset;
break;
}
}
}
/* In the ROM there could be multiple Expansion ROM Images... start
* searching them for an x86 image.
*/
do {
if (rom_base_addr == 0) {
printf("Error: no Expansion ROM address found!\n");
return -1;
}
set_ci();
u16 rom_signature = in16le((void *) rom_base_addr);
clr_ci();
if (rom_signature != 0xaa55) {
printf
("Error: invalid Expansion ROM signature: %02x!\n",
*((u16 *) rom_base_addr));
return -1;
}
set_ci();
// at offset 0x18 is the (16bit little-endian) pointer to the PCI Data Structure
pci_ds_offset = in16le((void *) (rom_base_addr + 0x18));
//copy the PCI Data Structure
memcpy(&pci_ds, (void *) (rom_base_addr + pci_ds_offset),
sizeof(pci_ds));
clr_ci();
#if CONFIG_X86EMU_DEBUG
DEBUG_PRINTF("PCI Data Structure @%lx:\n",
rom_base_addr + pci_ds_offset);
dump((void *) &pci_ds, sizeof(pci_ds));
#endif
if (strncmp((const char *) pci_ds.signature, "PCIR", 4) != 0) {
printf("Invalid PCI Data Structure found!\n");
break;
}
//little-endian conversion
pci_ds.vendor_id = in16le(&pci_ds.vendor_id);
pci_ds.device_id = in16le(&pci_ds.device_id);
pci_ds.img_length = in16le(&pci_ds.img_length);
pci_ds.pci_ds_length = in16le(&pci_ds.pci_ds_length);
#ifdef DO_THIS_TEST_TWICE
if (pci_ds.vendor_id != bios_device.pci_vendor_id) {
printf
("Image has invalid Vendor ID: %04x, expected: %04x\n",
pci_ds.vendor_id, bios_device.pci_vendor_id);
break;
}
if (pci_ds.device_id != bios_device.pci_device_id) {
printf
("Image has invalid Device ID: %04x, expected: %04x\n",
pci_ds.device_id, bios_device.pci_device_id);
break;
}
#endif
DEBUG_PRINTF("Image Length: %d\n", pci_ds.img_length * 512);
DEBUG_PRINTF("Image Code Type: %d\n", pci_ds.code_type);
if (pci_ds.code_type == 0) {
//x86 image
//store image address and image length in bios_device struct
bios_device.img_addr = rom_base_addr;
bios_device.img_size = pci_ds.img_length * 512;
// we found the image, exit the loop
break;
} else {
// no x86 image, check next image (if any)
rom_base_addr += pci_ds.img_length * 512;
}
if ((pci_ds.indicator & 0x80) == 0x80) {
//last image found, exit the loop
DEBUG_PRINTF("Last PCI Expansion ROM Image found.\n");
break;
}
}
while (bios_device.img_addr == 0);
// in case we did not find a valid x86 Expansion ROM Image
if (bios_device.img_addr == 0) {
printf("Error: no valid x86 Expansion ROM Image found!\n");
return -1;
}
#endif
return 0;
}
u8
biosemu_dev_init(struct device * device)
{
u8 rval = 0;
//init bios_device struct
DEBUG_PRINTF("%s\n", __func__);
memset(&bios_device, 0, sizeof(bios_device));
#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
bios_device.ihandle = of_open(device_name);
if (bios_device.ihandle == 0) {
DEBUG_PRINTF("%s is no valid device!\n", device_name);
return -1;
}
bios_device.phandle = of_finddevice(device_name);
#else
bios_device.dev = device;
#endif
biosemu_dev_get_addr_info();
#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
biosemu_dev_find_vmem_addr();
biosemu_dev_get_puid();
#endif
biosemu_dev_get_device_vendor_id();
return rval;
}
// translate address function using translate_address_array assembled
// by dev_get_addr_info... MUCH faster than calling translate_address_dev
// and accessing client interface for every translation...
// returns: 0 if addr not found in translate_address_array, 1 if found.
u8
biosemu_dev_translate_address(int type, unsigned long * addr)
{
int i = 0;
translate_address_t ta;
#if !CONFIG_PCI_OPTION_ROM_RUN_YABEL
/* we don't need this hack for coreboot... we can access legacy areas */
//check if it is an access to legacy VGA Mem... if it is, map the address
//to the vmem BAR and then translate it...
// (translation info provided by Ben Herrenschmidt)
// NOTE: the translation seems to only work for NVIDIA cards... but it is needed
// to make some NVIDIA cards work at all...
if ((bios_device.vmem_size > 0)
&& ((*addr >= 0xA0000) && (*addr < 0xB8000))) {
*addr = (*addr - 0xA0000) * 4 + 2 + bios_device.vmem_addr;
}
if ((bios_device.vmem_size > 0)
&& ((*addr >= 0xB8000) && (*addr < 0xC0000))) {
u8 shift = *addr & 1;
*addr &= 0xfffffffe;
*addr = (*addr - 0xB8000) * 4 + shift + bios_device.vmem_addr;
}
#endif
for (i = 0; i <= taa_last_entry; i++) {
ta = translate_address_array[i];
if ((*addr >= ta.address) && (*addr <= (ta.address + ta.size)) && (ta.info & type)) {
*addr += ta.address_offset;
return 1;
}
}
return 0;
}

View File

@ -1,269 +0,0 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_exec.c,v 1.16 2001/04/30 14:34:57 tsi Exp $ */
/*
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
*
* Part of this is based on code taken from DOSEMU
* (C) Copyright 1992, ..., 1999 the "DOSEMU-Development-Team"
*/
/*
* To debug port accesses define PRINT_PORT.
* Note! You also have to comment out ioperm()
* in xf86EnableIO(). Otherwise we won't trap
* on PIO.
*/
#include <sys/io.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdtypes.h>
#include <x86emu/x86emu.h>
#include "helper_exec.h"
#include "testbios.h"
/* general software interrupt handler */
u32 getIntVect(int num)
{
return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
}
void pushw(u16 val)
{
X86_ESP -= 2;
MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
}
int run_bios_int(int num)
{
u32 eflags;
eflags = X86_EFLAGS;
pushw(eflags);
pushw(X86_CS);
pushw(X86_IP);
X86_CS = MEM_RW((num << 2) + 2);
X86_IP = MEM_RW(num << 2);
printf("%s: INT %x CS:IP = %x:%x\n", __FUNCTION__,
num, MEM_RW((num << 2) + 2), MEM_RW(num << 2));
return 1;
}
#if 0
int port_rep_inb(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -1 : 1;
u32 dst = base;
while (count--) {
MEM_WB(dst, x_inb(port));
dst += inc;
}
return dst - base;
}
int port_rep_inw(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -2 : 2;
u32 dst = base;
while (count--) {
MEM_WW(dst, x_inw(port));
dst += inc;
}
return dst - base;
}
int port_rep_inl(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -4 : 4;
u32 dst = base;
while (count--) {
MEM_WL(dst, x_inl(port));
dst += inc;
}
return dst - base;
}
int port_rep_outb(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -1 : 1;
u32 dst = base;
while (count--) {
x_outb(port, MEM_RB(dst));
dst += inc;
}
return dst - base;
}
int port_rep_outw(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -2 : 2;
u32 dst = base;
while (count--) {
x_outw(port, MEM_RW(dst));
dst += inc;
}
return dst - base;
}
int port_rep_outl(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -4 : 4;
u32 dst = base;
while (count--) {
x_outl(port, MEM_RL(dst));
dst += inc;
}
return dst - base;
}
#endif
u8 x_inb(u16 port)
{
u8 val;
val = inb(port);
printf("inb(0x%04x) = 0x%02x\n", port, val);
return val;
}
u16 x_inw(u16 port)
{
u16 val;
val = inw(port);
printf("inw(0x%04x) = 0x%04x\n", port, val);
return val;
}
u32 x_inl(u16 port)
{
u32 val;
val = inl(port);
printf("inl(0x%04x) = 0x%08x\n", port, val);
return val;
}
void x_outb(u16 port, u8 val)
{
printf("outb(0x%02x, 0x%04x)\n",
val, port);
outb(val, port);
}
void x_outw(u16 port, u16 val)
{
printf("outw(0x%04x, 0x%04x)\n", val, port);
outw(val, port);
}
void x_outl(u16 port, u32 val)
{
printf("outl(0x%08x, 0x%04x)\n", val, port);
outl(val, port);
}
#if 0
u8 Mem_rb(int addr)
{
return (*current->mem->rb) (current, addr);
}
u16 Mem_rw(int addr)
{
return (*current->mem->rw) (current, addr);
}
u32 Mem_rl(int addr)
{
return (*current->mem->rl) (current, addr);
}
void Mem_wb(int addr, u8 val)
{
(*current->mem->wb) (current, addr, val);
}
void Mem_ww(int addr, u16 val)
{
(*current->mem->ww) (current, addr, val);
}
void Mem_wl(int addr, u32 val)
{
(*current->mem->wl) (current, addr, val);
}
#endif
void getsecs(unsigned long *sec, unsigned long *usec)
{
struct timeval tv;
gettimeofday(&tv, 0);
*sec = tv.tv_sec;
*usec = tv.tv_usec;
}
#define TAG(Cfg1Addr) (Cfg1Addr & 0xffff00)
#define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff)
u8 bios_checksum(u8 * start, int size)
{
u8 sum = 0;
while (size-- > 0)
sum += *start++;
return sum;
}
/*
* Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
* an attempt to detect a legacy ISA card. If they find one they might
* act very strange: for example they might configure the card as a
* monochrome card. This might cause some drivers to choke.
* To avoid this we attempt legacy VGA by writing to all know VGA
* disable registers before we call the BIOS initialization and
* restore the original values afterwards. In beween we hold our
* breath. To get to a (possibly exising) ISA card need to disable
* our current PCI card.
*/
/*
* This is just for booting: we just want to catch pure
* legacy vga therefore we don't worry about mmio etc.
* This stuff should really go into vgaHW.c. However then
* the driver would have to load the vga-module prior to
* doing int10.
*/
/*void
LockLegacyVGA(int screenIndex,legacyVGAPtr vga)
{
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
vga->save_msr = inb(0x3CC);
vga->save_vse = inb(0x3C3);
vga->save_46e8 = inb(0x46e8);
vga->save_pos102 = inb(0x102);
outb(0x3C2, ~(u8)0x03 & vga->save_msr);
outb(0x3C3, ~(u8)0x01 & vga->save_vse);
outb(0x46e8, ~(u8)0x08 & vga->save_46e8);
outb(0x102, ~(u8)0x01 & vga->save_pos102);
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
}
void
UnlockLegacyVGA(int screenIndex, legacyVGAPtr vga)
{
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
outb(0x102, vga->save_pos102);
outb(0x46e8, vga->save_46e8);
outb(0x3C3, vga->save_vse);
outb(0x3C2, vga->save_msr);
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
}
*/

View File

@ -1,32 +0,0 @@
#ifndef __HELPER_EXEC_H__
#define __HELPER_EXEC_H__
u32 getIntVect(int num);
int run_bios_int(int num);
void pushw(u16 val);
int port_rep_inb(u16 port, u32 base, int d_f, u32 count);
int port_rep_inw(u16 port, u32 base, int d_f, u32 count);
int port_rep_inl(u16 port, u32 base, int d_f, u32 count);
int port_rep_outb(u16 port, u32 base, int d_f, u32 count);
int port_rep_outw(u16 port, u32 base, int d_f, u32 count);
int port_rep_outl(u16 port, u32 base, int d_f, u32 count);
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);
u8 Mem_rb(int addr);
u16 Mem_rw(int addr);
u32 Mem_rl(int addr);
void Mem_wb(int addr, u8 val);
void Mem_ww(int addr, u16 val);
void Mem_wl(int addr, u32 val);
void getsecs(unsigned long *sec, unsigned long *usec);
u8 bios_checksum(u8 * start, int size);
#endif

View File

@ -1,313 +0,0 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_mem.c,v 1.21 2001/05/22 16:24:37 tsi Exp $ */
/*
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
*/
#include <stdio.h>
#define _INT10_PRIVATE
#define REG pInt
#if 0
typedef enum {
OPT_NOINT10,
OPT_INIT_PRIMARY,
OPT_BIOS_LOCATION
} INT10Opts;
static const OptionInfoRec INT10Options[] = {
{OPT_NOINT10, "NoINT10", OPTV_BOOLEAN, {0}, FALSE},
{OPT_INIT_PRIMARY, "InitPrimary", OPTV_BOOLEAN, {0}, FALSE},
{OPT_BIOS_LOCATION, "BiosLocation", OPTV_STRING, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE},
};
#endif
#ifdef DEBUG
void dprint(unsigned long start, unsigned long size)
{
int i, j;
char *c = (char *) start;
for (j = 0; j < (size >> 4); j++) {
char *d = c;
printf("\n0x%lx: ", (unsigned long) c);
for (i = 0; i < 16; i++)
printf("%2.2x ", (unsigned char) (*(c++)));
c = d;
for (i = 0; i < 16; i++) {
printf("%c", ((((unsigned char) (*c)) > 32) && (((unsigned char) (*c)) < 128)) ?
(unsigned char) (*(c)) : '.');
c++;
}
}
printf("\n");
}
#endif /* DEBUG */
#if 0
#ifndef _PC
/*
* here we are really paranoid about faking a "real"
* BIOS. Most of this information was pulled from
* dosemu.
*/
void setup_int_vect(void)
{
int i;
/* let the int vects point to the SYS_BIOS seg */
for (i = 0; i < 0x80; i++) {
MEM_WW(i << 2, 0);
MEM_WW((i << 2) + 2, SYS_BIOS >> 4);
}
reset_int_vect(current);
/* font tables default location (int 1F) */
MEM_WW(0x1f << 2, 0xfa6e);
/* int 11 default location (Get Equipment Configuration) */
MEM_WW(0x11 << 2, 0xf84d);
/* int 12 default location (Get Conventional Memory Size) */
MEM_WW(0x12 << 2, 0xf841);
/* int 15 default location (I/O System Extensions) */
MEM_WW(0x15 << 2, 0xf859);
/* int 1A default location (RTC, PCI and others) */
MEM_WW(0x1a << 2, 0xff6e);
/* int 05 default location (Bound Exceeded) */
MEM_WW(0x05 << 2, 0xff54);
/* int 08 default location (Double Fault) */
MEM_WW(0x08 << 2, 0xfea5);
/* int 13 default location (Disk) */
MEM_WW(0x13 << 2, 0xec59);
/* int 0E default location (Page Fault) */
MEM_WW(0x0e << 2, 0xef57);
/* int 17 default location (Parallel Port) */
MEM_WW(0x17 << 2, 0xefd2);
/* fdd table default location (int 1e) */
MEM_WW(0x1e << 2, 0xefc7);
/* Set Equipment flag to VGA */
i = MEM_RB(0x0410) & 0xCF;
MEM_WB(0x0410, i);
/* XXX Perhaps setup more of the BDA here. See also int42(0x00). */
}
#endif
int setup_system_bios(void *base_addr)
{
char *base = (char *) base_addr;
/*
* we trap the "industry standard entry points" to the BIOS
* and all other locations by filling them with "hlt"
* TODO: implement hlt-handler for these
*/
memset(base, 0xf4, 0x10000);
/* set bios date */
strcpy(base + 0x0FFF5, "06/11/99");
/* set up eisa ident string */
strcpy(base + 0x0FFD9, "PCI_ISA");
/* write system model id for IBM-AT */
*((unsigned char *) (base + 0x0FFFE)) = 0xfc;
return 1;
}
void reset_int_vect(void)
{
/*
* This table is normally located at 0xF000:0xF0A4. However, int 0x42,
* function 0 (Mode Set) expects it (or a copy) somewhere in the bottom
* 64kB. Note that because this data doesn't survive POST, int 0x42 should
* only be used during EGA/VGA BIOS initialisation.
*/
static const unsigned char VideoParms[] = {
/* Timing for modes 0x00 & 0x01 */
0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
/* Timing for modes 0x02 & 0x03 */
0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
/* Timing for modes 0x04, 0x05 & 0x06 */
0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70,
0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
/* Timing for mode 0x07 */
0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19,
0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
/* Display page lengths in little endian order */
0x00, 0x08, /* Modes 0x00 and 0x01 */
0x00, 0x10, /* Modes 0x02 and 0x03 */
0x00, 0x40, /* Modes 0x04 and 0x05 */
0x00, 0x40, /* Modes 0x06 and 0x07 */
/* Number of columns for each mode */
40, 40, 80, 80, 40, 40, 80, 80,
/* CGA Mode register value for each mode */
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29,
/* Padding */
0x00, 0x00, 0x00, 0x00
};
int i;
for (i = 0; i < sizeof(VideoParms); i++)
MEM_WB(i + (0x1000 - sizeof(VideoParms)), VideoParms[i]);
MEM_WW(0x1d << 2, 0x1000 - sizeof(VideoParms));
MEM_WW((0x1d << 2) + 2, 0);
printf("SETUP INT\n");
MEM_WW(0x10 << 2, 0xf065);
MEM_WW((0x10 << 2) + 2, SYS_BIOS >> 4);
MEM_WW(0x42 << 2, 0xf065);
MEM_WW((0x42 << 2) + 2, SYS_BIOS >> 4);
MEM_WW(0x6D << 2, 0xf065);
MEM_WW((0x6D << 2) + 2, SYS_BIOS >> 4);
}
void set_return_trap(void)
{
/*
* Here we set the exit condition: We return when we encounter
* 'hlt' (=0xf4), which we locate at address 0x600 in x86 memory.
*/
MEM_WB(0x0600, 0xf4);
/*
* Allocate a segment for the stack
*/
xf86Int10AllocPages(1, current->stackseg);
}
void *xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex)
{
EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
OptionInfoPtr options = NULL;
if (pEnt->device) {
pointer configOptions = NULL;
/* Check if xf86CollectOptions() has already been called */
if (((pEnt->index < 0) ||
!xf86Screens[pEnt->index] ||
!(configOptions = xf86Screens[pEnt->index]->options)) &&
pEnt->device)
configOptions = pEnt->device->options;
if (configOptions) {
if (!(options = (OptionInfoPtr) xalloc(sizeof(INT10Options))))
return NULL;
(void) memcpy(options, INT10Options, sizeof(INT10Options));
xf86ProcessOptions(pScrn->scrnIndex, configOptions, options);
}
}
xfree(pEnt);
return options;
}
Bool int10skip(void *options)
{
Bool noint10 = FALSE;
if (!options)
return FALSE;
xf86GetOptValBool(options, OPT_NOINT10, &noint10);
return noint10;
}
Bool int10_check_bios(int scrnIndex, int codeSeg, unsigned char *vbiosMem)
{
int size;
if ((codeSeg & 0x1f) || /* Not 512-byte aligned otherwise */
((codeSeg << 4) < V_BIOS) || ((codeSeg << 4) >= SYS_SIZE))
return FALSE;
if (xf86IsPc98())
return FALSE;
if ((*vbiosMem != 0x55) || (*(vbiosMem + 1) != 0xAA) || !*(vbiosMem + 2))
return FALSE;
size = *(vbiosMem + 2) * 512;
if ((size + (codeSeg << 4)) > SYS_SIZE)
return FALSE;
if (bios_checksum(vbiosMem, size))
xf86DrvMsg(scrnIndex, X_WARNING, "Bad V_BIOS checksum\n");
return TRUE;
}
Bool initPrimary(void *options)
{
Bool initPrimary = FALSE;
if (!options)
return FALSE;
xf86GetOptValBool(options, OPT_INIT_PRIMARY, &initPrimary);
return initPrimary;
}
void xf86int10ParseBiosLocation(void *options, xf86int10BiosLocationPtr bios)
{
char *s;
char *p;
char *str = NULL;
if (options)
str = xf86GetOptValString(options, OPT_BIOS_LOCATION);
bios->bus = BUS_NONE;
if (!str)
return;
s = xstrdup(str);
p = strtok(s, ":");
if (xf86NameCmp(p, "pci"))
bios->bus = BUS_PCI;
else if (xf86NameCmp(p, "primary"))
bios->bus = BUS_ISA;
xfree(s);
if (bios->bus == BUS_NONE)
return;
s = xstrdup(str);
p = strchr(s, ':');
switch (bios->bus) {
case BUS_ISA:
if (p)
bios->location.legacy = atoi(++p);
else
bios->location.legacy = 0;
break;
case BUS_PCI:
if (p) {
bios->location.pci.bus = atoi(++p);
if ((p = strchr(p, ':'))) {
bios->location.pci.dev = atoi(++p);
if ((p = strchr(p, ':'))) {
bios->location.pci.func = atoi(++p);
break;
}
}
}
/* fall through */
bios->bus = BUS_NONE;
break;
default:
break;
}
xfree(s);
}
#endif

View File

@ -0,0 +1,24 @@
/*
* 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.
*/
#ifndef _BYTEORDER_H
#define _BYTEORDER_H
#define __LITTLE_ENDIAN 1234
#define cpu_to_le16(x) ((uint16_t)(x))
#define cpu_to_le32(x) ((uint32_t)(x))
#endif /* _BYTEORDER_H */

View File

@ -1,4 +0,0 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H
#include <sys/io.h>
#endif

View File

@ -0,0 +1,35 @@
/*
* 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.
*/
#define CONFIG_PCI_OPTION_ROM_RUN_YABEL 1
#define CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES 0
#define CONFIG_YABEL_DIRECTHW 1
#define CONFIG_X86EMU_DEBUG 1
#define CONFIG_X86EMU_DEBUG_TIMINGS 0
#define CONFIG_X86EMU_DEBUG_JMP 0
#define CONFIG_X86EMU_DEBUG_TRACE 0
#define CONFIG_X86EMU_DEBUG_PNP 0
#define CONFIG_X86EMU_DEBUG_DISK 0
#define CONFIG_X86EMU_DEBUG_PMM 0
#define CONFIG_X86EMU_DEBUG_VBE 0
#define CONFIG_X86EMU_DEBUG_INT10 0
#define CONFIG_X86EMU_DEBUG_INTERRUPTS 0
#define CONFIG_X86EMU_DEBUG_CHECK_VMEM_ACCESS 0
#define CONFIG_X86EMU_DEBUG_MEM 0
#define CONFIG_X86EMU_DEBUG_IO 0
#define CONFIG_ARCH_X86 1
#define CONFIG_ARCH_ARM 0

View File

@ -1,6 +1,21 @@
/*
* 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.
*/
#ifndef _CONSOLE_CONSOLE_H
#define _CONSOLE_CONSOLE_H
#define CONFIG_X86EMU_DEBUG 1
int printk(int msg_level, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
#endif

View File

@ -1,3 +1,18 @@
/*
* 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.
*/
#ifndef _STDTYPES_H
#define _STDTYPES_H

View File

@ -0,0 +1,57 @@
/*
* This file is part of the coreboot project.
*
* 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.
*/
#ifndef _SWAB_H
#define _SWAB_H
/*
* linux/byteorder/swab.h
* Byte-swapping, independently from CPU endianness
* swabXX[ps]?(foo)
*
* Francois-Rene Rideau <fare@tunes.org> 19971205
* separated swab functions from cpu_to_XX,
* to clean up support for bizarre-endian architectures.
*
* See asm-i386/byteorder.h and such for examples of how to provide
* architecture-dependent optimized versions
*
*/
/* casts are necessary for constants, because we never know how for sure
* how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
*/
#define swab16(x) \
((unsigned short)( \
(((unsigned short)(x) & (unsigned short)0x00ffU) << 8) | \
(((unsigned short)(x) & (unsigned short)0xff00U) >> 8) ))
#define swab32(x) \
((unsigned int)( \
(((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \
(((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \
(((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \
(((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) ))
#define swab64(x) \
((uint64_t)( \
(((uint64_t)(x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(((uint64_t)(x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & (uint64_t)0xff00000000000000ULL) >> 56) ))
#endif /* _SWAB_H */

View File

@ -1,476 +0,0 @@
#include <stdio.h>
#include <stdtypes.h>
#include "testbios.h"
extern int verbose;
#ifndef _PC
/*
* This is derived from a number of PC system BIOS'es. The intent here is to
* provide very primitive video support, before an EGA/VGA BIOS installs its
* own interrupt vector. Here, "Ignored" calls should remain so. "Not
* Implemented" denotes functionality that can be implemented should the need
* arise. What are "Not Implemented" throughout are video memory accesses.
* Also, very little input validity checking is done here.
*/
int int42_handler(void)
{
#if 0
if (verbose && X86_AH != 0x0e) {
printf("int%x\n", current->num);
x86emu_dump_xregs();
}
switch (X86_AH) {
case 0x00:
/* Set Video Mode */
/* Enter: AL = video mode number */
/* Leave: Nothing */
/* Implemented (except for clearing the screen) */
{ /* Localise */
int i;
u16 ioport, int1d, regvals, tmp;
u8 mode, cgamode, cgacolour;
/*
* Ignore all mode numbers but 0x00-0x13. Some systems also ignore
* 0x0B and 0x0C, but don't do that here.
*/
if (X86_AL > 0x13)
break;
/*
* You didn't think that was really the mode set, did you? There
* are only so many slots in the video parameter table...
*/
mode = X86_AL;
ioport = 0x03D4;
switch (MEM_RB(0x0410) & 0x30) {
case 0x30: /* MDA */
mode = 0x07; /* Force mode to 0x07 */
ioport = 0x03B4;
break;
case 0x10: /* CGA 40x25 */
if (mode >= 0x07)
mode = 0x01;
break;
case 0x20: /* CGA 80x25 (MCGA?) */
if (mode >= 0x07)
mode = 0x03;
break;
case 0x00: /* EGA/VGA */
if (mode >= 0x07) /* Don't try MDA timings */
mode = 0x01; /* !?!?! */
break;
}
/* Locate data in video parameter table */
int1d = MEM_RW(0x1d << 2);
regvals = ((mode >> 1) << 4) + int1d;
cgacolour = 0x30;
if (mode == 0x06) {
regvals -= 0x10;
cgacolour = 0x3F;
}
/** Update BIOS Data Area **/
/* Video mode */
MEM_WB(0x0449, mode);
/* Columns */
tmp = MEM_RB(mode + int1d + 0x48);
MEM_WW(0x044A, tmp);
/* Page length */
tmp = MEM_RW((mode & 0x06) + int1d + 0x40);
MEM_WW(0x044C, tmp);
/* Start Address */
MEM_WW(0x044E, 0);
/* Cursor positions, one for each display page */
for (i = 0x0450; i < 0x0460; i += 2)
MEM_WW(i, 0);
/* Cursor start & end scanlines */
tmp = MEM_RB(regvals + 0x0B);
MEM_WB(0x0460, tmp);
tmp = MEM_RB(regvals + 0x0A);
MEM_WB(0x0461, tmp);
/* Current display page number */
MEM_WB(0x0462, 0);
/* CRTC I/O address */
MEM_WW(0x0463, ioport);
/* CGA Mode register value */
cgamode = MEM_RB(mode + int1d + 0x50);
MEM_WB(0x0465, cgamode);
/* CGA Colour register value */
MEM_WB(0x0466, cgacolour);
/* Rows */
MEM_WB(0x0484, (25 - 1));
/* Programme the mode */
outb(ioport + 4, cgamode & 0x37); /* Turn off screen */
for (i = 0; i < 0x10; i++) {
tmp = MEM_RB(regvals + i);
outb(ioport, i);
outb(ioport + 1, tmp);
}
outb(ioport + 5, cgacolour); /* Select colour mode */
outb(ioport + 4, cgamode); /* Turn on screen */
}
break;
case 0x01:
/* Set Cursor Type */
/* Enter: CH = starting line for cursor */
/* CL = ending line for cursor */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 ioport = MEM_RW(0x0463);
MEM_WB(0x0460, X86_CL);
MEM_WB(0x0461, X86_CH);
outb(ioport, 0x0A);
outb(ioport + 1, X86_CH);
outb(ioport, 0x0B);
outb(ioport + 1, X86_CL);
}
break;
case 0x02:
/* Set Cursor Position */
/* Enter: BH = display page number */
/* DH = row */
/* DL = column */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 offset, ioport;
MEM_WB((X86_BH << 1) + 0x0450, X86_DL);
MEM_WB((X86_BH << 1) + 0x0451, X86_DH);
if (X86_BH != MEM_RB(0x0462))
break;
offset = (X86_DH * MEM_RW(0x044A)) + X86_DL;
offset += MEM_RW(0x044E) << 1;
ioport = MEM_RW(0x0463);
outb(ioport, 0x0E);
outb(ioport + 1, offset >> 8);
outb(ioport, 0x0F);
outb(ioport + 1, offset & 0xFF);
}
break;
case 0x03:
/* Get Cursor Position */
/* Enter: BH = display page number */
/* Leave: CH = starting line for cursor */
/* CL = ending line for cursor */
/* DH = row */
/* DL = column */
/* Implemented */
{ /* Localise */
X86_CL = MEM_RB(0x0460);
X86_CH = MEM_RB(0x0461);
X86_DL = MEM_RB((X86_BH << 1) + 0x0450);
X86_DH = MEM_RB((X86_BH << 1) + 0x0451);
}
break;
case 0x04:
/* Get Light Pen Position */
/* Enter: Nothing */
/* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */
/* BX = pixel column */
/* CX = pixel row */
/* DH = character row */
/* DL = character column */
/* Not Implemented */
{ /* Localise */
printf("int%x - Get Light Pen Position. "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
X86_AH = X86_BX = X86_CX = X86_DX = 0;
}
break;
case 0x05:
/* Set Display Page */
/* Enter: AL = display page number */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 start, ioport = MEM_RW(0x0463);
u8 x, y;
/* Calculate new start address */
MEM_WB(0x0462, X86_AL);
start = X86_AL * MEM_RW(0x044C);
MEM_WW(0x044E, start);
start <<= 1;
/* Update start address */
outb(ioport, 0x0C);
outb(ioport + 1, start >> 8);
outb(ioport, 0x0D);
outb(ioport + 1, start & 0xFF);
/* Switch cursor position */
y = MEM_RB((X86_AL << 1) + 0x0450);
x = MEM_RB((X86_AL << 1) + 0x0451);
start += (y * MEM_RW(0x044A)) + x;
/* Update cursor position */
outb(ioport, 0x0E);
outb(ioport + 1, start >> 8);
outb(ioport, 0x0F);
outb(ioport + 1, start & 0xFF);
}
break;
case 0x06:
/* Initialise or Scroll Window Up */
/* Enter: AL = lines to scroll up */
/* BH = attribute for blank */
/* CH = upper y of window */
/* CL = left x of window */
/* DH = lower y of window */
/* DL = right x of window */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
printf("int%x: Initialise or Scroll Window Up - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x07:
/* Initialise or Scroll Window Down */
/* Enter: AL = lines to scroll down */
/* BH = attribute for blank */
/* CH = upper y of window */
/* CL = left x of window */
/* DH = lower y of window */
/* DL = right x of window */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
printf("int%x: Initialise or Scroll Window Down - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x08:
/* Read Character and Attribute at Cursor */
/* Enter: BH = display page number */
/* Leave: AH = attribute */
/* AL = character */
/* Not Implemented */
{ /* Localise */
printf
("int%x: Read Character and Attribute at Cursor - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
X86_AX = 0;
}
break;
case 0x09:
/* Write Character and Attribute at Cursor */
/* Enter: AL = character */
/* BH = display page number */
/* BL = attribute (text) or colour (graphics) */
/* CX = replication count */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
printf
("int%x: Write Character and Attribute at Cursor - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x0a:
/* Write Character at Cursor */
/* Enter: AL = character */
/* BH = display page number */
/* BL = colour */
/* CX = replication count */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
printf("int%x: Write Character at Cursor - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x0b:
/* Set Palette, Background or Border */
/* Enter: BH = 0x00 or 0x01 */
/* BL = colour or palette (respectively) */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 ioport = MEM_RW(0x0463) + 5;
u8 cgacolour = MEM_RB(0x0466);
if (X86_BH) {
cgacolour &= 0xDF;
cgacolour |= (X86_BL & 0x01) << 5;
} else {
cgacolour &= 0xE0;
cgacolour |= X86_BL & 0x1F;
}
MEM_WB(0x0466, cgacolour);
outb(ioport, cgacolour);
}
break;
case 0x0c:
/* Write Graphics Pixel */
/* Enter: AL = pixel value */
/* BH = display page number */
/* CX = column */
/* DX = row */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
printf("int%x: Write Graphics Pixel - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x0d:
/* Read Graphics Pixel */
/* Enter: BH = display page number */
/* CX = column */
/* DX = row */
/* Leave: AL = pixel value */
/* Not Implemented */
{ /* Localise */
printf("int%x: Write Graphics Pixel - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
X86_AL = 0;
}
break;
case 0x0e:
/* Write Character in Teletype Mode */
/* Enter: AL = character */
/* BH = display page number */
/* BL = foreground colour */
/* Leave: Nothing */
/* Not Implemented */
/* WARNING: Emulation of BEL characters will require */
/* emulation of RTC and PC speaker I/O. */
/* Also, this recurses through int 0x10 */
/* which might or might not have been */
/* installed yet. */
{ /* Localise */
#ifdef PARANOID
printf("int%x: Write Character in Teletype Mode - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
#endif
printf("%c", X86_AL);
}
break;
case 0x0f:
/* Get Video Mode */
/* Enter: Nothing */
/* Leave: AH = number of columns */
/* AL = video mode number */
/* BH = display page number */
/* Implemented */
{ /* Localise */
X86_AH = MEM_RW(0x044A);
X86_AL = MEM_RB(0x0449);
X86_BH = MEM_RB(0x0462);
}
break;
case 0x10:
/* Colour Control (subfunction in AL) */
/* Enter: Various */
/* Leave: Various */
/* Ignored */
break;
case 0x11:
/* Font Control (subfunction in AL) */
/* Enter: Various */
/* Leave: Various */
/* Ignored */
break;
case 0x12:
/* Miscellaneous (subfunction in BL) */
/* Enter: Various */
/* Leave: Various */
/* Ignored. Previous code here optionally allowed */
/* the enabling and disabling of VGA, but no system */
/* BIOS I've come across actually implements it. */
break;
case 0x13:
/* Write String in Teletype Mode */
/* Enter: AL = write mode */
/* BL = attribute (if (AL & 0x02) == 0) */
/* CX = string length */
/* DH = row */
/* DL = column */
/* ES:BP = string segment:offset */
/* Leave: Nothing */
/* Not Implemented */
/* WARNING: Emulation of BEL characters will require */
/* emulation of RTC and PC speaker I/O. */
/* Also, this recurses through int 0x10 */
/* which might or might not have been */
/* installed yet. */
{ /* Localise */
printf("int%x: Write String in Teletype Mode - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
default:
/* Various extensions */
/* Enter: Various */
/* Leave: Various */
/* Ignored */
break;
}
#endif
return 1;
}
#endif

View File

@ -1,11 +0,0 @@
#include <stdio.h>
#include <stdtypes.h>
#include "testbios.h"
int int15_handler(void)
{
printf("\nint15 encountered.\n");
x86emu_dump_xregs();
X86_EAX = 0;
return 1;
}

View File

@ -1,9 +0,0 @@
#include <stdio.h>
#include "testbios.h"
int int16_handler(void)
{
printf("\nint16: keyboard not supported right now.\n");
x86emu_dump_xregs();
return 1;
}

View File

@ -1,171 +0,0 @@
#include <stdio.h>
#include <stdtypes.h>
#include "testbios.h"
#include "pci-userspace.h"
#define DEBUG_INT1A
#define SUCCESSFUL 0x00
#define DEVICE_NOT_FOUND 0x86
#define BAD_REGISTER_NUMBER 0x87
extern int verbose;
int int1A_handler(void)
{
PCITAG tag = NULL;
pciVideoPtr pvp = NULL;
if (verbose) {
printf("\nint1a encountered.\n");
//x86emu_dump_xregs();
}
switch (X86_AX) {
case 0xb101:
X86_EAX = 0x00; /* no config space/special cycle support */
X86_AL = 0x01; /* config mechanism 1 */
X86_EDX = 0x20494350; /* " ICP" */
X86_EBX = 0x0210; /* Version 2.10 */
X86_ECX &= 0xFF00;
X86_ECX |= (pciNumBuses & 0xFF); /* Max bus number in system */
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
#ifdef DEBUG_INT1A
if (verbose)
printf("PCI bios present.\n");
#endif
return 1;
case 0xb102:
if (X86_DX == pvp->vendor_id && X86_CX == pvp->device_id && X86_ESI == 0) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
X86_EBX = pciSlotBX(tag); // XXX used to be pvp, but both are NULL
}
#ifdef SHOW_ALL_DEVICES
else if ((pvp = xf86FindPciDeviceVendor(X86_EDX, X86_ECX, X86_ESI, pvp))) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
X86_EBX = pciSlotBX(pvp);
}
#endif
else {
X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x ebx=0x%x eflags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS);
#endif
return 1;
case 0xb103:
#if 0
if (X86_CL == pvp->interface &&
X86_CH == pvp->subclass &&
((X86_ECX & 0xFFFF0000) >> 16) == pvp->class) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EBX = pciSlotBX(pvp);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
}
#else
/* FIXME: dirty hack */
if (0);
#endif
#ifdef SHOW_ALL_DEVICES
else if ((pvp = FindPciClass(X86_CL, X86_CH,
(X86_ECX & 0xffff0000) >> 16,
X86_ESI, pvp))) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
X86_EBX = pciSlotBX(pvp);
}
#endif
else {
X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
case 0xb108:
if ((tag = findPci(X86_EBX))) {
X86_CL = pciReadByte(tag, X86_EDI);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
#endif
return 1;
case 0xb109:
if ((tag = findPci(X86_EBX))) {
X86_CX = pciReadWord(tag, X86_EDI);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
#endif
return 1;
case 0xb10a:
if ((tag = findPci(X86_EBX))) {
X86_ECX = pciReadLong(tag, X86_EDI);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
#endif
return 1;
case 0xb10b:
if ((tag = findPci(X86_EBX))) {
pciWriteByte(tag, X86_EDI, X86_CL);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
case 0xb10c:
if ((tag = findPci(X86_EBX))) {
pciWriteWord(tag, X86_EDI, X86_CX);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
case 0xb10d:
if ((tag = findPci(X86_EBX))) {
pciWriteLong(tag, X86_EDI, X86_ECX);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
printf("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
default:
printf("int1a: subfunction not implemented.\n");
return 0;
}
}

View File

@ -1,20 +0,0 @@
#include <stdio.h>
#include "testbios.h"
int intE6_handler(void)
{
#if 0
pciVideoPtr pvp;
if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex)))
X86_AX = (pvp->bus << 8) | (pvp->device << 3) | (pvp->func & 0x7);
pushw(X86_CS);
pushw(X86_IP);
X86_CS = pInt->BIOSseg;
X86_EIP = 0x0003;
X86_ES = 0; /* standard pc es */
#endif
printf("intE6 not supported right now.\n");
x86emu_dump_xregs();
return 1;
}

View File

@ -1,31 +1,30 @@
/*
* 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 <pci/pci.h>
#include "pci-userspace.h"
#ifdef PCI_LIB_VERSION
#define LIBPCI_CHECK_VERSION(major,minor,micro) \
((((major) << 16) | ((minor) << 8) | (micro)) <= PCI_LIB_VERSION)
#else
#define LIBPCI_CHECK_VERSION(major,minor,micro) \
( (LIBPCI_MAJOR_VERSION > (major)) || \
(LIBPCI_MAJOR_VERSION == (major) && LIBPCI_MINOR_VERSION > (minor)) || \
(LIBPCI_MAJOR_VERSION == (major) && LIBPCI_MINOR_VERSION == (minor)) && \
LIBPCI_MICRO_VERSION >= (micro) )
#endif
#define PCITAG struct pci_filter *
#define DEBUG_PCI 1
struct pci_access *pacc;
struct pci_dev *dev;
static struct pci_access *pacc;
struct pci_filter ltag;
int pciNumBuses = 0;
int pciInit(void)
int pci_initialize(void)
{
struct pci_dev *dev;
pacc = pci_alloc();
pci_init(pacc);
@ -36,133 +35,80 @@ int pciInit(void)
return 0;
}
int pciExit(void)
int pci_exit(void)
{
pci_cleanup(pacc);
return 0;
}
PCITAG findPci(unsigned short bx)
{
PCITAG tag = &ltag;
int bus = (bx >> 8) & 0xFF;
int slot = (bx >> 3) & 0x1F;
int func = bx & 0x7;
tag->bus = bus;
tag->slot = slot;
tag->func = func;
#if LIBPCI_CHECK_VERSION(2,1,99)
if (pci_get_dev(pacc, 0, bus, slot, func))
#else
if (pci_get_dev(pacc, bus, slot, func))
#endif
return tag;
return NULL;
}
u32 pciSlotBX(PCITAG tag)
{
return (tag->bus << 8) | (tag->slot << 3) | (tag->func);
}
u8 pciReadByte(PCITAG tag, u32 idx)
u8 pci_read_config8(struct device *dev, unsigned int where)
{
struct pci_dev *d;
#if LIBPCI_CHECK_VERSION(2,1,99)
if ((d = pci_get_dev(pacc, 0, tag->bus, tag->slot, tag->func)))
#else
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
#endif
return pci_read_byte(d, idx);
if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func)))
return pci_read_byte(d, where);
#ifdef DEBUG_PCI
printf("PCI: device not found while read byte (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
dev->busno, dev->slot, dev->func);
#endif
return 0;
}
u16 pciReadWord(PCITAG tag, u32 idx)
u16 pci_read_config16(struct device *dev, unsigned int where)
{
struct pci_dev *d;
#if LIBPCI_CHECK_VERSION(2,1,99)
if ((d = pci_get_dev(pacc, 0, tag->bus, tag->slot, tag->func)))
#else
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
#endif
return pci_read_word(d, idx);
if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func)))
return pci_read_word(d, where);
#ifdef DEBUG_PCI
printf("PCI: device not found while read word (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
dev->busno, dev->slot, dev->func);
#endif
return 0;
}
u32 pciReadLong(PCITAG tag, u32 idx)
u32 pci_read_config32(struct device *dev, unsigned int where)
{
struct pci_dev *d;
#if LIBPCI_CHECK_VERSION(2,1,99)
if ((d = pci_get_dev(pacc, 0, tag->bus, tag->slot, tag->func)))
#else
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
#endif
return pci_read_long(d, idx);
if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func)))
return pci_read_long(d, where);
#ifdef DEBUG_PCI
printf("PCI: device not found while read long (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
printf("PCI: device not found while read dword (%x:%x.%x)\n",
dev->busno, dev->slot, dev->func);
#endif
return 0;
}
void pciWriteLong(PCITAG tag, u32 idx, u32 data)
void pci_write_config8(struct device *dev, unsigned int where, u8 val)
{
struct pci_dev *d;
#if LIBPCI_CHECK_VERSION(2,1,99)
if ((d = pci_get_dev(pacc, 0, tag->bus, tag->slot, tag->func)))
#else
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
#endif
pci_write_long(d, idx, data);
if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func)))
pci_write_byte(d, where, val);
#ifdef DEBUG_PCI
else
printf("PCI: device not found while write long (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
printf("PCI: device not found while write byte (%x:%x.%x)\n",
dev->busno, dev->slot, dev->func);
#endif
}
void pciWriteWord(PCITAG tag, u32 idx, u16 data)
void pci_write_config16(struct device *dev, unsigned int where, u16 val)
{
struct pci_dev *d;
#if LIBPCI_CHECK_VERSION(2,1,99)
if ((d = pci_get_dev(pacc, 0, tag->bus, tag->slot, tag->func)))
#else
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
#endif
pci_write_word(d, idx, data);
if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func)))
pci_write_word(d, where, val);
#ifdef DEBUG_PCI
else
printf("PCI: device not found while write word (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
dev->busno, dev->slot, dev->func);
#endif
}
void pciWriteByte(PCITAG tag, u32 idx, u8 data)
void pci_write_config32(struct device *dev, unsigned int where, u32 val)
{
struct pci_dev *d;
#if LIBPCI_CHECK_VERSION(2,1,99)
if ((d = pci_get_dev(pacc, 0, tag->bus, tag->slot, tag->func)))
#else
if ((d = pci_get_dev(pacc, tag->bus, tag->slot, tag->func)))
#endif
pci_write_long(d, idx, data);
if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func)))
pci_write_long(d, where, val);
#ifdef DEBUG_PCI
else
printf("PCI: device not found while write long (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
printf("PCI: device not found while write dword (%x:%x.%x)\n",
dev->busno, dev->slot, dev->func);
#endif
}

View File

@ -1,62 +1,35 @@
/*
* 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.
*/
#ifndef __PCI_USERSPACE_H__
#define __PCI_USERSPACE_H__
#include <pci/pci.h>
typedef unsigned long pciaddr_t;
typedef u8 byte;
typedef u16 word;
#if 0
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
word bus; /* Higher byte can select host bridges */
byte dev, func; /* Device and function */
/* These fields are set by pci_fill_info() */
int known_fields; /* Set of info fields already known */
word vendor_id, device_id; /* Identity of the device */
int irq; /* IRQ number */
pciaddr_t base_addr[6]; /* Base addresses */
pciaddr_t size[6]; /* Region sizes */
pciaddr_t rom_base_addr; /* Expansion ROM base address */
pciaddr_t rom_size; /* Expansion ROM size */
/* Fields used internally: */
void *access;
void *methods;
byte *cache; /* Cached information */
int cache_len;
int hdrtype; /* Direct methods: header type */
void *aux; /* Auxillary data */
struct device {
int busno;
int slot;
int func;
};
int pci_initialize(void);
int pci_exit(void);
struct pci_filter {
int bus, slot, func; /* -1 = ANY */
int vendor, device;
};
#endif
#define PCITAG struct pci_filter *
#define pciVideoPtr struct pci_dev *
extern int pciNumBuses;
int pciInit(void);
int pciExit(void);
PCITAG findPci(unsigned short bx);
//u32 pciSlotBX(pciVideoPtr pvp);
u32 pciSlotBX(PCITAG tag);
void pciWriteLong(PCITAG tag, u32 idx, u32 data);
void pciWriteWord(PCITAG tag, u32 idx, u16 data);
void pciWriteByte(PCITAG tag, u32 idx, u8 data);
u32 pciReadLong(PCITAG tag, u32 idx);
u16 pciReadWord(PCITAG tag, u32 idx);
u8 pciReadByte(PCITAG tag, u32 idx);
u8 pci_read_config8(struct device *dev, unsigned int where);
u16 pci_read_config16(struct device *dev, unsigned int where);
u32 pci_read_config32(struct device *dev, unsigned int where);
void pci_write_config8(struct device *dev, unsigned int where, u8 val);
void pci_write_config16(struct device *dev, unsigned int where, u16 val);
void pci_write_config32(struct device *dev, unsigned int where, u32 val);
#endif

View File

@ -1,3 +1,18 @@
/*
* 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>
@ -7,75 +22,28 @@
#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 "helper_exec.h"
#include <arch/byteorder.h>
#include "device.h"
#include "testbios.h"
#include "pci-userspace.h"
int X86EMU_set_debug(int debug);
unsigned short get_device(char *arg_val);
biosemu_device_t bios_device;
extern int teststart, testend;
_ptr p;
ptr current = 0;
unsigned char biosmem[1024 * 1024];
#define BIOSMEM_SIZE (1024 * 1024)
unsigned char biosmem[BIOSMEM_SIZE];
int verbose = 0;
/* Interrupt multiplexer */
static 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();
}
}
static unsigned char *mapitin(char *file, off_t where, size_t size)
{
void *z;
@ -90,14 +58,57 @@ static unsigned char *mapitin(char *file, off_t where, size_t size)
close(fd);
return z;
}
X86EMU_pioFuncs myfuncs = {
x_inb, x_inw, x_inl,
x_outb, x_outw, x_outl
};
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;
printf ("<%d> ", msg_level);
va_start(args, fmt);
i = vprintf(fmt, args);
va_end(args);
return i;
}
static void usage(char *name)
{
@ -106,11 +117,24 @@ static void usage(char *name)
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 i, c, trace = 0;
int c, trace = 0;
unsigned char *cp;
char *filename;
ssize_t size = 0;
@ -118,12 +142,14 @@ int main(int argc, char **argv)
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;
//char *fsegname = 0;
//unsigned char *fsegptr;
unsigned short initialip = 0, initialcs = 0, devfn = 0;
X86EMU_intrFuncs intFuncs[256];
//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;
@ -132,7 +158,7 @@ int main(int argc, char **argv)
{"help", 0, 0, 'h'},
{"trace", 0, 0, 't'},
{"base", 1, 0, 'b'},
{"fseg", 1, 0, 'f'},
//{"fseg", 1, 0, 'f'},
{"instructionpointer", 1, 0, 'i'},
{"codesegment", 1, 0, 'c'},
{"absegment", 1, 0, 'a'},
@ -156,10 +182,10 @@ int main(int argc, char **argv)
case 't':
trace = 1;
break;
case 'b':
base = strtol(optarg, 0, 0);
have_base = 1;
break;
//case 'b':
// base = strtol(optarg, 0, 0);
// have_base = 1;
// break;
case 'i':
initialip = strtol(optarg, 0, 0);
have_ip = 1;
@ -175,9 +201,9 @@ int main(int argc, char **argv)
case 'p':
parse_rom = 1;
break;
case 'f':
fsegname = optarg;
break;
// case 'f':
// fsegname = optarg;
// break;
case 'a':
absegname = optarg;
break;
@ -220,10 +246,10 @@ int main(int argc, char **argv)
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_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");
@ -234,7 +260,7 @@ int main(int argc, char **argv)
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");
@ -250,6 +276,7 @@ int main(int argc, char **argv)
}
}
}
#endif
if (absegname) {
abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
@ -257,10 +284,6 @@ int main(int argc, char **argv)
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) {
@ -275,17 +298,20 @@ int main(int argc, char **argv)
* basically this means initializing PCI and
* intXX handlers.
*/
pciInit();
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;
@ -322,68 +348,33 @@ int main(int argc, char **argv)
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 */
pciExit();
pci_exit();
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;
}
int printk(int msg_level, const char *fmt, ...)
{
va_list args;
int i;
printf ("<%d> ", msg_level);
va_start(args, fmt);
i = vprintf(fmt, args);
va_end(args);
return i;
}

View File

@ -1,19 +1,21 @@
/* Derived from:
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
/*
* This file is part of the coreboot project.
*
* Copyright 1999 Egbert Eich
*
* 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.
*/
#ifndef __TESTBIOS_H__
#define __TESTBIOS_H__
void x86emu_dump_xregs(void);
int int15_handler(void);
int int16_handler(void);
int int1A_handler(void);
int int42_handler(void);
int intE6_handler(void);
#include <stdtypes.h>
#include <x86emu/x86emu.h>
@ -57,42 +59,4 @@ int intE6_handler(void);
#define X86_CH M.x86.R_CH
#define X86_DH M.x86.R_DH
/* int10 info structure */
typedef struct {
u16 BIOSseg;
u16 inb40time;
struct _mem *mem;
int num;
int ax;
int bx;
int cx;
int dx;
int si;
int di;
int es;
int bp;
int flags;
int stackseg;
} _ptr, *ptr;
typedef struct _mem {
u8(*rb) (ptr, int);
u16(*rw) (ptr, int);
u32(*rl) (ptr, int);
void (*wb) (ptr, int, u8);
void (*ww) (ptr, int, u16);
void (*wl) (ptr, int, u32);
} mem;
#define MEM_WB(where, what) wrb(where,what)
#define MEM_WW(where, what) wrw(where, what)
#define MEM_WL(where, what) wrl(where, what)
#define MEM_RB(where) rdb(where)
#define MEM_RW(where) rdw(where)
#define MEM_RL(where) rdl(where)
extern ptr current;
#endif