44,7 → 44,7 |
#define __CHK_IO__ |
*/ |
|
#define __LL_DEBUG__ |
//#define __LL_DEBUG__ |
|
#define VM86_STACK_SIZE 1024 |
|
60,9 → 60,10 |
static LIN_ADDR vm86_stack; |
static LIN_ADDR vm86_iretAddress; |
|
|
struct registers *global_regs; |
WORD VM86_ret_ctx; |
|
|
#ifdef __DUMB_CODE__ |
static LIN_ADDR vm86_code; |
static BYTE prova86[] = { |
84,19 → 85,7 |
0}; |
#endif |
|
#ifdef __LL_DEBUG__ |
static BYTE vm86_retAddr[] = { |
0x1e, /* push ds */ |
0xb8,0x00,0xb8, /* mov ax,0xb800 */ |
0x8e,0xd8, /* mov ds,ax */ |
0xbf,0x3e,0x01, /* mov di,0x013c (316) */ |
0xb0,'%', /* mov ax,'%' */ |
0x88,0x05, /* mov ds:[di],al */ |
0x1f, /* pop ds */ |
0xcd, 0x48}; /* int 0x48 */ |
#else |
static BYTE vm86_retAddr[] = {0xcd, 0x48}; /* int 48h */ |
#endif |
|
TSS *vm86_get_tss(void) |
{ |
103,59 → 92,6 |
return &(vm86_TSS.t); |
} |
|
/* This is the return point from V86 mode, called through int 0x48 |
* (see vm86-exc.s). We double check that this function is called in |
* the V86 TSS. Otherwise, Panic!!! |
*/ |
void vm86_return(DWORD n, struct registers r) |
{ |
CONTEXT c = get_TR(); |
#ifdef __LL_DEBUG__ |
DWORD cs,eip; |
void *esp; |
DWORD a; |
/* message("Gotta code=%d [0 called from GPF/1 int 0x48]\n",code);*/ |
#endif |
if (c == X_VM86_TSS) { |
global_regs = &r; |
#ifdef __LL_DEBUG__ |
message("TSS CS=%x IP=%lx\n",vm86_TSS.t.cs,vm86_TSS.t.eip); |
message("Switching to %x\n", vm86_TSS.t.back_link); |
a = (DWORD)(vm86_iretAddress); |
cs = (a & 0xFF000) >> 4; |
eip = (a & 0xFFF); |
message("Real-Mode Address is CS=%lx IP=%lx\nLinear=%lx\n",cs,eip,a); |
esp = /* (void *)(tos)*/ (void *)0x69; |
message("Stack frame: %p %lx %lx\n", |
esp, vm86_TSS.t.esp0, vm86_TSS.t.esp); |
message("%lx ",lmempeekd(esp)); /* bp */ |
message("%lx ",lmempeekd(esp+4)); /* eip */ |
message("%lx ",lmempeekd(esp+8)); /* 0x0d */ |
message("%lx\n",lmempeekd(esp+12)); /* error code */ |
/* The error code is given by the selector causing shifted and or-ed with |
3 bits: [LDT/GDT | IDT | Ext/Int] |
If IDT == 1 -> the fault was provoked bu an interrupt (Internal if the |
Ext/Int bit is 0, External if the bit is 1) |
Else the LDT/GDT bit shows if the selector belongs to the LDT (if 1) |
or GDT (if 0) |
*/ |
message("%lx ",lmempeekd(esp+16)); /* EIP of faulting instr */ |
message("%lx ",lmempeekd(esp+20)); /* CS of faulting instr*/ |
message("%lx ",lmempeekd(esp+24)); /* EFLAGS*/ |
message("%lx\n",lmempeekd(esp+28)); /* old ESP*/ |
message("%lx ",lmempeekd(esp+32)); /* old SS*/ |
message("%lx ",lmempeekd(esp+36)); /* old ES*/ |
message("%lx ",lmempeekd(esp+40)); /* old DS*/ |
message("%lx\n",lmempeekd(esp+44)); /* old FS*/ |
#endif |
ll_context_load(vm86_TSS.t.back_link); |
} |
message("Here?\n"); |
halt(); |
} |
|
extern void vm86_exc(void); |
|
/* Just a debugging function; it dumps the status of the TSS */ |
void vm86_dump_TSS(void) |
{ |
189,7 → 125,8 |
GDT_place(X_VM86_TSS,(DWORD)(&vm86_TSS), |
sizeof(vm86_TSS),FREE_TSS386,GRAN_16); |
|
IDT_place(0x48, (void *)(vm86_return)); |
/* Return Registers */ |
global_regs = DOS_alloc(sizeof(struct registers)); |
|
/* Prepare a real-mode stack, obtaining it from the |
* DOS memory allocator! |
241,8 → 178,14 |
DWORD vm86_flags, vm86_cs,vm86_ip; |
LIN_ADDR vm86_stackPtr; |
DWORD *IRQTable_entry; |
BYTE p1,p2; |
|
SYS_FLAGS f; |
|
if (service < 0x10 || in == NULL) return -1; |
|
f = ll_fsave(); |
|
/* Setup the stack frame */ |
vm86_tmpAddr = (DWORD)(vm86_stack); |
vm86_TSS.t.ss = (vm86_tmpAddr & 0xFF000) >> 4; |
262,12 → 205,11 |
vm86_tmpAddr + VM86_STACK_SIZE,(DWORD)vm86_TSS.t.ss,vm86_TSS.t.esp); |
#endif |
/* Wanted VM86 mode + IOPL = 3! */ |
vm86_TSS.t.eflags = CPU_FLAG_VM | CPU_FLAG_IOPL; |
vm86_TSS.t.eflags = CPU_FLAG_VM + CPU_FLAG_IOPL; |
/* Preload some standard values into the registers */ |
vm86_TSS.t.ss0 = X_FLATDATA_SEL; |
vm86_TSS.t.esp0 = (DWORD)&(vm86_stack0[VM86_STACK_SIZE-1]); |
|
|
#ifdef __DUMB_CODE__ |
vm86_TSS.t.cs = ((DWORD)(vm86_code) & 0xFFFF0) >> 4; |
vm86_TSS.t.eip = ((DWORD)(vm86_code) & 0x000F); |
277,8 → 219,20 |
message("(DUMB CODE) Go...\n"); |
#endif |
vm86_TSS.t.back_link = ll_context_save(); |
VM86_ret_ctx = vm86_TSS.t.back_link; |
|
p1 = inp(0x21); |
p2 = inp(0xA1); |
outp(0x21,0xFF); |
outp(0xA1,0xFF); |
|
sti(); |
ll_context_load(X_VM86_TSS); |
|
cli(); |
outp(0x21,p1); |
outp(0xA1,p2); |
|
#ifdef __LL_DEBUG_ |
message("(DUMB CODE) I am back...\n"); |
#endif |
310,29 → 264,32 |
message("CS:%x IP:%lx\n", vm86_TSS.t.cs, vm86_TSS.t.eip); |
#endif |
/* Let's use the ll standard call... */ |
|
vm86_TSS.t.back_link = ll_context_save(); |
VM86_ret_ctx = vm86_TSS.t.back_link; |
|
p1 = inp(0x21); |
p2 = inp(0xA1); |
outp(0x21,0xFF); |
outp(0xA1,0xFF); |
sti(); |
|
ll_context_load(X_VM86_TSS); |
|
|
cli(); |
outp(0x21,p1); |
outp(0xA1,p2); |
|
#ifdef __LL_DEBUG__ |
message("I am back...\n"); |
message("TSS CS=%hx IP=%lx\n", vm86_TSS.t.cs, vm86_TSS.t.eip); |
{ char *xp = (char *)(vm86_iretAddress + 0xe); |
message("PM reentry linear address=%p\n", vm86_iretAddress); |
message("Executing code: %x ",(unsigned char)(*xp)); xp++; |
message("%x\n",(unsigned char)(*xp));} |
#endif |
/* Send back in the X_*REGS structure the value obtained with |
* the real-mode interrupt call |
*/ |
if (out != NULL) { |
/* |
out->x.ax = (WORD)vm86_TSS.t.eax; |
out->x.bx = (WORD)vm86_TSS.t.ebx; |
out->x.cx = (WORD)vm86_TSS.t.ecx; |
out->x.dx = (WORD)vm86_TSS.t.edx; |
out->x.si = (WORD)vm86_TSS.t.esi; |
out->x.di = (WORD)vm86_TSS.t.edi; |
out->x.cflag = (WORD)vm86_TSS.t.eflags; |
*/ |
|
out->x.ax = global_regs->eax; |
out->x.bx = global_regs->ebx; |
out->x.cx = global_regs->ecx; |
340,6 → 297,10 |
out->x.si = global_regs->esi; |
out->x.di = global_regs->edi; |
out->x.cflag = global_regs->flags; |
|
//message("ax = %d bx = %d cx = %d dx = %d\n",out->x.ax,out->x.bx,out->x.cx,out->x.dx); |
//message("si = %d di = %d\n",out->x.si,out->x.di); |
|
} |
if (s != NULL) { |
s->es = vm86_TSS.t.es; |
346,5 → 307,8 |
s->ds = vm86_TSS.t.ds; |
} |
#endif |
|
ll_frestore(f); |
|
return 1; |
} |