📄 v86bios.c
字号:
/* * 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) & 0xFFCARD8 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);#endifstatic 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);}voidcall_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); } }}intmap(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 voidunmap(void){ munmap(0,SIZE);}static voidbootBIOS(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 intmap_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 voidunmap_vram(void){ if (!vram_mapped) return; munmap((void*)VRAM_START,VRAM_SIZE); vram_mapped = 0;}static intcopy_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -