⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v86.c

📁 AT91RM9200的完整启动代码:包括loader, boot及U-boot三部分均已编译通过!欢迎下载使用!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 "debug.h"#include <sys/vm86.h>#include <unistd.h>#include <errno.h>#include <asm/unistd.h>#include <stdio.h>#include <string.h>#include <signal.h>#include <setjmp.h>#include "v86bios.h"#include "AsmMacros.h"struct vm86_struct vm86s;static int vm86_GP_fault(void);static int vm86_do_int(int num);static void dump_code(void);static void dump_registers(void);static void stack_trace(void);static int vm86_rep(struct vm86_struct *ptr);#define CPU_REG(x) (vm86s.regs.##x)#define CPU_REG_LW(reg)      (*((CARD16 *)&CPU_REG(reg)))#define CPU_REG_HW(reg)      (*((CARD16 *)&CPU_REG(reg) + 1))#define CPU_REG_LB(reg)      (*(CARD8 *)&CPU_REG(e##reg))#define SEG_ADR(type, seg, reg)  type((CPU_REG_LW(seg) << 4) \                                      + CPU_REG_LW(e##reg))#define DF (1 << 10)struct pio P;voidsetup_io(void) {    if (!Config.PrintPort && !Config.IoStatistics) {    P.inb = (CARD8(*)(CARD16))inb;    P.inw = (CARD16(*)(CARD16))inw;    P.inl = (CARD32(*)(CARD16))inl;    P.outb = (void(*)(CARD16,CARD8))outb;    P.outw = (void(*)(CARD16,CARD16))outw;    P.outl = (void(*)(CARD16,CARD32))outl;    } else {    P.inb = p_inb;    P.inw = p_inw;    P.inl = p_inl;    P.outb = p_outb;    P.outw = p_outw;    P.outl = p_outl;    }}    static voidsetup_vm86(unsigned long bios_start, i86biosRegsPtr regs){    CARD32 eip;    CARD16 cs;        vm86s.flags = VM86_SCREEN_BITMAP;    vm86s.flags = 0;    vm86s.screen_bitmap = 0;    vm86s.cpu_type = CPU_586;    memset(&vm86s.int_revectored, 0xff,sizeof(vm86s.int_revectored)) ;    memset(&vm86s.int21_revectored, 0xff,sizeof(vm86s.int21_revectored)) ;    eip = bios_start & 0xFFFF;    cs = (bios_start & 0xFF0000) >> 4;        CPU_REG(eax) = regs->ax;    CPU_REG(ebx) = regs->bx;    CPU_REG(ecx) = regs->cx;    CPU_REG(edx) = regs->dx;    CPU_REG(esi) = 0;    CPU_REG(edi) = regs->di;    CPU_REG(ebp) = 0;    CPU_REG(eip) = eip;    CPU_REG(cs) = cs;                   CPU_REG(esp) = 0x100;    CPU_REG(ss) = 0x30;               /* This is the standard pc bios stack */    CPU_REG(es) = regs->es;    CPU_REG(ds) = 0x40;               /* standard pc ds */    CPU_REG(fs) = 0;    CPU_REG(gs) = 0;    CPU_REG(eflags) |= (VIF_MASK | VIP_MASK);}voidcollect_bios_regs(i86biosRegsPtr regs){    regs->ax = CPU_REG(eax);    regs->bx = CPU_REG(ebx);    regs->cx = CPU_REG(ecx);    regs->dx = CPU_REG(edx);    regs->es = CPU_REG(es);    regs->ds = CPU_REG(ds);    regs->di = CPU_REG(edi);    regs->si = CPU_REG(esi);}static intdo_vm86(void){    int retval;    #ifdef V86BIOS_DEBUG    dump_registers();#endif//    retval = SYS_vm86old(&vm86s);//    retval = syscall(SYS_vm86old,&vm86s);    retval = vm86_rep(&vm86s);        switch (VM86_TYPE(retval)) {    case VM86_UNKNOWN:        if (!vm86_GP_fault()) return 0;        break;    case VM86_STI:        fprintf(stderr,"vm86_sti :-((\n");        stack_trace();        dump_code();        return 0;    case VM86_INTx:        if (!vm86_do_int(VM86_ARG(retval))) {            fprintf(stderr,"\nUnknown vm86_int: %X\n\n",VM86_ARG(retval));            dump_registers();            return 0;        }        /* I'm not sure yet what to do if we can handle ints */        break;    case VM86_SIGNAL:        fprintf(stderr,"received signal\n");        return 0;    default:        fprintf(stderr,"unknown type(0x%x)=0x%x\n",                VM86_ARG(retval),VM86_TYPE(retval));        dump_registers();        dump_code();        stack_trace();        return 0;    }        return 1;}static jmp_buf x86_esc;static voidvmexit(int unused){    longjmp(x86_esc,1);}voiddo_x86(unsigned long bios_start, i86biosRegsPtr regs){    static void (*org_handler)(int);        setup_vm86(bios_start, regs);    if (setjmp(x86_esc) == 0) {        org_handler = signal(2,vmexit);        while(do_vm86()) {};        signal(2,org_handler);        collect_bios_regs(regs);    } else {        signal(2,org_handler);        printf("interrupted at 0x%x\n",((CARD16)CPU_REG(cs)) << 4           | (CARD16)CPU_REG(eip));    }}/* get the linear address */#define LIN_PREF_SI  ((pref_seg << 4) + CPU_REG_LW(esi))#define LWECX       (prefix66 ^ prefix67 ? CPU_REG(ecx) : CPU_REG_LW(ecx))static intvm86_GP_fault(void){    unsigned char *csp, *lina;    CARD32 org_eip;    int pref_seg;    int done,is_rep,prefix66,prefix67;    csp = lina = SEG_ADR((unsigned char *), cs, ip);#ifdef V86BIOS_DEBUG    printf("exception: \n");    dump_code();#endif    is_rep = 0;    prefix66 = prefix67 = 0;    pref_seg = -1;    /* eat up prefixes */    done = 0;    do {        switch (*(csp++)) {        case 0x66:      /* operand prefix */  prefix66=1; break;        case 0x67:      /* address prefix */  prefix67=1; break;        case 0x2e:      /* CS */              pref_seg=CPU_REG(cs); break;        case 0x3e:      /* DS */              pref_seg=CPU_REG(ds); break;        case 0x26:      /* ES */              pref_seg=CPU_REG(es); break;        case 0x36:      /* SS */              pref_seg=CPU_REG(ss); break;        case 0x65:      /* GS */              pref_seg=CPU_REG(gs); break;        case 0x64:      /* FS */              pref_seg=CPU_REG(fs); break;        case 0xf2:      /* repnz */        case 0xf3:      /* rep */             is_rep=1; break;        default: done=1;        }    } while (!done);    csp--;   /* oops one too many */    org_eip = CPU_REG(eip);    CPU_REG_LW(eip) += (csp - lina);    switch (*csp) {    case 0x6c:                    /* insb */        /* NOTE: ES can't be overwritten; prefixes 66,67 should use esi,edi,ecx         * but is anyone using extended regs in real mode? */        /* WARNING: no test for DI wrapping! */        CPU_REG_LW(edi) += port_rep_inb(CPU_REG_LW(edx),                                         SEG_ADR((CARD8 *),es,di),                                        CPU_REG_LW(eflags)&DF,                                        (is_rep? LWECX:1));        if (is_rep) LWECX = 0;        CPU_REG_LW(eip)++;        break;    case 0x6d:                  /* (rep) insw / insd */        /* NOTE: ES can't be overwritten */        /* WARNING: no test for _DI wrapping! */        if (prefix66) {            CPU_REG_LW(edi) += port_rep_inl(CPU_REG_LW(edx),                                            SEG_ADR((CARD32 *),es,di),                                            CPU_REG_LW(eflags)&DF,                                            (is_rep? LWECX:1));        }        else {            CPU_REG_LW(edi) += port_rep_inw(CPU_REG_LW(edx),                                             SEG_ADR((CARD16 *),es,di),                                            CPU_REG_LW(eflags)&DF,                                            (is_rep? LWECX:1));        }        if (is_rep) LWECX = 0;        CPU_REG_LW(eip)++;        break;    case 0x6e:                  /* (rep) outsb */        if (pref_seg < 0) pref_seg = CPU_REG_LW(ds);        /* WARNING: no test for _SI wrapping! */        CPU_REG_LW(esi) += port_rep_outb(CPU_REG_LW(edx),(CARD8*)LIN_PREF_SI,                                         CPU_REG_LW(eflags)&DF,                                         (is_rep? LWECX:1));        if (is_rep) LWECX = 0;        CPU_REG_LW(eip)++;        break;    case 0x6f:                  /* (rep) outsw / outsd */        if (pref_seg < 0) pref_seg = CPU_REG_LW(ds);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -