v86bios.c

来自「适合KS8695X」· C语言 代码 · 共 934 行 · 第 1/2 页

C
934
字号
/*
 * Copyright 1999 Egbert Eich
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of the authors not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  The authors makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */
#define DELETE
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <readline/readline.h>
#include <readline/history.h>
#if defined(__alpha__) || defined (__ia64__)
#include <sys/io.h>
#elif defined(HAVE_SYS_PERM)
#include <sys/perm.h>
#endif
#include "debug.h"
#include "v86bios.h"
#include "pci.h"
#include "AsmMacros.h"

#define SIZE 0x100000
#define VRAM_START 0xA0000
#define VRAM_SIZE 0x1FFFF
#define V_BIOS_SIZE 0x1FFFF
#define BIOS_START 0x7C00            /* default BIOS entry */
#define BIOS_MEM 0x600

/*CARD8 code[] = { 0xb8 , 0xf0 , 0xf0, 0xf4 }; */
#define VB_X(x) (V_BIOS >> x) & 0xFF
CARD8 code[] = { 6, 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xf4 };
/*CARD8 code[] = { 0x9a, 0x03, 0x00, 0x00, VB_X(12), 0xb8, 0x03, 0x00, */
/*0xcd, 0x10, 0xf4 }; */
/*CARD8 code[] = {  0xb8 , 0xf0 , 0xf0 ,0xf4 }; */

int ioperm_list[IOPERM_BITS] = {0,};

static void sig_handler(int);
static int map(void);
static void unmap(void);
static void bootBIOS(CARD16 ax);
static int map_vram(void);
static void unmap_vram(void);
static int copy_vbios(memType v_base);
static int copy_sys_bios(void);
static void save_bios_to_file(void);
static int setup_system_bios(void);
static CARD32 setup_int_vect(void);
#ifdef __ia32__
static CARD32 setup_primary_int_vect(void);
#endif
static int chksum(CARD8 *start);
static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax);
static void print_regs(i86biosRegsPtr regs);
static void print_usage(void);
static void set_hlt(Bool set);
static void set_ioperm(void);

extern void yyparse();

void loadCodeToMem(unsigned char *ptr, CARD8 *code);
void dprint(unsigned long start, unsigned long size);

static int vram_mapped = 0;
static char* bios_var = NULL;
static CARD8 save_msr;
static CARD8 save_pos102;
static CARD8 save_vse;
static CARD8 save_46e8;
static haltpoints hltp[20] = { {0, 0}, };

console Console = {-1,-1};
struct config Config;

int main(int argc,char **argv)
{
    int c;

    Config.PrintPort = PRINT_PORT;
    Config.IoStatistics = IO_STATISTICS;
    Config.PrintIrq = PRINT_IRQ;
    Config.PrintPci = PRINT_PCI;
    Config.ShowAllDev = SHOW_ALL_DEV;
    Config.PrintIp = PRINT_IP;
    Config.SaveBios = SAVE_BIOS;
    Config.Trace = TRACE;
    Config.ConfigActiveOnly = CONFIG_ACTIVE_ONLY;  /* boot */
    Config.ConfigActiveDevice = CONFIG_ACTIVE_DEVICE; /* boot */
    Config.MapSysBios = MAP_SYS_BIOS;
    Config.Resort = RESORT;  /* boot */
    Config.FixRom = FIX_ROM;
    Config.NoConsole = NO_CONSOLE;
    Config.BootOnly = FALSE;
    Config.Verbose = VERBOSE;

    opterr = 0;
    while ((c = getopt(argc,argv,"psicaPStAdbrfnv:?")) != EOF) {
    switch(c) {
    case 'p':
	Config.PrintPort = TRUE;
	break;
    case 's':
	Config.IoStatistics = TRUE;
	break;
    case 'i':
	Config.PrintIrq = TRUE;
	break;
    case 'c':
	Config.PrintPci = TRUE;
	break;
    case 'a':
	Config.ShowAllDev = TRUE;
	break;
    case 'P':
	Config.PrintIp = TRUE;
	break;
    case 'S':
	Config.SaveBios = TRUE;
	break;
    case 't':
	Config.Trace = TRUE;
	break;
    case 'A':
	Config.ConfigActiveOnly = TRUE;
	break;
    case 'd':
	Config.ConfigActiveDevice = TRUE;
	break;
    case 'b':
	Config.MapSysBios = TRUE;
	break;
    case 'r':
	Config.Resort = TRUE;
	break;
    case 'f':
	Config.FixRom = TRUE;
	break;
    case 'n':
	Config.NoConsole = TRUE;
	break;
    case 'v':
	Config.Verbose = strtol(optarg,NULL,0);
	break;
    case '?':
	print_usage();
	break;
    default:
	break;
    }
    }


    if (!map())
    exit(1);

    if (!setup_system_bios())
    exit(1);

    iopl(3);

    scan_pci();

    save_msr = inb(0x3CC);
    save_vse = inb(0x3C3);
    save_46e8 = inb(0x46e8);
    save_pos102 = inb(0x102);

    if (Config.BootOnly) {

    if (!CurrentPci && !Config.ConfigActiveDevice
	&& !Config.ConfigActiveOnly) {
	iopl(0);
	unmap();
	exit (1);
    }
    call_boot(NULL);
    } else {
    using_history();
    yyparse();
    }

    unmap();

    pciVideoRestore();

    outb(0x102, save_pos102);
    outb(0x46e8, save_46e8);
    outb(0x3C3, save_vse);
    outb(0x3C2, save_msr);

    iopl(0);

    close_console(Console);

    exit(0);
}


