pm.c

来自「适合KS8695X」· C语言 代码 · 共 1,810 行 · 第 1/4 页

C
1,810
字号
	    break;
	    }
	else
	    return 0;
	}

    context.vm.regs.eip += i;
    return 1;
}

static void debug_info(int vret)
{
    int i;
    unsigned char *p;

    fputs("vm86() failed\n", stderr);
    fprintf(stderr, "return = 0x%x\n", vret);
    fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax);
    fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx);
    fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx);
    fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx);
    fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi);
    fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi);
    fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp);
    fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip);
    fprintf(stderr, "cs  = 0x%04x\n", context.vm.regs.cs);
    fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp);
    fprintf(stderr, "ss  = 0x%04x\n", context.vm.regs.ss);
    fprintf(stderr, "ds  = 0x%04x\n", context.vm.regs.ds);
    fprintf(stderr, "es  = 0x%04x\n", context.vm.regs.es);
    fprintf(stderr, "fs  = 0x%04x\n", context.vm.regs.fs);
    fprintf(stderr, "gs  = 0x%04x\n", context.vm.regs.gs);
    fprintf(stderr, "eflags  = 0x%08lx\n", context.vm.regs.eflags);
    fputs("cs:ip = [ ", stderr);
    p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff));
    for (i = 0; i < 16; ++i)
	    fprintf(stderr, "%02x ", (unsigned int)p[i]);
    fputs("]\n", stderr);
    fflush(stderr);
}

static int run_vm86(void)
{
    unsigned int vret;

    for (;;) {
	vret = vm86(&context.vm);
	if (VM86_TYPE(vret) == VM86_INTx) {
	    unsigned int v = VM86_ARG(vret);
	    if (v == RETURN_TO_32_INT)
		return 1;
	    pushw(context.vm.regs.eflags);
	    pushw(context.vm.regs.cs);
	    pushw(context.vm.regs.eip);
	    context.vm.regs.cs = get_int_seg(v);
	    context.vm.regs.eip = get_int_off(v);
	    context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK);
	    continue;
	    }
	if (VM86_TYPE(vret) != VM86_UNKNOWN)
	    break;
	if (!emulate())
	    break;
	}
    debug_info(vret);
    return 0;
}

#define IND(ereg) context.vm.regs.ereg = regs->ereg
#define OUTD(ereg) regs->ereg = context.vm.regs.ereg

void PMAPI DPMI_int86(int intno, DPMI_regs *regs)
{
    if (!inited)
	PM_init();
    memset(&context.vm.regs, 0, sizeof(context.vm.regs));
    IND(eax); IND(ebx); IND(ecx); IND(edx); IND(esi); IND(edi);
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = get_int_seg(intno);
    context.vm.regs.eip = get_int_off(intno);
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
    OUTD(eax); OUTD(ebx); OUTD(ecx); OUTD(edx); OUTD(esi); OUTD(edi);
    regs->flags = context.vm.regs.eflags;
}

#define IN(ereg) context.vm.regs.ereg = in->e.ereg
#define OUT(ereg) out->e.ereg = context.vm.regs.ereg

int PMAPI PM_int86(int intno, RMREGS *in, RMREGS *out)
{
    if (!inited)
	PM_init();
    memset(&context.vm.regs, 0, sizeof(context.vm.regs));
    IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = get_int_seg(intno);
    context.vm.regs.eip = get_int_off(intno);
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
    OUT(eax); OUT(ebx); OUT(ecx); OUT(edx); OUT(esi); OUT(edi);
    out->x.cflag = context.vm.regs.eflags & 1;
    return out->x.ax;
}

int PMAPI PM_int86x(int intno, RMREGS *in, RMREGS *out,
    RMSREGS *sregs)
{
    if (!inited)
	PM_init();
    if (intno == 0x21) {
	time_t today = time(NULL);
	struct tm *t;
	t = localtime(&today);
	out->x.cx = t->tm_year + 1900;
	out->h.dh = t->tm_mon + 1;
	out->h.dl = t->tm_mday;
	}
    else {
	unsigned int seg, off;
	seg = get_int_seg(intno);
	off = get_int_off(intno);
	memset(&context.vm.regs, 0, sizeof(context.vm.regs));
	IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);
	context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
	context.vm.regs.cs = seg;
	context.vm.regs.eip = off;
	context.vm.regs.es = sregs->es;
	context.vm.regs.ds = sregs->ds;
	context.vm.regs.fs = sregs->fs;
	context.vm.regs.gs = sregs->gs;
	context.vm.regs.ss = context.stack_seg;
	context.vm.regs.esp = context.stack_off;
	pushw(DEFAULT_VM86_FLAGS);
	pushw(context.ret_seg);
	pushw(context.ret_off);
	run_vm86();
	OUT(eax); OUT(ebx); OUT(ecx); OUT(edx); OUT(esi); OUT(edi);
	sregs->es = context.vm.regs.es;
	sregs->ds = context.vm.regs.ds;
	sregs->fs = context.vm.regs.fs;
	sregs->gs = context.vm.regs.gs;
	out->x.cflag = context.vm.regs.eflags & 1;
	}
    return out->e.eax;
}

