aboutsummaryrefslogtreecommitdiffstats
path: root/int10/i10_vbios.c
diff options
context:
space:
mode:
Diffstat (limited to 'int10/i10_vbios.c')
-rw-r--r--int10/i10_vbios.c329
1 files changed, 186 insertions, 143 deletions
diff --git a/int10/i10_vbios.c b/int10/i10_vbios.c
index 89c6b7c..328ad84 100644
--- a/int10/i10_vbios.c
+++ b/int10/i10_vbios.c
@@ -22,6 +22,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
+#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
@@ -52,19 +53,22 @@ void log_err(char *format, ...) __attribute__ ((format (printf, 1, 2)));
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(void);
+static int map_vram(hd_data_t *hd_data);
static void unmap_vram(void);
-static int copy_vbios(void);
+static int copy_vbios(hd_data_t *hd_data);
// static int copy_sbios(void);
#if MAP_SYS_BIOS
-static int copy_sys_bios(void);
+static int copy_sys_bios(hd_data_t *hd_data);
#endif
-static int copy_bios_ram();
-static int setup_system_bios(void);
+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);
@@ -75,13 +79,13 @@ static sigjmp_buf longjmp_buf;
static void sigsegv_handler(int);
-int InitInt10(int pci_cfg_method)
+int InitInt10(hd_data_t *hd_data, int pci_cfg_method)
{
if(geteuid()) return -1;
if(!map()) return -1;
- if(!setup_system_bios()) {
+ if(!setup_system_bios(hd_data)) {
unmap();
return -1;
}
@@ -93,41 +97,37 @@ int InitInt10(int pci_cfg_method)
return -1;
}
+#if 0
scan_pci(pci_cfg_method);
for(; CurrentPci; CurrentPci = CurrentPci->next) {
if(CurrentPci->active) break;
}
+#endif
iopl(0);
setup_int_vect();
- if(!copy_vbios()) {
+ if(!copy_vbios(hd_data)) {
unmap();
return -1;
}
-#if 0
- if(!copy_sbios()) {
+ if(hd_data->flags.biosvram) map_vram(hd_data);
+
+ if(!copy_bios_ram(hd_data)) {
unmap();
return -1;
}
-#endif
- if(!map_vram() || !copy_bios_ram()) {
+ if(!int10_bios_ok()) {
unmap();
return -1;
}
int10inited = 1;
-#if 0
- /* int 13 default location (fdd) */
- ((CARD16*)0)[(0x13<<1)+1] = 0xf000;
- ((CARD16*)0)[0x13<<1] = 0xec59;
-#endif
-
return 0;
}
@@ -143,6 +143,36 @@ void FreeInt10()
}
+/*
+ * 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);
@@ -261,42 +291,67 @@ void unmap()
}
-static int
-map_vram(void)
+int map_vram(hd_data_t *hd_data)
{
- int mem_fd;
+ int mem_fd;
#ifdef __ia64__
- if ((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC))<0)
+ if((mem_fd = open(MEM_FILE,O_RDWR | O_SYNC)) < 0)
#else
- if ((mem_fd = open(MEM_FILE,O_RDWR))<0)
+ if((mem_fd = open(MEM_FILE,O_RDWR)) < 0)
#endif
- {
- perror("opening memory");
- return 0;
- }
+ {
+ 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)
+ 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)
+ 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
- {
- perror("mmap error in map_hardware_ram");
- close(mem_fd);
- return (0);
- }
- vram_mapped = 1;
- close(mem_fd);
- return (1);
+ {
+ 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;
}
@@ -317,129 +372,53 @@ void unmap_vram()
* 0: failed
* 1: ok
*/
-int copy_vbios()
+int copy_vbios(hd_data_t *hd_data)
{
- int mem_fd, size, ok = 0;
+ unsigned size;
unsigned char tmp[3];
+ int i;
- if((mem_fd = open(MEM_FILE, O_RDONLY)) == -1) {
- log_err("vbe: failed to open BIOS memory, errno = %d", errno);
-
+ 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(lseek(mem_fd, (off_t) V_BIOS, SEEK_SET) != (off_t) V_BIOS) {
- log_err("vbe: lseek failed, errno = %d\n", errno);
- }
- else {
- if(read(mem_fd, tmp, sizeof tmp) != sizeof tmp) {
- log_err("vbe: failed to read %u bytes at 0x%x, errno = %d\n", (unsigned) sizeof tmp, V_BIOS, errno);
- }
- else {
- if(lseek(mem_fd, V_BIOS, SEEK_SET) != V_BIOS) {
- log_err("vbe: lseek failed, errno = %d\n", errno);
- }
- else {
- if(tmp[0] != 0x55 || tmp[1] != 0xAA ) {
- log_err("vbe: no bios found at: 0x%x\n", V_BIOS);
- }
- else {
- size = tmp[2] * 0x200;
-
- if(read(mem_fd, (char *) V_BIOS, size) != size) {
- log_err("vbe: failed to read %d bytes at 0x%x, errno = %d\n", size, V_BIOS, errno);
- }
- else {
- if(chksum((CARD8 *) V_BIOS)) ok = 1;
- }
- }
- }
- }
+ if(tmp[0] != 0x55 || tmp[1] != 0xAA ) {
+ log_err("vbe: no bios found at: 0x%x\n", V_BIOS);
+ return 0;
}
- close(mem_fd);
-
- return ok;
-}
-
-
-#if 0
-#define SYS_BIOS 0xe0000
-#define SYS_BIOS_SIZE 0x20000
-int copy_sbios()
-{
- int fd;
+ size = tmp[2] * 0x200;
- if((fd = open(MEM_FILE, O_RDONLY)) < 0) {
- perror("opening memory");
+ 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(lseek(fd,(off_t) SYS_BIOS, SEEK_SET) == (off_t) SYS_BIOS) {
- read(fd, (void *) SYS_BIOS, SYS_BIOS_SIZE);
- }
-
- close(fd);
+ 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;
}
-#endif
#if MAP_SYS_BIOS
static int
-copy_sys_bios(void)
+copy_sys_bios(hd_data_t *hd_data)
{
-#define SYS_BIOS 0xF0000
- int mem_fd;
-
- if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
- perror("opening memory");
- return (0);
- }
-
- if (lseek(mem_fd,(off_t) SYS_BIOS,SEEK_SET) != (off_t) SYS_BIOS)
- goto Error;
- if (read(mem_fd, (char *)SYS_BIOS, (size_t) 0xFFFF) != (size_t) 0xFFFF)
- goto Error;
-
- close(mem_fd);
- return (1);
-
-Error:
- perror("sys_bios");
- close(mem_fd);
- return (0);
+ return hd_read_mmap(hd_data, MEM_FILE, (unsigned char *) 0xf0000, 0xf0000, 0xffff);
}
#endif
-static int
-copy_bios_ram(void)
+static int copy_bios_ram(hd_data_t *hd_data)
{
-#define BIOS_RAM 0
- int mem_fd;
-
- if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
- perror("opening memory");
- return (0);
- }
-
- if (lseek(mem_fd,(off_t) BIOS_RAM,SEEK_SET) != (off_t) BIOS_RAM)
- goto Error;
- if (read(mem_fd, (char *)BIOS_RAM, (size_t) 0x1000) != (size_t) 0x1000)
- goto Error;
-
- close(mem_fd);
- return (1);
-
-Error:
- perror("bios_ram");
- close(mem_fd);
- return (0);
+ 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 */);
@@ -510,13 +489,13 @@ setup_int_vect(void)
}
static int
-setup_system_bios(void)
+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()) return 0;
+ if (!copy_sys_bios(hd_data)) return 0;
return 1;
#endif
// memset((void *)0xF0000,0xf4,0xfff7);
@@ -569,3 +548,67 @@ int chksum(CARD8 *start)
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;
+}