ron minnich has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/42238 )
Change subject: Revert "Redo testbios utility to use all of YABEL" ......................................................................
Revert "Redo testbios utility to use all of YABEL"
This reverts commit 05082737a9507a8bbb238d9d439f74a72a7606e8.
The change to use YABEL was a noble idea but never seems to have worked. Revert to a tested version (tested today) that works.
This includes changes to get it all to build again.
It also includes a bug fix for something that seems to have been there for 16+ years!
Change-Id: Iba4088c1c68c7cab86300d0e786d1ce473ff094f Signed-off-by: Ronald G. Minnich rminnich@gmail.com --- M util/vgabios/Makefile D util/vgabios/device.c A util/vgabios/helper_exec.c A util/vgabios/helper_exec.h A util/vgabios/helper_mem.c D util/vgabios/include/arch/byteorder.h A util/vgabios/include/arch/io.h M util/vgabios/include/console/console.h D util/vgabios/include/swab.h A util/vgabios/int10.c A util/vgabios/int15.c A util/vgabios/int16.c A util/vgabios/int1a.c A util/vgabios/inte6.c M util/vgabios/pci-userspace.c M util/vgabios/pci-userspace.h M util/vgabios/testbios.c M util/vgabios/testbios.h 18 files changed, 1,830 insertions(+), 907 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/38/42238/1
diff --git a/util/vgabios/Makefile b/util/vgabios/Makefile index 1baf5ba..713680a 100644 --- a/util/vgabios/Makefile +++ b/util/vgabios/Makefile @@ -9,55 +9,35 @@ #
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 = -Wno-sign-compare -Wno-unused-parameter -Wno-format +CBCFLAGS = -DCONFIG_ARCH_X86=1 -Wno-sign-compare -Wno-unused-but-set-variable -Wno-unused-parameter
-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 +INCLUDES = -Iinclude -I$(TOP)/src/device/oprom/include/ +INCLUDES += --include $(TOP)/src/include/kconfig.h +CBINCLUDES = -I$(TOP)/src --include include/stdtypes.h +CBINCLUDES += --include $(TOP)/src/commonlib/include/commonlib/loglevel.h +CBINCLUDES += -include stdio.h +CBINCLUDES += -include string.h
-CBINCLUDES = -I$(TOP)/src -include include/stdtypes.h -include $(TOP)/src/include/endian.h -CBINCLUDES += -include stdio.h -include sys/io.h +SOURCE = int10.c int15.c int16.c int1a.c inte6.c testbios.c +SOURCE += helper_exec.c helper_mem.c pci-userspace.c
-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 = sys.c decode.c ops.c ops2.c prim_ops.c fpu.c debug.c +X86EMU_DIR = $(TOP)/src/device/oprom/x86emu X86EMU_SOURCE = $(addprefix $(X86EMU_DIR)/, $(X86EMU)) -OBJECTS:=$(addprefix $(OUT)/,$(SOURCE:.c=.o)) $(addprefix $(OUT)/, $(X86EMU:.c=.o)) +OBJECTS:=$(SOURCE:.c=.o) $(X86EMU:.c=.o)
LIBS=-lpci
all: dep testbios
-$(OBJECTS): includes - testbios: $(OBJECTS) printf " LINK $(notdir $@)\n" $(CC) $(CFLAGS) -o $@ $^ $(LIBS) @@ -66,37 +46,21 @@ $(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 $(OBJECTS) *~ testbios - rm -rf $(OUT) + rm -f *.o *~ testbios
distclean: clean rm -f .dependencies
-$(OUT)/%.o: $(X86EMU_DIR)/%.c +%.o: $(X86EMU_DIR)/%.c printf " CC (x86emu) $(notdir $<)\n" - mkdir -p $(dir $@) $(CC) $(CFLAGS) $(CBCFLAGS) $(INCLUDES) $(CBINCLUDES) -c -o $@ $<
-$(OUT)/%.o: %.c +%.o: %.c printf " CC $(notdir $<)\n" - mkdir -p $(dir $@) $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
-.PHONY: all includes clean distclean +.PHONY: all clean distclean .SILENT:
-include .dependencies diff --git a/util/vgabios/device.c b/util/vgabios/device.c deleted file mode 100644 index d130314..0000000 --- a/util/vgabios/device.c +++ /dev/null @@ -1,471 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -#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; -} diff --git a/util/vgabios/helper_exec.c b/util/vgabios/helper_exec.c new file mode 100644 index 0000000..4d6aae5 --- /dev/null +++ b/util/vgabios/helper_exec.c @@ -0,0 +1,269 @@ +/* $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]); +} +*/ diff --git a/util/vgabios/helper_exec.h b/util/vgabios/helper_exec.h new file mode 100644 index 0000000..7115ffb --- /dev/null +++ b/util/vgabios/helper_exec.h @@ -0,0 +1,32 @@ +#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 diff --git a/util/vgabios/helper_mem.c b/util/vgabios/helper_mem.c new file mode 100644 index 0000000..50a303b --- /dev/null +++ b/util/vgabios/helper_mem.c @@ -0,0 +1,313 @@ +/* $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 diff --git a/util/vgabios/include/arch/byteorder.h b/util/vgabios/include/arch/byteorder.h deleted file mode 100644 index 349e28b..0000000 --- a/util/vgabios/include/arch/byteorder.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#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 */ diff --git a/util/vgabios/include/arch/io.h b/util/vgabios/include/arch/io.h new file mode 100644 index 0000000..f28499d --- /dev/null +++ b/util/vgabios/include/arch/io.h @@ -0,0 +1,4 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H +#include <sys/io.h> +#endif diff --git a/util/vgabios/include/console/console.h b/util/vgabios/include/console/console.h index 0aa5595..2841c3c 100644 --- a/util/vgabios/include/console/console.h +++ b/util/vgabios/include/console/console.h @@ -2,7 +2,7 @@
#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 diff --git a/util/vgabios/include/swab.h b/util/vgabios/include/swab.h deleted file mode 100644 index bffabbf..0000000 --- a/util/vgabios/include/swab.h +++ /dev/null @@ -1,46 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#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 */ diff --git a/util/vgabios/int10.c b/util/vgabios/int10.c new file mode 100644 index 0000000..21ba7fb --- /dev/null +++ b/util/vgabios/int10.c @@ -0,0 +1,476 @@ +#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 diff --git a/util/vgabios/int15.c b/util/vgabios/int15.c new file mode 100644 index 0000000..a1235bb --- /dev/null +++ b/util/vgabios/int15.c @@ -0,0 +1,11 @@ +#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; +} diff --git a/util/vgabios/int16.c b/util/vgabios/int16.c new file mode 100644 index 0000000..06df826 --- /dev/null +++ b/util/vgabios/int16.c @@ -0,0 +1,9 @@ +#include <stdio.h> +#include "testbios.h" + +int int16_handler(void) +{ + printf("\nint16: keyboard not supported right now.\n"); + x86emu_dump_xregs(); + return 1; +} diff --git a/util/vgabios/int1a.c b/util/vgabios/int1a.c new file mode 100644 index 0000000..9fcff8a --- /dev/null +++ b/util/vgabios/int1a.c @@ -0,0 +1,171 @@ +#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; + } +} diff --git a/util/vgabios/inte6.c b/util/vgabios/inte6.c new file mode 100644 index 0000000..19b6110 --- /dev/null +++ b/util/vgabios/inte6.c @@ -0,0 +1,20 @@ +#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; +} diff --git a/util/vgabios/pci-userspace.c b/util/vgabios/pci-userspace.c index 5d8a7fe..a43bf9c 100644 --- a/util/vgabios/pci-userspace.c +++ b/util/vgabios/pci-userspace.c @@ -1,17 +1,33 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#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
-static struct pci_access *pacc; +struct pci_access *pacc; +struct pci_dev *dev;
-int pci_initialize(void) +struct pci_filter ltag; + + +int pciNumBuses = 0; + +int pciInit(void) { - struct pci_dev *dev; - pacc = pci_alloc();
pci_init(pacc); @@ -22,80 +38,133 @@ return 0; }
-int pci_exit(void) +int pciExit(void) { pci_cleanup(pacc); return 0; }
-u8 pci_read_config8(struct device *dev, unsigned int where) +PCITAG findPci(unsigned short bx) +{ + PCITAG tag = <ag; + + 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) { struct pci_dev *d; - if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func))) - return pci_read_byte(d, where); +#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); #ifdef DEBUG_PCI printf("PCI: device not found while read byte (%x:%x.%x)\n", - dev->busno, dev->slot, dev->func); + tag->bus, tag->slot, tag->func); #endif return 0; }
-u16 pci_read_config16(struct device *dev, unsigned int where) +u16 pciReadWord(PCITAG tag, u32 idx) { struct pci_dev *d; - if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func))) - return pci_read_word(d, where); +#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); #ifdef DEBUG_PCI printf("PCI: device not found while read word (%x:%x.%x)\n", - dev->busno, dev->slot, dev->func); + tag->bus, tag->slot, tag->func); #endif return 0; }
-u32 pci_read_config32(struct device *dev, unsigned int where) +u32 pciReadLong(PCITAG tag, u32 idx) { struct pci_dev *d; - if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func))) - return pci_read_long(d, where); +#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); #ifdef DEBUG_PCI - printf("PCI: device not found while read dword (%x:%x.%x)\n", - dev->busno, dev->slot, dev->func); + printf("PCI: device not found while read long (%x:%x.%x)\n", + tag->bus, tag->slot, tag->func); #endif return 0; }
-void pci_write_config8(struct device *dev, unsigned int where, u8 val) + +void pciWriteLong(PCITAG tag, u32 idx, u32 data) { struct pci_dev *d; - if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func))) - pci_write_byte(d, where, val); +#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); #ifdef DEBUG_PCI else - printf("PCI: device not found while write byte (%x:%x.%x)\n", - dev->busno, dev->slot, dev->func); + printf("PCI: device not found while write long (%x:%x.%x)\n", + tag->bus, tag->slot, tag->func); #endif }
-void pci_write_config16(struct device *dev, unsigned int where, u16 val) +void pciWriteWord(PCITAG tag, u32 idx, u16 data) { struct pci_dev *d; - if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func))) - pci_write_word(d, where, val); +#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); #ifdef DEBUG_PCI else printf("PCI: device not found while write word (%x:%x.%x)\n", - dev->busno, dev->slot, dev->func); + tag->bus, tag->slot, tag->func); #endif + }
-void pci_write_config32(struct device *dev, unsigned int where, u32 val) +void pciWriteByte(PCITAG tag, u32 idx, u8 data) { struct pci_dev *d; - if ((d = pci_get_dev(pacc, 0, dev->busno, dev->slot, dev->func))) - pci_write_long(d, where, val); +#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); #ifdef DEBUG_PCI else - printf("PCI: device not found while write dword (%x:%x.%x)\n", - dev->busno, dev->slot, dev->func); + printf("PCI: device not found while write long (%x:%x.%x)\n", + tag->bus, tag->slot, tag->func); #endif } diff --git a/util/vgabios/pci-userspace.h b/util/vgabios/pci-userspace.h index 879a91d..e59faf3 100644 --- a/util/vgabios/pci-userspace.h +++ b/util/vgabios/pci-userspace.h @@ -3,20 +3,62 @@ #ifndef __PCI_USERSPACE_H__ #define __PCI_USERSPACE_H__
-struct device { - int busno; - int slot; - int func; +#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 */ };
-int pci_initialize(void); -int pci_exit(void);
-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); +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);
#endif diff --git a/util/vgabios/testbios.c b/util/vgabios/testbios.c index d66c857..34e3219 100644 --- a/util/vgabios/testbios.c +++ b/util/vgabios/testbios.c @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -9,28 +7,75 @@ #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 "helper_exec.h" #include "testbios.h" #include "pci-userspace.h" int X86EMU_set_debug(int debug); - -biosemu_device_t bios_device; +unsigned short get_device(char *arg_val);
extern int teststart, testend;
-#define BIOSMEM_SIZE (1024 * 1024) -unsigned char biosmem[BIOSMEM_SIZE]; +_ptr p; +ptr current = 0; +unsigned char biosmem[1024 * 1024];
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; @@ -45,9 +90,254 @@ close(fd);
return z; + }
-static unsigned short get_device(char *arg_val) +X86EMU_pioFuncs myfuncs = { + x_inb, x_inw, x_inl, + x_outb, x_outw, x_outl +}; + + +static 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; + 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; + + 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 (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 { + const char *date = "01/01/99"; + for (i = 0; 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; @@ -81,6 +371,7 @@ devfn = strtol(tok, 0, 0); }
+ return devfn; }
@@ -89,280 +380,10 @@ va_list args; int i;
- putchar('<'); - putchar('0' + msg_level); - putchar('>'); - putchar(' '); + printf ("<%d> ", msg_level); 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 = NULL; - void *abseg = NULL; - 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; -} diff --git a/util/vgabios/testbios.h b/util/vgabios/testbios.h index 487b2b1..d895fa3 100644 --- a/util/vgabios/testbios.h +++ b/util/vgabios/testbios.h @@ -1,8 +1,20 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +/* Derived from: + * XFree86 int10 module + * execute BIOS int 10h calls in x86 real mode environment + * Copyright 1999 Egbert Eich + */
#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>
@@ -46,4 +58,42 @@ #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