#define OUTR(ereg) in->e.ereg = context.vm.regs.ereg

void PMAPI PM_callRealMode(uint seg,uint off, RMREGS *in,
    RMSREGS *sregs)
{
    if (!inited)
	PM_init();
    memset(&context.vm.regs, 0, sizeof(context.vm.regs));
    IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = seg;
    context.vm.regs.eip = off;
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    context.vm.regs.es = sregs->es;
    context.vm.regs.ds = sregs->ds;
    context.vm.regs.fs = sregs->fs;
    context.vm.regs.gs = sregs->gs;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
    OUTR(eax); OUTR(ebx); OUTR(ecx); OUTR(edx); OUTR(esi); OUTR(edi);
    sregs->es = context.vm.regs.es;
    sregs->ds = context.vm.regs.ds;
    sregs->fs = context.vm.regs.fs;
    sregs->gs = context.vm.regs.gs;
    in->x.cflag = context.vm.regs.eflags & 1;
}

void PMAPI PM_availableMemory(ulong *physical,ulong *total)
{
    FILE    *mem = fopen("/proc/meminfo","r");
    char    buf[1024];

    fgets(buf,1024,mem);
    fgets(buf,1024,mem);
    sscanf(buf,"Mem: %*d %*d %ld", physical);
    fgets(buf,1024,mem);
    sscanf(buf,"Swap: %*d %*d %ld", total);
    fclose(mem);
    *total += *physical;
}

void * PMAPI PM_allocLockedMem(uint size,ulong *physAddr,ibool contiguous,ibool below16M)
{
    /* TODO: Implement this for Linux */
    return NULL;
}

void PMAPI PM_freeLockedMem(void *p,uint size,ibool contiguous)
{
    /* TODO: Implement this for Linux */
}

void * PMAPI PM_allocPage(
    ibool locked)
{
    /* TODO: Implement this for Linux */
    return NULL;
}

void PMAPI PM_freePage(
    void *p)
{
    /* TODO: Implement this for Linux */
}

void PMAPI PM_setBankA(int bank)
{
    if (!inited)
	PM_init();
    memset(&context.vm.regs, 0, sizeof(context.vm.regs));
    context.vm.regs.eax = 0x4F05;
    context.vm.regs.ebx = 0x0000;
    context.vm.regs.edx = bank;
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = get_int_seg(0x10);
    context.vm.regs.eip = get_int_off(0x10);
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
}

void PMAPI PM_setBankAB(int bank)
{
    if (!inited)
	PM_init();
    memset(&context.vm.regs, 0, sizeof(context.vm.regs));
    context.vm.regs.eax = 0x4F05;
    context.vm.regs.ebx = 0x0000;
    context.vm.regs.edx = bank;
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = get_int_seg(0x10);
    context.vm.regs.eip = get_int_off(0x10);
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
    context.vm.regs.eax = 0x4F05;
    context.vm.regs.ebx = 0x0001;
    context.vm.regs.edx = bank;
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = get_int_seg(0x10);
    context.vm.regs.eip = get_int_off(0x10);
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
}

void PMAPI PM_setCRTStart(int x,int y,int waitVRT)
{
    if (!inited)
	PM_init();
    memset(&context.vm.regs, 0, sizeof(context.vm.regs));
    context.vm.regs.eax = 0x4F07;
    context.vm.regs.ebx = waitVRT;
    context.vm.regs.ecx = x;
    context.vm.regs.edx = y;
    context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
    context.vm.regs.cs = get_int_seg(0x10);
    context.vm.regs.eip = get_int_off(0x10);
    context.vm.regs.ss = context.stack_seg;
    context.vm.regs.esp = context.stack_off;
    pushw(DEFAULT_VM86_FLAGS);
    pushw(context.ret_seg);
    pushw(context.ret_off);
    run_vm86();
}

