aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--get-edid.h4
-rw-r--r--hd.h12
-rw-r--r--int10/Makefile2
-rw-r--r--int10/i10_vbios.c329
-rw-r--r--int10/vbios.h4
-rw-r--r--monitor-get-edid-using-vbe.c29
-rw-r--r--vbe.c23
8 files changed, 236 insertions, 169 deletions
diff --git a/Makefile b/Makefile
index f534f90..1c31330 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ endif
TARGETS = monitor-get-edid-using-vbe cvt
-CFLAGS = -O -Wall -g
+CFLAGS = -O -Wall -g -I.
OBJS = monitor-get-edid-using-vbe.c vbe.o libint10.a libx86emu.a
ifeq (i386,$(ARCH))
diff --git a/get-edid.h b/get-edid.h
index d13aa3b..eb45d11 100644
--- a/get-edid.h
+++ b/get-edid.h
@@ -1,2 +1,4 @@
int verbose;
-int get_edid(char *edid);
+
+struct hd_data_struct;
+int get_edid(struct hd_data_struct *hd_data, char *edid);
diff --git a/hd.h b/hd.h
new file mode 100644
index 0000000..bef83b0
--- /dev/null
+++ b/hd.h
@@ -0,0 +1,12 @@
+#ifndef HD_H
+#define HD_H
+
+typedef struct hd_data_struct {
+ struct flag_struct {
+ unsigned cpuemu:1; /**< use CPU emulation to run BIOS code (i386 only) */
+ unsigned nobioscrc:1; /**< internal: don't check VBIOS crc */
+ unsigned biosvram:1; /**< internal: map Video BIOS RAM (128k at 0xa0000) */
+ } flags;
+} hd_data_t;
+
+#endif /* HD_H */
diff --git a/int10/Makefile b/int10/Makefile
index b2a5591..de02cd2 100644
--- a/int10/Makefile
+++ b/int10/Makefile
@@ -1,5 +1,5 @@
CC = gcc
-INCS =
+INCS = -I.. -I.
CFLAGS = -O -Wall
SRCS = emu_vm86.c i10_int.c i10_io.c i10_pci.c i10_v86.c i10_vbios.c
OBJS = $(SRCS:%.c=%.o)
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;
+}
diff --git a/int10/vbios.h b/int10/vbios.h
index 6bd5e80..edcb715 100644
--- a/int10/vbios.h
+++ b/int10/vbios.h
@@ -1,4 +1,6 @@
-int InitInt10(int);
+#include "hd.h"
+
+int InitInt10(hd_data_t *, int);
int CallInt10(int *ax, int *bx, int *cx, unsigned char *buf, int len, int cpuemu);
int CallInt13(int *ax, int *bx, int *cx, int *dx, unsigned char *buf, int len, int cpuemu);
void FreeInt10(void);
diff --git a/monitor-get-edid-using-vbe.c b/monitor-get-edid-using-vbe.c
index 50366f2..1b5a470 100644
--- a/monitor-get-edid-using-vbe.c
+++ b/monitor-get-edid-using-vbe.c
@@ -10,6 +10,7 @@
#include <sys/ioctl.h>
#include <sys/vt.h>
#include "get-edid.h"
+#include "hd.h"
int verbose = 0;
@@ -19,16 +20,30 @@ int main(int argc, char **argv)
int try_in_console = 0;
int i;
- for (i = 1; i < argc; i++)
- if (strcmp(argv[i], "-v") == 0) verbose = 1;
- else if (strcmp(argv[i], "--try-in-console") == 0) try_in_console = 1;
- else if (strcmp(argv[i], "-h") == 0 ||
- strcmp(argv[i], "--help") == 0) {
+ /* Hardware Data defaults */
+ hd_data_t hd_data;
+ hd_data.flags.biosvram = 0; /* don't map video BIOS RAM */
+ hd_data.flags.nobioscrc = 1; /* don't check VBIOS CRC */
+ hd_data.flags.cpuemu = 1; /* use CPU emulator everywhere... */
+#ifdef __i386__
+ hd_data.flags.cpuemu = 0; /* ... but ia32, unless VBIOS CRC is invalid */
+#endif
+
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (strcmp(arg, "-v") == 0) verbose = 1;
+ else if (strcmp(arg, "--try-in-console") == 0) try_in_console = 1;
+ else if (strcmp(arg, "--map-bios-vram") == 0) hd_data.flags.biosvram = 1;
+ else if (strcmp(arg, "--check-bios-crc") == 0) hd_data.flags.nobioscrc = 0;
+ else if (strcmp(arg, "--use-cpuemu") == 0) hd_data.flags.cpuemu = 1;
+ else if (strcmp(arg, "-h") == 0 ||
+ strcmp(arg, "--help") == 0) {
printf("usage: monitor-get-edid [-v]\n");
exit(1);
}
+ }
- int size = get_edid(edid);
+ int size = get_edid(&hd_data, edid);
if (!size && try_in_console) {
int non_X_console = 1;
@@ -41,7 +56,7 @@ int main(int argc, char **argv)
ioctl(fd, VT_ACTIVATE, non_X_console) == 0 &&
ioctl(fd, VT_WAITACTIVE, non_X_console) == 0) {
/* retrying */
- size = get_edid(edid);
+ size = get_edid(&hd_data, edid);
/* restore */
ioctl(fd, VT_ACTIVATE, current.v_active) == 0 &&
diff --git a/vbe.c b/vbe.c
index feceb70..5b3f87e 100644
--- a/vbe.c
+++ b/vbe.c
@@ -21,13 +21,6 @@
#define LRMI
#endif
-/* This specifies whether CPU emulation is used or real mode execution */
-#ifdef __i386__
-#define cpuemu 0
-#else
-#define cpuemu 1
-#endif
-
#include <stdarg.h>
int box_is_xbox();
@@ -119,7 +112,7 @@ static void parse_vbe_info(unsigned char *v)
log_err("Product revision: %s\n", get_str(tmp, sizeof tmp, v + 0x1e));
}
-static int vbe_check_vbe_info(void)
+static int vbe_check_vbe_info(hd_data_t *hd_data)
{
int i;
unsigned char v[0x200];
@@ -133,7 +126,7 @@ static int vbe_check_vbe_info(void)
strcpy(v, "VBE2");
/* Get VBE block */
- i = CallInt10(&ax, &bx, &cx, v, sizeof(v), cpuemu) & 0xffff;
+ i = CallInt10(&ax, &bx, &cx, v, sizeof(v), hd_data->flags.cpuemu) & 0xffff;
if (i != 0x4f) {
log_err("VBE: Error (0x4f00): 0x%04x\n", i);
return 0;
@@ -143,7 +136,7 @@ static int vbe_check_vbe_info(void)
}
/* Get EDID info. */
-int vbe_get_edid_info(char *edid)
+int vbe_get_edid_info(hd_data_t *hd_data, char *edid)
{
int i;
int ax, bx, cx;
@@ -154,7 +147,7 @@ int vbe_get_edid_info(char *edid)
cx = 0;
/* Get EDID block */
- i = CallInt10(&ax, &bx, &cx, edid, 256, cpuemu) & 0xffff;
+ i = CallInt10(&ax, &bx, &cx, edid, 256, hd_data->flags.cpuemu) & 0xffff;
if (i != 0x4f) {
log_err("EDID: Error (0x4f15): 0x%04x\n", i);
return 0;
@@ -281,7 +274,7 @@ int get_edid__old(char *edid)
}
#endif
-int get_edid(char *edid)
+int get_edid(hd_data_t *hd_data, char *edid)
{
int pci_config_type = 1; /* Determine PCI configuration type */
int ok = 0;
@@ -292,9 +285,9 @@ int get_edid(char *edid)
}
if (!box_is_xbox()) {
- if (InitInt10(pci_config_type) == 0) {
- ok = vbe_check_vbe_info()
- && vbe_get_edid_info(edid);
+ if (InitInt10(hd_data, pci_config_type) == 0) {
+ ok = vbe_check_vbe_info(hd_data)
+ && vbe_get_edid_info(hd_data, edid);
FreeInt10();
}
}