v86bios.c
来自「适合KS8695X」· C语言 代码 · 共 934 行 · 第 1/2 页
C
934 行
fprintf(stderr,"Cannot read\n");
goto Error;
}
free(tmp);
close(mem_fd);
if (!chksum((CARD8*)v_base))
return (0);
return (1);
Error:
perror("v_bios");
close(mem_fd);
return (0);
}
static int
copy_sys_bios(void)
{
#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);
}
void
loadCodeToMem(unsigned char *ptr, CARD8 code[])
{
int i;
CARD8 val;
int size = code[0];
for ( i=1;i<=size;i++) {
val = code[i];
*ptr++ = val;
}
return;
}
void
dprint(unsigned long start, unsigned long size)
{
int i,j;
char *c = (char *)start;
for (j = 0; j < (size >> 4); j++) {
char *d = c;
printf("\n0x%lx: ",(unsigned long)c);
for (i = 0; i<16; i++)
printf("%2.2x ",(unsigned char) (*(c++)));
c = d;
for (i = 0; i<16; i++) {
printf("%c",((((CARD8)(*c)) > 32) && (((CARD8)(*c)) < 128)) ?
(unsigned char) (*(c)): '.');
c++;
}
}
printf("\n");
}
static void
save_bios_to_file(void)
{
static int num = 0;
int size, count;
char file_name[256];
int fd;
sprintf(file_name,"bios_%i.fil",num);
if ((fd = open(file_name,O_WRONLY | O_CREAT | O_TRUNC,00644)) == -1)
return;
size = (*(unsigned char*)(V_BIOS + 2)) * 512;
#ifdef V86BIOS_DEBUG
dprint(V_BIOS,20);
#endif
if ((count = write(fd,(void *)(V_BIOS),size)) != size)
fprintf(stderr,"only saved %i of %i bytes\n",size,count);
num++;
}
static void
sig_handler(int unused)
{
fflush(stdout);
fflush(stderr);
/* put system back in a save state */
unmap_vram();
pciVideoRestore();
outb(0x102, save_pos102);
outb(0x46e8, save_46e8);
outb(0x3C3, save_vse);
outb(0x3C2, save_msr);
close_console(Console);
iopl(0);
unmap();
exit(1);
}
/*
* For initialization we just pass ax to the BIOS.
* PCI BIOSes need this. All other register are set 0.
*/
static void setup_bios_regs(i86biosRegsPtr regs, CARD32 ax)
{
regs->ax = ax;
regs->bx = 0;
regs->cx = 0;
regs->dx = 0;
regs->es = 0;
regs->ds = 0x40; /* standard pc ds */
regs->si = 0;
regs->di = 0;
}
/*
* here we are really paranoid about faking a "real"
* BIOS. Most of this information was pulled from
* dosem.
*/
#ifdef __ia32__
static CARD32
setup_primary_int_vect(void)
{
int mem_fd;
CARD32 vbase;
void *map;
if ((mem_fd = open(MEM_FILE,O_RDWR))<0)
{
perror("opening memory");
return (0);
}
if ((map = mmap((void *) 0, (size_t) 0x2000,
PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED,
mem_fd, 0)) == (void *)-1) {
perror("mmap error in map_hardware_ram (2)");
close(mem_fd);
return (0);
}
close(mem_fd);
memcpy(0,map,BIOS_MEM);
munmap(map,0x2000);
/*
* create a backup copy of the bios variables to write back the
* modified values
*/
if (!bios_var)
bios_var = (char *)malloc(BIOS_MEM);
memcpy(bios_var,0,BIOS_MEM);
vbase = (*((CARD16*)(0x10 << 2) + 1)) << 4;
if (Config.Verbose > 0) printf("vbase: 0x%x\n",vbase);
return vbase;
}
#endif
static CARD32
setup_int_vect(void)
{
const CARD16 cs = 0x0;
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;
return V_BIOS;
}
static int
setup_system_bios(void)
{
char *date = "06/01/99";
char *eisa_ident = "PCI/ISA";
if (Config.MapSysBios) {
if (!copy_sys_bios()) return 0;
return 1;
} else {
/* 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;
}
}
static void
update_bios_vars(void)
{
int mem_fd;
void *map;
memType i;
#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;
}
if ((map = mmap((void *) 0, (size_t) 0x2000,
PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED,
mem_fd, 0)) == (void *)-1) {
perror("mmap error in map_hardware_ram (3)");
close(mem_fd);
return;
}
for (i = 0; i < BIOS_MEM; i++) {
if (bios_var[i] != *(CARD8*)i)
*((CARD8*)map + i) = *(CARD8*)i;
}
munmap(map,0x2000);
close(mem_fd);
}
static int
chksum(CARD8 *start)
{
CARD16 size;
CARD8 val = 0;
int i;
size = *(start+2) * 512;
for (i = 0; i<size; i++)
val += *(start + i);
if (!val)
return 1;
fprintf(stderr,"BIOS cksum wrong!\n");
return 0;
}
void
runINT(int num, i86biosRegsPtr Regs)
{
Bool isVideo = FALSE;
CARD8 code_int[] = { 3, 0xcd, 0x00, 0xf4 };
code_int[2] = (CARD8) num;
if (num == 0x10)
isVideo = TRUE;
if (!setup_system_bios())
return;
if ((isVideo && (!CurrentPci || CurrentPci->active)) || !isVideo) {
CARD32 vbios_base;
#ifdef __ia32__
if (!(vbios_base = setup_primary_int_vect()))
#else
if (!(vbios_base = setup_int_vect()))
#endif
return;
if (!copy_vbios(vbios_base))
return;
}
if (!map_vram())
return;
#ifdef V86BIOS_DEBUG
printf("starting BIOS\n");
#endif
loadCodeToMem((unsigned char *) BIOS_START, code_int);
setup_io();
print_regs(Regs);
set_ioperm();
set_hlt(TRUE);
do_x86(BIOS_START,Regs);
set_hlt(FALSE);
print_regs(Regs);
#ifdef V86BIOS_DEBUG
printf("done\n");
#endif
if ((isVideo && (!CurrentPci || CurrentPci->active)) || !isVideo)
update_bios_vars();
}
static void
print_regs(i86biosRegsPtr regs)
{
printf("ax=%x bx=%x cx=%x dx=%x ds=%x es=%x di=%x si=%x\n",
(CARD16)regs->ax,(CARD16)regs->bx,(CARD16)regs->cx,(CARD16)regs->dx,
(CARD16)regs->ds,(CARD16)regs->es,(CARD16)regs->di,
(CARD16)regs->si);
}
static void
print_usage(void)
{
}
void
add_hlt(unsigned long val)
{
int i;
if (val < BIOS_MEM || (val > VRAM_START && val < (VRAM_START + VRAM_SIZE))
|| val >= SIZE) {
printf("address out of range\n");
return;
}
for (i=0; i<20; i++) {
if (hltp[i].address == 0) {
hltp[i].address = (void*)val;
break;
}
}
if (i == 20) printf("no more hltpoints available\n");
}
void
del_hlt(int val)
{
if (val == 21) { /* delete all */
int i;
printf("clearing all hltpoints\n");
for (i=0; i <20; i++)
hltp[i].address = NULL;
} else if (val >= 0 && val <20)
hltp[val].address = NULL;
else printf("hltpoint %i out of range: valid range 0-19\n",val);
}
void
list_hlt()
{
int i;
for (i=0; i<20; i++)
if (hltp[i].address)
printf("hltpoint[%i]: 0x%lx\n",i,(unsigned long)hltp[i].address);
}
static void
set_hlt(Bool set)
{
int i;
for (i=0; i<20; i++)
if (hltp[i].address) {
if (set) {
hltp[i].orgval = *(CARD8*)hltp[i].address;
*(CARD8*)hltp[i].address = 0xf4;
} else
*(CARD8*)hltp[i].address = hltp[i].orgval;
}
}
static void
set_ioperm(void)
{
int i, start;
ioperm(0,IOPERM_BITS,0);
for (i = 0; i < IOPERM_BITS;i++)
if (ioperm_list[i]) {
start = i;
for (;i < IOPERM_BITS; i++) {
if (!ioperm_list[i]) {
ioperm(start,i - start, 1);
break;
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?