Subject: [PATCH 4/5] integration of biosemu (aka YABEL) into coreboot

Signed-off-by: Pattrick Hueper <phueper@hueper.net>
Acked-by: Myles Watson <mylesgw@gmail.com>


git-svn-id: svn://coreboot.org/repository/coreboot-v3@1076 f3766cd6-281f-0410-b1cd-43a5c92072e9
This commit is contained in:
Myles Watson 2008-12-16 22:46:55 +00:00
commit 80aa586a51
22 changed files with 864 additions and 413 deletions

View file

@ -233,6 +233,12 @@ ifneq ($(strip $(CC)),)
LIBGCC_FILE_NAME := $(shell $(CC) -print-libgcc-file-name)
endif
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
# biosemu wants libgcc
ifneq ($(strip $(CC)),)
LIBGCC_FILE_NAME := $(shell $(CC) -print-libgcc-file-name)
endif
endif
STAGE2_OBJ += $(obj)/util/x86emu/libx86emu.a $(LIBGCC_FILE_NAME)
endif

View file

@ -26,7 +26,7 @@ config PCI_OPTION_ROM_RUN
Execute PCI/AGP option ROMs if available. This is required to
enable PCI/AGP VGA plugin cards. This option is not exposed
to the user but set by the options PCI_OPTION_ROM_RUN_VM86
and PCI_OPTION_ROM_RUN_X86EMU.
, PCI_OPTION_ROM_RUN_X86EMU and PCI_OPTION_ROM_RUN_YABEL.
choice
prompt "Execute PCI Option ROMs"
@ -46,6 +46,23 @@ config PCI_OPTION_ROM_RUN_X86EMU
x86emu is slow, big and safe. All 16bit x86 code is executed
in an encapsulated environment where it can not break out.
config PCI_OPTION_ROM_RUN_YABEL
bool "YABEL"
select PCI_OPTION_ROM_RUN
help
YABEL: Yet another BIOS Emulation Layer
If you choose this option, the x86 instruction set emulator
x86emu is used to execute 16bit legacy BIOS option ROMs just
like the "x86emu" choice.
The BIOS Emulation code is very different from the "x86emu"
choice however, it is a more complete legacy BIOS implementation
and should be able to execute more Option ROMs than the
"x86emu" choice
YABEL is even slower and bigger than x86emu and just as safe.
All 16bit x86 code is executed in an encapsulated environment
where it can not break out.
config PCI_OPTION_ROM_RUN_VM86
bool "vm86"
select PCI_OPTION_ROM_RUN
@ -66,6 +83,30 @@ config PCI_OPTION_ROM_RUN_NONE
endchoice
config YABEL_ADVANCED_SETTINGS
depends EXPERT && PCI_OPTION_ROM_RUN_YABEL
bool "Enable advanced YABEL Settings"
default n
help
Set this to enable advanced YABEL settings
menu "Advanced YABEL Settings"
depends YABEL_ADVANCED_SETTINGS
config YABEL_VIRTMEM_LOCATION
hex "YABEL Virtual Memory Location"
help
Set the location that YABEL uses for "virtual" memory.
YABEL uses its own memory where INT handlers, BIOS Config
Area and Option ROM code is copied to. This is needed to
keep YABEL in its own environment. This memory area will be
overwritten by YABEL, so no necessary data for coreboot
must reside here.
If YABEL_ADVANCED_SETTINGS is not enabled, the code defaults
to 0x1000000 (16 MB).
endmenu
# TODO: This should probably become a CMOS option.
config MULTIPLE_VGA_INIT
bool "Initialize all VGA cards"

View file

