123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755 |
- /*
- *
- * Copyright © 2000 Keith Packard
- *
- * 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 Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD 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.
- */
- /*
- Copyright (c) 2000 by Juliusz Chroboczek
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #ifdef HAVE_CONFIG_H
- #include <kdrive-config.h>
- #endif
- #include "vm86.h"
- #define PUSHW(vi, i) \
- { vi->vms.regs.esp -= 2;\
- LMW(vi,MAKE_POINTER(vi->vms.regs.ss, vi->vms.regs.esp)) = i;}
- static int vm86old(struct vm86_struct *vms);
- static int vm86_loop(Vm86InfoPtr vi);
- static const U8 rev_ints[32] = { 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0x80,
- };
- static const U8 retcode_data[2] = { 0xCD, 0xFF };
- Vm86InfoPtr Vm86Setup(int mapHoles)
- {
- int devmem = -1, devzero = -1;
- void *magicMem, *loMem, *hiMem;
- void *hole1, *hole2;
- U32 stack_base, ret_code;
- Vm86InfoPtr vi = NULL;
- devmem = open("/dev/mem", O_RDWR);
- if (devmem < 0) {
- perror("open /dev/mem");
- goto fail;
- }
- devzero = open("/dev/zero", O_RDWR);
- if (devzero < 0) {
- perror("open /dev/zero");
- goto fail;
- }
- loMem = MAP_FAILED;
- hiMem = MAP_FAILED;
- hole1 = MAP_FAILED;
- hole2 = MAP_FAILED;
- magicMem = mmap((void *)MAGICMEM_BASE, MAGICMEM_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_FIXED, devmem, MAGICMEM_BASE);
- if (magicMem == MAP_FAILED) {
- ErrorF("Couldn't map magic memory\n");
- goto unmapfail;
- }
- if (mapHoles) {
- hole1 = mmap((void *)HOLE1_BASE, HOLE1_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_FIXED, devzero, HOLE1_BASE);
- if (hole1 == MAP_FAILED) {
- ErrorF("Couldn't map first hole\n");
- goto unmapfail;
- }
- }
- loMem = mmap((void *)LOMEM_BASE, LOMEM_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_FIXED, devzero, LOMEM_BASE);
- if (loMem == MAP_FAILED) {
- ErrorF("Couldn't map low memory\n");
- munmap(magicMem, MAGICMEM_SIZE);
- goto unmapfail;
- }
- if (mapHoles) {
- hole2 = mmap((void *)HOLE2_BASE, HOLE2_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_FIXED, devzero, HOLE2_BASE);
- if (hole2 == MAP_FAILED) {
- ErrorF("Couldn't map first hole\n");
- goto unmapfail;
- }
- }
- hiMem = mmap((void *)HIMEM_BASE, HIMEM_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_SHARED | MAP_FIXED, devmem, HIMEM_BASE);
- if (hiMem == MAP_FAILED) {
- ErrorF("Couldn't map high memory\n");
- goto unmapfail;
- }
- vi = malloc(sizeof(Vm86InfoRec));
- if (!vi)
- goto unmapfail;
- vi->magicMem = magicMem;
- vi->hole1 = hole1;
- vi->loMem = loMem;
- vi->hole2 = hole2;
- vi->hiMem = hiMem;
- vi->brk = LOMEM_BASE;
- stack_base = Vm86AllocateMemory(vi, STACK_SIZE);
- if (stack_base == ALLOC_FAIL)
- goto unmapfail;
- ret_code = Vm86AllocateMemory(vi, sizeof(retcode_data));
- if (ret_code == ALLOC_FAIL)
- goto unmapfail;
- vi->stack_base = stack_base;
- vi->ret_code = ret_code;
- memset(&vi->vms, 0, sizeof(struct vm86_struct));
- vi->vms.flags = 0;
- vi->vms.screen_bitmap = 0;
- vi->vms.cpu_type = CPU_586;
- memcpy(&vi->vms.int_revectored, rev_ints, sizeof(rev_ints));
- iopl(3);
- if (devmem >= 0)
- close(devmem);
- if (devzero >= 0)
- close(devzero);
- return vi;
- unmapfail:
- if (magicMem != MAP_FAILED)
- munmap(magicMem, MAGICMEM_SIZE);
- if (hole1 != MAP_FAILED)
- munmap(hole1, HOLE1_SIZE);
- if (loMem != MAP_FAILED)
- munmap(loMem, LOMEM_SIZE);
- if (hole2 != MAP_FAILED)
- munmap(hole2, HOLE2_SIZE);
- if (hiMem != MAP_FAILED)
- munmap(hiMem, HIMEM_SIZE);
- fail:
- if (devmem >= 0)
- close(devmem);
- if (devzero >= 0)
- close(devzero);
- if (vi)
- free(vi);
- return NULL;
- }
- void Vm86Cleanup(Vm86InfoPtr vi)
- {
- if (vi->magicMem != MAP_FAILED)
- munmap(vi->magicMem, MAGICMEM_SIZE);
- if (vi->hole1 != MAP_FAILED)
- munmap(vi->hole1, HOLE1_SIZE);
- if (vi->loMem != MAP_FAILED)
- munmap(vi->loMem, LOMEM_SIZE);
- if (vi->hole2 != MAP_FAILED)
- munmap(vi->hole2, HOLE2_SIZE);
- if (vi->hiMem != MAP_FAILED)
- munmap(vi->hiMem, HIMEM_SIZE);
- free(vi);
- }
- int Vm86DoInterrupt(Vm86InfoPtr vi, int num)
- {
- U16 seg, off;
- int code;
- if (num < 0 || num > 256) {
- ErrorF("Interrupt %d doesn't exist\n", num);
- return -1;
- }
- seg = MMW(vi, num * 4 + 2);
- off = MMW(vi, num * 4);
- if (MAKE_POINTER(seg, off) < ROM_BASE ||
- MAKE_POINTER(seg, off) >= ROM_BASE + ROM_SIZE) {
- ErrorF
- ("Interrupt pointer (seg %x off %x) doesn't point at ROM\n",
- seg, off);
- return -1;
- }
- memcpy(&(LM(vi, vi->ret_code)), retcode_data, sizeof(retcode_data));
- vi->vms.regs.eflags = IF_MASK | IOPL_MASK;
- vi->vms.regs.ss = POINTER_SEGMENT(vi->stack_base);
- vi->vms.regs.esp = STACK_SIZE;
- PUSHW(vi, IF_MASK | IOPL_MASK);
- PUSHW(vi, POINTER_SEGMENT(vi->ret_code));
- PUSHW(vi, POINTER_OFFSET(vi->ret_code));
- vi->vms.regs.cs = seg;
- vi->vms.regs.eip = off;
- OsBlockSignals();
- code = vm86_loop(vi);
- OsReleaseSignals();
- if (code < 0) {
- ErrorF("vm86 failed (errno %d)\n", errno);
- return -1;
- } else if (code != 0) {
- ErrorF("vm86 returned 0x%04X\n", code);
- return -1;
- } else
- return 0;
- }
- int Vm86DoPOST(Vm86InfoPtr vi)
- {
- U16 seg, off;
- int code;
- seg = 0xC000;
- off = 3;
- if (MAKE_POINTER(seg, off) < ROM_BASE ||
- MAKE_POINTER(seg, off) >= ROM_BASE + ROM_SIZE) {
- ErrorF("BIOS pointer (seg %x off %x) doesn't point at ROM\n",
- seg, off);
- return -1;
- }
- memcpy(&(LM(vi, vi->ret_code)), retcode_data, sizeof(retcode_data));
- vi->vms.regs.ss = POINTER_SEGMENT(vi->stack_base);
- vi->vms.regs.esp = STACK_SIZE;
- PUSHW(vi, POINTER_SEGMENT(vi->ret_code));
- PUSHW(vi, POINTER_OFFSET(vi->ret_code));
- vi->vms.regs.cs = seg;
- vi->vms.regs.eip = off;
- OsBlockSignals();
- code = vm86_loop(vi);
- OsReleaseSignals();
- if (code < 0) {
- ErrorF("vm86 failed (errno %d)\n", errno);
- return -1;
- } else if (code != 0) {
- ErrorF("vm86 returned 0x%04X\n", code);
- return -1;
- } else
- return 0;
- }
- #define DEBUG_VBE 0
- #if DEBUG_VBE
- #define DBG(x) ErrorF x; usleep(10*1000)
- #else
- #define DBG(x)
- #endif
- static inline U8 vm86_inb(U16 port)
- {
- U8 value;
- if (port != 0x3da) {
- DBG(("inb 0x%04x", port));
- }
- asm volatile ("inb %w1,%b0":"=a" (value):"d"(port));
- if (port != 0x3da) {
- DBG((" = 0x%02x\n", value));
- }
- return value;
- }
- static inline U16 vm86_inw(U16 port)
- {
- U16 value;
- DBG(("inw 0x%04x", port));
- asm volatile ("inw %w1,%w0":"=a" (value):"d"(port));
- DBG((" = 0x%04x\n", value));
- return value;
- }
- static inline U32 vm86_inl(U16 port)
- {
- U32 value;
- DBG(("inl 0x%04x", port));
- asm volatile ("inl %w1,%0":"=a" (value):"d"(port));
- DBG((" = 0x%08x\n", value));
- return value;
- }
- static inline void vm86_outb(U16 port, U8 value)
- {
- #if 0
- static U8 CR;
- if (port == 0x3d4)
- CR = value;
- if (port == 0x3d5 && CR == 0xa4) {
- DBG(("outb 0x%04x = 0x%02x (skipped)\n", port, value));
- return;
- }
- #endif
- DBG(("outb 0x%04x = 0x%02x\n", port, value));
- asm volatile ("outb %b0,%w1"::"a" (value), "d"(port));
- }
- static inline void vm86_outw(U16 port, U16 value)
- {
- DBG(("outw 0x%04x = 0x%04x\n", port, value));
- asm volatile ("outw %w0,%w1"::"a" (value), "d"(port));
- }
- static inline void vm86_outl(U16 port, U32 value)
- {
- DBG(("outl 0x%04x = 0x%08x\n", port, value));
- asm volatile ("outl %0,%w1"::"a" (value), "d"(port));
- }
- #define SEG_CS 1
- #define SEG_DS 2
- #define SEG_ES 3
- #define SEG_SS 4
- #define SEG_GS 5
- #define SEG_FS 6
- #define REP 1
- #define REPNZ 2
- #define SET_8(_x, _y) (_x) = ((_x) & ~0xFF) | ((_y) & 0xFF);
- #define SET_16(_x, _y) (_x) = ((_x) & ~0xFFFF) | ((_y) & 0xFFFF);
- #define INC_IP(_i) SET_16(regs->eip, (regs->eip + _i))
- #define AGAIN INC_IP(1); goto again;
- static int Vm86IsMemory(Vm86InfoPtr vi, U32 i)
- {
- if (i >= MAGICMEM_BASE && i < MAGICMEM_BASE + MAGICMEM_SIZE)
- return 1;
- else if (i >= LOMEM_BASE && i < LOMEM_BASE + LOMEM_SIZE)
- return 1;
- else if (i >= HIMEM_BASE && i < HIMEM_BASE + HIMEM_SIZE)
- return 1;
- else
- return 0;
- }
- static void Vm86WriteMemory(Vm86InfoPtr vi, U32 i, U8 val)
- {
- if (i >= MAGICMEM_BASE && i < MAGICMEM_BASE + MAGICMEM_SIZE)
- MM(vi, i) = val;
- else if (i >= LOMEM_BASE && i < LOMEM_BASE + LOMEM_SIZE)
- LM(vi, i) = val;
- else if (i >= HIMEM_BASE && i < HIMEM_BASE + HIMEM_SIZE)
- HM(vi, i) = val;
- else {
- ErrorF("Writing unmapped memory at 0x%08X\n", i);
- }
- }
- static void Vm86WriteMemoryW(Vm86InfoPtr vi, U32 i, U16 val)
- {
- if (i >= MAGICMEM_BASE && i < MAGICMEM_BASE + MAGICMEM_SIZE)
- MMW(vi, i) = val;
- else if (i >= LOMEM_BASE && i < LOMEM_BASE + LOMEM_SIZE)
- LMW(vi, i) = val;
- else if (i >= HIMEM_BASE && i < HIMEM_BASE + HIMEM_SIZE)
- HMW(vi, i) = val;
- else {
- ErrorF("Writing unmapped memory at 0x%08X\n", i);
- }
- }
- static void Vm86WriteMemoryL(Vm86InfoPtr vi, U32 i, U32 val)
- {
- if (i >= MAGICMEM_BASE && i < MAGICMEM_BASE + MAGICMEM_SIZE)
- MML(vi, i) = val;
- else if (i >= LOMEM_BASE && i < LOMEM_BASE + LOMEM_SIZE)
- LML(vi, i) = val;
- else if (i >= HIMEM_BASE && i < HIMEM_BASE + HIMEM_SIZE)
- HML(vi, i) = val;
- else {
- ErrorF("Writing unmapped memory at 0x%08X\n", i);
- }
- }
- static int vm86_emulate(Vm86InfoPtr vi)
- {
- struct vm86_regs *regs = &vi->vms.regs;
- U8 opcode;
- int size;
- int pref_seg _X_UNUSED = 0, pref_rep = 0, pref_66 = 0;
- again:
- if (!Vm86IsMemory(vi, MAKE_POINTER(regs->cs, regs->eip))) {
- ErrorF("Trying to execute unmapped memory\n");
- return -1;
- }
- opcode = Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip));
- switch (opcode) {
- case 0x2E:
- pref_seg = SEG_CS;
- AGAIN;
- case 0x3E:
- pref_seg = SEG_DS;
- AGAIN;
- case 0x26:
- pref_seg = SEG_ES;
- AGAIN;
- case 0x36:
- pref_seg = SEG_SS;
- AGAIN;
- case 0x65:
- pref_seg = SEG_GS;
- AGAIN;
- case 0x64:
- pref_seg = SEG_FS;
- AGAIN;
- case 0x66:
- pref_66 = 1;
- AGAIN;
- case 0x67:
- // pref_67 = 1;
- AGAIN;
- case 0xF2:
- pref_rep = REPNZ;
- AGAIN;
- case 0xF3:
- pref_rep = REP;
- AGAIN;
- case 0xEC: /* IN AL, DX */
- SET_8(regs->eax, vm86_inb(regs->edx & 0xFFFF));
- INC_IP(1);
- break;
- case 0xED: /* IN AX, DX */
- if (pref_66)
- regs->eax = vm86_inl(regs->edx & 0xFFFF);
- else
- SET_16(regs->eax, vm86_inw(regs->edx & 0xFFFF));
- INC_IP(1);
- break;
- case 0xE4: /* IN AL, imm8 */
- SET_8(regs->eax,
- vm86_inb(Vm86Memory
- (vi, MAKE_POINTER(regs->cs, regs->eip + 1))));
- INC_IP(2);
- break;
- case 0xE5: /* IN AX, imm8 */
- if (pref_66)
- regs->eax =
- vm86_inl(Vm86Memory
- (vi,
- MAKE_POINTER(regs->cs, regs->eip + 1)));
- else
- SET_16(regs->eax,
- vm86_inw(Vm86Memory
- (vi,
- MAKE_POINTER(regs->cs,
- regs->eip + 1))));
- INC_IP(2);
- break;
- case 0x6C: /* INSB */
- case 0x6D: /* INSW */
- if (opcode == 0x6C) {
- Vm86WriteMemory(vi, MAKE_POINTER(regs->es, regs->edi),
- vm86_inb(regs->edx & 0xFFFF));
- size = 1;
- } else if (pref_66) {
- Vm86WriteMemoryL(vi, MAKE_POINTER(regs->es, regs->edi),
- vm86_inl(regs->edx & 0xFFFF));
- size = 4;
- } else {
- Vm86WriteMemoryW(vi, MAKE_POINTER(regs->es, regs->edi),
- vm86_inw(regs->edx & 0xFFFF));
- size = 2;
- }
- if (regs->eflags & (1 << 10))
- regs->edi -= size;
- else
- regs->edi += size;
- if (pref_rep) {
- if (pref_66) {
- regs->ecx--;
- if (regs->ecx != 0)
- goto again;
- } else {
- SET_16(regs->ecx, regs->ecx - 1);
- if ((regs->ecx & 0xFFFF) != 0)
- goto again;
- }
- }
- INC_IP(1);
- break;
- case 0xEE: /* OUT DX, AL */
- vm86_outb(regs->edx & 0xFFFF, regs->eax & 0xFF);
- INC_IP(1);
- break;
- case 0xEF: /* OUT DX, AX */
- if (pref_66)
- vm86_outl(regs->edx & 0xFFFF, regs->eax);
- else
- vm86_outw(regs->edx & 0xFFFF, regs->eax & 0xFFFF);
- INC_IP(1);
- break;
- case 0xE6: /* OUT imm8, AL */
- vm86_outb(Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip + 1)),
- regs->eax & 0xFF);
- INC_IP(2);
- break;
- case 0xE7: /* OUT imm8, AX */
- if (pref_66)
- vm86_outl(Vm86Memory
- (vi, MAKE_POINTER(regs->cs, regs->eip + 1)),
- regs->eax);
- else
- vm86_outw(Vm86Memory
- (vi, MAKE_POINTER(regs->cs, regs->eip + 1)),
- regs->eax & 0xFFFF);
- INC_IP(2);
- break;
- case 0x6E: /* OUTSB */
- case 0x6F: /* OUTSW */
- if (opcode == 0x6E) {
- vm86_outb(regs->edx & 0xFFFF,
- Vm86Memory(vi,
- MAKE_POINTER(regs->es,
- regs->edi)));
- size = 1;
- } else if (pref_66) {
- vm86_outl(regs->edx & 0xFFFF,
- Vm86Memory(vi,
- MAKE_POINTER(regs->es,
- regs->edi)));
- size = 4;
- } else {
- vm86_outw(regs->edx & 0xFFFF,
- Vm86Memory(vi,
- MAKE_POINTER(regs->es,
- regs->edi)));
- size = 2;
- }
- if (regs->eflags & (1 << 10))
- regs->edi -= size;
- else
- regs->edi += size;
- if (pref_rep) {
- if (pref_66) {
- regs->ecx--;
- if (regs->ecx != 0)
- goto again;
- } else {
- SET_16(regs->ecx, regs->ecx - 1);
- if ((regs->ecx & 0xFFFF) != 0)
- goto again;
- }
- }
- INC_IP(1);
- break;
- case 0x0F:
- ErrorF("Hit 0F trap in VM86 code\n");
- return -1;
- case 0xF0:
- ErrorF("Hit lock prefix in VM86 code\n");
- return -1;
- case 0xF4:
- ErrorF("Hit HLT in VM86 code\n");
- return -1;
- default:
- ErrorF("Unhandled GP fault in VM86 code (opcode = 0x%02X)\n",
- opcode);
- return -1;
- }
- return 0;
- }
- #undef SEG_CS
- #undef SEG_DS
- #undef SEG_ES
- #undef SEG_SS
- #undef SEG_GS
- #undef SEG_FS
- #undef REP
- #undef REPNZ
- #undef SET_8
- #undef SET_16
- #undef INC_IP
- #undef AGAIN
- static void Vm86Debug(Vm86InfoPtr vi)
- {
- struct vm86_regs *regs = &vi->vms.regs;
- int i;
- ErrorF("eax=0x%08lX ebx=0x%08lX ecx=0x%08lX edx=0x%08lX\n",
- regs->eax, regs->ebx, regs->ecx, regs->edx);
- ErrorF("esi=0x%08lX edi=0x%08lX ebp=0x%08lX\n",
- regs->esi, regs->edi, regs->ebp);
- ErrorF("eip=0x%08lX esp=0x%08lX eflags=0x%08lX\n",
- regs->eip, regs->esp, regs->eflags);
- ErrorF
- ("cs=0x%04X ds=0x%04X es=0x%04X fs=0x%04X gs=0x%04X\n",
- regs->cs, regs->ds, regs->es, regs->fs, regs->gs);
- for (i = -7; i < 8; i++) {
- ErrorF(" %s%02X",
- i == 0 ? "->" : "",
- Vm86Memory(vi, MAKE_POINTER(regs->cs, regs->eip + i)));
- }
- ErrorF("\n");
- }
- static int vm86_loop(Vm86InfoPtr vi)
- {
- int code;
- while (1) {
- code = vm86old(&vi->vms);
- switch (VM86_TYPE(code)) {
- case VM86_SIGNAL:
- continue;
- case VM86_UNKNOWN:
- code = vm86_emulate(vi);
- if (code < 0) {
- Vm86Debug(vi);
- return -1;
- }
- break;
- case VM86_INTx:
- if (VM86_ARG(code) == 0xFF)
- return 0;
- else {
- PUSHW(vi, vi->vms.regs.eflags)
- PUSHW(vi, vi->vms.regs.cs);
- PUSHW(vi, vi->vms.regs.eip);
- vi->vms.regs.cs =
- MMW(vi, VM86_ARG(code) * 4 + 2);
- vi->vms.regs.eip = MMW(vi, VM86_ARG(code) * 4);
- }
- break;
- case VM86_STI:
- ErrorF("VM86 code enabled interrupts\n");
- Vm86Debug(vi);
- return -1;
- default:
- ErrorF("Unexpected result code 0x%X from vm86\n", code);
- Vm86Debug(vi);
- return -1;
- }
- }
- }
- U8 Vm86Memory(Vm86InfoPtr vi, U32 i)
- {
- if (i >= MAGICMEM_BASE && i < MAGICMEM_BASE + MAGICMEM_SIZE)
- return MM(vi, i);
- else if (i >= LOMEM_BASE && i < LOMEM_BASE + LOMEM_SIZE)
- return LM(vi, i);
- else if (i >= HIMEM_BASE && i < HIMEM_BASE + HIMEM_SIZE)
- return HM(vi, i);
- else {
- ErrorF("Reading unmapped memory at 0x%08X\n", i);
- return 0;
- }
- }
- U16 Vm86MemoryW(Vm86InfoPtr vi, U32 i)
- {
- if (i >= MAGICMEM_BASE && i < MAGICMEM_BASE + MAGICMEM_SIZE)
- return MMW(vi, i);
- else if (i >= LOMEM_BASE && i < LOMEM_BASE + LOMEM_SIZE)
- return LMW(vi, i);
- else if (i >= HIMEM_BASE && i < HIMEM_BASE + HIMEM_SIZE)
- return HMW(vi, i);
- else {
- ErrorF("Reading unmapped memory at 0x%08X\n", i);
- return 0;
- }
- }
- int Vm86AllocateMemory(Vm86InfoPtr vi, int n)
- {
- int ret;
- if (n < 0) {
- ErrorF("Asked to allocate negative amount of memory\n");
- return vi->brk;
- }
- n = (n + 15) & ~15;
- if (vi->brk + n > LOMEM_BASE + LOMEM_SIZE) {
- ErrorF("Out of low memory\n");
- exit(2);
- }
- ret = vi->brk;
- vi->brk += n;
- return ret;
- }
- int Vm86MarkMemory(Vm86InfoPtr vi)
- {
- return vi->brk;
- }
- void Vm86ReleaseMemory(Vm86InfoPtr vi, int mark)
- {
- vi->brk = mark;
- }
- static int vm86old(struct vm86_struct *vm)
- {
- int res = -1;
- #ifndef __x86_64__
- asm volatile ("pushl %%ebx\n\t"
- "movl %2, %%ebx\n\t"
- "movl %1,%%eax\n\t"
- "int $0x80\n\t"
- "popl %%ebx":"=a" (res):"n"(113), "r"(vm));
- #endif
- if (res < 0) {
- errno = -res;
- res = -1;
- } else
- errno = 0;
- return res;
- }
|