void
call_boot(struct device *dev)
{
    int Active_is_Pci = 0;
    CARD32 vbios_base;

    CurrentPci = PciList;
    Console = open_console();

    set_ioperm();


    signal(2,sig_handler);
    signal(11,sig_handler);

    /* disable primary card */
    pciVideoRestore(); /* reset PCI state to see primary card */
    outb(0x3C2,~(CARD8)0x03 & save_msr);
    outb(0x3C3,~(CARD8)0x01 & save_vse);
    outb(0x46e8, ~(CARD8)0x08 & save_46e8);
    outb(0x102, ~(CARD8)0x01 & save_pos102);

    pciVideoDisable();

    while (CurrentPci) {
    CARD16 ax;

    if (CurrentPci->active) {
	Active_is_Pci = 1;
	if (!Config.ConfigActiveDevice && !dev) {
	CurrentPci = CurrentPci->next;
	continue;
	}
    } else if (Config.ConfigActiveOnly && !dev) {
	CurrentPci = CurrentPci->next;
	continue;
    }
    if (dev && ((dev->type != PCI)
	    || (dev->type == PCI
	    && (dev->loc.pci.dev != CurrentPci->dev
		|| dev->loc.pci.bus != CurrentPci->bus
		|| dev->loc.pci.func != CurrentPci->func)))) {
	CurrentPci = CurrentPci->next;
	continue;
    }

    EnableCurrent();

    if (CurrentPci->active) {
	outb(0x102, save_pos102);
	outb(0x46e8, save_46e8);
	outb(0x3C3, save_vse);
	outb(0x3C2, save_msr);
    }

    /* clear interrupt vectors */
#ifdef __ia32__
    vbios_base = CurrentPci->active ? setup_primary_int_vect()
	: setup_int_vect();
#else
    vbios_base = setup_int_vect();
#endif
    ax = ((CARD16)(CurrentPci->bus) << 8)
	| (CurrentPci->dev << 3) | (CurrentPci->func & 0x7);
    if (Config.Verbose > 1) P_printf("ax: 0x%x\n",ax);

    BootBios = findPciByIDs(CurrentPci->bus,CurrentPci->dev,
		   CurrentPci->func);
    if (!((mapPciRom(BootBios) && chksum((CARD8*)V_BIOS))
	  || (CurrentPci->active && copy_vbios(vbios_base)))) {
	CurrentPci = CurrentPci->next;
	continue;
    }
    if (!map_vram()) {
	CurrentPci = CurrentPci->next;
	continue;
    }
    if (Config.SaveBios) save_bios_to_file();
    printf("initializing PCI bus: %i dev: %i func: %i\n",CurrentPci->bus,
	   CurrentPci->dev,CurrentPci->func);
    bootBIOS(ax);
    unmap_vram();

    if (CurrentPci->active)
	close_console(Console);

    if (dev) return;

    CurrentPci = CurrentPci->next;
    }

    /* We have an ISA device - configure if requested */
    if (!Active_is_Pci /* no isa card in system! */
    && ((!dev && (Config.ConfigActiveDevice || Config.ConfigActiveOnly))
	|| (dev && dev->type == ISA))) {

    pciVideoDisable();

    if (!dev || dev->type == ISA) {
	outb(0x102, save_pos102);
	outb(0x46e8, save_46e8);
	outb(0x3C3, save_vse);
	outb(0x3C2, save_msr);

#ifdef __ia32__
	vbios_base = setup_primary_int_vect();
#else
	vbios_base = setup_int_vect();
#endif
	if (copy_vbios(vbios_base)) {

	if (Config.SaveBios) save_bios_to_file();
	if  (map_vram()) {
	    printf("initializing ISA bus\n");
	    bootBIOS(0);
	}
	}

	unmap_vram();
	sleep(1);
	close_console(Console);
    }
    }


}

