void PrintException (struct ContextState *es, char *str, int panic) { int privilege; privilege = es->return_cs & 0x03; if (privilege != 0) { KPRINTF("return_ss = %#010x return_esp = %#010x", es->return_ss, es->return_esp); } KPRINTF("return_eflags = %#010x cr2 = %#010x", es->return_eflags, GetCR2()); KPRINTF("return_cs = %#010x return_eip = %#010x", es->return_cs, es->return_eip); KPRINTF("error_code = %#010x exception = %#010x", es->error_code, es->exception); KPRINTF("EAX = %#010x ECX = %#010x", es->eax, es->ecx); KPRINTF("EDX = %#010x EBX = %#010x", es->edx, es->ebx); KPRINTF("EBP = %#010x ", es->ebp); KPRINTF("ESI = %#010x EDI = %#010x", es->esi, es->edi); KPRINTF ("EXCEPTION = %d #%s name = %s", es->exception, exception_string[es->exception % 32], current_process->exe_name); KPRINTF ("pid = %d, Name = %s", current_process->pid, current_process->exe_name); if (panic == TRUE) KPANIC (str); }
void kloader_cmain(struct mem_map_entry mem_map[], uint32_t mem_entry_count) { screen_init(); screen_cursor_hide(); terminal_init(); KINFO("Welcome to Nox (Bootloader mode)"); mem_mgr_init(mem_map, mem_entry_count); ata_init(); fs_init(); struct fat_part_info* part_info = fs_get_system_part(); struct fat_dir_entry kernel; if(!fat_get_dir_entry(part_info, "KERNEL ELF", &kernel)) { KPANIC("Failed to locate KERNEL.ELF"); while(1); } intptr_t kernel_entry_point; if(!elf_load_trusted("KERNEL ELF", &kernel_entry_point)) { KWARN("Failed to load elf!"); } kernel_entry cmain = (kernel_entry)(kernel_entry_point); cmain(mem_map, mem_entry_count); KINFO("Bootloader done"); while(1); }
int32 V86Start (struct ContextState *state) { struct Msg *msg; uint32 signals; if ((v86_msgport = CreateMsgPort()) != NULL) { KSignal (v86_init_pid, SIG_INIT); } else { KPANIC ("V86 error"); } while (1) { signals = KWait (1 << v86_msgport->signal); if (signals & (1 << v86_msgport->signal)) if ((msg = GetMsg (v86_msgport)) != NULL) break; } handler_v86msg = (struct V86Msg *) msg; state->eax = handler_v86msg->state->eax; state->ebx = handler_v86msg->state->ebx; state->ecx = handler_v86msg->state->ecx; state->edx = handler_v86msg->state->edx; state->esi = handler_v86msg->state->esi; state->edi = handler_v86msg->state->edi; state->ebp = handler_v86msg->state->ebp; state->gs = PL3_DATA_SEGMENT; state->fs = PL3_DATA_SEGMENT; state->es = PL3_DATA_SEGMENT; state->ds = PL3_DATA_SEGMENT; state->v86_gs = handler_v86msg->state->gs; state->v86_fs = handler_v86msg->state->fs; state->v86_es = handler_v86msg->state->es; state->v86_ds = handler_v86msg->state->ds; *(uint8 *)(0x00010000) = OPCODE_INT; *(uint8 *)(0x00010001) = handler_v86msg->vector; *(uint8 *)(0x00010002) = OPCODE_IRET; state->return_eip = 0x0000; state->return_cs = 0x1000; state->return_eflags = EFLG_IF | EFLG_VM; state->return_esp = 0xfff0; state->return_ss = 0x2000; return 0; }
void CondWait (struct Cond *cond, struct Mutex *mutex) { struct Process *proc; if (current_process == NULL) return; DisableInterrupts(); /* Release Mutex */ if (mutex->locked == TRUE) { proc = LIST_HEAD (&mutex->blocked_list); if (proc != NULL) { LIST_REM_HEAD (&mutex->blocked_list, blocked_entry); proc->state = PROC_STATE_READY; SchedReady (proc); } else { mutex->locked = FALSE; } } else { KPANIC ("CondWait() on a free mutex"); } /* Block current process on Condvar */ LIST_ADD_TAIL (&cond->blocked_list, current_process, blocked_entry); current_process->state = PROC_STATE_COND_BLOCKED; SchedUnready (current_process); Reschedule(); /* Now acquire mutex */ if (mutex->locked == TRUE) { LIST_ADD_TAIL (&mutex->blocked_list, current_process, blocked_entry); current_process->state = PROC_STATE_MUTEX_BLOCKED; SchedUnready (current_process); Reschedule(); } else { mutex->locked = TRUE; } EnableInterrupts(); }
int CondTimedWait (volatile struct Cond *cond, struct Mutex *mutex, struct TimeVal *tv) { struct Process *proc; struct Timer timer; if (current_process == NULL) return 0; DisableInterrupts(); if (mutex->locked == TRUE) { /* Release Mutex */ proc = LIST_HEAD (&mutex->blocked_list); if (proc != NULL) { LIST_REM_HEAD (&mutex->blocked_list, blocked_entry); proc->state = PROC_STATE_READY; SchedReady (proc); } else { mutex->locked = FALSE; } } else { KPANIC ("CondTimedWait() on a free mutex"); } /* Block current process on Condvar */ LIST_ADD_TAIL (&cond->blocked_list, current_process, blocked_entry); SetTimer (&timer, TIMER_TYPE_RELATIVE, tv, &CondTimedWaitCallout, &cond); current_process->state = PROC_STATE_COND_BLOCKED; SchedUnready (current_process); Reschedule(); CancelTimer (&timer); /* Now acquire mutex */ if (mutex->locked == TRUE) { LIST_ADD_TAIL (&mutex->blocked_list, current_process, blocked_entry); current_process->state = PROC_STATE_MUTEX_BLOCKED; SchedUnready (current_process); Reschedule(); } else { mutex->locked = TRUE; } EnableInterrupts(); if (cond == NULL) return -1; else return 0; }
int CreateArgEnv (struct ArgInfo *ai, char **argv, char **env) { void *buf; char **kargv, **kenv; char **targv, **tenv; KPRINTF ("CreateArgEnv()"); if ((buf = (void *)KMap (ARG_MAX, VM_PROT_READWRITE)) != (void *)MAP_FAILED) { ai->buf = buf; ai->nbytes_free = ARG_MAX; ai->current_pos = buf; ai->argc = 0; ai->envc = 0; kargv = NULL; kenv = NULL; if (argv != NULL) if ((kargv = ReadPointerArray (argv, ai)) == NULL) goto ErrorExit; if (env != NULL) if ((kenv = ReadPointerArray (env, ai)) == NULL) goto ErrorExit; targv = kargv; tenv = kenv; if (targv != NULL) { while (*targv != NULL) { if ((*targv = ReadArgString (*targv, ai)) == NULL) goto ErrorExit; targv++; ai->argc ++; } } if (tenv != NULL) { while (*tenv != NULL) { if ((*tenv = ReadArgString (*tenv, ai)) == NULL) goto ErrorExit; tenv++; ai->envc ++; } } ai->argv = kargv; ai->env = kenv; return 0; ErrorExit: KUnmap ((vm_addr)buf); } KPANIC ("CreateArgEnv FAILED"); return -1; }
void root_beginio (void *ioreq) { struct FSReq *fsreq = ioreq; struct RootFilp *filp; struct Mount *mount; int len; KPRINTF ("root_beginio()"); fsreq->flags |= IOF_QUICK; switch (fsreq->cmd) { case FS_CMD_OPEN: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_PIPE: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_CLOSE: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_DUP: /* Might want to dup() the handle? */ fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_READ: fsreq->error = ENOSYS; fsreq->nbytes_transferred = -1; fsreq->rc = -1; break; case FS_CMD_WRITE: fsreq->error = ENOSYS; fsreq->nbytes_transferred = -1; fsreq->rc = -1; break; case FS_CMD_LSEEK: fsreq->error = ENOSYS; fsreq->position = -1; break; case FS_CMD_UNLINK: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_RENAME: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_FTRUNCATE: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_FSTAT: fsreq->stat->st_mode = S_IFDIR | (S_IRUSR | S_IRGRP | S_IROTH); fsreq->stat->st_nlink = 1; /* ??? 0 ??? */ fsreq->stat->st_uid = 1; fsreq->stat->st_gid = 1; fsreq->stat->st_rdev = 5; fsreq->stat->st_size = 0; fsreq->stat->st_atime = 0; fsreq->stat->st_mtime = 0; fsreq->stat->st_ctime = 0; fsreq->stat->st_blocks = 0; fsreq->error = 0; fsreq->rc = 0; break; case FS_CMD_STAT: fsreq->stat->st_mode = S_IFDIR | (S_IRUSR | S_IRGRP | S_IROTH); fsreq->stat->st_nlink = 1; /* ??? 0 ??? */ fsreq->stat->st_uid = 1; fsreq->stat->st_gid = 1; fsreq->stat->st_rdev = 5; fsreq->stat->st_size = 0; fsreq->stat->st_atime = 0; fsreq->stat->st_mtime = 0; fsreq->stat->st_ctime = 0; fsreq->stat->st_blocks = 0; fsreq->error = 0; fsreq->rc = 0; break; case FS_CMD_FSTATFS: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_FSYNC: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_SYNC: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_MKDIR: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_RMDIR: fsreq->error = ENOSYS; fsreq->rc = -1; break; case FS_CMD_OPENDIR: { if ((filp = KMalloc (sizeof (struct RootFilp))) != NULL) { filp->device = &root_handler; filp->seek_mount = LIST_HEAD (&mount_list); LIST_ADD_TAIL (&root_filp_list, filp, filp_entry); fsreq->filp = filp; fsreq->device = &root_handler; fsreq->error = 0; fsreq->rc = 0; } else { fsreq->error = ENOSYS; fsreq->rc = -1; } break; } case FS_CMD_CLOSEDIR: { filp = fsreq->filp; LIST_REM_ENTRY (&root_filp_list, filp, filp_entry); KFree (filp); fsreq->error = 0; fsreq->rc = 0; break; } case FS_CMD_READDIR: filp = fsreq->filp; mount = filp->seek_mount; if (mount != NULL) { len = StrLen (mount->name); if (len + 1 <= NAME_MAX) { CopyOut (fsreq->as, &fsreq->dirent->d_name, mount->name, len + 1); filp->seek_mount = LIST_NEXT (mount, mount_list_entry); fsreq->error = 0; fsreq->rc = 0; } else { fsreq->dirent = NULL; fsreq->error = ENAMETOOLONG; fsreq->rc = -1; } } else { fsreq->dirent = NULL; fsreq->error = 0; fsreq->rc = -1; } break; case FS_CMD_REWINDDIR: filp = fsreq->filp; filp->seek_mount = LIST_HEAD (&mount_list); fsreq->error = 0; fsreq->rc = 0; break; case FS_CMD_ISATTY: fsreq->error = 0; fsreq->rc = 0; break; case FS_CMD_TCGETATTR: fsreq->error = ENOTTY; fsreq->rc = -1; break; case FS_CMD_TCSETATTR: fsreq->error = ENOTTY; fsreq->rc = -1; break; case FS_CMD_IOCTL: fsreq->error = ENOSYS; fsreq->rc = -1; break; default: { KPANIC ("ROOT Unknown command"); fsreq->error = ENOSYS; fsreq->rc = -1; break; } } }
int cd_opendevice (int unit, void *ioreq, uint32 flags) { struct FSReq *fsreq = ioreq; struct CDSB *cdsb; struct MountEnviron *me; struct BlkReq blkreq; KPRINTF ("cd_opendevice ()"); if ((cdsb = KMalloc (sizeof (struct CDSB))) != NULL) { me = fsreq->me; if (OpenDevice (me->device_name, me->device_unit, &blkreq, me->device_flags) == 0) { /* FIXME: Shouldn't need it (also in fat handler) */ MemSet (cdsb, 0, sizeof (struct CDSB)); /* Need it as cdsb->validated isn't initialized */ cdsb->device = blkreq.device; cdsb->unitp = blkreq.unitp; cdsb->me = fsreq->me; cdsb->reference_cnt = 0; LIST_INIT (&cdsb->node_list); LIST_INIT (&cdsb->active_filp_list); LIST_INIT (&cdsb->invalid_filp_list); cdsb->root_node.flags = ISO_DIRECTORY; cdsb->root_node.cdsb = cdsb; cdsb->root_node.reference_cnt = 0; if ((cdsb->buf = CreateBuf (cdsb->device, cdsb->unitp, me->buffer_cnt, me->block_size, me->partition_start, me->partition_end, me->writethru_critical, me->writeback_delay, me->max_transfer)) != NULL) { if (KSpawn (CDTask, cdsb, 10, "cd.handler") != -1) { KWait (SIGF_INIT); RWWriteLock (&mountlist_rwlock); cd_device.reference_cnt ++; cdsb->device_mount = MakeMount (cdsb->me, &cd_device, cdsb); AddMount (cdsb->device_mount); RWUnlock (&mountlist_rwlock); fsreq->unitp = cdsb; fsreq->error = 0; fsreq->rc = 0; return 0; } } CloseDevice (&blkreq); } KFree (cdsb); } fsreq->error = IOERR_OPENFAIL; fsreq->rc = -1; KPANIC ("CD OpenDevice FAIL"); return -1; }
void DispatchException (struct ContextState *es) { int privilege_level; int pf_direction; vm_addr pf_addr; if (isr_depth > 0) PrintException (es, "Exception in interrupt Handler", TRUE); if (es->return_eflags & EFLG_VM) { KPANIC ("V86 Exception"); switch (es->exception) { case EXCEPTION_GP: EnableInterrupts(); V86GPHandler (es); DisableInterrupts(); break; default: PrintException (es, "#GP in V86", TRUE); } } else if ((privilege_level = es->return_cs & 0x03) == 0) { switch (es->exception) { case EXCEPTION_PF: pf_addr = GetCR2(); if ((es->error_code & PF_ERRORCODE_DIRECTION) == 0) pf_direction = PF_DIR_READ; else pf_direction = PF_DIR_WRITE; EnableInterrupts(); if (PageFault (pf_addr, pf_direction, privilege_level) != 0) { if (current_process->archproc.resume_eip != 0 && current_process->archproc.resume_esp != 0) { es->return_eip = current_process->archproc.resume_eip; es->return_esp = current_process->archproc.resume_esp; current_process->archproc.resume_eip = 0; current_process->archproc.resume_esp = 0; } else { PrintException (es, "#PF in Kernel", TRUE); } } DisableInterrupts(); break; default: PrintException (es, "Exception in Kernel", TRUE); } } else { switch (es->exception) { case EXCEPTION_DE: /* Divide Error */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; case EXCEPTION_DB: /* Debug */ current_process->usignal.sig_pending |= SIGFTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_signo = SIGTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_code = 0; current_process->usignal.siginfo_data[SIGTRAP-1].si_value.sival_int = 0; break; case EXCEPTION_NMI: /* Non-Maskable Interupt */ break; case EXCEPTION_BP: /* Breakpoint */ current_process->usignal.sig_pending |= SIGFTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_signo = SIGTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_code = 0; current_process->usignal.siginfo_data[SIGTRAP-1].si_value.sival_int = 0; break; case EXCEPTION_OF: /* Overflow */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_BR: /* Boundary-Range Exceeded */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_UD: /* Undefined-Opcode */ current_process->usignal.sig_pending |= SIGFILL; current_process->usignal.siginfo_data[SIGILL-1].si_signo = SIGILL; current_process->usignal.siginfo_data[SIGILL-1].si_code = 0; current_process->usignal.siginfo_data[SIGILL-1].si_value.sival_int = 0; break; case EXCEPTION_NM: /* Device-Not Available */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_DF: /* Double-Fault */ KPANIC ("DF"); break; case EXCEPTION_CSO: /* Reserved : Coprocessor Segment Overrun */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; case EXCEPTION_TS: /* Invalid TSS */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_NP: /* Segment / Not Present */ current_process->usignal.sig_pending |= SIGFBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_signo = SIGBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_code = 0; current_process->usignal.siginfo_data[SIGBUS-1].si_value.sival_int = 0; break; case EXCEPTION_SS: /* Stack Segment */ current_process->usignal.sig_pending |= SIGFBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_signo = SIGBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_code = 0; current_process->usignal.siginfo_data[SIGBUS-1].si_value.sival_int = 0; break; case EXCEPTION_GP: /* General Protection */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_PF: pf_addr = GetCR2(); if ((es->error_code & PF_ERRORCODE_DIRECTION) == 0) pf_direction = PF_DIR_READ; else pf_direction = PF_DIR_WRITE; EnableInterrupts(); if (PageFault (pf_addr, pf_direction, privilege_level) != 0) { current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; PrintException (es, "Page Fault in PL3", FALSE); } DisableInterrupts(); break; case EXCEPTION_RESV: /* Reserved */ break; case EXCEPTION_MF: /* Math Fault */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; case EXCEPTION_AC: /* Alignment Check */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_MC: /* Machine Check */ break; case EXCEPTION_XF: /* Extended Math Fault */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; default: /* Unknown Exception */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; } } }
int V86HandleOpcode (struct ContextState *state) { bool is_operand32 = FALSE; bool is_address32 = FALSE; uint32 *sp32; uint16 *sp16; uint32 eflags; uint8 *ip; uint32 new_ip; uint32 new_cs; uint8 *vector; while (1) { ip = V86GetAddress (state->return_eip, state->return_cs); switch (*ip) { case PREFIX_O32: is_operand32 = TRUE; state->return_eip = (state->return_eip + 1) & 0x0000ffff; continue; case PREFIX_A32: is_address32 = TRUE; ip++; state->return_eip = (state->return_eip + 1) & 0x0000ffff; continue; case OPCODE_PUSHF: if (is_operand32 == TRUE) { state->return_esp = ((state->return_esp & 0x0000ffff) - 4) & 0x0000ffff; sp32 = V86GetAddress (state->return_esp, state->return_ss); eflags = state->return_eflags & V86_EFLAG_MASK; *sp32 = (v86_if == TRUE) ? eflags | EFLAG_IF : eflags & ~EFLAG_IF; } else { state->return_esp = ((state->return_esp & 0x0000ffff) - 2) & 0x0000ffff; sp16 = V86GetAddress (state->return_esp, state->return_ss); eflags = state->return_eflags & V86_EFLAG_MASK; *sp16 = (uint16) (v86_if == TRUE) ? eflags | EFLAG_IF : eflags & ~EFLAG_IF; } state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_POPF: if (is_operand32 == TRUE) { sp32 = V86GetAddress (state->return_esp, state->return_ss); eflags = *sp32; state->return_eflags = (eflags & V86_EFLAG_MASK) | EFLAG_IF | EFLAG_VM; v86_if = (eflags & EFLAG_IF) ? TRUE : FALSE; state->return_esp = ((state->return_esp & 0x0000ffff) + 4) & 0x0000ffff; } else { sp16 = V86GetAddress (state->return_esp, state->return_ss); eflags = *sp16; state->return_eflags = (eflags & V86_EFLAG_MASK) | EFLAG_IF | EFLAG_VM; v86_if = (eflags & EFLAG_IF) ? TRUE : FALSE; state->return_esp = ((state->return_esp & 0x0000ffff) + 2) & 0x0000ffff; } state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_INT: { state->return_eip = (state->return_eip + 1) & 0x0000ffff; vector = V86GetAddress (state->return_eip, state->return_cs); V86GetInterruptVector (*vector, &new_ip, &new_cs); state->return_eip = (state->return_eip + 1) & 0x0000ffff; state->return_esp = ((state->return_esp & 0x0000ffff) - 2) & 0x0000ffff; sp16 = V86GetAddress (state->return_esp, state->return_ss); *sp16 = (uint16) state->return_eip; state->return_esp = ((state->return_esp & 0x0000ffff) - 2) & 0x0000ffff; sp16 = V86GetAddress (state->return_esp, state->return_ss); *sp16 = (uint16) state->return_cs; state->return_esp = ((state->return_esp & 0x0000ffff) - 2) & 0x0000ffff; sp16 = V86GetAddress (state->return_esp, state->return_ss); eflags = (v86_if == TRUE) ? (state->return_eflags & V86_EFLAG_MASK) | EFLAG_IF : (state->return_eflags & V86_EFLAG_MASK) & ~EFLAG_IF; *sp16 = (uint16) eflags; state->return_eflags = (state->return_eflags & ~(EFLAG_IF | EFLAG_TF | EFLAG_AC)) | EFLAG_VM; v86_if = FALSE; state->return_eip = new_ip & 0x0000ffff; state->return_cs = new_cs & 0x0000ffff; return 0; } case OPCODE_IRET: if (state->return_eip == 0x0002 && state->return_cs == 0x1000) { return 1; } else { sp16 = V86GetAddress (state->return_esp, state->return_ss); eflags = *sp16; eflags = (eflags & 0x257fd5) | (state->return_eflags & 0x1a0000); state->return_eflags = eflags | EFLAG_IF | EFLAG_VM; v86_if = (eflags & EFLAG_IF) ? TRUE : FALSE; state->return_esp = ((state->return_esp & 0x0000ffff) + 2) & 0x0000ffff; sp16 = V86GetAddress (state->return_esp, state->return_ss); state->return_cs = *sp16; state->return_esp = ((state->return_esp & 0x0000ffff) + 2) & 0x0000ffff; sp16 = V86GetAddress (state->return_esp, state->return_ss); state->return_eip = *sp16; state->return_esp = ((state->return_esp & 0x0000ffff) + 2) & 0x0000ffff; return 0; } case OPCODE_CLI: v86_if = FALSE; state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_STI: v86_if = TRUE; state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_OUTB: OutByte (state->edx, state->eax); state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_INB: state->eax = InByte (state->edx); state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_OUTWL: if(is_operand32 == FALSE) OutWord (state->edx, state->eax); else OutLong (state->edx, state->eax); state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_INWL: if(is_operand32 == FALSE) state->eax = InWord (state->edx); else state->eax = InLong (state->edx); state->return_eip = (state->return_eip + 1) & 0x0000ffff; return 0; case OPCODE_OUTB_AL_NN: OutByte (*(ip+1), state->eax); state->return_eip = (state->return_eip + 2) & 0x0000ffff; return 0; case OPCODE_INB_NN_AL: state->eax = InByte (*(ip+1)); state->return_eip = (state->return_eip + 2) & 0x0000ffff; return 0; case OPCODE_OUTWL_EAX_NN: if (is_operand32 == FALSE) OutWord (*(ip+1), state->eax); else OutLong (*(ip+1), state->eax); state->return_eip = (state->return_eip + 2) & 0x0000ffff; return 0; case OPCODE_INWL_NN_EAX: if(is_operand32 == FALSE) state->eax = InWord (*(ip+1)); else state->eax = InLong (*(ip+1)); state->return_eip = (state->return_eip + 2) & 0x0000ffff; return 0; case OPCODE_HLT: { KPANIC ("Halt in V86"); } default: { KPRINTF ("opcode = %#010x", *ip); KPANIC ("#GP Unknown V86 opcode"); } } } }