diff options
Diffstat (limited to 'int10/i10_vbios.c')
-rw-r--r-- | int10/i10_vbios.c | 606 |
1 files changed, 0 insertions, 606 deletions
diff --git a/int10/i10_vbios.c b/int10/i10_vbios.c deleted file mode 100644 index 5d12741..0000000 --- a/int10/i10_vbios.c +++ /dev/null @@ -1,606 +0,0 @@ -/* - * 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. - */ -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdint.h> -#include <errno.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <string.h> -#include <stdlib.h> -#include <signal.h> -#include <sys/stat.h> -#include <setjmp.h> -#if defined(__alpha__) || defined (__ia64__) -#include <sys/io.h> -//#elif defined(HAVE_SYS_PERM) -#else -#include <sys/perm.h> -#endif -#include "v86bios.h" -#include "pci.h" -#include "AsmMacros.h" -#include "vbios.h" - -void log_err(char *format, ...) __attribute__ ((format (printf, 1, 2))); - -#define SIZE 0x100000 -#define VRAM_START 0xA0000 -#define VRAM_SIZE 0x1FFFF -#define V_BIOS_SIZE 0x1FFFF -#define BIOS_START 0x7C00 /* default BIOS entry */ - -static CARD8 code[] = { 0xcd, 0x10, 0xf4 }; /* int 0x10, hlt */ -// static CARD8 code13[] = { 0xcd, 0x13, 0xf4 }; /* int 0x13, hlt */ - -static int int10_bios_ok(void); -static int map(void); -static void unmap(void); -static int map_vram(hd_data_t *hd_data); -static void unmap_vram(void); -static int copy_vbios(hd_data_t *hd_data); -// static int copy_sbios(void); -#if MAP_SYS_BIOS -static int copy_sys_bios(hd_data_t *hd_data); -#endif -static int copy_bios_ram(hd_data_t *hd_data); -static int setup_system_bios(hd_data_t *hd_data); -static void setup_int_vect(void); -static int chksum(CARD8 *start); -#define hd_read_mmap(UNUSED, NAME, BUF, START, SIZE) i10_read_mmap(NAME, BUF, START, SIZE) -static int i10_read_mmap(char *name, unsigned char *buf, off_t start, unsigned size); - -void loadCodeToMem(unsigned char *ptr, CARD8 *code); - -static int vram_mapped = 0; -static int int10inited = 0; - -static sigjmp_buf longjmp_buf; - -static void sigsegv_handler(int); - -int InitInt10(hd_data_t *hd_data) -{ - if(geteuid()) return -1; - - if(!map()) return -1; - - if(!setup_system_bios(hd_data)) { - unmap(); - return -1; - } - - setup_io(); - - if(iopl(3) < 0) { - unmap(); - return -1; - } - - iopl(0); - - setup_int_vect(); - - if(!copy_vbios(hd_data)) { - unmap(); - return -1; - } - - if(hd_data->flags.biosvram) map_vram(hd_data); - - if(!copy_bios_ram(hd_data)) { - unmap(); - return -1; - } - - if(!int10_bios_ok()) { - unmap(); - return -1; - } - - int10inited = 1; - - return 0; -} - - -void FreeInt10() -{ - if(!int10inited) return; - - unmap_vram(); - unmap(); - - int10inited = 0; -} - - -/* - * Check whether int 0x10 points to some useful code. - */ -int int10_bios_ok() -{ - unsigned cs, ip; - unsigned char *p; - - ip = ((uint16_t *) 0)[0x10 * 2]; - cs = ((uint16_t *) 0)[0x10 * 2 + 1]; - - p = (unsigned char *)(uintptr_t) ((cs << 4) + ip); - - log_err( - " vbe: int 10h points to %04x:%04x: %02x %02x %02x %02x %02x %02x %02x %02x\n", - cs, ip, - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7] - ); - - /* It can't possibly start with all zeros. */ - if( !(p[0] || p[1] || p[2] || p[3]) ) { - log_err(" vbe: oops, int 10h points into nirvana!\n"); - - return 0; - } - - return 1; -} - - -void sigsegv_handler(int num) -{ - siglongjmp(longjmp_buf, num + 1000); -} - - -int CallInt10(int *ax, int *bx, int *cx, unsigned char *buf, int len, int cpuemu) -{ - i86biosRegs bRegs; - void (*old_sigsegv_handler)(int) = SIG_DFL; - void (*old_sigill_handler)(int) = SIG_DFL; - void (*old_sigtrap_handler)(int) = SIG_DFL; - int jmp; - - if(!int10inited) return -1; - memset(&bRegs, 0, sizeof bRegs); - bRegs.ax = *ax; - bRegs.bx = *bx; - bRegs.cx = *cx; - bRegs.dx = 0; - bRegs.es = 0x7e0; - bRegs.di = 0x0; - if(buf) memcpy((unsigned char *) 0x7e00, buf, len); - - iopl(3); - - jmp = sigsetjmp(longjmp_buf, 1); - - if(!jmp) { - old_sigsegv_handler = signal(SIGSEGV, sigsegv_handler); - old_sigill_handler = signal(SIGILL, sigsegv_handler); - old_sigtrap_handler = signal(SIGTRAP, sigsegv_handler); - - loadCodeToMem((unsigned char *) BIOS_START, code); - do_x86(BIOS_START, &bRegs, cpuemu); - } - else { - int10inited = 0; - log_err("oops: got signal %d in vm86() code\n", jmp - 1000); - } - - signal(SIGTRAP, old_sigtrap_handler); - signal(SIGILL, old_sigill_handler); - signal(SIGSEGV, old_sigsegv_handler); - - iopl(0); - - if(buf) memcpy(buf, (unsigned char *) 0x7e00, len); - - *ax = bRegs.ax; - *bx = bRegs.bx; - *cx = bRegs.cx; - - return bRegs.ax; -} - - -#if 0 -int CallInt13(int *ax, int *bx, int *cx, int *dx, unsigned char *buf, int len, int cpuemu) -{ - i86biosRegs bRegs; - - if(!int10inited) return -1; - memset(&bRegs, 0, sizeof bRegs); - bRegs.ax = *ax; - bRegs.bx = *bx; - bRegs.cx = *cx; - bRegs.dx = *dx; - bRegs.es = 0x7e0; - bRegs.ds = 0x7e0; - bRegs.di = 0x0; - bRegs.si = 0x0; - if(buf) memcpy((unsigned char *) 0x7e00, buf, len); - - iopl(3); - - loadCodeToMem((unsigned char *) BIOS_START, code13); - do_x86(BIOS_START, &bRegs, cpuemu); - - iopl(0); - - if(buf) memcpy(buf, (unsigned char *) 0x7e00, len); - - *ax = bRegs.ax; - *bx = bRegs.bx; - *cx = bRegs.cx; - *dx = bRegs.dx; - - return bRegs.ax; -} -#endif - - -int map() -{ - void* mem; - - mem = mmap(0, (size_t) SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0); - - if(mem) { - perror("anonymous map"); - return 0; - } - - memset(mem, 0, SIZE); - - loadCodeToMem((unsigned char *) BIOS_START, code); - - return 1; -} - - -void unmap() -{ - munmap(0, SIZE); -} - - -int map_vram(hd_data_t *hd_data) -{ - 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 - { - log_err("map vram: open /dev/mem failed (%s)\n", strerror(errno)); - - return 0; - } - -#ifndef __alpha__ - 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 - ) -#else - 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 - ) -#endif - { - log_err( - "/dev/mem[0x%x, %u]: mmap(, %u,,,, 0x%x) failed: %s\n", - (unsigned) VRAM_START, VRAM_SIZE, VRAM_SIZE, (unsigned) VRAM_START, strerror(errno) - ); - - close(mem_fd); - - return 0; - } - - log_err( - "/dev/mem[0x%x, %u]: mmap(, %u,,,, 0x%x) ok\n", - (unsigned) VRAM_START, VRAM_SIZE, VRAM_SIZE, (unsigned) VRAM_START - ); - - vram_mapped = 1; - - close(mem_fd); - - return 1; -} - - -void unmap_vram() -{ - if(!vram_mapped) return; - - munmap((void*) VRAM_START, VRAM_SIZE); - - vram_mapped = 0; -} - - -/* - * Read video BIOS from /dev/mem. - * - * Return: - * 0: failed - * 1: ok - */ -int copy_vbios(hd_data_t *hd_data) -{ - unsigned size; - unsigned char tmp[3]; - int i; - - if(!hd_read_mmap(hd_data, MEM_FILE, tmp, V_BIOS, sizeof tmp)) { - log_err("vbe: failed to read %u bytes at 0x%x\n", (unsigned) sizeof tmp, V_BIOS); - return 0; - } - - if(tmp[0] != 0x55 || tmp[1] != 0xAA ) { - log_err("vbe: no bios found at: 0x%x\n", V_BIOS); - return 0; - } - - size = tmp[2] * 0x200; - - if(!hd_read_mmap(hd_data, MEM_FILE, (unsigned char *) V_BIOS, V_BIOS, size)) { - log_err("vbe: failed to read %d bytes at 0x%x\n", size, V_BIOS); - return 0; - } - - if((i = chksum((CARD8 *) V_BIOS)) || !hd_data->flags.nobioscrc) return i; -#ifdef __i386__ - /* use cpu emulation for broken BIOSes */ - hd_data->flags.cpuemu |= 1; -#endif - - return 1; -} - - -#if MAP_SYS_BIOS -static int -copy_sys_bios(hd_data_t *hd_data) -{ - return hd_read_mmap(hd_data, MEM_FILE, (unsigned char *) 0xf0000, 0xf0000, 0xffff); -} -#endif - - -static int copy_bios_ram(hd_data_t *hd_data) -{ - return hd_read_mmap(hd_data, MEM_FILE, (unsigned char *) 0, 0, 0x1000); -} - -void loadCodeToMem(unsigned char *ptr, CARD8 *code) -{ - while((*ptr++ = *code++) != 0xf4 /* hlt */); - - return; -} - - -/* - * here we are really paranoid about faking a "real" - * BIOS. Most of this information was pulled from - * dosem. - */ -static void -setup_int_vect(void) -{ - const CARD16 cs = 0x0000; - const CARD16 ip = 0x0; - int i; - - /* let the int vects point to the SYS_BIOS seg */ - for (i=0; i<0x80; i++) { - ((CARD16*)0)[i<<1] = ip; - ((CARD16*)0)[(i<<1)+1] = cs; - } - /* video interrupts default location */ - ((CARD16*)0)[(0x42<<1)+1] = 0xf000; - ((CARD16*)0)[0x42<<1] = 0xf065; - ((CARD16*)0)[(0x10<<1)+1] = 0xf000; - ((CARD16*)0)[0x10<<1] = 0xf065; - /* video param table default location (int 1d) */ - ((CARD16*)0)[(0x1d<<1)+1] = 0xf000; - ((CARD16*)0)[0x1d<<1] = 0xf0A4; - /* font tables default location (int 1F) */ - ((CARD16*)0)[(0x1f<<1)+1] = 0xf000; - ((CARD16*)0)[0x1f<<1] = 0xfa6e; - - /* int 11 default location */ - ((CARD16*)0)[(0x11<1)+1] = 0xf000; - ((CARD16*)0)[0x11<<1] = 0xf84d; - /* int 12 default location */ - ((CARD16*)0)[(0x12<<1)+1] = 0xf000; - ((CARD16*)0)[0x12<<1] = 0xf841; - /* int 15 default location */ - ((CARD16*)0)[(0x15<<1)+1] = 0xf000; - ((CARD16*)0)[0x15<<1] = 0xf859; - /* int 1A default location */ - ((CARD16*)0)[(0x1a<<1)+1] = 0xf000; - ((CARD16*)0)[0x1a<<1] = 0xff6e; - /* int 05 default location */ - ((CARD16*)0)[(0x05<<1)+1] = 0xf000; - ((CARD16*)0)[0x05<<1] = 0xff54; - /* int 08 default location */ - ((CARD16*)0)[(0x8<<1)+1] = 0xf000; - ((CARD16*)0)[0x8<<1] = 0xfea5; - /* int 13 default location (fdd) */ - ((CARD16*)0)[(0x13<<1)+1] = 0xf000; - ((CARD16*)0)[0x13<<1] = 0xec59; - /* int 0E default location */ - ((CARD16*)0)[(0xe<<1)+1] = 0xf000; - ((CARD16*)0)[0xe<<1] = 0xef57; - /* int 17 default location */ - ((CARD16*)0)[(0x17<<1)+1] = 0xf000; - ((CARD16*)0)[0x17<<1] = 0xefd2; - /* fdd table default location (int 1e) */ - ((CARD16*)0)[(0x1e<<1)+1] = 0xf000; - ((CARD16*)0)[0x1e<<1] = 0xefc7; -} - -static int -setup_system_bios(hd_data_t *hd_data) -{ - char *date = "06/01/99"; - char *eisa_ident = "PCI/ISA"; - -#if MAP_SYS_BIOS - if (!copy_sys_bios(hd_data)) return 0; - return 1; -#endif -// memset((void *)0xF0000,0xf4,0xfff7); - - /* - * 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((void *)0xF0000,0xf4,0x10000); - - /* - * TODO: we should copy the fdd table (0xfec59-0xfec5b) - * the video parameter table (0xf0ac-0xf0fb) - * and the font tables (0xfa6e-0xfe6d) - * from the original bios here - */ - - /* set bios date */ - strcpy((char *)0xFFFF5,date); - /* set up eisa ident string */ - strcpy((char *)0xFFFD9,eisa_ident); - /* write system model id for IBM-AT */ - ((char *)0)[0xFFFFE] = 0xfc; - - return 1; -} - - -/* - * Check BIOS CRC. - * - * Return: - * 0: failed - * 1: ok - */ -int chksum(CARD8 *start) -{ - CARD16 size; - CARD8 val = 0; - int i; - - size = start[2] * 0x200; - for(i = 0; i < size; i++) val += start[i]; - - if(!val) return 1; - - log_err("vbe: BIOS chksum wrong\n"); - - return 0; -} - - -/* - * Read using mmap(). - */ -int i10_read_mmap(char *name, unsigned char *buf, off_t start, unsigned size) -{ - off_t map_start, xofs; - int psize = getpagesize(), fd; - unsigned map_size; - void *p; - struct stat sbuf; - - if(!size || !name) return 0; - - memset(buf, 0, size); - - map_start = start & -psize; - xofs = start - map_start; - - map_size = (xofs + size + psize - 1) & -psize; - - fd = open(name, O_RDONLY); - - if(fd == -1) return 0; - - if(!fstat(fd, &sbuf) && S_ISREG(sbuf.st_mode)) { - if(sbuf.st_size < start + size) { - if(sbuf.st_size > start) { - size = sbuf.st_size - start; - } - else { - size = 0; - } - } - } - - if(!size) { - close(fd); - return 0; - } - - p = mmap(NULL, map_size, PROT_READ, MAP_PRIVATE, fd, map_start); - - if(p == MAP_FAILED) { - log_err( - "%s[0x%x, %u]: mmap(, %u,,,, 0x%x) failed: %s\n", - name, (unsigned) start, size, map_size, (unsigned) map_start, strerror(errno) - ); - close(fd); - return 0; - } - if (0) log_err( - "%s[0x%x, %u]: mmap(, %u,,,, 0x%x) ok\n", - name, (unsigned) start, size, map_size, (unsigned) map_start - ); - - memcpy(buf, p + xofs, size); - - munmap(p, map_size); - - close(fd); - - return 1; -} |