static void ShV86Handler(void) { context_v86_t ctx; uint8_t *ip; ThrGetV86Context(&ctx); ip = FP_TO_LINEAR(ctx.cs, ctx.eip); switch (ip[0]) { case 0xcd: switch (ip[1]) { case 0x20: ThrExitThread(0); break; case 0x21: ShInt21(&ctx); break; } ctx.eip += 2; break; default: wprintf(L"v86: illegal instruction %x\n", ip[0]); ThrExitThread(0); break; } ThrSetV86Context(&ctx); ThrContinueV86(); }
static void ShInt21(context_v86_t *ctx) { void *ptr; char *ch; uint32_t key; switch ((uint16_t) ctx->regs.eax >> 8) { case 0: ThrExitThread(0); break; case 1: while (!FsRead(ProcGetProcessInfo()->std_in, &key, 0, sizeof(key), NULL)) ; wprintf(L"%c", (uint8_t) key); ctx->regs.eax = (ctx->regs.eax & 0xffffff00) | (uint8_t) key; break; case 2: wprintf(L"%c", ctx->regs.edx & 0xff); break; case 9: ptr = FP_TO_LINEAR(ctx->v86_ds, ctx->regs.edx); ch = strchr(ptr, '$'); fwrite(ptr, 1, ch - (char*) ptr, stdout); break; case 0x4c: ThrExitThread(ctx->regs.eax & 0xff); break; } }
void graphics_install_vesa(uint16_t x, uint16_t y) { blog("Setting up VESA video controller..."); /* VESA Structs */ struct VesaControllerInfo *info = (void*)0x10000; struct VesaModeInfo *modeinfo = (void*)0x9000; /* 8086 Emulator Status */ tRME_State *emu; void * lowCache; lowCache = malloc(RME_BLOCK_SIZE); memcpy(lowCache, NULL, RME_BLOCK_SIZE); emu = RME_CreateState(); emu->Memory[0] = lowCache; for (int i = RME_BLOCK_SIZE; i < 0x100000; i += RME_BLOCK_SIZE) { emu->Memory[i/RME_BLOCK_SIZE] = (void*)i; } int ret, mode; /* Find modes */ uint16_t * modes; memcpy(info->Signature, "VBE2", 4); emu->AX.W = 0x4F00; emu->ES = 0x1000; emu->DI.W = 0; ret = RME_CallInt(emu, 0x10); if (info->Version < 0x200 || info->Version > 0x300) { bfinish(2); kprintf("\033[JYou have attempted to use the VESA/VBE2 driver\nwith a card that does not support VBE2.\n"); kprintf("\nSystem responded to VBE request with version: 0x%x\n", info->Version); STOP; } modes = (void*)FP_TO_LINEAR(info->Videomodes.Segment,info->Videomodes.Offset); uint16_t best_x = 0; uint16_t best_y = 0; uint16_t best_b = 0; uint16_t best_mode = 0; for (int i = 1; modes[i] != 0xFFFF; ++i) { emu->AX.W = 0x4F01; emu->CX.W = modes[i]; emu->ES = 0x0900; emu->DI.W = 0x0000; RME_CallInt(emu, 0x10); #if PROMPT_FOR_MODE kprintf("%d = %dx%d:%d\n", i, modeinfo->Xres, modeinfo->Yres, modeinfo->bpp); } kprintf("Please select a mode: "); char buf[10]; kgets(buf, 10); mode = atoi(buf); #else if ((abs(modeinfo->Xres - x) < abs(best_x - x)) && (abs(modeinfo->Yres - y) < abs(best_y - y))) { best_mode = i; best_x = modeinfo->Xres; best_y = modeinfo->Yres; best_b = modeinfo->bpp; } }
uint8_t *ip; uint16_t *stack, *ivt; /* xxx - need to validate CS, EIP, SS and ESP here */ ip = FP_TO_LINEAR(ctx->cs, ctx->eip); ivt = (uint16_t*) 0; stack = (uint16_t*) FP_TO_LINEAR(ctx->ss, ctx->esp); switch (ip[0]) { case 0xcd: /* INT n */ stack -= 3; ctx->esp = ((ctx->esp & 0xffff) - 6) & 0xffff; stack[0] = (uint16_t) (ctx->eip + 2); stack[1] = ctx->cs; stack[2] = (uint16_t) ctx->eflags; if (current->v86_if) stack[2] |= EFLAG_IF; else stack[2] &= ~EFLAG_IF; current->v86_if = false; ctx->cs = ivt[ip[1] * 2 + 1]; ctx->eip = ivt[ip[1] * 2]; return true; /* continue execution */ default: /* something wrong */ return false; /* terminate the app */
bool i386V86Gpf(context_v86_t *ctx) { uint8_t *ip; uint16_t *stack, *ivt; uint32_t *stack32; bool is_operand32, is_address32; ip = FP_TO_LINEAR(ctx->cs, ctx->eip); ivt = (uint16_t*) 0; stack = (uint16_t*) FP_TO_LINEAR(ctx->ss, ctx->esp); stack32 = (uint32_t*) stack; is_operand32 = is_address32 = false; TRACE4("i386V86Gpf: cs:ip = %04x:%04x ss:sp = %04x:%04x: ", ctx->cs, ctx->eip, ctx->ss, ctx->esp); while (true) { switch (ip[0]) { case 0x66: /* O32 */ TRACE0("o32 "); is_operand32 = true; ip++; ctx->eip = (uint16_t) (ctx->eip + 1); break; case 0x67: /* A32 */ TRACE0("a32 "); is_address32 = true; ip++; ctx->eip = (uint16_t) (ctx->eip + 1); break; case 0x9c: /* PUSHF */ TRACE0("pushf\n"); if (is_operand32) { ctx->esp = ((ctx->esp & 0xffff) - 4) & 0xffff; stack32--; stack32[0] = ctx->eflags & VALID_FLAGS; if (current->v86_if) stack32[0] |= EFLAG_IF; else stack32[0] &= ~EFLAG_IF; } else { ctx->esp = ((ctx->esp & 0xffff) - 2) & 0xffff; stack--; stack[0] = (uint16_t) ctx->eflags; if (current->v86_if) stack[0] |= EFLAG_IF; else stack[0] &= ~EFLAG_IF; } ctx->eip = (uint16_t) (ctx->eip + 1); return true; case 0x9d: /* POPF */ TRACE0("popf\n"); if (is_operand32) { ctx->eflags = EFLAG_IF | EFLAG_VM | (stack32[0] & VALID_FLAGS); current->v86_if = (stack32[0] & EFLAG_IF) != 0; ctx->esp = ((ctx->esp & 0xffff) + 4) & 0xffff; } else { ctx->eflags = EFLAG_IF | EFLAG_VM | stack[0]; current->v86_if = (stack[0] & EFLAG_IF) != 0; ctx->esp = ((ctx->esp & 0xffff) + 2) & 0xffff; } ctx->eip = (uint16_t) (ctx->eip + 1); return true; case 0xcd: /* INT n */ TRACE1("interrupt 0x%x => ", ip[1]); switch (ip[1]) { case 0x30: TRACE0("syscall\n"); if (ctx->regs.eax == SYS_ThrExitThread) ThrExitThread(0); return true; case 0x20: case 0x21: /*i386V86EmulateInt21(ctx);*/ if (current->v86_in_handler) return false; TRACE1("redirect to %x\n", current->v86_handler); current->v86_in_handler = true; current->v86_context = *ctx; current->kernel_esp += sizeof(context_v86_t) - sizeof(context_t); ctx->eflags = EFLAG_IF | 2; ctx->eip = current->v86_handler; ctx->cs = USER_FLAT_CODE | 3; ctx->ds = ctx->es = ctx->gs = ctx->ss = USER_FLAT_DATA | 3; ctx->fs = USER_THREAD_INFO | 3; ctx->esp = current->user_stack_top; return true; default: stack -= 3; ctx->esp = ((ctx->esp & 0xffff) - 6) & 0xffff; stack[0] = (uint16_t) (ctx->eip + 2); stack[1] = ctx->cs; stack[2] = (uint16_t) ctx->eflags; if (current->v86_if) stack[2] |= EFLAG_IF; else stack[2] &= ~EFLAG_IF; ctx->cs = ivt[ip[1] * 2 + 1]; ctx->eip = ivt[ip[1] * 2]; TRACE2("%04x:%04x\n", ctx->cs, ctx->eip); return true; } break; case 0xcf: /* IRET */ TRACE0("iret => "); ctx->eip = stack[0]; ctx->cs = stack[1]; ctx->eflags = EFLAG_IF | EFLAG_VM | stack[2]; current->v86_if = (stack[2] & EFLAG_IF) != 0; ctx->esp = ((ctx->esp & 0xffff) + 6) & 0xffff; TRACE2("%04x:%04x\n", ctx->cs, ctx->eip); return true; case 0xfa: /* CLI */ TRACE0("cli\n"); current->v86_if = false; ctx->eip = (uint16_t) (ctx->eip + 1); return true; case 0xfb: /* STI */ TRACE0("sti\n"); current->v86_if = true; ctx->eip = (uint16_t) (ctx->eip + 1); return true; default: wprintf(L"unhandled opcode 0x%x\n", ip[0]); return false; } } return false; }