diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | get-edid.h | 4 | ||||
-rw-r--r-- | hd.h | 12 | ||||
-rw-r--r-- | int10/Makefile | 2 | ||||
-rw-r--r-- | int10/i10_vbios.c | 329 | ||||
-rw-r--r-- | int10/vbios.h | 4 | ||||
-rw-r--r-- | monitor-get-edid-using-vbe.c | 29 | ||||
-rw-r--r-- | vbe.c | 23 |
8 files changed, 236 insertions, 169 deletions
@@ -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)) @@ -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); @@ -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 && @@ -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(); } } |