@ -18,14 +18,34 @@
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
#X86EMU_INCLUDE = -I $(src)/util/x86emu/include
X86EMU_SRC = debug.c decode.c fpu.c ops.c ops2.c prim_ops.c sys.c
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
BIOSEMU_SRC = biosemu.c pcbios/pcibios.c
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
BIOSEMU_SRC = biosemu.c debug.c device.c mem.c io.c interrupt.c
#TODO: add vbe.c, currently not needed...
#BIOSEMU_SRC +=vbe.c
#PH: TODO: remove the compat files??
BIOSEMU_SRC += compat/functions.c
X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel
X86EMU_INCLUDE += -I $(src)/util/x86emu
#TODO: remove these, these are .h files from slof, to make the merge easier...
X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel/compat
endif
VM86_SRC = vm86.c vm86_gdt.c
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(BIOSEMU_SRC)
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_YABEL),y)
LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(patsubst %,yabel/%,$(BIOSEMU_SRC))
endif
ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_VM86),y)
LIBX86EMU_SRC=$(VM86_SRC)
endif
@ -47,5 +67,5 @@ $(obj)/util/x86emu/libx86emu.a: $(LIBX86EMU_OBJS) $(src)/.config
$(obj)/util/x86emu/%.o: $(src)/util/x86emu/%.c
$(Q)mkdir -p $(dir $@)
$(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n"
$(Q)$(CC) $(INITCFLAGS) -I$(src)/util/x86emu/include -c $< -o $@
$(Q)$(CC) -Werror $(INITCFLAGS) $(X86EMU_INCLUDE) -I$(src)/util/x86emu/include -c $< -o $@

View file

@ -10,12 +10,9 @@
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <types.h>
#include <cpu.h>
#include "debug.h"
@ -32,6 +29,7 @@
#include <rtas.h>
#include <device/device.h>
static X86EMU_memFuncs my_mem_funcs = {
my_rdb, my_rdw, my_rdl,
@ -43,44 +41,30 @@ static X86EMU_pioFuncs my_pio_funcs = {
my_outb, my_outw, my_outl
};
void dump(uint8_t * addr, uint32_t len);
void dump(u8 * addr, u32 len);
uint32_t
biosemu(char argc, char **argv)
u32
biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev)
{
uint8_t *rom_image;
u8 *rom_image;
int i = 0;
uint8_t *biosmem;
uint32_t biosmem_size;
#ifdef DEBUG
debug_flags = DEBUG_PRINT_INT10 | DEBUG_PNP;// | DEBUG_PMM;// | DEBUG_INTR | DEBUG_CHECK_VMEM_ACCESS | DEBUG_MEM | DEBUG_IO;// | DEBUG_TRACE_X86EMU | DEBUG_JMP;
debug_flags = DEBUG_PRINT_INT10 | DEBUG_PNP | DEBUG_PMM | DEBUG_INTR;// | DEBUG_CHECK_VMEM_ACCESS | DEBUG_MEM | DEBUG_IO;// | DEBUG_TRACE_X86EMU | DEBUG_JMP;
#endif
if (argc < 3) {
printf("Usage %s <vmem_base> <device_path>\n", argv[0]);
for (i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
return -1;
}
// argv[1] is address of virtual BIOS mem...
// argv[2] is the size
biosmem = (uint8_t *) strtoul(argv[1], 0, 16);
biosmem_size = strtoul(argv[2], 0, 16);
if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
printf("Error: Not enough virtual memory: %x, required: %x!\n",
biosmem_size, MIN_REQUIRED_VMEM_SIZE);
return -1;
}
// argv[3] is the device to open and use...
if (dev_init(argv[3]) != 0) {
if (biosemu_dev_init(dev) != 0) {
printf("Error initializing device!\n");
return -1;
}
if (dev_check_exprom() != 0) {
if (biosemu_dev_check_exprom() != 0) {
printf("Error: Device Expansion ROM invalid!\n");
return -1;
}
rom_image = (uint8_t *) bios_device.img_addr;
rom_image = (u8 *) bios_device.img_addr;
DEBUG_PRINTF("executing rom_image from %p\n", rom_image);
DEBUG_PRINTF("biosmem at %p\n", biosmem);
@ -98,9 +82,9 @@ biosemu(char argc, char **argv)
// copy expansion ROM image to segment OPTION_ROM_CODE_SEGMENT
// NOTE: this sometimes fails, some bytes are 0x00... so we compare
// after copying and do some retries...
uint8_t *mem_img = biosmem + (OPTION_ROM_CODE_SEGMENT << 4);
uint8_t copy_count = 0;
uint8_t cmp_result = 0;
u8 *mem_img = biosmem + (OPTION_ROM_CODE_SEGMENT << 4);
u8 copy_count = 0;
u8 cmp_result = 0;
do {
#if 0
set_ci();
@ -108,7 +92,7 @@ biosemu(char argc, char **argv)
clr_ci();
#else
// memcpy fails... try copy byte-by-byte with set/clr_ci
uint8_t c;
u8 c;
for (i = 0; i < bios_device.img_size; i++) {
set_ci();
c = *(rom_image + i);

View file

@ -0,0 +1,83 @@
/* this file contains functions provided by SLOF, that the current biosemu implementation needs
* they should go away inthe future...
*/
#include <types.h>
#include <device/device.h>
#include <config.h>
#define VMEM_SIZE 1024 *1024 /* 1 MB */
#ifdef CONFIG_YABEL_VIRTMEM_LOCATION
u8* vmem = (u8 *) CONFIG_YABEL_VIRTMEM_LOCATION;
#else
u8* vmem = (u8 *) (16*1024*1024); /* default to 16MB */
#endif
u32 biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev);
void run_bios(struct device * dev, unsigned long addr)
{
biosemu(vmem, VMEM_SIZE, dev);
}
u64 get_time(void)
{
u64 act;
u32 eax, edx;
__asm__ __volatile__(
"rdtsc"
: "=a"(eax), "=d"(edx)
: /* no inputs, no clobber */);
act = ((u64) edx << 32) | eax;
return act;
}
unsigned int
read_io(void *addr, size_t sz)
{
unsigned int ret;
/* since we are using inb instructions, we need the port number as 16bit value */
u16 port = (u16)(u32) addr;
switch (sz) {
case 1:
asm volatile ("inb %1, %b0" : "=a"(ret) : "d" (port));
break;
case 2:
asm volatile ("inw %1, %w0" : "=a"(ret) : "d" (port));
break;
case 4:
asm volatile ("inl %1, %0" : "=a"(ret) : "d" (port));
break;
default:
ret = 0;
}
return ret;
}
int
write_io(void *addr, unsigned int value, size_t sz)
{
u16 port = (u16)(u32) addr;
switch (sz) {
/* since we are using inb instructions, we need the port number as 16bit value */
case 1:
asm volatile ("outb %b0, %1" : : "a"(value), "d" (port));
break;
case 2:
asm volatile ("outw %w0, %1" : : "a"(value), "d" (port));
break;
case 4:
asm volatile ("outl %0, %1" : : "a"(value), "d" (port));
break;
default:
return -1;
}
return 0;
}

View file

@ -0,0 +1,56 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* 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
*****************************************************************************/
#ifndef OF_H
#define OF_H
#define p32 int
#define p32cast (int) (unsigned long) (void*)
#define phandle_t p32
#define ihandle_t p32
typedef struct
{
unsigned int serv;
int nargs;
int nrets;
unsigned int args[16];
} of_arg_t;
phandle_t of_finddevice (const char *);
phandle_t of_peer (phandle_t);
phandle_t of_child (phandle_t);
phandle_t of_parent (phandle_t);
int of_getprop (phandle_t, const char *, void *, int);
void * of_call_method_3 (const char *, ihandle_t, int);
ihandle_t of_open (const char *);
void of_close(ihandle_t);
int of_read (ihandle_t , void*, int);
int of_write (ihandle_t, void*, int);
int of_seek (ihandle_t, int, int);
void * of_claim(void *, unsigned int , unsigned int );
void of_release(void *, unsigned int );
int of_yield(void);
void * of_set_callback(void *);
unsigned int romfs_lookup(const char *, void **);
int vpd_read(unsigned int , unsigned int , char *);
int vpd_write(unsigned int , unsigned int , char *);
int write_mm_log(char *, unsigned int , unsigned short );
#endif

View file

@ -0,0 +1,45 @@
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* 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
*****************************************************************************/
#ifndef RTAS_H
#define RTAS_H
#include "of.h"
typedef struct dtime {
unsigned int year;
unsigned int month;
unsigned int day;
unsigned int hour;
unsigned int minute;
unsigned int second;
unsigned int nano;
} dtime;
typedef void (*thread_t) (int);
int rtas_token(const char *);
int rtas_call(int, int, int, int *, ...);
void rtas_init(void);
int rtas_pci_config_read (long long, int, int, int, int);
int rtas_pci_config_write (long long, int, int, int, int, int);
int rtas_set_time_of_day(dtime *);
int rtas_get_time_of_day(dtime *);
int rtas_ibm_update_flash_64(long long, long long);
int rtas_ibm_update_flash_64_and_reboot(long long, long long);
int rtas_system_reboot(void);
int rtas_start_cpu (int, thread_t, int);
int rtas_stop_self (void);
int rtas_ibm_manage_flash(int);
#endif

View file

@ -0,0 +1,7 @@
#ifndef _BIOSEMU_COMPAT_TIME_H
#define _BIOSEMU_COMPAT_TIME_H
/* TODO: check how this works in x86 */
static unsigned long tb_freq = 0;
#endif

View file

@ -14,10 +14,10 @@
#include "debug.h"
uint32_t debug_flags = 0;
u32 debug_flags = 0;
void
dump(uint8_t * addr, uint32_t len)
dump(u8 * addr, u32 len)
{
printf("\n\r%s(%p, %x):\n", __FUNCTION__, addr, len);
while (len) {

View file

@ -12,12 +12,24 @@
#ifndef _BIOSEMU_DEBUG_H_
#define _BIOSEMU_DEBUG_H_
#include <stdio.h>
#include <stdint.h>
#include <types.h>
extern uint32_t debug_flags;
extern u32 debug_flags;
// from x86emu...needed for debugging
extern void x86emu_dump_xregs();
extern void x86emu_dump_xregs(void);
/* printf is not available in coreboot... use printk */
#include <console.h>
/* uurgs... yuck... x86emu/x86emu.h is redefining printk... we include it here
* and use its redefinition of printk
* TODO: FIX!!!! */
#include "x86emu/x86emu.h"
#define printf printk
/* PH: empty versions of set/clr_ci
* TODO: remove! */
static inline void clr_ci(void) {};
static inline void set_ci(void) {};
#define DEBUG_IO 0x1
#define DEBUG_MEM 0x2
@ -35,6 +47,7 @@ extern void x86emu_dump_xregs();
#define DEBUG_JMP 0x2000
//#define DEBUG
//#undef DEBUG
#ifdef DEBUG
#define CHECK_DBG(_flag) if (debug_flags & _flag)
@ -69,6 +82,6 @@ extern void x86emu_dump_xregs();
#endif //DEBUG
void dump(uint8_t * addr, uint32_t len);
void dump(u8 * addr, u32 len);
#endif

View file

@ -13,28 +13,123 @@
#include "device.h"
#include "rtas.h"
#include <stdio.h>
#include <string.h>
#include "debug.h"
#include <device/device.h>
#include <device/pci_ops.h>
#include <device/pci.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
translate_address_t translate_address_array[11];
u8 taa_last_entry;
typedef struct {
uint8_t info;
uint8_t bus;
uint8_t devfn;
uint8_t cfg_space_offset;
uint64_t address;
uint64_t size;
u8 info;
u8 bus;
u8 devfn;
u8 cfg_space_offset;
u64 address;
u64 size;
} __attribute__ ((__packed__)) assigned_address_t;
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
/* coreboot version */
void
biosemu_dev_get_addr_info(void)
{
int taa_index = 0;
int i = 0;
struct resource *r;
u8 bus = bios_device.dev->bus->link;
u16 devfn = bios_device.dev->path.pci.devfn;
DEBUG_PRINTF("bus: %x, devfn: %x\n", bus, devfn);
for (i = 0; i < bios_device.dev->resources; i++) {
r = &bios_device.dev->resource[i];
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;
/* dont 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.dev->rom_address;
translate_address_array[taa_index].size = 0; /* TODO: do we need the size? */
/* dont 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", __FUNCTION__);
/* 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;
/* dont 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;
/* dont 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;
/* dont 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;
#ifdef 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: 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
}
#else
// use translate_address_dev and get_puid from net-snk's net_support.c
void translate_address_dev(uint64_t *, phandle_t);
uint64_t get_puid(phandle_t node);
void translate_address_dev(u64 *, phandle_t);
u64 get_puid(phandle_t node);
// scan all adresses assigned to the device ("assigned-addresses" and "reg")
// store in translate_address_array for faster translation using dev_translate_address
void
dev_get_addr_info()
biosemu_dev_get_addr_info(void)
{
// get bus/dev/fn from assigned-addresses
int32_t len;
@ -52,7 +147,7 @@ dev_get_addr_info()
int i = 0;
// index to insert data into translate_address_array
int taa_index = 0;
uint64_t address_offset;
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;
@ -108,17 +203,18 @@ dev_get_addr_info()
}
#endif
}
#endif
// 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
void
dev_find_vmem_addr()
biosemu_dev_find_vmem_addr(void)
{
int i = 0;
translate_address_t ta;
int8_t tai_np = -1, tai_p = -1; // translate_address_array index for non-prefetchable and prefetchable memory
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];
@ -156,36 +252,44 @@ dev_find_vmem_addr()
//bios_device.vmem_size = 0;
}
#ifndef CONFIG_PCI_OPTION_ROM_RUN_YABEL
void
dev_get_puid()
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
void
dev_get_device_vendor_id()
biosemu_dev_get_device_vendor_id(void)
{
uint32_t pci_config_0 =
u32 pci_config_0;
#ifdef 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 =
(uint16_t) ((pci_config_0 & 0xFFFF0000) >> 16);
bios_device.pci_vendor_id = (uint16_t) (pci_config_0 & 0x0000FFFF);
(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, wether the device has a valid Expansion ROM, also search the PCI Data Structure and
* any Expansion ROM Header (using dev_scan_exp_header()) for needed information */
uint8_t
dev_check_exprom()
u8
biosemu_dev_check_exprom()
{
int i = 0;
translate_address_t ta;
uint64_t rom_base_addr = 0;
uint16_t pci_ds_offset;
unsigned long rom_base_addr = 0;
u16 pci_ds_offset;
pci_data_struct_t pci_ds;
// check for ExpROM Address (Offset 30) in taa
for (i = 0; i <= taa_last_entry; i++) {
@ -203,12 +307,12 @@ dev_check_exprom()
return -1;
}
set_ci();
uint16_t rom_signature = *((uint16_t *) rom_base_addr);
u16 rom_signature = in16le((void *) rom_base_addr);
clr_ci();
if (rom_signature != 0x55aa) {
if (rom_signature != 0xaa55) {
printf
("Error: invalid Expansion ROM signature: %02x!\n",
*((uint16_t *) rom_base_addr));
*((u16 *) rom_base_addr));
return -1;
}
set_ci();
@ -219,7 +323,7 @@ dev_check_exprom()
sizeof(pci_ds));
clr_ci();
#ifdef DEBUG
DEBUG_PRINTF("PCI Data Structure @%llx:\n",
DEBUG_PRINTF("PCI Data Structure @%lx:\n",
rom_base_addr + pci_ds_offset);
dump((void *) &pci_ds, sizeof(pci_ds));
#endif
@ -244,8 +348,8 @@ dev_check_exprom()
pci_ds.device_id, bios_device.pci_device_id);
break;
}
//DEBUG_PRINTF("Image Length: %d\n", pci_ds.img_length * 512);
//DEBUG_PRINTF("Image Code Type: %d\n", pci_ds.code_type);
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
@ -272,23 +376,30 @@ dev_check_exprom()
return 0;
}
uint8_t
dev_init(char *device_name)
u8
biosemu_dev_init(struct device * device)
{
uint8_t rval = 0;
u8 rval = 0;
//init bios_device struct
DEBUG_PRINTF("%s(%s)\n", __FUNCTION__, device_name);
DEBUG_PRINTF("%s(%s)\n", __FUNCTION__, device->dtsname);
memset(&bios_device, 0, sizeof(bios_device));
#ifndef 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);
dev_get_addr_info();
dev_find_vmem_addr();
dev_get_puid();
dev_get_device_vendor_id();
#else
bios_device.dev = device;
#endif
biosemu_dev_get_addr_info();
#ifndef CONFIG_PCI_OPTION_ROM_RUN_YABEL
biosemu_dev_find_vmem_addr();
biosemu_dev_get_puid();
#endif
biosemu_dev_get_device_vendor_id();
return rval;
}
@ -296,11 +407,13 @@ dev_init(char *device_name)
// 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.
uint8_t
dev_translate_address(uint64_t * addr)
u8
biosemu_dev_translate_address(unsigned long * addr)
{
int i = 0;
translate_address_t ta;
#ifndef CONFIG_PCI_OPTION_ROM_RUN_YABEL
/* we dont 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)
@ -312,10 +425,11 @@ dev_translate_address(uint64_t * addr)
}
if ((bios_device.vmem_size > 0)
&& ((*addr >= 0xB8000) && (*addr < 0xC0000))) {
uint8_t shift = *addr & 1;
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))) {

View file

@ -13,78 +13,88 @@
#ifndef DEVICE_LIB_H
#define DEVICE_LIB_H
#include <stdint.h>
#include <types.h>
#include <cpu.h>
#include "of.h"
#include <stdio.h>
#include "debug.h"
#include <byteorder.h>
// a Expansion Header Struct as defined in Plug and Play BIOS Spec 1.0a Chapter 3.2
typedef struct {
char signature[4]; // signature
uint8_t structure_revision;
uint8_t length; // in 16 byte blocks
uint16_t next_header_offset; // offset to next Expansion Header as 16bit little-endian value, as offset from the start of the Expansion ROM
uint8_t reserved;
uint8_t checksum; // the sum of all bytes of the Expansion Header must be 0
uint32_t device_id; // PnP Device ID as 32bit little-endian value
uint16_t p_manufacturer_string; //16bit little-endian offset from start of Expansion ROM
uint16_t p_product_string; //16bit little-endian offset from start of Expansion ROM
uint8_t device_base_type;
uint8_t device_sub_type;
uint8_t device_if_type;
uint8_t device_indicators;
u8 structure_revision;
u8 length; // in 16 byte blocks
u16 next_header_offset; // offset to next Expansion Header as 16bit little-endian value, as offset from the start of the Expansion ROM
u8 reserved;
u8 checksum; // the sum of all bytes of the Expansion Header must be 0
u32 device_id; // PnP Device ID as 32bit little-endian value
u16 p_manufacturer_string; //16bit little-endian offset from start of Expansion ROM
u16 p_product_string; //16bit little-endian offset from start of Expansion ROM
u8 device_base_type;
u8 device_sub_type;
u8 device_if_type;
u8 device_indicators;
// the following vectors are all 16bit little-endian offsets from start of Expansion ROM
uint16_t bcv; // Boot Connection Vector
uint16_t dv; // Disconnect Vector
uint16_t bev; // Bootstrap Entry Vector
uint16_t reserved_2;
uint16_t sriv; // Static Resource Information Vector
u16 bcv; // Boot Connection Vector
u16 dv; // Disconnect Vector
u16 bev; // Bootstrap Entry Vector
u16 reserved_2;
u16 sriv; // Static Resource Information Vector
} __attribute__ ((__packed__)) exp_header_struct_t;
// a PCI Data Struct as defined in PCI 2.3 Spec Chapter 6.3.1.2
typedef struct {
uint8_t signature[4]; // signature, the String "PCIR"
uint16_t vendor_id;
uint16_t device_id;
uint16_t reserved;
uint16_t pci_ds_length; // PCI Data Structure Length, 16bit little-endian value
uint8_t pci_ds_revision;
uint8_t class_code[3];
uint16_t img_length; // length of the Exp.ROM Image, 16bit little-endian value in 512 bytes
uint16_t img_revision;
uint8_t code_type;
uint8_t indicator;
uint16_t reserved_2;
u8 signature[4]; // signature, the String "PCIR"
u16 vendor_id;
u16 device_id;
u16 reserved;
u16 pci_ds_length; // PCI Data Structure Length, 16bit little-endian value
u8 pci_ds_revision;
u8 class_code[3];
u16 img_length; // length of the Exp.ROM Image, 16bit little-endian value in 512 bytes
u16 img_revision;
u8 code_type;
u8 indicator;
u16 reserved_2;
} __attribute__ ((__packed__)) pci_data_struct_t;
typedef struct {
uint8_t bus;
uint8_t devfn;
uint64_t puid;
u8 bus;
u8 devfn;
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
struct device* dev;
#else
u64 puid;
phandle_t phandle;
ihandle_t ihandle;
#endif
// store the address of the BAR that is used to simulate
// legacy VGA memory accesses
uint64_t vmem_addr;
uint64_t vmem_size;
u64 vmem_addr;
u64 vmem_size;
// used to buffer I/O Accesses, that do not access the I/O Range of the device...
// 64k might be overkill, but we can buffer all I/O accesses...
uint8_t io_buffer[64 * 1024];
uint16_t pci_vendor_id;
uint16_t pci_device_id;
u8 io_buffer[64 * 1024];
u16 pci_vendor_id;
u16 pci_device_id;
// translated address of the "PC-Compatible" Expansion ROM Image for this device
uint64_t img_addr;
uint32_t img_size; // size of the Expansion ROM Image (read from the PCI Data Structure)
} device_t;
unsigned long img_addr;
u32 img_size; // size of the Expansion ROM Image (read from the PCI Data Structure)
} biosemu_device_t;
typedef struct {
uint8_t info;
uint8_t bus;
uint8_t devfn;
uint8_t cfg_space_offset;
uint64_t address;
uint64_t address_offset;
uint64_t size;
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
unsigned long info;
#else
u8 info;
#endif
u8 bus;
u8 devfn;
u8 cfg_space_offset;
u64 address;
u64 address_offset;
u64 size;
} __attribute__ ((__packed__)) translate_address_t;
// array to store address translations for this
@ -94,56 +104,73 @@ typedef struct {
// 6 BARs, 1 Exp. ROM, 1 Cfg.Space, and 3 Legacy
// translations are supported... this should be enough for
// most devices... for VGA it is enough anyways...
translate_address_t translate_address_array[11];
extern translate_address_t translate_address_array[11];
// index of last translate_address_array entry
// set by get_dev_addr_info function
uint8_t taa_last_entry;
extern u8 taa_last_entry;
device_t bios_device;
/* the device we are working with... */
extern biosemu_device_t bios_device;
uint8_t dev_init(char *device_name);
// NOTE: for dev_check_exprom to work, dev_init MUST be called first!
uint8_t dev_check_exprom();
u8 biosemu_dev_init(struct device * device);
// NOTE: for dev_check_exprom to work, biosemu_dev_init MUST be called first!
u8 biosemu_dev_check_exprom(void);
uint8_t dev_translate_address(uint64_t * addr);
u8 biosemu_dev_translate_address(unsigned long * addr);
/* endianness swap functions for 16 and 32 bit words
* copied from axon_pciconfig.c
*/
static inline void
out32le(void *addr, uint32_t val)
out32le(void *addr, u32 val)
{
#ifdef __i386
*((u32*) addr) = cpu_to_le32(val);
#else
asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
#endif
}
static inline uint32_t
static inline u32
in32le(void *addr)
{
uint32_t val;
u32 val;
#ifdef __i386
val = cpu_to_le32(*((u32 *) addr));
#else
asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
#endif
return val;
}
static inline void
out16le(void *addr, uint16_t val)
out16le(void *addr, u16 val)
{
#ifdef __i386
*((u16*) addr) = cpu_to_le16(val);
#else
asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
#endif
}
static inline uint16_t
static inline u16
in16le(void *addr)
{
uint16_t val;
u16 val;
#ifdef __i386
val = cpu_to_le16(*((u16*) addr));
#else
asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
#endif
return val;
}
/* debug function, dumps HID1 and HID4 to detect wether caches are on/off */
static inline void
dumpHID()
dumpHID(void)
{
uint64_t hid;
u64 hid;
//HID1 = 1009
__asm__ __volatile__("mfspr %0, 1009":"=r"(hid));
printf("HID1: %016llx\n", hid);

View file

@ -10,8 +10,6 @@
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdio.h>
#include <rtas.h>
#include "biosemu.h"
@ -22,6 +20,9 @@
#include <x86emu/x86emu.h>
#include <x86emu/prim_ops.h>
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
#include <device/pci_ops.h>
#endif
//setup to run the code at the address, that the Interrupt Vector points to...
@ -45,7 +46,7 @@ setupInt(int intNum)
// handle int10 (VGA BIOS Interrupt)
void
handleInt10()
handleInt10(void)
{
// the data for INT10 is stored in BDA (0000:0400h) offset 49h-66h
// function number in AH
@ -109,7 +110,7 @@ handleInt10()
//AL: char, BH: page number, BL: attribute, CX: number of times to write
//BDA offset 62h is current page number
CHECK_DBG(DEBUG_PRINT_INT10) {
uint32_t i = 0;
u32 i = 0;
if (M.x86.R_BH == my_rdb(0x462)) {
for (i = 0; i < M.x86.R_CX; i++)
printf("%c", M.x86.R_AL);
@ -121,7 +122,7 @@ handleInt10()
//AL: char, BH: page number, BL: attribute, CX: number of times to write
//BDA offset 62h is current page number
CHECK_DBG(DEBUG_PRINT_INT10) {
uint32_t i = 0;
u32 i = 0;
if (M.x86.R_BH == my_rdb(0x462)) {
for (i = 0; i < M.x86.R_CX; i++)
printf("%c", M.x86.R_AL);
@ -164,7 +165,7 @@ handleInt10()
}
// this table translates ASCII chars into their XT scan codes:
static uint8_t keycode_table[256] = {
static u8 keycode_table[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0 - 7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 8 - 15
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 16 - 23
@ -202,13 +203,13 @@ static uint8_t keycode_table[256] = {
;
void
translate_keycode(uint64_t * keycode)
translate_keycode(u64 * keycode)
{
uint8_t scan_code = 0;
uint8_t char_code = 0;
u8 scan_code = 0;
u8 char_code = 0;
if (*keycode < 256) {
scan_code = keycode_table[*keycode];
char_code = (uint8_t) * keycode & 0xff;
char_code = (u8) * keycode & 0xff;
} else {
switch (*keycode) {
case 0x1b50:
@ -223,23 +224,23 @@ translate_keycode(uint64_t * keycode)
}
}
//assemble scan/char code in keycode
*keycode = (uint64_t) ((((uint16_t) scan_code) << 8) | char_code);
*keycode = (u64) ((((u16) scan_code) << 8) | char_code);
}
// handle int16 (Keyboard BIOS Interrupt)
void
handleInt16()
handleInt16(void)
{
// keyboard buffer is in BIOS Memory Area:
// offset 0x1a (WORD) pointer to next char in keybuffer
// offset 0x1c (WORD) pointer to next insert slot in keybuffer
// offset 0x1e-0x3e: 16 WORD Ring Buffer
// since we currently always read the char from the FW buffer,
// we misuse the ring buffer, we use it as pointer to a uint64_t that stores
// we misuse the ring buffer, we use it as pointer to a u64 that stores
// multi-byte keys (e.g. special keys in VT100 terminal)
// and as long as a key is available (not 0) we dont read further keys
uint64_t *keycode = (uint64_t *) (M.mem_base + 0x41e);
int8_t c;
u64 *keycode = (u64 *) (M.mem_base + 0x41e);
s8 c;
// function number in AH
DEBUG_PRINTF_INTR("%s(): Keyboard Interrupt: function: %x.\n",
__FUNCTION__, M.x86.R_AH);
@ -249,7 +250,7 @@ handleInt16()
case 0x00:
// get keystroke
if (*keycode) {
M.x86.R_AX = (uint16_t) * keycode;
M.x86.R_AX = (u16) * keycode;
// clear keycode
*keycode = 0;
} else {
@ -264,9 +265,10 @@ handleInt16()
if (*keycode) {
// already read, but not yet taken
CLEAR_FLAG(F_ZF);
M.x86.R_AX = (uint16_t) * keycode;
M.x86.R_AX = (u16) * keycode;
} else {
c = getchar();
/* TODO: we need getchar... */
c = -1; //getchar();
if (c == -1) {
// no key available
SET_FLAG(F_ZF);
@ -279,7 +281,8 @@ handleInt16()
// TODO: only after ESC?? what about other multibyte keys
printf("tt%c%c", 0x08, 0x08); // 0x08 == Backspace
while ((c = getchar()) != -1) {
/* TODO: we need getchar... */
while ((c = -1 /*getchar()*/) != -1) {
*keycode = (*keycode << 8) | c;
DEBUG_PRINTF(" key read: %0llx\n",
*keycode);
@ -292,7 +295,7 @@ handleInt16()
SET_FLAG(F_ZF);
} else {
CLEAR_FLAG(F_ZF);
M.x86.R_AX = (uint16_t) * keycode;
M.x86.R_AX = (u16) * keycode;
//X86EMU_trace_on();
//M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
}
@ -312,10 +315,10 @@ handleInt16()
// handle int1a (PCI BIOS Interrupt)
void
handleInt1a()
handleInt1a(void)
{
// function number in AX
uint8_t bus, devfn, offs;
u8 bus, devfn, offs;
switch (M.x86.R_AX) {
case 0xb101:
// Installation check
@ -376,10 +379,14 @@ handleInt1a()
switch (M.x86.R_AX) {
case 0xb108:
M.x86.R_CL =
(uint8_t) rtas_pci_config_read(bios_device.
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_read_config8(bios_device.dev, offs);
#else
(u8) rtas_pci_config_read(bios_device.
puid, 1,
bus, devfn,
offs);
#endif
DEBUG_PRINTF_INTR
("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n",
__FUNCTION__, M.x86.R_AX, offs,
@ -387,10 +394,14 @@ handleInt1a()
break;
case 0xb109:
M.x86.R_CX =
(uint16_t) rtas_pci_config_read(bios_device.
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_read_config16(bios_device.dev, offs);
#else
(u16) rtas_pci_config_read(bios_device.
puid, 2,
bus, devfn,
offs);
#endif
DEBUG_PRINTF_INTR
("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n",
__FUNCTION__, M.x86.R_AX, offs,
@ -398,10 +409,14 @@ handleInt1a()
break;
case 0xb10a:
M.x86.R_ECX =
(uint32_t) rtas_pci_config_read(bios_device.
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_read_config32(bios_device.dev, offs);
#else
(u32) rtas_pci_config_read(bios_device.
puid, 4,
bus, devfn,
offs);
#endif
DEBUG_PRINTF_INTR
("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n",
__FUNCTION__, M.x86.R_AX, offs,
@ -432,24 +447,36 @@ handleInt1a()
} else {
switch (M.x86.R_AX) {
case 0xb10b:
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_write_config8(bios_device.dev, offs, M.x86.R_CL);
#else
rtas_pci_config_write(bios_device.puid, 1, bus,
devfn, offs, M.x86.R_CL);
#endif
DEBUG_PRINTF_INTR
("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n",
__FUNCTION__, M.x86.R_AX, offs,
M.x86.R_CL);
break;
case 0xb10c:
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_write_config16(bios_device.dev, offs, M.x86.R_CX);
#else
rtas_pci_config_write(bios_device.puid, 2, bus,
devfn, offs, M.x86.R_CX);
#endif
DEBUG_PRINTF_INTR
("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n",
__FUNCTION__, M.x86.R_AX, offs,
M.x86.R_CX);
break;
case 0xb10d:
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
pci_write_config32(bios_device.dev, offs, M.x86.R_ECX);
#else
rtas_pci_config_write(bios_device.puid, 4, bus,
devfn, offs, M.x86.R_ECX);
#endif
DEBUG_PRINTF_INTR
("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n",
__FUNCTION__, M.x86.R_AX, offs,
@ -475,7 +502,7 @@ handleInt1a()
void
handleInterrupt(int intNum)
{
uint8_t int_handled = 0;
u8 int_handled = 0;
#ifndef DEBUG_PRINT_INT10
// this printf makes output by int 10 unreadable...
// so we only enable it, if int10 print is disabled
@ -531,7 +558,7 @@ handleInterrupt(int intNum)
// prepare and execute Interrupt 10 (VGA Interrupt)
void
runInt10()
runInt10(void)
{
// Initialize stack and data segment
M.x86.R_SS = STACK_SEGMENT;
@ -569,7 +596,7 @@ runInt10()
// prepare and execute Interrupt 13 (Disk Interrupt)
void
runInt13()
runInt13(void)
{
// Initialize stack and data segment
M.x86.R_SS = STACK_SEGMENT;

View file

@ -14,8 +14,8 @@
void handleInterrupt(int intNum);
void runInt10();
void runInt10(void);
void runInt13();
void runInt13(void);
#endif

View file

@ -10,80 +10,83 @@
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdio.h>
#include <cpu.h>
#include "device.h"
#include "rtas.h"
#include "debug.h"
#include "device.h"
#include <stdint.h>
#include <types.h>
#include <x86emu/x86emu.h>
#include <time.h>
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
#include <device/pci_ops.h>
#endif
// those are defined in net-snk/oflib/pci.c
extern unsigned int read_io(void *, size_t);
extern int write_io(void *, unsigned int, size_t);
//defined in net-snk/kernel/timer.c
extern uint64_t get_time(void);
extern u64 get_time(void);
// these are not used, only needed for linking, must be overridden using X86emu_setupPioFuncs
// with the functions and struct below
void
outb(uint8_t val, uint16_t port)
outb(u8 val, u16 port)
{
printf("WARNING: outb not implemented!\n");
HALT_SYS();
}
void
outw(uint16_t val, uint16_t port)
outw(u16 val, u16 port)
{
printf("WARNING: outw not implemented!\n");
HALT_SYS();
}
void
outl(uint32_t val, uint16_t port)
outl(u32 val, u16 port)
{
printf("WARNING: outl not implemented!\n");
HALT_SYS();
}
uint8_t
inb(uint16_t port)
u8
inb(u16 port)
{
printf("WARNING: inb not implemented!\n");
HALT_SYS();
return 0;
}
uint16_t
inw(uint16_t port)
u16
inw(u16 port)
{
printf("WARNING: inw not implemented!\n");
HALT_SYS();
return 0;
}
uint32_t
inl(uint16_t port)
u32
inl(u16 port)
{
printf("WARNING: inl not implemented!\n");
HALT_SYS();
return 0;
}
uint32_t pci_cfg_read(X86EMU_pioAddr addr, uint8_t size);
void pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size);
uint8_t handle_port_61h();
u32 pci_cfg_read(X86EMU_pioAddr addr, u8 size);
void pci_cfg_write(X86EMU_pioAddr addr, u32 val, u8 size);
u8 handle_port_61h(void);
uint8_t
u8
my_inb(X86EMU_pioAddr addr)
{
uint8_t rval = 0xFF;
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
u8 rval = 0xFF;
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access Device I/O (BAR or Legacy...)
DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__,
@ -106,7 +109,7 @@ my_inb(X86EMU_pioAddr addr)
case 0xCFE:
case 0xCFF:
// PCI Config Mechanism 1 Ports
return (uint8_t) pci_cfg_read(addr, 1);
return (u8) pci_cfg_read(addr, 1);
break;
case 0x0a:
CHECK_DBG(DEBUG_INTR) {
@ -119,7 +122,7 @@ my_inb(X86EMU_pioAddr addr)
DEBUG_PRINTF_IO
("%s(%04x) reading from bios_device.io_buffer\n",
__FUNCTION__, addr);
rval = *((uint8_t *) (bios_device.io_buffer + addr));
rval = *((u8 *) (bios_device.io_buffer + addr));
DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %02x\n",
__FUNCTION__, addr, rval);
return rval;
@ -128,20 +131,20 @@ my_inb(X86EMU_pioAddr addr)
}
}
uint16_t
u16
my_inw(X86EMU_pioAddr addr)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access Device I/O (BAR or Legacy...)
DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__,
addr);
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
uint16_t rval;
if ((translated_addr & (uint64_t) 0x1) == 0) {
u16 rval;
if ((translated_addr & (u64) 0x1) == 0) {
// 16 bit aligned access...
uint16_t tempval = read_io((void *)translated_addr, 2);
u16 tempval = read_io((void *)translated_addr, 2);
//little endian conversion
rval = in16le((void *) &tempval);
} else {
@ -157,13 +160,13 @@ my_inw(X86EMU_pioAddr addr)
case 0xCFC:
case 0xCFE:
//PCI Config Mechanism 1
return (uint16_t) pci_cfg_read(addr, 2);
return (u16) pci_cfg_read(addr, 2);
break;
default:
DEBUG_PRINTF_IO
("%s(%04x) reading from bios_device.io_buffer\n",
__FUNCTION__, addr);
uint16_t rval =
u16 rval =
in16le((void *) bios_device.io_buffer + addr);
DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %04x\n",
__FUNCTION__, addr, rval);
@ -173,20 +176,20 @@ my_inw(X86EMU_pioAddr addr)
}
}
uint32_t
u32
my_inl(X86EMU_pioAddr addr)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access Device I/O (BAR or Legacy...)
DEBUG_PRINTF_IO("%s(%x): access to Device I/O\n", __FUNCTION__,
addr);
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
uint32_t rval;
if ((translated_addr & (uint64_t) 0x3) == 0) {
u32 rval;
if ((translated_addr & (u64) 0x3) == 0) {
// 32 bit aligned access...
uint32_t tempval = read_io((void *) translated_addr, 4);
u32 tempval = read_io((void *) translated_addr, 4);
//little endian conversion
rval = in32le((void *) &tempval);
} else {
@ -209,7 +212,7 @@ my_inl(X86EMU_pioAddr addr)
DEBUG_PRINTF_IO
("%s(%04x) reading from bios_device.io_buffer\n",
__FUNCTION__, addr);
uint32_t rval =
u32 rval =
in32le((void *) bios_device.io_buffer + addr);
DEBUG_PRINTF_IO("%s(%04x) I/O Buffer --> %08x\n",
__FUNCTION__, addr, rval);
@ -220,10 +223,10 @@ my_inl(X86EMU_pioAddr addr)
}
void
my_outb(X86EMU_pioAddr addr, uint8_t val)
my_outb(X86EMU_pioAddr addr, u8 val)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access Device I/O (BAR or Legacy...)
DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
@ -245,33 +248,33 @@ my_outb(X86EMU_pioAddr addr, uint8_t val)
DEBUG_PRINTF_IO
("%s(%04x,%02x) writing to bios_device.io_buffer\n",
__FUNCTION__, addr, val);
*((uint8_t *) (bios_device.io_buffer + addr)) = val;
*((u8 *) (bios_device.io_buffer + addr)) = val;
break;
}
}
}
void
my_outw(X86EMU_pioAddr addr, uint16_t val)
my_outw(X86EMU_pioAddr addr, u16 val)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access Device I/O (BAR or Legacy...)
DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
__FUNCTION__, addr, val);
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
if ((translated_addr & (uint64_t) 0x1) == 0) {
if ((translated_addr & (u64) 0x1) == 0) {
// little-endian conversion
uint16_t tempval = in16le((void *) &val);
u16 tempval = in16le((void *) &val);
// 16 bit aligned access...
write_io((void *) translated_addr, tempval, 2);
} else {
// unaligned access, write single bytes, little-endian
write_io(((void *) (translated_addr + 1)),
(uint8_t) ((val & 0xFF00) >> 8), 1);
(u8) ((val & 0xFF00) >> 8), 1);
write_io(((void *) translated_addr),
(uint8_t) (val & 0x00FF), 1);
(u8) (val & 0x00FF), 1);
}
DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %04x\n", __FUNCTION__,
addr, val);
@ -293,30 +296,30 @@ my_outw(X86EMU_pioAddr addr, uint16_t val)
}
void
my_outl(X86EMU_pioAddr addr, uint32_t val)
my_outl(X86EMU_pioAddr addr, u32 val)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access Device I/O (BAR or Legacy...)
DEBUG_PRINTF_IO("%s(%x, %x): access to Device I/O\n",
__FUNCTION__, addr, val);
//DEBUG_PRINTF_IO("%s(%04x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
if ((translated_addr & (uint64_t) 0x3) == 0) {
if ((translated_addr & (u64) 0x3) == 0) {
// little-endian conversion
uint32_t tempval = in32le((void *) &val);
u32 tempval = in32le((void *) &val);
// 32 bit aligned access...
write_io((void *) translated_addr, tempval, 4);
} else {
// unaligned access, write single bytes, little-endian
write_io(((void *) translated_addr + 3),
(uint8_t) ((val & 0xFF000000) >> 24), 1);
(u8) ((val & 0xFF000000) >> 24), 1);
write_io(((void *) translated_addr + 2),
(uint8_t) ((val & 0x00FF0000) >> 16), 1);
(u8) ((val & 0x00FF0000) >> 16), 1);
write_io(((void *) translated_addr + 1),
(uint8_t) ((val & 0x0000FF00) >> 8), 1);
(u8) ((val & 0x0000FF00) >> 8), 1);
write_io(((void *) translated_addr),
(uint8_t) (val & 0x000000FF), 1);
(u8) (val & 0x000000FF), 1);
}
DEBUG_PRINTF_IO("%s(%04x) Device I/O <-- %08x\n", __FUNCTION__,
addr, val);
@ -336,16 +339,16 @@ my_outl(X86EMU_pioAddr addr, uint32_t val)
}
}
uint32_t
pci_cfg_read(X86EMU_pioAddr addr, uint8_t size)
u32
pci_cfg_read(X86EMU_pioAddr addr, u8 size)
{
uint32_t rval = 0xFFFFFFFF;
u32 rval = 0xFFFFFFFF;
if ((addr >= 0xCFC) && ((addr + size) <= 0xCFF)) {
// PCI Configuration Mechanism 1 step 1
// write to 0xCF8, sets bus, device, function and Config Space offset
// later read from 0xCFC-0xCFF returns the value...
uint8_t bus, devfn, offs;
uint32_t port_cf8_val = my_inl(0xCF8);
u8 bus, devfn, offs;
u32 port_cf8_val = my_inl(0xCF8);
if ((port_cf8_val & 0x80000000) != 0) {
//highest bit enables config space mapping
bus = (port_cf8_val & 0x00FF0000) >> 16;
@ -360,11 +363,25 @@ pci_cfg_read(X86EMU_pioAddr addr, uint8_t size)
bus, devfn, offs);
HALT_SYS();
} else {
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
switch (size) {
case 1:
rval = pci_read_config8(bios_device.dev, offs);
break;
case 2:
rval = pci_read_config16(bios_device.dev, offs);
break;
case 4:
rval = pci_read_config32(bios_device.dev, offs);
break;
}
#else
rval =
(uint32_t) rtas_pci_config_read(bios_device.
(u32) rtas_pci_config_read(bios_device.
puid, size,
bus, devfn,
offs);
#endif
DEBUG_PRINTF_IO
("%s(%04x) PCI Config Read @%02x, size: %d --> 0x%08x\n",
__FUNCTION__, addr, offs, size, rval);
@ -375,14 +392,14 @@ pci_cfg_read(X86EMU_pioAddr addr, uint8_t size)
}
void
pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size)
pci_cfg_write(X86EMU_pioAddr addr, u32 val, u8 size)
{
if ((addr >= 0xCFC) && ((addr + size) <= 0xCFF)) {
// PCI Configuration Mechanism 1 step 1
// write to 0xCF8, sets bus, device, function and Config Space offset
// later write to 0xCFC-0xCFF sets the value...
uint8_t bus, devfn, offs;
uint32_t port_cf8_val = my_inl(0xCF8);
u8 bus, devfn, offs;
u32 port_cf8_val = my_inl(0xCF8);
if ((port_cf8_val & 0x80000000) != 0) {
//highest bit enables config space mapping
bus = (port_cf8_val & 0x00FF0000) >> 16;
@ -397,9 +414,23 @@ pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size)
bus, devfn, offs);
HALT_SYS();
} else {
#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
switch (size) {
case 1:
pci_write_config8(bios_device.dev, offs, val);
break;
case 2:
pci_write_config16(bios_device.dev, offs, val);
break;
case 4:
pci_write_config32(bios_device.dev, offs, val);
break;
}
#else
rtas_pci_config_write(bios_device.puid,
size, bus, devfn, offs,
val);
#endif
DEBUG_PRINTF_IO
("%s(%04x) PCI Config Write @%02x, size: %d <-- 0x%08x\n",
__FUNCTION__, addr, offs, size, val);
@ -408,14 +439,14 @@ pci_cfg_write(X86EMU_pioAddr addr, uint32_t val, uint8_t size)
}
}
uint8_t
handle_port_61h()
u8
handle_port_61h(void)
{
static uint64_t last_time = 0;
uint64_t curr_time = get_time();
uint64_t time_diff; // time since last call
uint32_t period_ticks; // length of a period in ticks
uint32_t nr_periods; //number of periods passed since last call
static u64 last_time = 0;
u64 curr_time = get_time();
u64 time_diff; // time since last call
u32 period_ticks; // length of a period in ticks
u32 nr_periods; //number of periods passed since last call
// bit 4 should toggle with every (DRAM) refresh cycle... (66kHz??)
time_diff = curr_time - last_time;
// at 66kHz a period is ~ 15 ns long, converted to ticks: (tb_freq is ticks/second)
@ -424,8 +455,8 @@ handle_port_61h()
nr_periods = time_diff / period_ticks;
// if the number if ticks passed since last call is odd, we toggle bit 4
if ((nr_periods % 2) != 0) {
*((uint8_t *) (bios_device.io_buffer + 0x61)) ^= 0x10;
*((u8 *) (bios_device.io_buffer + 0x61)) ^= 0x10;
}
//finally read the value from the io_buffer
return *((uint8_t *) (bios_device.io_buffer + 0x61));
return *((u8 *) (bios_device.io_buffer + 0x61));
}

View file

@ -13,18 +13,18 @@
#ifndef _BIOSEMU_IO_H_
#define _BIOSEMU_IO_H_
#include <x86emu/x86emu.h>
#include <stdint.h>
#include <types.h>
uint8_t my_inb(X86EMU_pioAddr addr);
u8 my_inb(X86EMU_pioAddr addr);
uint16_t my_inw(X86EMU_pioAddr addr);
u16 my_inw(X86EMU_pioAddr addr);
uint32_t my_inl(X86EMU_pioAddr addr);
u32 my_inl(X86EMU_pioAddr addr);
void my_outb(X86EMU_pioAddr addr, uint8_t val);
void my_outb(X86EMU_pioAddr addr, u8 val);
void my_outw(X86EMU_pioAddr addr, uint16_t val);
void my_outw(X86EMU_pioAddr addr, u16 val);
void my_outl(X86EMU_pioAddr addr, uint32_t val);
void my_outl(X86EMU_pioAddr addr, u32 val);
#endif

View file

@ -10,8 +10,7 @@
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <types.h>
#include <cpu.h>
#include "debug.h"
#include "device.h"
@ -21,17 +20,17 @@
// define a check for access to certain (virtual) memory regions (interrupt handlers, BIOS Data Area, ...)
#ifdef DEBUG
static uint8_t in_check = 0; // to avoid recursion...
uint16_t ebda_segment;
uint32_t ebda_size;
static u8 in_check = 0; // to avoid recursion...
u16 ebda_segment;
u32 ebda_size;
//TODO: these macros have grown so large, that they should be changed to an inline function,
//just for the sake of readability...
//declare prototypes of the functions to follow, for use in DEBUG_CHECK_VMEM_ACCESS
uint8_t my_rdb(uint32_t);
uint16_t my_rdw(uint32_t);
uint32_t my_rdl(uint32_t);
u8 my_rdb(u32);
u16 my_rdw(u32);
u32 my_rdl(u32);
#define DEBUG_CHECK_VMEM_READ(_addr, _rval) \
if ((debug_flags & DEBUG_CHECK_VMEM_ACCESS) && (in_check == 0)) { \
@ -165,24 +164,24 @@ uint32_t my_rdl(uint32_t);
#endif
//defined in net-snk/kernel/timer.c
extern uint64_t get_time(void);
extern u64 get_time(void);
void update_time(uint32_t);
void update_time(u32);
// read byte from memory
uint8_t
my_rdb(uint32_t addr)
u8
my_rdb(u32 addr)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
uint8_t rval;
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
u8 rval;
if (translated != 0) {
//translation successfull, access VGA Memory (BAR or Legacy...)
DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n",
__FUNCTION__, addr);
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
set_ci();
rval = *((uint8_t *) translated_addr);
rval = *((u8 *) translated_addr);
clr_ci();
DEBUG_PRINTF_MEM("%s(%08x) VGA --> %02x\n", __FUNCTION__, addr,
rval);
@ -194,7 +193,7 @@ my_rdb(uint32_t addr)
HALT_SYS();
} else {
/* read from virtual memory */
rval = *((uint8_t *) (M.mem_base + addr));
rval = *((u8 *) (M.mem_base + addr));
DEBUG_CHECK_VMEM_READ(addr, rval);
return rval;
}
@ -202,12 +201,12 @@ my_rdb(uint32_t addr)
}
//read word from memory
uint16_t
my_rdw(uint32_t addr)
u16
my_rdw(u32 addr)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
uint16_t rval;
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
u16 rval;
if (translated != 0) {
//translation successfull, access VGA Memory (BAR or Legacy...)
DEBUG_PRINTF_MEM("%s(%08x): access to VGA Memory\n",
@ -219,10 +218,10 @@ my_rdw(uint32_t addr)
//read bytes a using my_rdb, because of the remapping to BARs
//words may not be contiguous in memory, so we need to translate
//every address...
rval = ((uint8_t) my_rdb(addr)) |
(((uint8_t) my_rdb(addr + 1)) << 8);
rval = ((u8) my_rdb(addr)) |
(((u8) my_rdb(addr + 1)) << 8);
} else {
if ((translated_addr & (uint64_t) 0x1) == 0) {
if ((translated_addr & (u64) 0x1) == 0) {
// 16 bit aligned access...
set_ci();
rval = in16le((void *) translated_addr);
@ -230,8 +229,8 @@ my_rdw(uint32_t addr)
} else {
// unaligned access, read single bytes
set_ci();
rval = (*((uint8_t *) translated_addr)) |
(*((uint8_t *) translated_addr + 1) << 8);
rval = (*((u8 *) translated_addr)) |
(*((u8 *) translated_addr + 1) << 8);
clr_ci();
}
}
@ -253,12 +252,12 @@ my_rdw(uint32_t addr)
}
//read long from memory
uint32_t
my_rdl(uint32_t addr)
u32
my_rdl(u32 addr)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
uint32_t rval;
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
u32 rval;
if (translated != 0) {
//translation successfull, access VGA Memory (BAR or Legacy...)
DEBUG_PRINTF_MEM("%s(%x): access to VGA Memory\n",
@ -270,12 +269,12 @@ my_rdl(uint32_t addr)
//read bytes a using my_rdb, because of the remapping to BARs
//dwords may not be contiguous in memory, so we need to translate
//every address...
rval = ((uint8_t) my_rdb(addr)) |
(((uint8_t) my_rdb(addr + 1)) << 8) |
(((uint8_t) my_rdb(addr + 2)) << 16) |
(((uint8_t) my_rdb(addr + 3)) << 24);
rval = ((u8) my_rdb(addr)) |
(((u8) my_rdb(addr + 1)) << 8) |
(((u8) my_rdb(addr + 2)) << 16) |
(((u8) my_rdb(addr + 3)) << 24);
} else {
if ((translated_addr & (uint64_t) 0x3) == 0) {
if ((translated_addr & (u64) 0x3) == 0) {
// 32 bit aligned access...
set_ci();
rval = in32le((void *) translated_addr);
@ -283,10 +282,10 @@ my_rdl(uint32_t addr)
} else {
// unaligned access, read single bytes
set_ci();
rval = (*((uint8_t *) translated_addr)) |
(*((uint8_t *) translated_addr + 1) << 8) |
(*((uint8_t *) translated_addr + 2) << 16) |
(*((uint8_t *) translated_addr + 3) << 24);
rval = (*((u8 *) translated_addr)) |
(*((u8 *) translated_addr + 1) << 8) |
(*((u8 *) translated_addr + 2) << 16) |
(*((u8 *) translated_addr + 3) << 24);
clr_ci();
}
}
@ -317,17 +316,17 @@ my_rdl(uint32_t addr)
//write byte to memory
void
my_wrb(uint32_t addr, uint8_t val)
my_wrb(u32 addr, u8 val)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access VGA Memory (BAR or Legacy...)
DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
__FUNCTION__, addr, val);
//DEBUG_PRINTF_MEM("%s(%08x): translated_addr: %llx\n", __FUNCTION__, addr, translated_addr);
set_ci();
*((uint8_t *) translated_addr) = val;
*((u8 *) translated_addr) = val;
clr_ci();
} else if (addr > M.mem_size) {
DEBUG_PRINTF("%s(%08x): Memory Access out of range!\n",
@ -337,15 +336,15 @@ my_wrb(uint32_t addr, uint8_t val)
} else {
/* write to virtual memory */
DEBUG_CHECK_VMEM_WRITE(addr, val);
*((uint8_t *) (M.mem_base + addr)) = val;
*((u8 *) (M.mem_base + addr)) = val;
}
}
void
my_wrw(uint32_t addr, uint16_t val)
my_wrw(u32 addr, u16 val)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access VGA Memory (BAR or Legacy...)
DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
@ -357,10 +356,10 @@ my_wrw(uint32_t addr, uint16_t val)
//read bytes a using my_rdb, because of the remapping to BARs
//words may not be contiguous in memory, so we need to translate
//every address...
my_wrb(addr, (uint8_t) (val & 0x00FF));
my_wrb(addr + 1, (uint8_t) ((val & 0xFF00) >> 8));
my_wrb(addr, (u8) (val & 0x00FF));
my_wrb(addr + 1, (u8) ((val & 0xFF00) >> 8));
} else {
if ((translated_addr & (uint64_t) 0x1) == 0) {
if ((translated_addr & (u64) 0x1) == 0) {
// 16 bit aligned access...
set_ci();
out16le((void *) translated_addr, val);
@ -368,10 +367,10 @@ my_wrw(uint32_t addr, uint16_t val)
} else {
// unaligned access, write single bytes
set_ci();
*((uint8_t *) translated_addr) =
(uint8_t) (val & 0x00FF);
*((uint8_t *) translated_addr + 1) =
(uint8_t) ((val & 0xFF00) >> 8);
*((u8 *) translated_addr) =
(u8) (val & 0x00FF);
*((u8 *) translated_addr + 1) =
(u8) ((val & 0xFF00) >> 8);
clr_ci();
}
}
@ -387,10 +386,10 @@ my_wrw(uint32_t addr, uint16_t val)
}
}
void
my_wrl(uint32_t addr, uint32_t val)
my_wrl(u32 addr, u32 val)
{
uint64_t translated_addr = addr;
uint8_t translated = dev_translate_address(&translated_addr);
unsigned long translated_addr = addr;
u8 translated = biosemu_dev_translate_address(&translated_addr);
if (translated != 0) {
//translation successfull, access VGA Memory (BAR or Legacy...)
DEBUG_PRINTF_MEM("%s(%x, %x): access to VGA Memory\n",
@ -402,12 +401,12 @@ my_wrl(uint32_t addr, uint32_t val)
//read bytes a using my_rdb, because of the remapping to BARs
//words may not be contiguous in memory, so we need to translate
//every address...
my_wrb(addr, (uint8_t) (val & 0x000000FF));
my_wrb(addr + 1, (uint8_t) ((val & 0x0000FF00) >> 8));
my_wrb(addr + 2, (uint8_t) ((val & 0x00FF0000) >> 16));
my_wrb(addr + 3, (uint8_t) ((val & 0xFF000000) >> 24));
my_wrb(addr, (u8) (val & 0x000000FF));
my_wrb(addr + 1, (u8) ((val & 0x0000FF00) >> 8));
my_wrb(addr + 2, (u8) ((val & 0x00FF0000) >> 16));
my_wrb(addr + 3, (u8) ((val & 0xFF000000) >> 24));
} else {
if ((translated_addr & (uint64_t) 0x3) == 0) {
if ((translated_addr & (u64) 0x3) == 0) {
// 32 bit aligned access...
set_ci();
out32le((void *) translated_addr, val);
@ -415,14 +414,14 @@ my_wrl(uint32_t addr, uint32_t val)
} else {
// unaligned access, write single bytes
set_ci();
*((uint8_t *) translated_addr) =
(uint8_t) (val & 0x000000FF);
*((uint8_t *) translated_addr + 1) =
(uint8_t) ((val & 0x0000FF00) >> 8);
*((uint8_t *) translated_addr + 2) =
(uint8_t) ((val & 0x00FF0000) >> 16);
*((uint8_t *) translated_addr + 3) =
(uint8_t) ((val & 0xFF000000) >> 24);
*((u8 *) translated_addr) =
(u8) (val & 0x000000FF);
*((u8 *) translated_addr + 1) =
(u8) ((val & 0x0000FF00) >> 8);
*((u8 *) translated_addr + 2) =
(u8) ((val & 0x00FF0000) >> 16);
*((u8 *) translated_addr + 3) =
(u8) ((val & 0xFF000000) >> 24);
clr_ci();
}
}
@ -443,16 +442,16 @@ my_wrl(uint32_t addr, uint32_t val)
//byte at 0x70 is timer overflow (set if midnight passed since last call to interrupt 1a function 00
//cur_val is the current value, of offset 6c...
void
update_time(uint32_t cur_val)
update_time(u32 cur_val)
{
//for convenience, we let the start of timebase be at midnight, we currently dont support
//real daytime anyway...
uint64_t ticks_per_day = tb_freq * 60 * 24;
u64 ticks_per_day = tb_freq * 60 * 24;
// at 18Hz a period is ~55ms, converted to ticks (tb_freq is ticks/second)
uint32_t period_ticks = (55 * tb_freq) / 1000;
uint64_t curr_time = get_time();
uint64_t ticks_since_midnight = curr_time % ticks_per_day;
uint32_t periods_since_midnight = ticks_since_midnight / period_ticks;
u32 period_ticks = (55 * tb_freq) / 1000;
u64 curr_time = get_time();
u64 ticks_since_midnight = curr_time % ticks_per_day;
u32 periods_since_midnight = ticks_since_midnight / period_ticks;
// if periods since midnight is smaller than last value, set overflow
// at BDA Offset 0x70
if (periods_since_midnight < cur_val) {

View file

@ -13,24 +13,24 @@
#ifndef _BIOSEMU_MEM_H_
#define _BIOSEMU_MEM_H_
#include <x86emu/x86emu.h>
#include <stdint.h>
#include <types.h>
// read byte from memory
uint8_t my_rdb(uint32_t addr);
u8 my_rdb(u32 addr);
//read word from memory
uint16_t my_rdw(uint32_t addr);
u16 my_rdw(u32 addr);
//read long from memory
uint32_t my_rdl(uint32_t addr);
u32 my_rdl(u32 addr);
//write byte to memory
void my_wrb(uint32_t addr, uint8_t val);
void my_wrb(u32 addr, u8 val);
//write word to memory
void my_wrw(uint32_t addr, uint16_t val);
void my_wrw(u32 addr, u16 val);
//write long to memory
void my_wrl(uint32_t addr, uint32_t val);
void my_wrl(u32 addr, u32 val);
#endif

View file

@ -10,11 +10,9 @@
* IBM Corporation - initial implementation
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <types.h>
#include <cpu.h>
#include "debug.h"
@ -40,63 +38,63 @@ static X86EMU_pioFuncs my_pio_funcs = {
};
// pointer to VBEInfoBuffer, set by vbe_prepare
uint8_t *vbe_info_buffer = 0;
u8 *vbe_info_buffer = 0;
// virtual BIOS Memory
uint8_t *biosmem;
uint32_t biosmem_size;
u8 *biosmem;
u32 biosmem_size;
// these structs are for input from and output to OF
typedef struct {
uint8_t display_type; // 0=NONE, 1= analog, 2=digital
uint16_t screen_width;
uint16_t screen_height;
uint16_t screen_linebytes; // bytes per line in framebuffer, may be more than screen_width
uint8_t color_depth; // color depth in bpp
uint32_t framebuffer_address;
uint8_t edid_block_zero[128];
u8 display_type; // 0=NONE, 1= analog, 2=digital
u16 screen_width;
u16 screen_height;
u16 screen_linebytes; // bytes per line in framebuffer, may be more than screen_width
u8 color_depth; // color depth in bpp
u32 framebuffer_address;
u8 edid_block_zero[128];
} __attribute__ ((__packed__)) screen_info_t;
typedef struct {
uint8_t signature[4];
uint16_t size_reserved;
uint8_t monitor_number;
uint16_t max_screen_width;
uint8_t color_depth;
u8 signature[4];
u16 size_reserved;
u8 monitor_number;
u16 max_screen_width;
u8 color_depth;
} __attribute__ ((__packed__)) screen_info_input_t;
// these structs only store a subset of the VBE defined fields
// only those needed.
typedef struct {
char signature[4];
uint16_t version;
uint8_t *oem_string_ptr;
uint32_t capabilities;
uint16_t video_mode_list[256]; // lets hope we never have more than 256 video modes...
uint16_t total_memory;
u16 version;
u8 *oem_string_ptr;
u32 capabilities;
u16 video_mode_list[256]; // lets hope we never have more than 256 video modes...
u16 total_memory;
} vbe_info_t;
typedef struct {
uint16_t video_mode;
uint8_t mode_info_block[256];
uint16_t attributes;
uint16_t linebytes;
uint16_t x_resolution;
uint16_t y_resolution;
uint8_t x_charsize;
uint8_t y_charsize;
uint8_t bits_per_pixel;
uint8_t memory_model;
uint32_t framebuffer_address;
u16 video_mode;
u8 mode_info_block[256];
u16 attributes;
u16 linebytes;
u16 x_resolution;
u16 y_resolution;
u8 x_charsize;
u8 y_charsize;
u8 bits_per_pixel;
u8 memory_model;
u32 framebuffer_address;
} vbe_mode_info_t;
typedef struct {
uint8_t port_number; // i.e. monitor number
uint8_t edid_transfer_time;
uint8_t ddc_level;
uint8_t edid_block_zero[128];
u8 port_number; // i.e. monitor number
u8 edid_transfer_time;
u8 ddc_level;
u8 edid_block_zero[128];
} vbe_ddc_info_t;
static inline uint8_t
static inline u8
vbe_prepare()
{
vbe_info_buffer = biosmem + (VBE_SEGMENT << 4); // segment:offset off VBE Data Area
@ -115,7 +113,7 @@ vbe_prepare()
}
// VBE Function 00h
uint8_t
u8
vbe_info(vbe_info_t * info)
{
vbe_prepare();
@ -162,12 +160,12 @@ vbe_info(vbe_info_t * info)
info->capabilities = in32le(vbe_info_buffer + 10);
// offset 14: 32 bit le containing segment:offset of supported video mode table
uint16_t *video_mode_ptr;
u16 *video_mode_ptr;
video_mode_ptr =
(uint16_t *) (biosmem +
(u16 *) (biosmem +
((in16le(vbe_info_buffer + 16) << 4) +
in16le(vbe_info_buffer + 14)));
uint32_t i = 0;
u32 i = 0;
do {
info->video_mode_list[i] = in16le(video_mode_ptr + i);
i++;
@ -184,7 +182,7 @@ vbe_info(vbe_info_t * info)
}
// VBE Function 01h
uint8_t
u8
vbe_get_mode_info(vbe_mode_info_t * mode_info)
{
vbe_prepare();
@ -252,7 +250,7 @@ vbe_get_mode_info(vbe_mode_info_t * mode_info)
}
// VBE Function 02h
uint8_t
u8
vbe_set_mode(vbe_mode_info_t * mode_info)
{
vbe_prepare();
@ -289,8 +287,8 @@ vbe_set_mode(vbe_mode_info_t * mode_info)
}
//VBE Function 08h
uint8_t
vbe_set_palette_format(uint8_t format)
u8
vbe_set_palette_format(u8 format)
{
vbe_prepare();
// call VBE function 09h (Set/Get Palette Data Function)
@ -325,8 +323,8 @@ vbe_set_palette_format(uint8_t format)
}
// VBE Function 09h
uint8_t
vbe_set_color(uint16_t color_number, uint32_t color_value)
u8
vbe_set_color(u16 color_number, u32 color_value)
{
vbe_prepare();
// call VBE function 09h (Set/Get Palette Data Function)
@ -367,8 +365,8 @@ vbe_set_color(uint16_t color_number, uint32_t color_value)
return 0;
}
uint8_t
vbe_get_color(uint16_t color_number, uint32_t * color_value)
u8
vbe_get_color(u16 color_number, u32 * color_value)
{
vbe_prepare();
// call VBE function 09h (Set/Get Palette Data Function)
@ -410,7 +408,7 @@ vbe_get_color(uint16_t color_number, uint32_t * color_value)
}
// VBE Function 15h
uint8_t
u8
vbe_get_ddc_info(vbe_ddc_info_t * ddc_info)
{
vbe_prepare();
@ -484,11 +482,11 @@ vbe_get_ddc_info(vbe_ddc_info_t * ddc_info)
return 0;
}
uint32_t
vbe_get_info(uint8_t argc, char ** argv)
u32
vbe_get_info(u8 argc, char ** argv)
{
uint8_t rval;
uint32_t i;
u8 rval;
u32 i;
if (argc < 4) {
printf
("Usage %s <vmem_base> <device_path> <address of screen_info_t>\n",
@ -510,7 +508,7 @@ vbe_get_info(uint8_t argc, char ** argv)
// argv[1] is address of virtual BIOS mem...
// argv[2] is the size
biosmem = (uint8_t *) strtoul(argv[1], 0, 16);
biosmem = (u8 *) strtoul(argv[1], 0, 16);
biosmem_size = strtoul(argv[2], 0, 16);;
if (biosmem_size < MIN_REQUIRED_VMEM_SIZE) {
printf("Error: Not enough virtual memory: %x, required: %x!\n",
@ -592,8 +590,8 @@ vbe_get_info(uint8_t argc, char ** argv)
sizeof(ddc_info.edid_block_zero));
}
#endif
if (*((uint64_t *) ddc_info.edid_block_zero) !=
(uint64_t) 0x00FFFFFFFFFFFF00) {
if (*((u64 *) ddc_info.edid_block_zero) !=
(u64) 0x00FFFFFFFFFFFF00) {
// invalid EDID signature... probably no monitor
output->display_type = 0x0;
@ -694,19 +692,19 @@ vbe_get_info(uint8_t argc, char ** argv)
// this way...)
// this resembles the palette that the kernel/X Server seems to expect...
uint8_t mixed_color_values[6] =
u8 mixed_color_values[6] =
{ 0xFF, 0xDA, 0xB3, 0x87, 0x54, 0x00 };
uint8_t primary_color_values[10] =
u8 primary_color_values[10] =
{ 0xF3, 0xE7, 0xCD, 0xC0, 0xA5, 0x96, 0x77, 0x66, 0x3F,
0x27
};
uint8_t mc_size = sizeof(mixed_color_values);
uint8_t prim_size = sizeof(primary_color_values);
u8 mc_size = sizeof(mixed_color_values);
u8 prim_size = sizeof(primary_color_values);
uint8_t curr_color_index;
uint32_t curr_color;
u8 curr_color_index;
u32 curr_color;
uint8_t r, g, b;
u8 r, g, b;
// 216 mixed colors
for (r = 0; r < mc_size; r++) {
for (g = 0; g < mc_size; g++) {
@ -715,9 +713,9 @@ vbe_get_info(uint8_t argc, char ** argv)
(r * mc_size * mc_size) +
(g * mc_size) + b;
curr_color = 0;
curr_color |= ((uint32_t) mixed_color_values[r]) << 16; //red value
curr_color |= ((uint32_t) mixed_color_values[g]) << 8; //green value
curr_color |= (uint32_t) mixed_color_values[b]; //blue value
curr_color |= ((u32) mixed_color_values[r]) << 16; //red value
curr_color |= ((u32) mixed_color_values[g]) << 8; //green value
curr_color |= (u32) mixed_color_values[b]; //blue value
vbe_set_color(curr_color_index,
curr_color);
}
@ -728,21 +726,21 @@ vbe_get_info(uint8_t argc, char ** argv)
// red
for (r = 0; r < prim_size; r++) {
curr_color_index = mc_size * mc_size * mc_size + r;
curr_color = ((uint32_t) primary_color_values[r]) << 16;
curr_color = ((u32) primary_color_values[r]) << 16;
vbe_set_color(curr_color_index, curr_color);
}
//green
for (g = 0; g < prim_size; g++) {
curr_color_index =
mc_size * mc_size * mc_size + prim_size + g;
curr_color = ((uint32_t) primary_color_values[g]) << 8;
curr_color = ((u32) primary_color_values[g]) << 8;
vbe_set_color(curr_color_index, curr_color);
}
//blue
for (b = 0; b < prim_size; b++) {
curr_color_index =
mc_size * mc_size * mc_size + prim_size * 2 + b;
curr_color = (uint32_t) primary_color_values[b];
curr_color = (u32) primary_color_values[b];
vbe_set_color(curr_color_index, curr_color);
}
// 10 shades of grey
@ -750,9 +748,9 @@ vbe_get_info(uint8_t argc, char ** argv)
curr_color_index =
mc_size * mc_size * mc_size + prim_size * 3 + i;
curr_color = 0;
curr_color |= ((uint32_t) primary_color_values[i]) << 16; //red
curr_color |= ((uint32_t) primary_color_values[i]) << 8; //green
curr_color |= ((uint32_t) primary_color_values[i]); //blue
curr_color |= ((u32) primary_color_values[i]) << 16; //red
curr_color |= ((u32) primary_color_values[i]) << 8; //green
curr_color |= ((u32) primary_color_values[i]); //blue
vbe_set_color(curr_color_index, curr_color);
}