diff options
author | Gwenolé Beauchesne <gbeauchesne@mandriva.org> | 2004-08-25 05:45:29 +0000 |
---|---|---|
committer | Gwenolé Beauchesne <gbeauchesne@mandriva.org> | 2004-08-25 05:45:29 +0000 |
commit | e0fbcfe868b509f256fcdc239178d32f617bb129 (patch) | |
tree | 26d7a7632d92979a6f7a39f0a707c935ca186e9f /tools/ddcprobe/int10/emu_vm86.c | |
parent | 56e607a5ce0c98074b0c3067e2bba76e9d73223d (diff) | |
download | drakx-e0fbcfe868b509f256fcdc239178d32f617bb129.tar drakx-e0fbcfe868b509f256fcdc239178d32f617bb129.tar.gz drakx-e0fbcfe868b509f256fcdc239178d32f617bb129.tar.bz2 drakx-e0fbcfe868b509f256fcdc239178d32f617bb129.tar.xz drakx-e0fbcfe868b509f256fcdc239178d32f617bb129.zip |
VGA softbootloader for Linux, uses an x86 CPU emulator on non x86 arches.
Diffstat (limited to 'tools/ddcprobe/int10/emu_vm86.c')
-rw-r--r-- | tools/ddcprobe/int10/emu_vm86.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/tools/ddcprobe/int10/emu_vm86.c b/tools/ddcprobe/int10/emu_vm86.c new file mode 100644 index 000000000..2603a5aeb --- /dev/null +++ b/tools/ddcprobe/int10/emu_vm86.c @@ -0,0 +1,154 @@ +#include <stdio.h> +#include <stdarg.h> +#ifdef __i386__ +#include <sys/vm86.h> +#else +#include "vm86_struct.h" +#endif + +#define INT2PTR(a) ((a) + (unsigned char *) 0) + +#include "../x86emu/include/x86emu.h" +#include "AsmMacros.h" + +int emu_vm86_ret; + +static u8 Mem_rb(u32 addr) { + return *(u8 *)(INT2PTR(addr)); +} +static void Mem_wb(u32 addr, u8 val) { + *(u8 *)INT2PTR(addr) = val; +} +#ifdef __ia64__ + +static u16 Mem_rw(u32 addr) { + return *(u8 *)INT2PTR(addr) | *(u8 *)INT2PTR(addr + 1) << 8; +} +static u32 Mem_rl(u32 addr) { + return *(u8 *)INT2PTR(addr) | *(u8 *)INT2PTR(addr + 1) << 8 | + *(u8 *)INT2PTR(addr + 2) << 16 | *(u8 *)INT2PTR(addr + 3) << 24; +} +static void Mem_ww(u32 addr, u16 val) { + *(u8 *)INT2PTR(addr) = val; + *(u8 *)INT2PTR(addr + 1) = val >> 8; +} +static void Mem_wl(u32 addr, u32 val) { + *(u8 *)INT2PTR(addr) = val; + *(u8 *)INT2PTR(addr + 1) = val >> 8; + *(u8 *)INT2PTR(addr + 2) = val >> 16; + *(u8 *)INT2PTR(addr + 3) = val >> 24; +} + +#else + +static u16 Mem_rw(u32 addr) { + return *(u16 *)INT2PTR(addr); +} +static u32 Mem_rl(u32 addr) { + return *(u32 *)INT2PTR(addr); +} +static void Mem_ww(u32 addr, u16 val) { + *(u16 *)INT2PTR(addr) = val; +} +static void Mem_wl(u32 addr, u32 val) { + *(u32 *)INT2PTR(addr) = val; +} + +#endif + +static void do_int(int num) { + emu_vm86_ret = VM86_INTx | (num << 8); + M.x86.intr = INTR_HALTED; +} + + +int +emu_vm86(struct vm86_struct *vm) +{ + int i; + + X86EMU_memFuncs memFuncs; + X86EMU_intrFuncs intFuncs[256]; + X86EMU_pioFuncs pioFuncs; + + memFuncs.rdb = Mem_rb; + memFuncs.rdw = Mem_rw; + memFuncs.rdl = Mem_rl; + memFuncs.wrb = Mem_wb; + memFuncs.wrw = Mem_ww; + memFuncs.wrl = Mem_wl; + X86EMU_setupMemFuncs(&memFuncs); + + pioFuncs.inb = (u8(*)(u16))inb; + pioFuncs.inw = (u16(*)(u16))inw; + pioFuncs.inl = (u32(*)(u16))inl; + pioFuncs.outb = (void(*)(u16, u8))outb; + pioFuncs.outw = (void(*)(u16, u16))outw; + pioFuncs.outl = (void(*)(u16, u32))outl; + X86EMU_setupPioFuncs(&pioFuncs); + + for (i=0;i<256;i++) + intFuncs[i] = do_int; + X86EMU_setupIntrFuncs(intFuncs); + + M.mem_base = 0; + M.mem_size = 1024*1024 + 1024; + + M.x86.R_EAX = vm->regs.eax; + M.x86.R_EBX = vm->regs.ebx; + M.x86.R_ECX = vm->regs.ecx; + M.x86.R_EDX = vm->regs.edx; + + M.x86.R_ESP = vm->regs.esp; + M.x86.R_EBP = vm->regs.ebp; + M.x86.R_ESI = vm->regs.esi; + M.x86.R_EDI = vm->regs.edi; + M.x86.R_EIP = vm->regs.eip; + M.x86.R_EFLG = vm->regs.eflags; + + M.x86.R_CS = vm->regs.cs; + M.x86.R_DS = vm->regs.ds; + M.x86.R_SS = vm->regs.ss; + M.x86.R_ES = vm->regs.es; + M.x86.R_FS = vm->regs.fs; + M.x86.R_GS = vm->regs.gs; + + emu_vm86_ret = 0; + X86EMU_exec(); + + vm->regs.eax = M.x86.R_EAX; + vm->regs.ebx = M.x86.R_EBX; + vm->regs.ecx = M.x86.R_ECX; + vm->regs.edx = M.x86.R_EDX; + + vm->regs.esp = M.x86.R_ESP; + vm->regs.ebp = M.x86.R_EBP; + vm->regs.esi = M.x86.R_ESI; + vm->regs.edi = M.x86.R_EDI; + vm->regs.eip = M.x86.R_EIP; + vm->regs.eflags = M.x86.R_EFLG; + + vm->regs.cs = M.x86.R_CS; + vm->regs.ds = M.x86.R_DS; + vm->regs.ss = M.x86.R_SS; + vm->regs.es = M.x86.R_ES; + vm->regs.fs = M.x86.R_FS; + vm->regs.gs = M.x86.R_GS; + + if (emu_vm86_ret == 0 && *(unsigned char *)INT2PTR(((u32)M.x86.R_CS << 4) + (M.x86.R_IP - 1)) == 0xf4) + { + vm->regs.eip--; + return VM86_UNKNOWN; + } + return emu_vm86_ret ? emu_vm86_ret : -1; +} + +void +printk(const char *fmt, ...) +{ + va_list argptr; + va_start(argptr, fmt); + vfprintf(stderr, fmt, argptr); + va_end(argptr); +} + |