int PMAPI PM_enableWriteCombine(ulong base,ulong length,uint type)
{
#ifdef ENABLE_MTRR
    struct mtrr_sentry sentry;

    if (mtrr_fd < 0)
	return PM_MTRR_ERR_NO_OS_SUPPORT;
    sentry.base = base;
    sentry.size = length;
    sentry.type = type;
    if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &sentry) == -1) {
	/* TODO: Need to decode MTRR error codes!! */
	return PM_MTRR_NOT_SUPPORTED;
	}
    return PM_MTRR_ERR_OK;
#else
    return PM_MTRR_ERR_NO_OS_SUPPORT;
#endif
}

/****************************************************************************
PARAMETERS:
callback    - Function to callback with write combine information

REMARKS:
Function to enumerate all write combine regions currently enabled for the
processor.
****************************************************************************/
int PMAPI PM_enumWriteCombine(
    PM_enumWriteCombine_t callback)
{
#ifdef ENABLE_MTRR
    struct mtrr_gentry gentry;

    if (mtrr_fd < 0)
	return PM_MTRR_ERR_NO_OS_SUPPORT;

    for (gentry.regnum = 0; ioctl (mtrr_fd, MTRRIOC_GET_ENTRY, &gentry) == 0;
	 ++gentry.regnum) {
	if (gentry.size > 0) {
	    /* WARNING: This code assumes that the types in pmapi.h match the ones */
	    /* in the Linux kernel (mtrr.h) */
	    callback(gentry.base, gentry.size, gentry.type);
	}
    }

    return PM_MTRR_ERR_OK;
#else
    return PM_MTRR_ERR_NO_OS_SUPPORT;
#endif
}

ibool PMAPI PM_doBIOSPOST(
    ushort axVal,
    ulong BIOSPhysAddr,
    void *copyOfBIOS,
    ulong BIOSLen)
{
    char        *bios_ptr = (char*)0xC0000;
    char        *old_bios;
    ulong       Current10, Current6D, *rvec = 0;
    RMREGS      regs;
    RMSREGS     sregs;

    /* The BIOS is mapped to 0xC0000 with a private memory mapping enabled
     * which means we have a copy on write scheme. Hence we simply copy
     * the secondary BIOS image over the top of the old one.
     */
    if (!inited)
	PM_init();
    if ((old_bios = PM_malloc(BIOSLen)) == NULL)
	return false;
    if (BIOSPhysAddr != 0xC0000) {
	memcpy(old_bios,bios_ptr,BIOSLen);
	memcpy(bios_ptr,copyOfBIOS,BIOSLen);
	}

    /* The interrupt vectors should already be mmap()'ed from 0-0x400 in PM_init */
    Current10 = rvec[0x10];
    Current6D = rvec[0x6D];

    /* POST the secondary BIOS */
    rvec[0x10] = rvec[0x42]; /* Restore int 10h to STD-BIOS */
    regs.x.ax = axVal;
    PM_callRealMode(0xC000,0x0003,&regs,&sregs);

    /* Restore interrupt vectors */
    rvec[0x10] = Current10;
    rvec[0x6D] = Current6D;

    /* Restore original BIOS image */
    if (BIOSPhysAddr != 0xC0000)
	memcpy(bios_ptr,old_bios,BIOSLen);
    PM_free(old_bios);
    return true;
}

int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
{
    p = p;  len = len;
    return 1;
}

int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
{
    p = p;  len = len;
    return 1;
}

int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
{
    p = p;  len = len;
    return 1;
}

int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
{
    p = p;  len = len;
    return 1;
}

PM_MODULE PMAPI PM_loadLibrary(
    const char *szDLLName)
{
    /* TODO: Implement this to load shared libraries! */
    (void)szDLLName;
    return NULL;
}

void * PMAPI PM_getProcAddress(
    PM_MODULE hModule,
    const char *szProcName)
{
    /* TODO: Implement this! */
    (void)hModule;
    (void)szProcName;
    return NULL;
}

void PMAPI PM_freeLibrary(
    PM_MODULE hModule)
{
    /* TODO: Implement this! */
    (void)hModule;
}

int PMAPI PM_setIOPL(
    int level)
{
    /* TODO: Move the IOPL switching into this function!! */
    return level;
}

void PMAPI PM_flushTLB(void)
{
    /* Do nothing on Linux. */
}

⌨️ 快捷键说明

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