int
map(void)
{
    void* mem;
    mem = mmap(0, (size_t)SIZE,
	       PROT_EXEC | PROT_READ | PROT_WRITE,
	       MAP_FIXED | MAP_PRIVATE | MAP_ANON,
	       -1, 0 );
    if (mem != 0) {
	perror("anonymous map");
	return (0);
    }
    memset(mem,0,SIZE);

    return (1);
}

static void
unmap(void)
{
    munmap(0,SIZE);
}

static void
bootBIOS(CARD16 ax)
{
    i86biosRegs bRegs;
#ifdef V86BIOS_DEBUG
    printf("starting BIOS\n");
#endif
    setup_io();
    setup_bios_regs(&bRegs, ax);
    loadCodeToMem((unsigned char *) BIOS_START, code);
    do_x86(BIOS_START,&bRegs);
#ifdef V86BIOS_DEBUG
    printf("done\n");
#endif
}

static int
map_vram(void)
{
    int mem_fd;

#ifdef __ia64__
    if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0)
#else
    if ((mem_fd = open(MEM_FILE,O_RDWR))<0)
#endif
	{
	perror("opening memory");
	return 0;
    }

#ifdef __alpha__
       if (!_bus_base()) sparse_shift = 7; /* Uh, oh, JENSEN... */
	 if (!_bus_base_sparse()) sparse_shift = 0;
	 if ((vram_map = mmap(0,(size_t) (VRAM_SIZE << sparse_shift),
						 PROT_READ | PROT_WRITE,
						 MAP_SHARED,
						 mem_fd, (VRAM_START << sparse_shift)
						 | _bus_base_sparse())) == (void *) -1)
#else
      if (mmap((void *) VRAM_START, (size_t) VRAM_SIZE,
			 PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
			 mem_fd, VRAM_START) == (void *) -1)
#endif
      {
	perror("mmap error in map_hardware_ram (1)");
	    close(mem_fd);
	    return (0);
	}
    vram_mapped = 1;
    close(mem_fd);
    return (1);
}

static void
unmap_vram(void)
{
    if (!vram_mapped) return;

    munmap((void*)VRAM_START,VRAM_SIZE);
    vram_mapped = 0;
}

static int
copy_vbios(memType v_base)
{
    int mem_fd;
    unsigned char *tmp;
    int size;

    if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
	perror("opening memory");
	return (0);
    }

    if (lseek(mem_fd,(off_t) v_base, SEEK_SET) != (off_t) v_base) {
	  fprintf(stderr,"Cannot lseek\n");
	  goto Error;
      }
    tmp = (unsigned char *)malloc(3);
    if (read(mem_fd, (char *)tmp, (size_t) 3) != (size_t) 3) {
	    fprintf(stderr,"Cannot read\n");
	goto Error;
    }
    if (lseek(mem_fd,(off_t) v_base,SEEK_SET) != (off_t) v_base)
	goto Error;

    if (*tmp != 0x55 || *(tmp+1) != 0xAA ) {
	fprintf(stderr,"No bios found at: 0x%lx\n",v_base);
	goto Error;
    }
#ifdef DEBUG
	dprint((unsigned long)tmp,0x100);
#endif
    size = *(tmp+2) * 512;

    if (read(mem_fd, (char *)v_base, (size_t) size) != (size_t) size) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?