diff --git a/reactos/boot/bootdata/hivesys.inf b/reactos/boot/bootdata/hivesys.inf index 128ae83640c..eaf9208aa63 100644 --- a/reactos/boot/bootdata/hivesys.inf +++ b/reactos/boot/bootdata/hivesys.inf @@ -441,6 +441,9 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Required",0x HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Vms",0x00020000,"%SystemRoot%\system32\csr.exe ObjectDirectory=\VMS SharedSection=128 Windows=Off SubSystemType=Text ServerDll=vmssrv,1 ProfileControl=Off RequestThreads=2 MaxRequestThreads=2 Sessions=Off" HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Windows",0x00020000,"%SystemRoot%\system32\csrss.exe" +; WOW Support +HKLM,"SYSTEM\CurrentControlSet\Control\Wow","",0x00000000,"" + ; PNP Root device HKLM,"SYSTEM\CurrentControlSet\Enum\HTREE\ROOT\0","",0x00000000,"" diff --git a/reactos/drivers/bus/acpi/ospm/osl.c b/reactos/drivers/bus/acpi/ospm/osl.c index 893d3965f79..9afe2045cff 100644 --- a/reactos/drivers/bus/acpi/ospm/osl.c +++ b/reactos/drivers/bus/acpi/ospm/osl.c @@ -27,11 +27,6 @@ #define NDEBUG #include -/* NDK FIXME */ -NTSTATUS -STDCALL -NtVdmControl (ULONG ControlCode, PVOID ControlData); - static PKINTERRUPT AcpiInterrupt; static BOOLEAN AcpiInterruptHandlerRegistered = FALSE; static OSD_HANDLER AcpiIrqHandler = NULL; @@ -143,13 +138,9 @@ acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, u32 size, void **virt) if (phys == 0x0) { /* Real mode Interrupt Vector Table */ Virtual = ExAllocatePool(NonPagedPool, size); - if (NT_SUCCESS(NtVdmControl(0, Virtual))) { IVTVirtualAddress = Virtual; *virt = Virtual; return AE_OK; - } else { - return AE_ERROR; - } } Address.QuadPart = (ULONG)phys; diff --git a/reactos/drivers/video/videoprt/int10.c b/reactos/drivers/video/videoprt/int10.c index d28e49818cb..0c9cc4cec00 100644 --- a/reactos/drivers/video/videoprt/int10.c +++ b/reactos/drivers/video/videoprt/int10.c @@ -145,53 +145,51 @@ IntInt10WriteMemory( return NO_ERROR; } -VP_STATUS NTAPI +VP_STATUS +NTAPI IntInt10CallBios( - IN PVOID Context, - IN OUT PINT10_BIOS_ARGUMENTS BiosArguments) + IN PVOID Context, + IN OUT PINT10_BIOS_ARGUMENTS BiosArguments) { - KV86M_REGISTERS Regs; - NTSTATUS Status; - PKPROCESS CallingProcess; - KAPC_STATE ApcState; + CONTEXT BiosContext; + NTSTATUS Status; + PKPROCESS CallingProcess; + KAPC_STATE ApcState; - DPRINT("IntInt10CallBios\n"); + /* Attach to CSRSS */ + IntAttachToCSRSS(&CallingProcess, &ApcState); - IntAttachToCSRSS(&CallingProcess, &ApcState); + /* Clear the context */ + RtlZeroMemory(&BiosContext, sizeof(CONTEXT)); - memset(&Regs, 0, sizeof(Regs)); - DPRINT("- Input register Eax: %x\n", BiosArguments->Eax); - Regs.Eax = BiosArguments->Eax; - DPRINT("- Input register Ebx: %x\n", BiosArguments->Ebx); - Regs.Ebx = BiosArguments->Ebx; - DPRINT("- Input register Ecx: %x\n", BiosArguments->Ecx); - Regs.Ecx = BiosArguments->Ecx; - DPRINT("- Input register Edx: %x\n", BiosArguments->Edx); - Regs.Edx = BiosArguments->Edx; - DPRINT("- Input register Esi: %x\n", BiosArguments->Esi); - Regs.Esi = BiosArguments->Esi; - DPRINT("- Input register Edi: %x\n", BiosArguments->Edi); - Regs.Edi = BiosArguments->Edi; - DPRINT("- Input register Ebp: %x\n", BiosArguments->Ebp); - Regs.Ebp = BiosArguments->Ebp; - DPRINT("- Input register SegDs: %x\n", BiosArguments->SegDs); - Regs.Ds = BiosArguments->SegDs; - DPRINT("- Input register SegEs: %x\n", BiosArguments->SegEs); - Regs.Es = BiosArguments->SegEs; - Status = Ke386CallBios(0x10, (PCONTEXT)&Regs); - BiosArguments->Eax = Regs.Eax; - BiosArguments->Ebx = Regs.Ebx; - BiosArguments->Ecx = Regs.Ecx; - BiosArguments->Edx = Regs.Edx; - BiosArguments->Esi = Regs.Esi; - BiosArguments->Edi = Regs.Edi; - BiosArguments->Ebp = Regs.Ebp; - BiosArguments->SegDs = Regs.Ds; - BiosArguments->SegEs = Regs.Es; + /* Fil out the bios arguments */ + BiosContext.Eax = BiosArguments->Eax; + BiosContext.Ebx = BiosArguments->Ebx; + BiosContext.Ecx = BiosArguments->Ecx; + BiosContext.Edx = BiosArguments->Edx; + BiosContext.Esi = BiosArguments->Esi; + BiosContext.Edi = BiosArguments->Edi; + BiosContext.Ebp = BiosArguments->Ebp; + BiosContext.SegDs = BiosArguments->SegDs; + BiosContext.SegEs = BiosArguments->SegEs; - IntDetachFromCSRSS(&CallingProcess, &ApcState); + /* Do the ROM BIOS call */ + Status = Ke386CallBios(0x10, &BiosContext); - return Status; + /* Return the arguments */ + BiosArguments->Eax = BiosContext.Eax; + BiosArguments->Ebx = BiosContext.Ebx; + BiosArguments->Ecx = BiosContext.Ecx; + BiosArguments->Edx = BiosContext.Edx; + BiosArguments->Esi = BiosContext.Esi; + BiosArguments->Edi = BiosContext.Edi; + BiosArguments->Ebp = BiosContext.Ebp; + BiosArguments->SegDs = BiosContext.SegDs; + BiosArguments->SegEs = BiosContext.SegEs; + + /* Detach and return status */ + IntDetachFromCSRSS(&CallingProcess, &ApcState); + return Status; } /* PUBLIC FUNCTIONS ***********************************************************/ diff --git a/reactos/include/ndk/asm.h b/reactos/include/ndk/asm.h index bfe88fd844e..0047dfec50e 100644 --- a/reactos/include/ndk/asm.h +++ b/reactos/include/ndk/asm.h @@ -471,6 +471,11 @@ Author: #define SERVICE_DESCRIPTOR_NUMBER 0x000C #define SERVICE_DESCRIPTOR_LENGTH 0x0010 +// +// VDM State Pointer +// +#define FIXED_NTVDMSTATE_LINEAR_PC_AT 0x714 + // // Machine types // diff --git a/reactos/include/ndk/i386/ketypes.h b/reactos/include/ndk/i386/ketypes.h index 1f078b8d963..df4d7b47f18 100644 --- a/reactos/include/ndk/i386/ketypes.h +++ b/reactos/include/ndk/i386/ketypes.h @@ -83,6 +83,7 @@ Author: #define EFLAGS_ALIGN_CHECK 0x40000 #define EFLAGS_VIF 0x80000 #define EFLAGS_VIP 0x100000 +#define EFLAGS_USER_SANITIZE 0x3F4DD7 #define EFLAG_SIGN 0x8000 #define EFLAG_ZERO 0x4000 diff --git a/reactos/ntoskrnl/KrnlFun.c b/reactos/ntoskrnl/KrnlFun.c index 9dca0e296d3..d0f38c0dee0 100644 --- a/reactos/ntoskrnl/KrnlFun.c +++ b/reactos/ntoskrnl/KrnlFun.c @@ -25,9 +25,10 @@ // - Use Object Type Mutex/Lock. // // Ke: -// - Reimplement the V86 support using a mode that will be compatible with -// VDM and the future and use ABIOS gates. -// - Implement Invalid Opcode and GPD handlers for V86-mode. +// - Clean up exp.c (remove all stack functions and use RtlWalkFrameChain/RtlCaptureStackBacktrace) +// - Sanitize some context fields during conversions +// - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord). +// - Forward exceptions to user-mode debugger. // - Implement stack fault and segment fault handlers. // - Implement kernel-mode GPF handler, possibly fixing below: // - Figure out why ES/DS gets messed up in VMWare, when doing KiServiceExit only, @@ -36,7 +37,6 @@ // - Add DR macro/save and VM macro/save. // - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion. // -// // Ex: // - Use pushlocks for handle implementation. // diff --git a/reactos/ntoskrnl/ex/init.c b/reactos/ntoskrnl/ex/init.c index 4b6676f0317..1f9b29c2ea8 100644 --- a/reactos/ntoskrnl/ex/init.c +++ b/reactos/ntoskrnl/ex/init.c @@ -560,7 +560,7 @@ ExpInitializeExecutive(VOID) /* Initalize the Process Manager */ PiInitProcessManager(); - + /* Break into the Debugger if requested */ if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C); @@ -638,6 +638,9 @@ ExpInitializeExecutive(VOID) /* Import and Load Registry Hives */ CmInitHives(SetupMode); + /* Initialize VDM support */ + KeI386VdmInitialize(); + /* Initialize the time zone information from the registry */ ExpInitTimeZoneInfo(); diff --git a/reactos/ntoskrnl/include/internal/i386/asmmacro.S b/reactos/ntoskrnl/include/internal/i386/asmmacro.S index fc90a3f71af..d67c7aa7888 100644 --- a/reactos/ntoskrnl/include/internal/i386/asmmacro.S +++ b/reactos/ntoskrnl/include/internal/i386/asmmacro.S @@ -150,6 +150,42 @@ _KiUnexpectedInterrupt&Number: .endr .endm +// +// @name INVALID_V86_OPCODE +// +// This macro creates one or more entries for unhandled V86 Opcodes +// in the V86 Opcode Table. +// +// @param count. +// Number of entries to generate. +// +// @remark None. +// +.macro INVALID_V86_OPCODE count + .rept \count + .byte 0 + .endr +.endm + +// +// @name INVALID_V86_OPCODE +// +// This macro prints out visible message and hangs the computer. +// +// @param None. +// +// @remark Temporary debugging use. +// +.macro UNHANDLED_V86_OPCODE + /* Print debug message, breakpoint and freeze */ + push ecx + push offset V86DebugMsg + call _DbgPrint + add esp, 8 + int 3 + jmp $ +.endm + // // @name SET_TF_DEBUG_HEADER // @@ -512,6 +548,134 @@ _KiUnexpectedInterrupt&Number: sti .endm +// +// @name V86_TRAP_PROLOG +// +// This macro creates a V86 Trap entry prologue. +// It should be used for entry into any fast-system call (KiGetTickCount, +// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler +// (KiSystemService) +// +// @param Label +// Unique label identifying the name of the caller function; will be +// used to append to the name of the DR helper function, which must +// already exist. +// +// @remark None. +// +.macro V86_TRAP_PROLOG Label + + /* Skip everything to the error code */ + sub esp, KTRAP_FRAME_ERROR_CODE + + /* Clear the error code */ + mov word ptr [esp+KTRAP_FRAME_ERROR_CODE+2], 0 + + /* Save the registers we'll trample */ + mov [esp+KTRAP_FRAME_EBX], ebx + mov [esp+KTRAP_FRAME_EAX], eax + mov [esp+KTRAP_FRAME_EBP], ebp + mov [esp+KTRAP_FRAME_ESI], esi + mov [esp+KTRAP_FRAME_EDI], edi + + /* Save PCR and Ring 3 segments */ + mov ebx, KGDT_R0_PCR + mov eax, KGDT_R3_DATA + RPL_MASK + + /* Save ECX and EDX too */ + mov [esp+KTRAP_FRAME_ECX], ecx + mov [esp+KTRAP_FRAME_EDX], edx + + /* Set debugging markers */ + mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1 + mov dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00 + + /* Now set segments (use OVERRIDE, 0x66) */ + .byte 0x66 + mov fs, bx + .byte 0x66 + mov ds, ax + .byte 0x66 + mov es, ax + + /* Set the trap frame in the stack and clear the direction flag */ + mov ebp, esp + cld + + /* Save the exception list */ + mov eax, [fs:KPCR_EXCEPTION_LIST] + mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax + + /* Check if we need debugging */ + mov eax, dr7 + test eax, ~DR7_RESERVED_MASK + mov [esp+KTRAP_FRAME_DR7], eax + // jnz Dr_&Label +.endm + +// +// @name V86_TRAP_EPILOG +// +// This macro creates an epilogue for leaving V86 traps +// +// @param None. +// +// @remark None. +// +.macro V86_TRAP_EPILOG + + /* Get the current thread and make it unalerted */ +ExitBegin: + mov ebx, [fs:KPCR_CURRENT_THREAD] + mov byte ptr [ebx+KTHREAD_ALERTED], 0 + + /* Check if it has User-mode APCs pending */ + cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0 + jne PendingUserApc + + /* It doesn't, pop the frame */ + add esp, KTRAP_FRAME_EDX + pop edx + pop ecx + pop eax + + /* Check if DR registers should be restored */ + test dword ptr [ebp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK + //jnz V86DebugRestore + + /* Finish popping the rest of the frame, and return to P-mode */ + add esp, 12 + pop edi + pop esi + pop ebx + pop ebp + add esp, 4 + iretd + +PendingUserApc: + + /* Raise to APC level */ + mov ecx, APC_LEVEL + call @KfRaiseIrql@4 + + /* Save KIRQL and deliver APCs */ + push eax + sti + push ebp + push 0 + push UserMode + call _KiDeliverApc@12 + + /* Restore IRQL */ + pop ecx + call @KfLowerIrql@4 + cli + + /* Check if we're not in V86 anymore */ + test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + jnz ExitBegin +.endm + // // @name TRAP_EPILOG // diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index 5c9669bef97..7360474a487 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -26,7 +26,8 @@ #define X86_CR4_OSFXSR 0x00000200 /* enable FXSAVE/FXRSTOR instructions */ #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable #XF exception */ -#define KF_RDTSC 0x00000002 /* time stamp counters are present */ +#define X86_FEATURE_VME 0x00000002 /* Virtual 8086 Extensions are present */ +#define X86_FEATURE_TSC 0x00000010 /* time stamp counters are present */ #define X86_FEATURE_PAE 0x00000040 /* physical address extension is present */ #define X86_FEATURE_CX8 0x00000100 /* CMPXCHG8B instruction present */ #define X86_FEATURE_SYSCALL 0x00000800 /* SYSCALL/SYSRET support present */ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 431c1c475c5..c4ce57f6a14 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -71,6 +71,10 @@ extern PULONG KiInterruptTemplateObject; extern PULONG KiInterruptTemplateDispatch; extern PULONG KiInterruptTemplate2ndDispatch; extern ULONG KiUnexpectedEntrySize; +extern PVOID Ki386IopmSaveArea; +extern ULONG KeI386EFlagsAndMaskV86; +extern ULONG KeI386EFlagsOrMaskV86; +extern BOOLEAN KeI386VirtualIntExtensions; /* MACROS *************************************************************************/ @@ -139,6 +143,8 @@ extern KSPIN_LOCK DispatcherDatabaseLock; /* One of the Reserved Wait Blocks, this one is for the Thread's Timer */ #define TIMER_WAIT_BLOCK 0x3L +#define IOPM_OFFSET FIELD_OFFSET(KTSS, IoMaps[0].IoMap) + /* INTERNAL KERNEL FUNCTIONS ************************************************/ /* threadsch.c ********************************************************************/ @@ -733,6 +739,24 @@ KiChainedDispatch( VOID ); +VOID +NTAPI +Ki386AdjustEsp0( + IN PKTRAP_FRAME TrapFrame +); + +VOID +NTAPI +Ki386SetupAndExitToV86Mode( + OUT PTEB VdmTeb +); + +VOID +NTAPI +KeI386VdmInitialize( + VOID +); + #include "ke_x.h" #endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */ diff --git a/reactos/ntoskrnl/include/internal/ntoskrnl.h b/reactos/ntoskrnl/include/internal/ntoskrnl.h index d14e91e1a26..743709528d5 100644 --- a/reactos/ntoskrnl/include/internal/ntoskrnl.h +++ b/reactos/ntoskrnl/include/internal/ntoskrnl.h @@ -35,6 +35,7 @@ #include "tag.h" #include "test.h" #include "inbv.h" +#include "vdm.h" #include /* diff --git a/reactos/ntoskrnl/include/internal/vdm.h b/reactos/ntoskrnl/include/internal/vdm.h new file mode 100644 index 00000000000..b97c50b18e7 --- /dev/null +++ b/reactos/ntoskrnl/include/internal/vdm.h @@ -0,0 +1,194 @@ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/include/vdm.h +* PURPOSE: Internal header for V86 and VDM Support +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ + +// +// Define this if you want debugging support +// +#define _VM_DEBUG_ 0x00 + +// +// These define the Debug Masks Supported +// +#define VM_EXEC_DEBUG 0x01 + +// +// Debug/Tracing support +// +#if _VM_DEBUG_ +#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented +#define VMTRACE DbgPrintEx +#else +#define VMTRACE(x, ...) \ + if (x & VdmpTraceLevel) DbgPrint(__VA_ARGS__) +#endif +#else +#define VMTRACE(x, ...) DPRINT(__VA_ARGS__) +#endif + +// +// Memory addresses inside CSRSS for V86 Support +// +#define TRAMPOLINE_BASE 0x10000 +#define TRAMPOLINE_TIB 0x12000 +#define TRAMPOLINE_TEB 0x13000 + +// +// BOP (Magic Opcode) to exit V86 Mode +// +#define TRAMPOLINE_BOP 0xFEC4C4 + +// +// VDM State Pointer +// +#define VdmState \ + (PULONG)FIXED_NTVDMSTATE_LINEAR_PC_AT + +// +// VDM Event Types +// +typedef enum _VdmEventClass +{ + VdmIO, + VdmStringIO, + VdmMemAccess, + VdmIntAck, + VdmBop, + VdmError, + VdmIrq13 +} VDMEVENTCLASS, *PVDMEVENTCLASS; + +// +// VDM Interrupt and Fault Handler Definitions +// +typedef struct _Vdm_InterruptHandler +{ + USHORT CsSelector; + USHORT Flags; + ULONG Eip; +} VDM_INTERRUPTHANDLER, *PVDM_INTERRUPTHANDLER; + +typedef struct _Vdm_FaultHandler +{ + USHORT CsSelector; + USHORT SsSelector; + ULONG Eip; + ULONG Esp; + ULONG Flags; +} VDM_FAULTHANDLER, *PVDM_FAULTHANDLER; + +// +// VDM Event Information +// +typedef struct _VdmEventInfo +{ + ULONG Size; + VDMEVENTCLASS Event; + ULONG InstructionSize; + union + { + //VDMIOINFO IoInfo; + //VDMSTRINGIOINFO StringIoInfo; + ULONG BopNumber; + //VDMFAULTINFO FaultInfo; + LONG ErrorStatus; + ULONG IntAckInfo; + }; +} VDMEVENTINFO, *PVDMEVENTINFO; + +// +// VDM Printer Information +// +typedef struct _Vdm_Printer_Info +{ + PUCHAR prt_state; + // TODO +} VDM_PRINTER_INFO, *PVDM_PRINTER_INFO; + +// +// VDM Trace Information +// +typedef struct _VdmTraceInfo +{ + // TODO + UCHAR Flags; + // TODO +} VDMTRACEINFO, *PVDMTRACEINFO; + +// +// VDM Family Table +// +typedef struct _tagFAMILY_TABLE +{ + INT numHookedAPIs; + // TODO +} FAMILY_TABLE, *PFAMILY_TABLE; + +// +// Thread Information Block for VDM Threads +// +typedef struct _Vdm_Tib +{ + ULONG Size; + PVDM_INTERRUPTHANDLER VdmInterruptTable; + PVDM_FAULTHANDLER VdmFaultTable; + CONTEXT MonitorContext; + CONTEXT VdmContext; + VDMEVENTINFO EventInfo; + VDM_PRINTER_INFO PrinterInfo; + ULONG TempArea1[2]; + ULONG TempArea2[2]; + VDMTRACEINFO TraceInfo; + ULONG IntelMSW; + LONG NumTasks; + PFAMILY_TABLE *pDpmFamTbls; + BOOLEAN ContinueExecution; +} VDM_TIB, *PVDM_TIB; + +// +// Process Information Block for VDM Processes +// +typedef struct _VDM_PROCESS_OBJECTS +{ + PVOID VdmIoListHead; // PVDM_IO_LISTHEAD + KAPC QueuedIntApc; + KAPC QueuedIntUserApc; + FAST_MUTEX DelayIntFastMutex; + KSPIN_LOCK DelayIntSpinLock; + LIST_ENTRY DelayIntListHead; + PVOID pIcaUserData; // VDMICAUSERDATA + PETHREAD MainThread; + PVDM_TIB VdmTib; + UCHAR PrinterState; + UCHAR PrinterControl; + UCHAR PrinterStatus; + UCHAR PrinterHostState; + USHORT AdlibStatus; + USHORT AdlibIndexRegister; + USHORT AdlibPhysPortStart; + USHORT AdlibPhysPortEnd; + USHORT AdlibVirtPortStart; + USHORT AdlibVirtPortEnd; + USHORT AdlibAction; + USHORT VdmControl; + ULONG PMCliTimeStamp; +} VDM_PROCESS_OBJECTS, *PVDM_PROCESS_OBJECTS; + +// +// Functions +// +NTSTATUS +NTAPI +VdmpStartExecution( + VOID +); + +// +// Global data inside the VDM +// + + diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 9328de8c826..98fabbba000 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -9,14 +9,6 @@ * Skywing (skywing@valhallalegends.com) */ -/* - * FIXMES: - * - Clean up file (remove all stack functions and use RtlWalkFrameChain/RtlCaptureStackBacktrace) - * - Sanitize some context fields. - * - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord). - * - Forward exceptions to user-mode debugger. - */ - /* INCLUDES *****************************************************************/ #include @@ -219,33 +211,6 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2) KeDumpStackFrames((PULONG)Tf->Ebp); } -ULONG -KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr) -/* - * FUNCTION: Called by the lowlevel execption handlers to print an amusing - * message and halt the computer - * ARGUMENTS: - * Complete CPU context - */ -{ - ULONG_PTR cr2; - ASSERT(ExceptionNr == 13 || ExceptionNr == 6); - - /* Get CR2 */ - cr2 = Ke386GetCr2(); - Tf->DbgArgPointer = cr2; - - /* - * If this was a V86 mode exception then handle it specially - */ - if (Tf->EFlags & (1 << 17)) - { - DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->EFlags, Tf->Eip, ExceptionNr); - return(KeV86Exception(ExceptionNr, Tf, cr2)); - } - return 0; -} - ULONG NTAPI KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame) @@ -969,7 +934,6 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, ULONG_PTR Stack, NewStack; ULONG Size; BOOLEAN UserDispatch = FALSE; - DPRINT("KiDispatchException() called\n"); /* Increase number of Exception Dispatches */ KeGetCurrentPrcb()->KeExceptionDispatchCount++; diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index e8876a3a872..c390e883189 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -587,7 +587,7 @@ Ki386SetProcessorFeatures(VOID) SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] = (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW) ? TRUE : FALSE; SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] = - (Pcr->PrcbData.FeatureBits & KF_RDTSC) ? TRUE : FALSE; + (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC) ? TRUE : FALSE; SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386Pae; SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] = (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? TRUE : FALSE; diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index 01619f7322c..3f3a39ede50 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -565,7 +565,7 @@ NotUserMode: mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS] /* Check if this is a VDM Process */ - //cmp dword ptr [ebx+KPROCESS_VDM_OBJECTS], 0 + //cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 //jz VdmProc /* Exit through common routine */ @@ -980,18 +980,12 @@ _KiTrap6: /* Enter trap */ TRAP_PROLOG(6) - /* Call the C exception handler */ - push 6 - push ebp - call _KiTrapHandler - add esp, 8 - - /* Check for v86 recovery */ - cmp eax, 1 + /* Not yet supported */ + int 3 + jmp $ /* Return to caller */ - jne _Kei386EoiHelper@0 - jmp _KiV86Complete + jmp _Kei386EoiHelper@0 .endfunc .func KiTrap7 @@ -1205,21 +1199,157 @@ _KiTrap12: .func KiTrap13 _KiTrap13: + + /* It this a V86 GPF? */ + test dword ptr [esp+12], EFLAGS_V86_MASK + jz NotV86 + + /* Enter V86 Trap */ + V86_TRAP_PROLOG kitd + + /* Make sure that this is a V86 process */ + mov ecx, [fs:KPCR_CURRENT_THREAD] + mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS] + cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0 + jnz RaiseIrql + + /* Otherwise, something is very wrong, raise an exception */ + sti + jmp $ + mov ebx, [ebp+KTRAP_FRAME_EIP] + mov esi, -1 + mov eax, STATUS_ACCESS_VIOLATION + jmp _DispatchTwoParam + +RaiseIrql: + + /* Go to APC level */ + mov ecx, APC_LEVEL + call @KfRaiseIrql@4 + + /* Save old IRQL and enable interrupts */ + push eax + sti + + /* Handle the opcode */ + call _Ki386HandleOpcodeV86@0 + + /* Check if this was VDM */ + test al, 0xFF + jnz NoReflect + + /* FIXME: TODO */ + int 3 + +NoReflect: + + /* Lower IRQL and disable interrupts */ + pop ecx + call @KfLowerIrql@4 + cli + + /* Check if this was a V86 trap */ + test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + jz NotV86Trap + + /* Exit the V86 Trap */ + V86_TRAP_EPILOG + +NotV86Trap: + + /* Either this wasn't V86, or it was, but an APC interrupted us */ + jmp _Kei386EoiHelper@0 + +NotV86: /* Enter trap */ TRAP_PROLOG(13) - /* Call the C exception handler */ - push 13 - push ebp - call _KiTrapHandler - add esp, 8 - - /* Check for v86 recovery */ - cmp eax, 1 + /* Check if this was from kernel-mode */ + test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK + jnz UserModeGpf - /* Return to caller */ - jne _Kei386EoiHelper@0 - jmp _KiV86Complete + /* FIXME: Check for GPF during GPF */ + + /* Get the opcode and trap frame */ + mov eax, [ebp+KTRAP_FRAME_EIP] + mov eax, [eax] + mov edx, [ebp+KTRAP_FRAME_EBP] + + /* We want to check if this was POP [DS/ES/FS/GS] */ + add edx, KTRAP_FRAME_DS + cmp al, 0x1F + jz SegPopGpf + add edx, KTRAP_FRAME_ES - KTRAP_FRAME_DS + cmp al, 7 + jz SegPopGpf + add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES + cmp ax, 0xA10F + jz SegPopGpf + add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS + cmp ax, 0xA90F + jz SegPopGpf + + /* It isn't, was it IRETD? */ + cmp al, 0xCF + jne NotIretGpf + + /* Get error code */ + lea edx, [ebp+KTRAP_FRAME_ESP] + mov ax, [ebp+KTRAP_FRAME_ERROR_CODE] + and ax, ~RPL_MASK + + /* Get CS */ + mov cx, word ptr [edx+4] + and cx, ~RPL_MASK + cmp cx, ax + jnz NotCsGpf + + /* This should be a Ki386CallBios return */ + mov eax, offset _Ki386BiosCallReturnAddress + cmp eax, [edx] + jne NotBiosGpf + mov eax, [edx+4] + cmp ax, KGDT_R0_CODE + RPL_MASK + jne NotBiosGpf + + /* Jump to return address */ + jmp _Ki386BiosCallReturnAddress + +NotBiosGpf: + /* Check if the thread was in kernel mode */ + mov ebx, [fs:KPCR_CURRENT_THREAD] + test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF + jz UserModeGpf + + /* Set RPL_MASK for check below */ + or word ptr [edx+4], RPL_MASK + +NotCsGpf: + /* Check if the IRET goes to user-mode */ + test dword ptr [edx+4], RPL_MASK + jz UserModeGpf + + /* FIXME: Handle IRET back to user-mode */ + int 3 + jmp $ + +NotIretGpf: + + /* FIXME: Handle RDMSR/WRMSR and lazy load */ + int 3 + jmp $ + +SegPopGpf: + + /* Handle segment POP fault */ + int 3 + jmp $ + +UserModeGpf: + + /* FIXME: Unhandled */ + int 3 + jmp $ .endfunc .func KiTrap14 diff --git a/reactos/ntoskrnl/ke/i386/v86m.c b/reactos/ntoskrnl/ke/i386/v86m.c deleted file mode 100644 index bf8b6643c3f..00000000000 --- a/reactos/ntoskrnl/ke/i386/v86m.c +++ /dev/null @@ -1,762 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/v86m.c - * PURPOSE: Support for v86 mode - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -/* GLOBALS *******************************************************************/ - -#define IOPL_FLAG ((1 << 12) | (1 << 13)) -#define INTERRUPT_FLAG (1 << 9) -#define TRAP_FLAG (1 << 8) -#define DIRECTION_FLAG (1 << 10) - -#define VALID_FLAGS (0xDFF) - -#define TRAMPOLINE_BASE (0x10000) - -VOID Ki386RetToV86Mode(KV86M_REGISTERS* InRegs, - KV86M_REGISTERS* OutRegs); -/* FUNCTIONS *****************************************************************/ - -ULONG -KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) -{ - PUCHAR ip; - PUSHORT sp; - PULONG dsp; - BOOL BigDataPrefix = FALSE; - BOOL BigAddressPrefix = FALSE; - BOOL RepPrefix = FALSE; - ULONG i = 0; - BOOL Exit = FALSE; - - ip = (PUCHAR)((Tf->SegCs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF)); - sp = (PUSHORT)((Tf->HardwareSegSs & 0xFFFF) * 16 + (Tf->HardwareEsp & 0xFFFF)); - dsp = (PULONG)sp; - - DPRINT("KeV86GPF handling %x at %x:%x ss:sp %x:%x Flags %x\n", - ip[0], Tf->SegCs, Tf->Eip, Tf->Ss, Tf->HardwareEsp, VTf->regs->Flags); - - while (!Exit) - { - //DPRINT1("ip: %lx\n", ip[i]); - switch (ip[i]) - { - /* 32-bit data prefix */ - case 0x66: - BigDataPrefix = TRUE; - i++; - Tf->Eip++; - break; - - /* 32-bit address prefix */ - case 0x67: - BigAddressPrefix = TRUE; - i++; - Tf->Eip++; - break; - - /* rep prefix */ - case 0xFC: - RepPrefix = TRUE; - i++; - Tf->Eip++; - break; - - /* sti */ - case 0xFB: - if (BigDataPrefix || BigAddressPrefix || RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) - { - Tf->Eip++; - VTf->regs->Vif = 1; - return(0); - } - Exit = TRUE; - break; - - /* cli */ - case 0xFA: - if (BigDataPrefix || BigAddressPrefix || RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) - { - Tf->Eip++; - VTf->regs->Vif = 0; - return(0); - } - Exit = TRUE; - break; - - /* pushf */ - case 0x9C: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) - { - Tf->Eip++; - if (!BigAddressPrefix) - { - Tf->HardwareEsp = Tf->HardwareEsp - 2; - sp = sp - 1; - sp[0] = (USHORT)(Tf->EFlags & 0xFFFF); - if (VTf->regs->Vif == 1) - { - sp[0] = (USHORT)(sp[0] | INTERRUPT_FLAG); - } - else - { - sp[0] = (USHORT)(sp[0] & (~INTERRUPT_FLAG)); - } - } - else - { - Tf->HardwareEsp = Tf->HardwareEsp - 4; - dsp = dsp - 1; - dsp[0] = Tf->EFlags; - dsp[0] = dsp[0] & VALID_FLAGS; - if (VTf->regs->Vif == 1) - { - dsp[0] = dsp[0] | INTERRUPT_FLAG; - } - else - { - dsp[0] = dsp[0] & (~INTERRUPT_FLAG); - } - } - return(0); - } - Exit = TRUE; - break; - - /* popf */ - case 0x9D: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) - { - Tf->Eip++; - if (!BigAddressPrefix) - { - Tf->EFlags = Tf->EFlags & (~0xFFFF); - Tf->EFlags = Tf->EFlags | (sp[0] & VALID_FLAGS); - if (Tf->EFlags & INTERRUPT_FLAG) - { - VTf->regs->Vif = 1; - } - else - { - VTf->regs->Vif = 0; - } - Tf->EFlags = Tf->EFlags | INTERRUPT_FLAG; - Tf->HardwareEsp = Tf->HardwareEsp + 2; - } - else - { - Tf->EFlags = Tf->EFlags | (dsp[0] & VALID_FLAGS); - if (dsp[0] & INTERRUPT_FLAG) - { - VTf->regs->Vif = 1; - } - else - { - VTf->regs->Vif = 0; - } - Tf->EFlags = Tf->EFlags | INTERRUPT_FLAG; - Tf->HardwareEsp = Tf->HardwareEsp + 2; - } - return(0); - } - Exit = TRUE; - break; - - /* iret */ - case 0xCF: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) - { - Tf->Eip = sp[0]; - Tf->SegCs = sp[1]; - Tf->EFlags = Tf->EFlags & (~0xFFFF); - Tf->EFlags = Tf->EFlags | sp[2]; - if (Tf->EFlags & INTERRUPT_FLAG) - { - VTf->regs->Vif = 1; - } - else - { - VTf->regs->Vif = 0; - } - Tf->EFlags = Tf->EFlags & (~INTERRUPT_FLAG); - Tf->HardwareEsp = Tf->HardwareEsp + 6; - return(0); - } - Exit = TRUE; - break; - - /* out imm8, al */ - case 0xE6: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - DPRINT("outb %d, %x\n", (ULONG)ip[i + 1], Tf->Eax & 0xFF); - WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[i + 1], - (UCHAR)(Tf->Eax & 0xFF)); - Tf->Eip = Tf->Eip + 2; - return(0); - } - Exit = TRUE; - break; - - /* out imm8, ax */ - case 0xE7: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - if (!BigDataPrefix) - { - DPRINT("outw %d, %x\n", (ULONG)ip[i + 1], Tf->Eax & 0xFFFF); - WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], (USHORT)(Tf->Eax & 0xFFFF)); - } - else - { - DPRINT("outl %d, %x\n", (ULONG)ip[i + 1], Tf->Eax); - WRITE_PORT_ULONG((PULONG)(ULONG)ip[1], Tf->Eax); - } - Tf->Eip = Tf->Eip + 2; - return(0); - } - Exit = TRUE; - break; - - /* out dx, al */ - case 0xEE: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - DPRINT("outb %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax & 0xFF); - WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), (UCHAR)(Tf->Eax & 0xFF)); - Tf->Eip = Tf->Eip + 1; - return(0); - } - Exit = TRUE; - break; - - /* out dx, ax */ - case 0xEF: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - if (!BigDataPrefix) - { - DPRINT("outw %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax & 0xFFFF); - WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF), - (USHORT)(Tf->Eax & 0xFFFF)); - } - else - { - DPRINT("outl %d, %x\n", Tf->Edx & 0xFFFF, Tf->Eax); - WRITE_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF), - Tf->Eax); - } - Tf->Eip = Tf->Eip + 1; - return(0); - } - Exit = TRUE; - break; - - /* in al, imm8 */ - case 0xE4: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - UCHAR v; - - v = READ_PORT_UCHAR((PUCHAR)(ULONG)ip[1]); - DPRINT("inb %d\t%X\n", (ULONG)ip[1], v); - Tf->Eax = Tf->Eax & (~0xFF); - Tf->Eax = Tf->Eax | v; - Tf->Eip = Tf->Eip + 2; - return(0); - } - Exit = TRUE; - break; - - /* in ax, imm8 */ - case 0xE5: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - if (!BigDataPrefix) - { - USHORT v; - v = READ_PORT_USHORT((PUSHORT)(ULONG)ip[1]); - DPRINT("inw %d\t%X\n", (ULONG)ip[1], v); - Tf->Eax = Tf->Eax & (~0xFFFF); - Tf->Eax = Tf->Eax | v; - } - else - { - ULONG v; - v = READ_PORT_ULONG((PULONG)(ULONG)ip[1]); - DPRINT("inl %d\t%X\n", (ULONG)ip[1], v); - Tf->Eax = v; - } - Tf->Eip = Tf->Eip + 2; - return(0); - } - Exit = TRUE; - break; - - /* in al, dx */ - case 0xEC: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - UCHAR v; - - v = READ_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF)); - DPRINT("inb %d\t%X\n", Tf->Edx & 0xFFFF, v); - Tf->Eax = Tf->Eax & (~0xFF); - Tf->Eax = Tf->Eax | v; - Tf->Eip = Tf->Eip + 1; - return(0); - } - Exit = TRUE; - break; - - /* in ax, dx */ - case 0xED: - if (RepPrefix) - { - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); - } - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - if (!BigDataPrefix) - { - USHORT v; - - v = READ_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF)); - DPRINT("inw %d\t%X\n", Tf->Edx & 0xFFFF, v); - Tf->Eax = Tf->Eax & (~0xFFFF); - Tf->Eax = Tf->Eax | v; - } - else - { - ULONG v; - - v = READ_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF)); - DPRINT("inl %d\t%X\n", Tf->Edx & 0xFFFF, v); - Tf->Eax = v; - } - Tf->Eip = Tf->Eip + 1; - return(0); - } - Exit = TRUE; - break; - - /* outsb */ - case 0x6E: - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - ULONG Count; - PUCHAR Port; - PUCHAR Buffer; - ULONG Offset; - - Count = 1; - if (RepPrefix) - { - Count = Tf->Ecx; - if (!BigAddressPrefix) - { - Count = Count & 0xFFFF; - } - } - - Port = (PUCHAR)(Tf->Edx & 0xFFFF); - Offset = Tf->Edi; - if (!BigAddressPrefix) - { - Offset = Offset & 0xFFFF; - } - Buffer = (PUCHAR)((Tf->SegEs * 16) + Offset); - for (; Count > 0; Count--) - { - WRITE_PORT_UCHAR(Port, *Buffer); - if (Tf->EFlags & DIRECTION_FLAG) - { - Buffer++; - } - else - { - Buffer--; - } - } - Tf->Eip++; - return(0); - } - Exit = TRUE; - break; - - /* insw/insd */ - case 0x6F: - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - ULONG Count; - PUCHAR Port; - PUSHORT BufferS = NULL; - PULONG BufferL = NULL; - ULONG Offset; - - Count = 1; - if (RepPrefix) - { - Count = Tf->Ecx; - if (!BigAddressPrefix) - { - Count = Count & 0xFFFF; - } - } - - Port = (PUCHAR)(Tf->Edx & 0xFFFF); - Offset = Tf->Edi; - if (!BigAddressPrefix) - { - Offset = Offset & 0xFFFF; - } - if (BigDataPrefix) - { - BufferL = (PULONG)((Tf->SegEs * 16) + Offset); - } - else - { - BufferS = (PUSHORT)((Tf->SegEs * 16) + Offset); - } - for (; Count > 0; Count--) - { - if (BigDataPrefix) - { - WRITE_PORT_ULONG((PULONG)Port, *BufferL); - } - else - { - WRITE_PORT_USHORT((PUSHORT)Port, *BufferS); - } - if (Tf->EFlags & DIRECTION_FLAG) - { - if (BigDataPrefix) - { - BufferL++; - } - else - { - BufferS++; - } - } - else - { - if (BigDataPrefix) - { - BufferL--; - } - else - { - BufferS--; - } - } - } - Tf->Eip++; - return(0); - } - Exit = TRUE; - break; - - /* insb */ - case 0x6C: - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - ULONG Count; - PUCHAR Port; - PUCHAR Buffer; - ULONG Offset; - - Count = 1; - if (RepPrefix) - { - Count = Tf->Ecx; - if (!BigAddressPrefix) - { - Count = Count & 0xFFFF; - } - } - - Port = (PUCHAR)(Tf->Edx & 0xFFFF); - Offset = Tf->Edi; - if (!BigAddressPrefix) - { - Offset = Offset & 0xFFFF; - } - Buffer = (PUCHAR)((Tf->SegEs * 16) + Offset); - for (; Count > 0; Count--) - { - *Buffer = READ_PORT_UCHAR(Port); - if (Tf->EFlags & DIRECTION_FLAG) - { - Buffer++; - } - else - { - Buffer--; - } - } - Tf->Eip++; - return(0); - } - Exit = TRUE; - break; - - /* insw/insd */ - case 0x6D: - if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) - { - ULONG Count; - PUCHAR Port; - PUSHORT BufferS = NULL; - PULONG BufferL = NULL; - ULONG Offset; - - Count = 1; - if (RepPrefix) - { - Count = Tf->Ecx; - if (!BigAddressPrefix) - { - Count = Count & 0xFFFF; - } - } - - Port = (PUCHAR)(Tf->Edx & 0xFFFF); - Offset = Tf->Edi; - if (!BigAddressPrefix) - { - Offset = Offset & 0xFFFF; - } - if (BigDataPrefix) - { - BufferL = (PULONG)((Tf->SegEs * 16) + Offset); - } - else - { - BufferS = (PUSHORT)((Tf->SegEs * 16) + Offset); - } - for (; Count > 0; Count--) - { - if (BigDataPrefix) - { - *BufferL = READ_PORT_ULONG((PULONG)Port); - } - else - { - *BufferS = READ_PORT_USHORT((PUSHORT)Port); - } - if (Tf->EFlags & DIRECTION_FLAG) - { - if (BigDataPrefix) - { - BufferL++; - } - else - { - BufferS++; - } - } - else - { - if (BigDataPrefix) - { - BufferL--; - } - else - { - BufferS--; - } - } - } - Tf->Eip++; - return(0); - } - Exit = TRUE; - break; - - /* Int nn */ - case 0xCD: - { - unsigned int inum; - unsigned int entry; - - inum = ip[1]; - entry = ((unsigned int *)0)[inum]; - - Tf->HardwareEsp = Tf->HardwareEsp - 6; - sp = sp - 3; - - sp[0] = (USHORT)((Tf->Eip & 0xFFFF) + 2); - sp[1] = (USHORT)(Tf->SegCs & 0xFFFF); - sp[2] = (USHORT)(Tf->EFlags & 0xFFFF); - if (VTf->regs->Vif == 1) - { - sp[2] = (USHORT)(sp[2] | INTERRUPT_FLAG); - } - DPRINT("sp[0] %x sp[1] %x sp[2] %x\n", sp[0], sp[1], sp[2]); - Tf->Eip = entry & 0xFFFF; - Tf->SegCs = entry >> 16; - Tf->EFlags = Tf->EFlags & (~TRAP_FLAG); - - return(0); - } - } - - /* FIXME: Also emulate ins and outs */ - /* FIXME: Handle opcode prefixes */ - /* FIXME: Don't allow the BIOS to write to sensitive I/O ports */ - } - - DPRINT1("V86GPF unhandled (was %x)\n", ip[i]); - *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; - return(1); -} - -ULONG -NTAPI -KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address) -{ - PUCHAR Ip; - PKV86M_TRAP_FRAME VTf; - - VTf = (PKV86M_TRAP_FRAME)Tf; - - /* - * Check if we have reached the recovery instruction - */ - Ip = (PUCHAR)((Tf->SegCs & 0xFFFF) * 16 + (Tf->Eip & 0xFFFF)); - - if (ExceptionNr == 6 && - memcmp(Ip, VTf->regs->RecoveryInstruction, 4) == 0 && - (Tf->SegCs * 16 + Tf->Eip) == VTf->regs->RecoveryAddress) - { - *VTf->regs->PStatus = STATUS_SUCCESS; - return(1); - } - - ASSERT(ExceptionNr == 13); - return(KeV86GPF(VTf, Tf)); -} - -NTSTATUS STDCALL -Ke386CallBios(ULONG Int, PCONTEXT regs) -{ - PUCHAR Ip; - KV86M_REGISTERS ORegs; - NTSTATUS Status; - PKV86M_REGISTERS Regs = (PKV86M_REGISTERS)regs; - - /* - * Set up a trampoline for executing the BIOS interrupt - */ - Ip = (PUCHAR)TRAMPOLINE_BASE; - Ip[0] = 0xCD; /* int XX */ - Ip[1] = Int; - Ip[2] = 0x63; /* arpl ax, ax */ - Ip[3] = 0xC0; - Ip[4] = 0x90; /* nop */ - Ip[5] = 0x90; /* nop */ - - /* - * Munge the registers - */ - Regs->Eip = 0; - Regs->Cs = TRAMPOLINE_BASE / 16; - Regs->Esp = 0xFFFF; - Regs->Ss = TRAMPOLINE_BASE / 16; - Regs->Eflags = (1 << 1) | (1 << 17) | (1 << 9); /* VM, IF */ - Regs->RecoveryAddress = TRAMPOLINE_BASE + 2; - Regs->RecoveryInstruction[0] = 0x63; /* arpl ax, ax */ - Regs->RecoveryInstruction[1] = 0xC0; - Regs->RecoveryInstruction[2] = 0x90; /* nop */ - Regs->RecoveryInstruction[3] = 0x90; /* nop */ - Regs->Flags = KV86M_EMULATE_CLI_STI | KV86M_ALLOW_IO_PORT_ACCESS; - Regs->Vif = 1; - Regs->PStatus = &Status; - - /* - * Execute the BIOS interrupt - */ - Ki386RetToV86Mode(Regs, &ORegs); - - /* - * Copy the return values back to the caller - */ - memcpy(Regs, &ORegs, sizeof(KV86M_REGISTERS)); - - return(Status); -} - diff --git a/reactos/ntoskrnl/ke/i386/v86m_sup.S b/reactos/ntoskrnl/ke/i386/v86m_sup.S index 078b0646410..8db3c4c7cc3 100644 --- a/reactos/ntoskrnl/ke/i386/v86m_sup.S +++ b/reactos/ntoskrnl/ke/i386/v86m_sup.S @@ -1,175 +1,844 @@ /* - * FILE: ntoskrnl/ke/i386/vm86_sup.S - * PURPOSE: V86 mode support - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * Created 09/10/00 + * FILE: ntoskrnl/ke/i386/v86m_sup.S + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: Virtual 8086 (V86) Mode Support + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * NOTE: See asmmacro.S for the V86 trap code. */ -#include - -.globl _Ki386RetToV86Mode -.globl _KiV86Complete +/* INCLUDES ******************************************************************/ - /* - * VOID Ki386RetToV86Mode(KV86M_REGISTERS* InRegs, - * KV86M_REGISTERS* OutRegs); - * - * Starts in v86 mode with the registers set to the - * specified values. - */ -_Ki386RetToV86Mode: - /* - * Setup a stack frame - */ - pushl %ebp - movl %esp, %ebp +#include +#include +.intel_syntax noprefix - /* - * Save registers - */ - pusha +/* FIXME: Can we make a nice macro to generate V86 Opcode handlers? */ - /* - * Get a pointer to IN_REGS - */ - movl 8(%ebp), %ebx +/* GLOBALS *******************************************************************/ - /* - * Save ebp - */ - pushl %ebp +// +// This table contains indexes into the OpcodeDispatchV86 Table for opcodes in +// Virtual-8086 Mode. +// There are 256 entries. +// +OpcodeIndex: + INVALID_V86_OPCODE 15 /* OP 00-14: UNHANDLED */ + .byte 1 /* OP 0F: 0F */ + INVALID_V86_OPCODE 22 /* OP 10-25: UNHANDLED */ + .byte 2 /* OP 26: ES Prefix */ + INVALID_V86_OPCODE 7 /* OP 27-2D: UNHANDLED */ + .byte 3 /* OP 2E: CS Prefix */ + INVALID_V86_OPCODE 7 /* OP 2F-35: UNHANDLED */ + .byte 4 /* OP 36: SS Prefix */ + INVALID_V86_OPCODE 7 /* OP 37-3D: UNHANDLED */ + .byte 5 /* OP 3E: DS Prefix */ + INVALID_V86_OPCODE 37 /* OP 3F-63: UNHANDLED */ + .byte 6 /* OP 64: FS Prefix */ + .byte 7 /* OP 65: GS Prefix */ + .byte 8 /* OP 66: OPER32 Prefix */ + .byte 9 /* OP 67: ADDR32 Prefix */ + INVALID_V86_OPCODE 4 /* OP 68-6B: UNHANDLED */ + .byte 10 /* OP 6C: INSB */ + .byte 11 /* OP 6D: INSW */ + .byte 12 /* OP 6E: OUTSB */ + .byte 13 /* OP 6F: OUTSW */ + INVALID_V86_OPCODE 43 /* OP 70-9A: UNHANDLED */ + .byte 19 /* OP 9B: NPX */ + .byte 14 /* OP 9C: PUSHF */ + .byte 15 /* OP 9D: POPF */ + INVALID_V86_OPCODE 47 /* OP 9E-CC: UNHANDLED */ + .byte 16 /* OP CD: INTnn */ + .byte 17 /* OP CE: INTO */ + .byte 18 /* OP CF: IRETD */ + INVALID_V86_OPCODE 8 /* OP D0-D7: UNHANDLED */ + .byte 19 /* OP D8: NPX */ + .byte 19 /* OP D9: NPX */ + .byte 19 /* OP DA: NPX */ + .byte 19 /* OP DB: NPX */ + .byte 19 /* OP DC: NPX */ + .byte 19 /* OP DD: NPX */ + .byte 19 /* OP DE: NPX */ + .byte 19 /* OP DF: NPX */ + INVALID_V86_OPCODE 4 /* OP DE-E3: UNHANDLED */ + .byte 20 /* OP E4: INBimm */ + .byte 21 /* OP E5: INWimm */ + .byte 22 /* OP E6: OUTBimm */ + .byte 23 /* OP E7: OUTWimm */ + INVALID_V86_OPCODE 4 /* OP E8-EB: UNHANDLED */ + .byte 24 /* OP EC: INB */ + .byte 25 /* OP EF: INW */ + .byte 26 /* OP EE: OUTB */ + .byte 27 /* OP EF: OUTW */ + .byte 28 /* OP F0: LOCK Prefix */ + .byte 0 /* OP F1: UNHANDLED */ + .byte 29 /* OP F2: REPNE Prefix */ + .byte 30 /* OP F3: REP Prefix */ + .byte 33 /* OP F4: HLT */ + INVALID_V86_OPCODE 5 /* OP F5-F9: UNHANDLED */ + .byte 31 /* OP FA: CLI */ + .byte 32 /* OP FB: STI */ + INVALID_V86_OPCODE 4 /* OP FC-FF: UNHANDLED */ - /* - * Save a pointer to IN_REGS which the v86m exception handler will - * use to handle exceptions - */ - pushl %ebx +// +// This table contains the emulation routines for +// Virtual-8086 Mode. There are 34 entries. +// +OpcodeDispatchV86: + .long _OpcodeInvalidV86 + .long _Opcode0FV86 + .long _OpcodeESPrefixV86 + .long _OpcodeCSPrefixV86 + .long _OpcodeSSPrefixV86 + .long _OpcodeDSPrefixV86 + .long _OpcodeFSPrefixV86 + .long _OpcodeGSPrefixV86 + .long _OpcodeOPER32PrefixV86 + .long _OpcodeADDR32PrefixV86 + .long _OpcodeINSBV86 + .long _OpcodeINSWV86 + .long _OpcodeOUTSBV86 + .long _OpcodeOUTSWV86 + .long _OpcodePUSHFV86 + .long _OpcodePOPFV86 + .long _OpcodeINTnnV86 + .long _OpcodeINTOV86 + .long _OpcodeIRETV86 + .long _OpcodeNPXV86 + .long _OpcodeINBimmV86 + .long _OpcodeINWimmV86 + .long _OpcodeOUTBimmV86 + .long _OpcodeOUTWimmV86 + .long _OpcodeINBV86 + .long _OpcodeINWV86 + .long _OpcodeOUTBV86 + .long _OpcodeOUTWV86 + .long _OpcodeLOCKPrefixV86 + .long _OpcodeREPNEPrefixV86 + .long _OpcodeREPPrefixV86 + .long _OpcodeCLIV86 + .long _OpcodeSTIV86 + .long _OpcodeHLTV86 - /* - * Since we are going to fiddle with the stack pointer this must be - * a critical section for this processor - */ - cli - - /* - * Save the exception handler stack from the TSS - */ - movl %fs:KPCR_TSS, %esi - pushl KTSS_ESP0(%esi) +_ExVdmOpcodeDispatchCounts: + .rept 34 + .long 0 + .endr - /* - * The stack used for handling exceptions from v86 mode in this thread - * will be the current stack adjusted so we don't overwrite the - * existing stack frames - */ - movl %esp, KTSS_ESP0(%esi) +V86DebugMsg: + .asciz "Received V86 Emulation Opcode: %lx\n" - /* - * Create the stack frame for an iret to v86 mode - */ - pushl KV86M_REGISTERS_GS(%ebx) - pushl KV86M_REGISTERS_FS(%ebx) - pushl KV86M_REGISTERS_DS(%ebx) - pushl KV86M_REGISTERS_ES(%ebx) - pushl KV86M_REGISTERS_SS(%ebx) - pushl KV86M_REGISTERS_ESP(%ebx) - pushl KV86M_REGISTERS_EFLAGS(%ebx) - pushl KV86M_REGISTERS_CS(%ebx) - pushl KV86M_REGISTERS_EIP(%ebx) +/* VIRTUAL-8086 MODE OPCODER HANDLERS ****************************************/ - /* - * Setup the CPU registers - */ - movl KV86M_REGISTERS_EAX(%ebx), %eax - movl KV86M_REGISTERS_ECX(%ebx), %ecx - movl KV86M_REGISTERS_EDX(%ebx), %edx - movl KV86M_REGISTERS_ESI(%ebx), %esi - movl KV86M_REGISTERS_EDI(%ebx), %edi - movl KV86M_REGISTERS_EBP(%ebx), %ebp - movl KV86M_REGISTERS_EBX(%ebx), %ebx +.func OpcodeInvalidV86 +_OpcodeInvalidV86: + UNHANDLED_V86_OPCODE +.endfunc - /* - * Go to v86 mode - */ - iret +.func Opcode0FV86 +_Opcode0FV86: + UNHANDLED_V86_OPCODE +.endfunc - /* - * Handle the completion of a vm86 routine. We are called from - * an exception handler with the registers at the point of the - * exception on the stack. - */ -_KiV86Complete: - /* Restore the original ebp */ - movl TF_ORIG_EBP(%esp), %ebp +.func OpcodeESPrefixV86 +_OpcodeESPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Get a pointer to the OUT_REGS structure */ - movl 12(%ebp), %ebx +.func OpcodeCSPrefixV86 +_OpcodeCSPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Skip debug information and unsaved registers */ - addl $0x30, %esp +.func OpcodeSSPrefixV86 +_OpcodeSSPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Ignore 32-bit segment registers */ - addl $12, %esp +.func OpcodeDSPrefixV86 +_OpcodeDSPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Save the vm86 registers into the OUT_REGS structure */ - popl KV86M_REGISTERS_EDX(%ebx) - popl KV86M_REGISTERS_ECX(%ebx) - popl KV86M_REGISTERS_EAX(%ebx) +.func OpcodeFSPrefixV86 +_OpcodeFSPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Restore the old previous mode */ - popl %eax - movb %al, %ss:KTHREAD_PREVIOUS_MODE(%esi) +.func OpcodeGSPrefixV86 +_OpcodeGSPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Restore the old exception handler list */ - popl %eax - movl %eax, %fs:KPCR_EXCEPTION_LIST - - /* Ignore the 32-bit fs register */ - addl $4, %esp +.func OpcodeOPER32PrefixV86 +_OpcodeOPER32PrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - popl KV86M_REGISTERS_EDI(%ebx) - popl KV86M_REGISTERS_ESI(%ebx) - popl KV86M_REGISTERS_EBX(%ebx) - popl KV86M_REGISTERS_EBP(%ebx) +.func OpcodeADDR32PrefixV86 +_OpcodeADDR32PrefixV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Ignore error code */ - addl $4, %esp +.func OpcodeINSBV86 +_OpcodeINSBV86: + UNHANDLED_V86_OPCODE +.endfunc - popl KV86M_REGISTERS_EIP(%ebx) - popl KV86M_REGISTERS_CS(%ebx) - popl KV86M_REGISTERS_EFLAGS(%ebx) - popl KV86M_REGISTERS_ESP(%ebx) - popl KV86M_REGISTERS_SS(%ebx) - popl KV86M_REGISTERS_ES(%ebx) - popl KV86M_REGISTERS_DS(%ebx) - popl KV86M_REGISTERS_FS(%ebx) - popl KV86M_REGISTERS_GS(%ebx) +.func OpcodeINSWV86 +_OpcodeINSWV86: + UNHANDLED_V86_OPCODE +.endfunc - /* - * We are going to fiddle with the stack so this must be a critical - * section for this process - */ - cli +.func OpcodeOUTSBV86 +_OpcodeOUTSBV86: + UNHANDLED_V86_OPCODE +.endfunc - /* - * Restore the exception handler stack in the TSS - */ - movl %fs:KPCR_TSS, %esi - popl KTSS_ESP0(%esi) +.func OpcodeOUTSWV86 +_OpcodeOUTSWV86: + UNHANDLED_V86_OPCODE +.endfunc - /* Exit the critical section */ - sti +.func OpcodePUSHFV86 +_OpcodePUSHFV86: - /* Ignore IN_REGS pointer */ - addl $4, %esp + /* Get VDM state */ + mov eax, 0x714 + mov eax, [eax] - /* Ignore ebp restored above */ - addl $4, %esp + /* Get EFLAGS and mask out IF */ + mov edx, [ebp+KTRAP_FRAME_EFLAGS] + and eax, ~EFLAGS_INTERRUPT_MASK - /* Return to caller */ - popa - movl %ebp, %esp - popl %ebp - ret + /* Mask align check and interrupt mask */ + and eax, EFLAGS_ALIGN_CHECK + 0x4000 + EFLAGS_INTERRUPT_MASK + or eax, edx + /* Add IOPL Mask */ + or eax, 0x3000 + + /* Get flat ESP */ + movzx ecx, word ptr [ebp+KTRAP_FRAME_SS] + shl ecx, 4 + movzx edx, word ptr [ebp+KTRAP_FRAME_ESP] + sub dx, 2 + + /* Check if there is an OPER32 prefix */ + test ebx, 0x4000 + jnz SkipPrefix + + /* Push EFLAGS */ + mov [ecx+edx], ax + +UpdateFrame: + + /* Update ESP and EIP */ + mov [ebp+KTRAP_FRAME_ESP], dx + add [ebp+KTRAP_FRAME_EIP], edi + + /* Return success */ + mov eax, 1 + ret + +SkipPrefix: + + /* Skip the prefix, push EFLAGS and jump back */ + sub dx, 2 + mov [edx+ecx], eax + jmp UpdateFrame +.endfunc + +.func OpcodePOPFV86 +_OpcodePOPFV86: + + /* Get VDM state */ + mov eax, 0x714 + + /* Get flat ESP */ + mov ecx, [ebp+KTRAP_FRAME_SS] + shl ecx, 4 + movzx edx, word ptr [ebp+KTRAP_FRAME_ESP] + + /* Pop EFLAGS */ + mov ecx, [ecx+edx] + add edx, 4 + + /* Check for OPER32 prefix */ + test ebx, 0x4000 + jnz NoPrefix + + /* Skip 2 bytes */ + and ecx, 0xFFFF + sub edx, 2 + +NoPrefix: + + /* Set new ESP */ + mov [ebp+KTRAP_FRAME_ESP], edx + + /* Mask out EFLAGS */ + and eax, ~0x3000 + mov ebx, ebx + and ebx, ~0x4000 + and ecx, EFLAGS_ALIGN_CHECK + 0x4000 + EFLAGS_INTERRUPT_MASK + + /* FIXME: Support VME */ + + /* Save VDM State pointer */ + push eax + + /* Set new EFLAGS, make sure to add IF and V86 */ + or ebx, EFLAGS_INTERRUPT_MASK + EFLAGS_V86_MASK + push [ebp+KTRAP_FRAME_EFLAGS] + mov [ebp+KTRAP_FRAME_EFLAGS], ebx + + /* Make sure we were in V86 mode */ + test ebx, EFLAGS_V86_MASK + jnz CheckEspAdjust + int 3 + +CheckEspAdjust: + + /* Check if we have to update ESP0 and fixup the stack from our push */ + test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + lea esp, [esp+4] + jnz NoAdjustEsp0 + + /* Adjust it */ + push ebp + call _Ki386AdjustEsp0@4 + +NoAdjustEsp0: + + /* Restore VDM state */ + pop eax + + /* Update the flags in the VDM State */ + LOCK and dword ptr [eax], ~(EFLAGS_ALIGN_CHECK + 0x4000 + EFLAGS_INTERRUPT_MASK) + LOCK or [eax], ecx + + /* Update EIP */ + add [ebp+KTRAP_FRAME_EIP], edi + + /* FIXME: Check for VDM Pending interrupts */ + + /* Return success */ + mov eax, 1 + ret +.endfunc + +.func OpcodeINTnnV86 +_OpcodeINTnnV86: + + /* Get EFlags */ + mov edx, [ebp+KTRAP_FRAME_EFLAGS] + + /* Remove the flag in the VDM State */ + mov eax, 0x714 + mov ecx, [eax] + LOCK and dword ptr [eax], ~EFLAGS_INTERRUPT_MASK + + /* Mask it out from EFLAGS too */ + mov eax, edx + and eax, ~EFLAGS_INTERRUPT_MASK + + /* Mask out the alignment check and IF flag from the VDM state */ + and ecx, EFLAGS_ALIGN_CHECK + EFLAGS_INTERRUPT_MASK + + /* FIXME: Support VME */ + + /* Now mask out VIF and TF */ + or eax, ecx + and edx, ~(EFLAGS_VIF + 0x4000 + EFLAGS_TF) + mov [ebp+KTRAP_FRAME_EFLAGS], edx + + /* Set the IOPL Mask */ + or eax, 0x3000 + + /* Get stack flat address */ + movzx ecx, word ptr [ebp+KTRAP_FRAME_SS] + shl ecx, 4 + movzx edx, word ptr [ebp+KTRAP_FRAME_ESP] + + /* Push EFLAGS */ + sub dx, 2 + mov word ptr [ecx+edx], ax + + /* Push CS */ + mov ax, word ptr [ebp+KTRAP_FRAME_CS] + sub dx, 2 + mov word ptr [ecx+edx], ax + + /* Push IP */ + movzx eax, word ptr [ebp+KTRAP_FRAME_EIP] + add eax, edi + inc eax + sub dx, 2 + mov word ptr [ecx+edx], ax + + /* Update ESP */ + mov [ebp+KTRAP_FRAME_ESP], dx + + /* Get the interrupt */ + inc esi + movzx ecx, byte ptr [esi] + /* FIXME: Analyze and see if this is a hooked VDM (PM) Interrupt */ + + /* Get the entry in the IVT */ + mov ebx, [ecx*4] + mov eax, ebx + shr eax, 16 + + /* Update EIP */ + mov word ptr [ebp+KTRAP_FRAME_EIP], bx + + /* Check if this was V86 mode */ + test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK + jnz SetCs + + /* Check if it was a kernel CS */ + or ax, RPL_MASK + cmp ax, KGDT_R0_CODE + jnb SetCs + + /* Set user-mode CS */ + mov ax, KGDT_R3_CODE + RPL_MASK + +SetCs: + /* Set new CS */ + mov [ebp+KTRAP_FRAME_CS], ax + + /* Return success */ + mov eax, 1 + ret +.endfunc + +.func OpcodeINTOV86 +_OpcodeINTOV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeIRETV86 +_OpcodeIRETV86: + + /* Get the VDM State */ + mov eax, 0x714 + + /* Get flat ESP */ + movzx ecx, word ptr [ebp+KTRAP_FRAME_SS] + shl ecx, 4 + movzx edx, word ptr [ebp+KTRAP_FRAME_ESP] + add ecx, edx + + /* Check for OPER32 prefix */ + test ebx, 0x4000 + jnz Iret32 + + /* Get flat IP */ + movzx edi, word ptr [ecx] + mov [ebp+KTRAP_FRAME_EIP], edi + movzx esi, word ptr [ecx+2] + mov [ebp+KTRAP_FRAME_CS], esi + + /* Update ESP */ + add edx, 6 + mov [ebp+KTRAP_FRAME_ESP], edx + + /* Get EFLAGS */ + movzx ebx, word ptr [ecx+4] + +MaskEFlags: + + /* Mask out EFLAGS */ + and ebx, ~(0x3000 + EFLAGS_VIF + 0x4000 + EFLAGS_VIP) + mov ecx, ebx + + /* FIXME: Check for VME support */ + + /* Save VDM state */ + push eax + + /* Enable V86 and Interrupts */ + or ebx, EFLAGS_V86_MASK + EFLAGS_INTERRUPT_MASK + + /* Save old flags */ + mov eax, [ebp+KTRAP_FRAME_EFLAGS] + push eax + + /* Mask out VIP and set new eflags */ + and eax, EFLAGS_VIP + or eax, ebx + mov [ebp+KTRAP_FRAME_EFLAGS], eax + + /* Check if we have to update ESP0 */ + pop ebx + test ebx, EFLAGS_V86_MASK + jnz NoEsp0Update + + /* Save ECX and ECX */ + push ecx + push edx + + /* Update esp0 and restore registers */ + push ebp + call _Ki386AdjustEsp0@4 + pop edx + pop ecx + +NoEsp0Update: + + /* Put VDM state in EAX and update VDM EFlags */ + pop eax + and ecx, EFLAGS_INTERRUPT_MASK + LOCK and dword ptr [eax], ~EFLAGS_INTERRUPT_MASK + LOCK or [eax], ecx + + /* Get flat EIP and check if this is the BOP */ + shl esi, 4 + add esi, edi + mov ax, [esi] + cmp ax, 0xC4C4 + jz IsBop + + /* FIXME: Check for VDM interrupts */ + + /* Return success */ +RetIret: + mov eax, 1 + ret + +IsBop: + + /* Call the BOP handler */ + push ebp + call _VdmDispatchBop@4 + jmp RetIret + +Iret32: + + /* Get 32-bit flat EIP */ + mov edi, [ecx] + mov [ebp+KTRAP_FRAME_EIP], edi + movzx esi, word ptr [ecx+4] + mov [ebp+KTRAP_FRAME_CS], esi + + /* Set new ESP */ + add edx, 12 + mov [ebp+KTRAP_FRAME_ESP], edx + + /* Get EFLAGS and continue */ + mov ebx, [ecx+8] + jmp MaskEFlags +.endfunc + +.func OpcodeNPXV86 +_OpcodeNPXV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeINBimmV86 +_OpcodeINBimmV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeINWimmV86 +_OpcodeINWimmV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeOUTBimmV86 +_OpcodeOUTBimmV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeOUTWimmV86 +_OpcodeOUTWimmV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeINBV86 +_OpcodeINBV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeINWV86 +_OpcodeINWV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeOUTBV86 +_OpcodeOUTBV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeOUTWV86 +_OpcodeOUTWV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeLOCKPrefixV86 +_OpcodeLOCKPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeREPNEPrefixV86 +_OpcodeREPNEPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeREPPrefixV86 +_OpcodeREPPrefixV86: + UNHANDLED_V86_OPCODE +.endfunc + +.func OpcodeCLIV86 +_OpcodeCLIV86: + + /* Get VDM State */ + mov eax, 0x714 + + /* FIXME: Support VME */ + + /* FIXME: Support VDM Interrupts */ + + /* Disable interrupts */ + LOCK and dword ptr [eax], ~EFLAGS_INTERRUPT_MASK + + /* Update EIP (remember EDI == instruction size) */ + add [ebp+KTRAP_FRAME_EIP], edi + + /* Return success */ + mov eax, 1 + ret +.endfunc + +.func OpcodeSTIV86 +_OpcodeSTIV86: + + /* Get VDM State */ + mov eax, 0x714 + + /* FIXME: Support VME */ + + /* Enable interrupts */ + LOCK or dword ptr [eax], EFLAGS_INTERRUPT_MASK + + /* Update EIP (remember EDI == instruction size) */ + add [ebp+KTRAP_FRAME_EIP], edi + + /* FIXME: Support VDM Interrupts */ + + /* Return success */ + mov eax, 1 + ret +.endfunc + +.func OpcodeHLTV86 +_OpcodeHLTV86: + UNHANDLED_V86_OPCODE +.endfunc + +/* FUNCTIONS *****************************************************************/ + +.globl _Ki386SetupAndExitToV86Mode@4 +.func Ki386SetupAndExitToV86Mode@4 +_Ki386SetupAndExitToV86Mode@4: + + /* Save nonvolatiles */ + push ebp + push ebx + push esi + push edi + + /* Give us a little stack */ + sub esp, 12 + mov ecx, esp + + /* Go past the KTRAP_FRAME and NPX Frame and set a new frame in EAX */ + sub esp, NPX_FRAME_LENGTH + and esp, ~15 + sub esp, KTRAP_FRAME_LENGTH + mov eax, esp + + /* Create a fake user-mode frame */ + mov dword ptr [eax+KTRAP_FRAME_CS], KGDT_R0_CODE + RPL_MASK + mov dword ptr [eax+KTRAP_FRAME_ES], 0 + mov dword ptr [eax+KTRAP_FRAME_DS], 0 + mov dword ptr [eax+KTRAP_FRAME_FS], 0 + mov dword ptr [eax+KTRAP_FRAME_GS], 0 + mov dword ptr [eax+KTRAP_FRAME_ERROR_CODE], 0 + + /* Get the current thread's initial stack */ + mov ebx, [fs:KPCR_SELF] + mov edi, [ebx+KPCR_CURRENT_THREAD] + mov edx, [edi+KTHREAD_INITIAL_STACK] + sub edx, NPX_FRAME_LENGTH + + /* Save it on our stack, as well as the real TEB addresses */ + mov [ecx], edx + mov edx, [edi+KTHREAD_TEB] + mov [ecx+4], edx + mov edx, [fs:KPCR_TEB] + mov [ecx+8] , edx + + /* Set our ESP in ESI, and the return function in EIP */ + mov edi, offset _Ki386BiosCallReturnAddress + mov [eax+KTRAP_FRAME_ESI], ecx + mov [eax+KTRAP_FRAME_EIP], edi + + /* Push the flags and sanitize them */ + pushfd + pop edi + and edi, 0x60DD7 + or edi, EFLAGS_INTERRUPT_MASK + + /* Set SS and ESP, and fill out the rest of the frame */ + mov dword ptr [eax+KTRAP_FRAME_SS], KGDT_R3_DATA + RPL_MASK; + mov dword ptr [eax+KTRAP_FRAME_ESP], 0x11FFE; + mov dword ptr [eax+KTRAP_FRAME_EFLAGS], edi + mov dword ptr [eax+KTRAP_FRAME_EXCEPTION_LIST], -1 + mov dword ptr [eax+KTRAP_FRAME_PREVIOUS_MODE], -1 + mov dword ptr [eax+KTRAP_FRAME_DR7], 0 + mov dword ptr [eax+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00 + + /* Jump past the frame now */ + add eax, KTRAP_FRAME_LENGTH + cli + + /* Save the current stack */ + push ecx + + /* Get the current thread's intial stack again */ + mov edi, [ebx+KPCR_CURRENT_THREAD] + mov esi, [edi+KTHREAD_INITIAL_STACK] + sub esi, NPX_FRAME_LENGTH + + /* Set the size of the copy, and the destination, and copy the NPX frame */ + mov ecx, NPX_FRAME_LENGTH / 4 + mov edi, eax + rep movsd + + /* Restore stack */ + pop ecx + + /* Get the current thread and TSS */ + mov edi, [ebx+KPCR_CURRENT_THREAD] + mov esi, [ebx+KPCR_TSS] + + /* Bias the V86 vrame */ + sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS + + /* Set exception list and new ESP */ + mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1 + mov [esi+KTSS_ESP0], eax + + /* Now skip past the NPX frame and V86 fields and set this as the intial stack */ + add eax, NPX_FRAME_LENGTH + (KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS) + mov [edi+KTHREAD_INITIAL_STACK], eax + + /* Setup our fake TEB pointer */ + mov eax, [ecx+0x20] + mov [fs:KPCR_TEB], eax + mov [edi+KTHREAD_TEB], eax + + /* Setup the descriptors for the fake TEB */ + mov ebx, [fs:KPCR_GDT] + mov [ebx+0x3A], ax + shr eax, 16 + mov [ebx+0x3C], al + mov [ebx+0x3F], ah + sti + + /* + * Start VDM execution. This will save this fake 32-bit KTRAP_FRAME and + * initialize a real 16-bit VDM context frame + */ + push 0 + push 0 // VdmStartExecution + call _NtVdmControl@8 + + /* Exit to V86 mode */ + mov ebp, esp + jmp _Kei386EoiHelper@0 +.endfunc + +.globl _Ki386BiosCallReturnAddress +.func Ki386BiosCallReturnAddress +_Ki386BiosCallReturnAddress: + + /* Get the PCR */ + mov eax, [fs:KPCR_SELF] + + /* Get NPX destination */ + mov edi, [ebp+KTRAP_FRAME_ESI] + mov edi, [edi] + + /* Get initial stack */ + mov ecx, [eax+KPCR_CURRENT_THREAD] + mov esi, [ecx+KTHREAD_INITIAL_STACK] + sub esi, NPX_FRAME_LENGTH + + /* Set length and copy the NPX frame */ + mov ecx, NPX_FRAME_LENGTH / 4 + rep movsd + + /* Restore stack */ + mov esp, [ebp+KTRAP_FRAME_ESI] + add esp, 4 + + /* Set initial stack */ + mov ecx, [eax+KPCR_CURRENT_THREAD] + mov [ecx+KTHREAD_INITIAL_STACK], edi + + /* Get TSS and set the ESP 0 */ + mov eax, [eax+KPCR_TSS] + sub edi, NPX_FRAME_LENGTH + (KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS) + mov [eax+KTSS_ESP0], edi + + /* Restore KTHREAD TEB in EDX */ + pop edx + mov [ecx+KTHREAD_TEB], edx + + /* Restore PCR TEB in EDX */ + pop edx + mov [fs:KPCR_TEB], edx + + /* Setup the descriptors for the real TEB */ + mov ebx, [fs:KPCR_GDT] + mov [ebx+0x3A], dx + shr edx, 16 + mov [ebx+0x3C], dl + mov [ebx+0x3F], dh + + /* Enable interrupts and pop back non-volatiles */ + sti + pop edi + pop esi + pop ebx + pop ebp + ret 4 +.endfunc + +.globl _Ki386HandleOpcodeV86@0 +.func Ki386HandleOpcodeV86@0 +_Ki386HandleOpcodeV86@0: + + /* Get flat EIP */ + mov esi, [ebp+KTRAP_FRAME_CS] + shl esi, 4 + add esi, [ebp+KTRAP_FRAME_EIP] + + /* Get the opcode entry in the table */ + movzx ecx, byte ptr [esi] + movzx edx, byte ptr OpcodeIndex[ecx] + + /* Set instruction length and prefix flags */ + mov edi, 1 + xor ebx, ebx + + /* Accounting statistics */ +// inc dword ptr _ExVdmOpcodeDispatchCounts[edx*4] // FIXME: Generates protection fault + + /* Handle the opcode */ + jmp OpcodeDispatchV86[edx*4] +.endfunc diff --git a/reactos/ntoskrnl/ke/i386/v86vdm.c b/reactos/ntoskrnl/ke/i386/v86vdm.c new file mode 100644 index 00000000000..357ceb085e6 --- /dev/null +++ b/reactos/ntoskrnl/ke/i386/v86vdm.c @@ -0,0 +1,122 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/i386/v86vdm.c + * PURPOSE: Manages the Kernel's support for Virtual-8086 Mode (V86) + * used by Video Drivers to access ROM BIOS functions, as well + * as the kernel architecture part of generic VDM support. + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +ULONG KeI386EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE; +ULONG KeI386EFlagsOrMaskV86 = EFLAGS_INTERRUPT_MASK; +PVOID Ki386IopmSaveArea; +BOOLEAN KeI386VirtualIntExtensions = FALSE; + +/* PRIVATE FUNCTIONS *********************************************************/ + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +Ke386CallBios(IN ULONG Int, + OUT PCONTEXT Context) +{ + PUCHAR Trampoline = (PUCHAR)TRAMPOLINE_BASE; + PTEB VdmTeb = (PTEB)TRAMPOLINE_TEB; + PVDM_TIB VdmTib = (PVDM_TIB)TRAMPOLINE_TIB; + ULONG ContextSize = FIELD_OFFSET(CONTEXT, ExtendedRegisters); + PKTHREAD Thread = KeGetCurrentThread(); + PKTSS Tss = KeGetPcr()->TSS; + PKPROCESS Process = Thread->ApcState.Process; + PVDM_PROCESS_OBJECTS VdmProcessObjects; + USHORT OldOffset, OldBase; + + /* Start with a clean TEB */ + RtlZeroMemory(VdmTeb, sizeof(TEB)); + + /* Write the interrupt and bop */ + *Trampoline++ = 0xCD; + *Trampoline++ = (UCHAR)Int; + *(PULONG)Trampoline = TRAMPOLINE_BOP; + + /* Setup the VDM TEB and TIB */ + VdmTeb->Vdm = (PVOID)TRAMPOLINE_TIB; + RtlZeroMemory(VdmTib, sizeof(VDM_TIB)); + VdmTib->Size = sizeof(VDM_TIB); + + /* Set a blank VDM state */ + *VdmState = 0; + + /* Copy the context */ + RtlMoveMemory(&VdmTib->VdmContext, Context, ContextSize); + VdmTib->VdmContext.SegCs = (ULONG_PTR)Trampoline >> 4; + VdmTib->VdmContext.SegSs = (ULONG_PTR)Trampoline >> 4; + VdmTib->VdmContext.Eip = 0; + VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG_PTR); + VdmTib->VdmContext.EFlags |= EFLAGS_V86_MASK | EFLAGS_INTERRUPT_MASK; + VdmTib->VdmContext.ContextFlags = CONTEXT_FULL; + + /* This can't be a real VDM process */ + ASSERT(PsGetCurrentProcess()->VdmObjects == NULL); + + /* Allocate VDM structure */ + VdmProcessObjects = ExAllocatePoolWithTag(NonPagedPool, + sizeof(VDM_PROCESS_OBJECTS), + TAG('K', 'e', ' ', ' ')); + if (!VdmProcessObjects) return STATUS_NO_MEMORY; + + /* Set it up */ + RtlZeroMemory(VdmProcessObjects, sizeof(VDM_PROCESS_OBJECTS)); + VdmProcessObjects->VdmTib = VdmTib; + PsGetCurrentProcess()->VdmObjects = VdmProcessObjects; + + /* Set the system affinity for the current thread */ + KeSetSystemAffinityThread(1); + + /* Make sure there's space for two IOPMs, then copy & clear the current */ + //ASSERT(((PKGDTENTRY)&KeGetPcr()->GDT[KGDT_TSS / 8])->LimitLow >= (0x2000 + IOPM_OFFSET - 1)); + RtlMoveMemory(Ki386IopmSaveArea, &Tss->IoMaps[0].IoMap, PAGE_SIZE * 2); + RtlZeroMemory(&Tss->IoMaps[0].IoMap, PAGE_SIZE * 2); + + /* Save the old offset and base, and set the new ones */ + OldOffset = Process->IopmOffset; + OldBase = Tss->IoMapBase; + Process->IopmOffset = IOPM_OFFSET; + Tss->IoMapBase = IOPM_OFFSET; + + /* Switch stacks and work the magic */ + Ki386SetupAndExitToV86Mode(VdmTeb); + + /* Restore IOPM */ + RtlMoveMemory(&Tss->IoMaps[0].IoMap, Ki386IopmSaveArea, PAGE_SIZE * 2); + Process->IopmOffset = OldOffset; + Tss->IoMapBase = OldBase; + + /* Restore affinity */ + KeRevertToUserAffinityThread(); + + /* Restore context */ + RtlMoveMemory(Context, &VdmTib->VdmContext, ContextSize); + Context->ContextFlags = CONTEXT_FULL; + + /* Free VDM objects */ + ExFreePool(PsGetCurrentProcess()->VdmObjects); + PsGetCurrentProcess()->VdmObjects = NULL; + + /* Return status */ + return STATUS_SUCCESS; +} + +/* EOF */ diff --git a/reactos/ntoskrnl/ke/i386/vdm.c b/reactos/ntoskrnl/ke/i386/vdm.c deleted file mode 100644 index d7addfbecca..00000000000 --- a/reactos/ntoskrnl/ke/i386/vdm.c +++ /dev/null @@ -1,112 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/vdm.c - * PURPOSE: Virtual DOS machine support - * - * PROGRAMMERS: David Welch (welch@mcmail.com) - */ - -/* INCLUDES *****************************************************************/ - -#include -#include - -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, NtEarlyInitVdm) -#endif - - -/* GLOBALS *******************************************************************/ - -static UCHAR OrigIVT[1024]; -static UCHAR OrigBDA[256]; -/* static UCHAR OrigEBDA[]; */ - -extern VOID Ki386RetToV86Mode(PKV86M_REGISTERS InRegs, - PKV86M_REGISTERS OutRegs); - -/* FUNCTIONS *****************************************************************/ - -VOID INIT_FUNCTION -NtEarlyInitVdm(VOID) -{ - /* GCC 3.4 warns if NULL is passed in parameter 2 to the standard function memcpy */ - PVOID start = (PVOID)0x0; - - /* - * Save various BIOS data tables. At this point the lower 4MB memory - * map is still active so we can just copy the data from low memory. - */ - memcpy(OrigIVT, start, 1024); - memcpy(OrigBDA, (PVOID)0x400, 256); -} - -/* - * @implemented - */ -NTSTATUS STDCALL NtVdmControl(ULONG ControlCode, - PVOID ControlData) -{ - KPROCESSOR_MODE PreviousMode; - NTSTATUS Status = STATUS_SUCCESS; - - PreviousMode = ExGetPreviousMode(); - - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - switch (ControlCode) - { - case 0: - ProbeForWrite(ControlData, - 1024, - 1); - memcpy(ControlData, OrigIVT, 1024); - break; - - case 1: - ProbeForWrite(ControlData, - 256, - 1); - memcpy(ControlData, OrigBDA, 256); - break; - - case 2: - { - KV86M_REGISTERS V86Registers; - - ProbeForWrite(ControlData, - sizeof(KV86M_REGISTERS), - 1); - memcpy(&V86Registers, - ControlData, - sizeof(KV86M_REGISTERS)); - - /* FIXME: This should use ->VdmObjects */ - KeGetCurrentProcess()->Unused = 1; - Ki386RetToV86Mode(&V86Registers, &V86Registers); - - /* FIXME: This should use ->VdmObjects */ - KeGetCurrentProcess()->Unused = 0; - - memcpy(ControlData, - &V86Registers, - sizeof(KV86M_REGISTERS)); - break; - } - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - return Status; -} - -/* EOF */ diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 10c52372731..74912e05706 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -104,6 +104,11 @@ KiSystemStartup(BOOLEAN BootProcessor) /* Initialize the Kernel Executive */ ExpInitializeExecutive(); + /* Create the IOPM Save Area */ + Ki386IopmSaveArea = ExAllocatePoolWithTag(NonPagedPool, + PAGE_SIZE * 2, + TAG('K', 'e', ' ', ' ')); + /* Free Initial Memory */ MiFreeInitMemory(); diff --git a/reactos/ntoskrnl/mkconfig.c b/reactos/ntoskrnl/mkconfig.c deleted file mode 100644 index 5c514890602..00000000000 --- a/reactos/ntoskrnl/mkconfig.c +++ /dev/null @@ -1,122 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mkconfig.c - * PURPOSE: No purpose listed. - * - * PROGRAMMERS: No programmer listed. - */ - -#include -#include -#include - -#define max(a, b) ((a) > (b) ? (a) : (b)) - -int -write_if_change(char* outbuf, char* filename) -{ - FILE* out; - unsigned int end; - char* cmpbuf; - unsigned int stat; - - out = fopen(filename, "rb"); - if (out == NULL) - { - out = fopen(filename, "wb"); - if (out == NULL) - { - fprintf(stderr, "Unable to create output file\n"); - return(1); - } - fputs(outbuf, out); - fclose(out); - return(0); - } - - fseek(out, 0, SEEK_END); - end = ftell(out); - cmpbuf = malloc(end); - if (cmpbuf == NULL) - { - fprintf(stderr, "Out of memory\n"); - fclose(out); - return(1); - } - - fseek(out, 0, SEEK_SET); - stat = fread(cmpbuf, 1, end, out); - if (stat != end) - { - fprintf(stderr, "Failed to read data\n"); - fclose(out); - return(1); - } - if (end == strlen(outbuf) && memcmp(cmpbuf, outbuf, end) == 0) - { - fclose(out); - return(0); - } - - fclose(out); - out = fopen(filename, "wb"); - if (out == NULL) - { - fprintf(stderr, "Unable to create output file\n"); - return(1); - } - - stat = fwrite(outbuf, 1, strlen(outbuf), out); - if (strlen(outbuf) != stat) - { - fprintf(stderr, "Unable to write output file\n"); - fclose(out); - return(1); - } - fclose(out); - return(0); -} - -int -main(int argc, char* argv[]) -{ - unsigned int i; - char* outbuf; - char* s; - char config[512]; - - if (argc == 1) - { - fprintf(stderr, "Not enough arguments\n"); - return(1); - } - - outbuf = malloc(256 * 1024); - if (outbuf == NULL) - { - fprintf(stderr, "Out of memory 1\n"); - return(1); - } - - s = outbuf; - s = s + sprintf(s, "/* Automatically generated, "); - s = s + sprintf(s, "Edit the Makefile to change configuration */\n"); - s = s + sprintf(s, "#ifndef __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H\n"); - s = s + sprintf(s, "#define __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H\n"); - strcpy(config, ""); - for (i = 2; i < argc; i++) - { - s = s + sprintf(s, "#define %s\n", argv[i]); - strcat(config, argv[i]); - if (i != (argc - 1)) - { - strcat(config, " "); - } - } - s = s + sprintf(s, "#define CONFIG \"%s\"\n", config); - s = s + sprintf(s, "#endif /* __NTOSKRNL_INCLUDE_INTERNAL_CONFIG_H */\n"); - - return(write_if_change(outbuf, argv[1])); -} diff --git a/reactos/ntoskrnl/mm/mm.c b/reactos/ntoskrnl/mm/mm.c index 9d9e342df35..032a9e5a17e 100644 --- a/reactos/ntoskrnl/mm/mm.c +++ b/reactos/ntoskrnl/mm/mm.c @@ -110,6 +110,7 @@ MmAccessFault(KPROCESSOR_MODE Mode, */ if (Mode != KernelMode) { + DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address); DbgPrint("%s:%d\n",__FILE__,__LINE__); return(STATUS_UNSUCCESSFUL); } diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index ba3473d7c6c..990489afc0c 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -40,9 +40,8 @@ trap.s tss.c usercall_asm.S - v86m.c + v86vdm.c v86m_sup.S - vdm.c apc.c @@ -328,6 +327,12 @@ sid.c token.c + + + vdmmain.c + vdmexec.c + + wmi.c diff --git a/reactos/ntoskrnl/ntoskrnl.txt b/reactos/ntoskrnl/ntoskrnl.txt deleted file mode 100644 index 1e2399186a4..00000000000 --- a/reactos/ntoskrnl/ntoskrnl.txt +++ /dev/null @@ -1,1084 +0,0 @@ -Name: Ntoskrnl.exe - -Description: Windows NT Executive - - -Ordinal Exported -Value: Name: -1 ExAcquireFastMutexUnsafe -2 ExInterlockedAddLargeStatistic -3 ExInterlockedCompareExchange64 -4 ExInterlockedPopEntrySList -5 ExInterlockedPushEntrySList -6 ExReleaseFastMutexUnsafe -7 ExReleaseResourceLite -8 ExfInterlockedAddUlong -9 ExfInterlockedInsertHeadList -10 ExfInterlockedInsertTailList -11 ExfInterlockedPopEntryList -12 ExfInterlockedPushEntryList -13 ExfInterlockedRemoveHeadList -14 Exfi386InterlockedDecrementLong -15 Exfi386InterlockedExchangeUlong -16 Exfi386InterlockedIncrementLong -17 InterlockedCompareExchange -18 InterlockedDecrement -19 InterlockedExchange -20 InterlockedExchangeAdd -21 InterlockedIncrement -22 IofCallDriver -23 IofCompleteRequest -24 KeSetSwapContextNotifyRoutine -25 KeSetThreadSelectNotifyRoutine -26 KeSetTimeUpdateNotifyRoutine -27 KefAcquireSpinLockAtDpcLevel -28 KefReleaseSpinLockFromDpcLevel -29 KiAcquireSpinLock -30 KiReleaseSpinLock -31 ObfDereferenceObject -32 ObfReferenceObject -33 Kei386EoiHelper -34 Kii386SpinOnSpinLock -35 CcCanIWrite -36 CcCopyRead -37 CcCopyWrite -38 CcDeferWrite -39 CcFastCopyRead -40 CcFastCopyWrite -41 CcFastMdlReadWait -42 CcFastReadNotPossible -43 CcFastReadWait -44 CcFlushCache -45 CcGetDirtyPages -46 CcGetFileObjectFromBcb -47 CcGetFileObjectFromSectionPtrs -48 CcGetLsnForFileObject -49 CcInitializeCacheMap -50 CcIsThereDirtyData -51 CcMapData -52 CcMdlRead -53 CcMdlReadComplete -54 CcMdlWriteComplete -55 CcPinMappedData -56 CcPinRead -57 CcPrepareMdlWrite -58 CcPreparePinWrite -59 CcPurgeCacheSection -60 CcRepinBcb -61 CcScheduleReadAhead -62 CcSetAdditionalCacheAttributes -63 CcSetBcbOwnerPointer -64 CcSetDirtyPageThreshold -65 CcSetDirtyPinnedData -66 CcSetFileSizes -67 CcSetLogHandleForFile -68 CcSetReadAheadGranularity -69 CcUninitializeCacheMap -70 CcUnpinData -71 CcUnpinDataForThread -72 CcUnpinRepinnedBcb -73 CcZeroData -74 DbgBreakPoint -75 DbgBreakPointWithStatus -76 DbgLoadImageSymbols -77 DbgPrint -78 DbgPrompt -79 ExAcquireResourceExclusive -80 ExAcquireResourceExclusiveLite -81 ExAcquireResourceSharedLite -82 ExAcquireSharedStarveExclusive -83 ExAcquireSharedWaitForExclusive -84 ExAllocateFromPagedLookasideList -85 ExAllocatePool -86 ExAllocatePoolWithQuota -87 ExAllocatePoolWithQuotaTag -88 ExAllocatePoolWithTag -89 ExConvertExclusiveToSharedLite -90 ExCreateCallback -91 ExDeleteNPagedLookasideList -92 ExDeletePagedLookasideList -93 ExDeleteResource -94 ExDeleteResourceLite -95 ExDesktopObjectType -96 ExDisableResourceBoostLite -97 ExEnumHandleTable -98 ExEventObjectType -99 ExExtendZone -100 ExFreePool -101 ExFreeToPagedLookasideList -102 ExGetExclusiveWaiterCount -103 ExGetPreviousMode -104 ExGetSharedWaiterCount -105 ExInitializeNPagedLookasideList -106 ExInitializePagedLookasideList -107 ExInitializeResource -108 ExInitializeResourceLite -109 ExInitializeZone -110 ExInterlockedAddLargeInteger -111 ExInterlockedAddUlong -112 ExInterlockedDecrementLong -113 ExInterlockedExchangeUlong -114 ExInterlockedExtendZone -115 ExInterlockedIncrementLong -116 ExInterlockedInsertHeadList -117 ExInterlockedInsertTailList -118 ExInterlockedPopEntryList -119 ExInterlockedPushEntryList -120 ExInterlockedRemoveHeadList -121 ExIsProcessorFeaturePresent -122 ExIsResourceAcquiredExclusiveLite -123 ExIsResourceAcquiredSharedLite -124 ExLocalTimeToSystemTime -125 ExNotifyCallback -126 ExPostSystemEvent -127 ExQueryPoolBlockSize -128 ExQueueWorkItem -129 ExRaiseAccessViolation -130 ExRaiseDatatypeMisalignment -131 ExRaiseException -132 ExRaiseHardError -133 ExRaiseStatus -134 ExRegisterCallback -135 ExReinitializeResourceLite -136 ExReleaseResourceForThread -137 ExReleaseResourceForThreadLite -138 ExSetResourceOwnerPointer -139 ExSystemExceptionFilter -140 ExSystemTimeToLocalTime -141 ExUnregisterCallback -142 ExWindowStationObjectType -143 Exi386InterlockedDecrementLong -144 Exi386InterlockedExchangeUlong -145 Exi386InterlockedIncrementLong -146 FsRtlAddLargeMcbEntry -147 FsRtlAddMcbEntry -148 FsRtlAddToTunnelCache -149 FsRtlAllocatePool -150 FsRtlAllocatePoolWithQuota -151 FsRtlAllocatePoolWithQuotaTag -152 FsRtlAllocatePoolWithTag -153 FsRtlAllocateResource -154 FsRtlAreNamesEqual -155 FsRtlBalanceReads -156 FsRtlCheckLockForReadAccess -157 FsRtlCheckLockForWriteAccess -158 FsRtlCheckOplock -159 FsRtlCopyRead -160 FsRtlCopyWrite -161 FsRtlCurrentBatchOplock -162 FsRtlDeleteKeyFromTunnelCache -163 FsRtlDeleteTunnelCache -164 FsRtlDeregisterUncProvider -165 FsRtlDissectDbcs -166 FsRtlDissectName -167 FsRtlDoesDbcsContainWildCards -168 FsRtlDoesNameContainWildCards -169 FsRtlFastCheckLockForRead -170 FsRtlFastCheckLockForWrite -171 FsRtlFastUnlockAll -172 FsRtlFastUnlockAllByKey -173 FsRtlFastUnlockSingle -174 FsRtlFindInTunnelCache -175 FsRtlGetFileSize -176 FsRtlGetNextFileLock -177 FsRtlGetNextLargeMcbEntry -178 FsRtlGetNextMcbEntry -179 FsRtlInitializeFileLock -180 FsRtlInitializeLargeMcb -181 FsRtlInitializeMcb -182 FsRtlInitializeOplock -183 FsRtlInitializeTunnelCache -184 FsRtlIsDbcsInExpression -185 FsRtlIsFatDbcsLegal -186 FsRtlIsHpfsDbcsLegal -187 FsRtlIsNameInExpression -188 FsRtlIsNtstatusExpected -189 FsRtlIsTotalDeviceFailure -190 FsRtlLegalAnsiCharacterArray -191 FsRtlLookupLargeMcbEntry -192 FsRtlLookupLastLargeMcbEntry -193 FsRtlLookupLastMcbEntry -194 FsRtlLookupMcbEntry -195 FsRtlMdlRead -196 FsRtlMdlReadComplete -197 FsRtlMdlReadCompleteDev -198 FsRtlMdlReadDev -199 FsRtlMdlWriteComplete -200 FsRtlMdlWriteCompleteDev -201 FsRtlNormalizeNtstatus -202 FsRtlNotifyChangeDirectory -203 FsRtlNotifyCleanup -204 FsRtlNotifyFullChangeDirectory -205 FsRtlNotifyFullReportChange -206 FsRtlNotifyInitializeSync -207 FsRtlNotifyReportChange -208 FsRtlNotifyUninitializeSync -209 FsRtlNumberOfRunsInLargeMcb -210 FsRtlNumberOfRunsInMcb -211 FsRtlOplockFsctrl -212 FsRtlOplockIsFastIoPossible -213 FsRtlPostPagingFileStackOverflow -214 FsRtlPostStackOverflow -215 FsRtlPrepareMdlWrite -216 FsRtlPrepareMdlWriteDev -217 FsRtlPrivateLock -218 FsRtlProcessFileLock -219 FsRtlRegisterUncProvider -220 FsRtlRemoveLargeMcbEntry -221 FsRtlRemoveMcbEntry -222 FsRtlSplitLargeMcb -223 FsRtlSyncVolumes -224 FsRtlTruncateLargeMcb -225 FsRtlTruncateMcb -226 FsRtlUninitializeFileLock -227 FsRtlUninitializeLargeMcb -228 FsRtlUninitializeMcb -229 FsRtlUninitializeOplock -230 HalDispatchTable -231 HalPrivateDispatchTable -232 IoAcquireCancelSpinLock -233 IoAcquireVpbSpinLock -234 IoAdapterObjectType -235 IoAllocateAdapterChannel -236 IoAllocateController -237 IoAllocateErrorLogEntry -238 IoAllocateIrp -239 IoAllocateMdl -240 IoAssignResources -241 IoAttachDevice -242 IoAttachDeviceByPointer -243 IoAttachDeviceToDeviceStack -244 IoBuildAsynchronousFsdRequest -245 IoBuildDeviceIoControlRequest -246 IoBuildPartialMdl -247 IoBuildSynchronousFsdRequest -248 IoCallDriver -249 IoCancelIrp -250 IoCheckDesiredAccess -251 IoCheckEaBufferValidity -252 IoCheckFunctionAccess -253 IoCheckShareAccess -254 IoCompleteRequest -255 IoConnectInterrupt -256 IoCreateController -257 IoCreateDevice -258 IoCreateFile -259 IoCreateNotificationEvent -260 IoCreateStreamFileObject -261 IoCreateSymbolicLink -262 IoCreateSynchronizationEvent -263 IoCreateUnprotectedSymbolicLink -264 IoDeleteController -265 IoDeleteDevice -266 IoDeleteSymbolicLink -267 IoDetachDevice -268 IoDeviceHandlerObjectSize -269 IoDeviceHandlerObjectType -270 IoDeviceObjectType -271 IoDisconnectInterrupt -272 IoDriverObjectType -273 IoEnqueueIrp -274 IoFastQueryNetworkAttributes -275 IoFileObjectType -276 IoFreeController -277 IoFreeIrp -278 IoFreeMdl -279 IoGetAttachedDevice -280 IoGetBaseFileSystemDeviceObject -281 IoGetConfigurationInformation -282 IoGetCurrentProcess -283 IoGetDeviceObjectPointer -284 IoGetDeviceToVerify -285 IoGetFileObjectGenericMapping -286 IoGetInitialStack -287 IoGetRelatedDeviceObject -288 IoGetRequestorProcess -289 IoGetStackLimits -290 IoGetTopLevelIrp -291 IoInitializeIrp -292 IoInitializeTimer -293 IoIsOperationSynchronous -294 IoIsSystemThread -295 IoMakeAssociatedIrp -296 IoOpenDeviceInstanceKey -297 IoPageRead -298 IoQueryDeviceDescription -299 IoQueryDeviceEnumInfo -300 IoQueryFileInformation -301 IoQueryVolumeInformation -302 IoQueueThreadIrp -303 IoRaiseHardError -304 IoRaiseInformationalHardError -305 IoReadOperationCount -306 IoReadTransferCount -307 IoRegisterDriverReinitialization -308 IoRegisterFileSystem -309 IoRegisterFsRegistrationChange -310 IoRegisterShutdownNotification -311 IoReleaseCancelSpinLock -312 IoReleaseVpbSpinLock -313 IoRemoveShareAccess -314 IoReportHalResourceUsage -315 IoReportResourceUsage -316 IoSetDeviceToVerify -317 IoSetHardErrorOrVerifyDevice -318 IoSetInformation -319 IoSetShareAccess -320 IoSetThreadHardErrorMode -321 IoSetTopLevelIrp -322 IoStartNextPacket -323 IoStartNextPacketByKey -324 IoStartPacket -325 IoStartTimer -326 IoStatisticsLock -327 IoStopTimer -328 IoSynchronousPageWrite -329 IoThreadToProcess -330 IoUnregisterFileSystem -331 IoUnregisterFsRegistrationChange -332 IoUnregisterShutdownNotification -333 IoUpdateShareAccess -334 IoVerifyVolume -335 IoWriteErrorLogEntry -336 IoWriteOperationCount -337 IoWriteTransferCount -338 KdDebuggerEnabled -339 KdDebuggerNotPresent -340 KdPollBreakIn -341 Ke386CallBios -342 Ke386IoSetAccessProcess -343 Ke386QueryIoAccessMap -344 Ke386SetIoAccessMap -345 KeAcquireSpinLockAtDpcLevel -346 KeAddSystemServiceTable -347 KeAttachProcess -348 KeBoostCurrentThread -349 KeBugCheck -350 KeBugCheckEx -351 KeCancelTimer -352 KeClearEvent -353 KeConnectInterrupt -354 KeDcacheFlushCount -355 KeDelayExecutionThread -356 KeDeregisterBugCheckCallback -357 KeDetachProcess -358 KeDisconnectInterrupt -359 KeEnterCriticalRegion -360 KeEnterKernelDebugger -361 KeFindConfigurationEntry -362 KeFindConfigurationNextEntry -363 KeFlushEntireTb -364 KeGetCurrentThread -365 KeGetPreviousMode -366 KeI386AbiosCall -367 KeI386AllocateGdtSelectors -368 KeI386Call16BitCStyleFunction -369 KeI386Call16BitFunction -370 KeI386FlatToGdtSelector -371 KeI386GetLid -372 KeI386MachineType -373 KeI386ReleaseGdtSelectors -374 KeI386ReleaseLid -375 KeI386SetGdtSelector -376 KeIcacheFlushCount -377 KeInitializeApc -378 KeInitializeDeviceQueue -379 KeInitializeDpc -380 KeInitializeEvent -381 KeInitializeInterrupt -382 KeInitializeMutant -383 KeInitializeMutex -384 KeInitializeQueue -385 KeInitializeSemaphore -386 KeInitializeSpinLock -387 KeInitializeTimer -388 KeInitializeTimerEx -389 KeInsertByKeyDeviceQueue -390 KeInsertDeviceQueue -391 KeInsertHeadQueue -392 KeInsertQueue -393 KeInsertQueueApc -394 KeInsertQueueDpc -395 KeIsExecutingDpc -396 KeLeaveCriticalRegion -397 KeLoaderBlock -398 KeNumberProcessors -399 KeProfileInterrupt -400 KeProfileInterruptWithSource -401 KePulseEvent -402 KeQuerySystemTime -403 KeQueryTickCount -404 KeQueryTimeIncrement -405 KeRaiseUserException -406 KeReadStateEvent -407 KeReadStateMutant -408 KeReadStateMutex -409 KeReadStateQueue -410 KeReadStateSemaphore -411 KeReadStateTimer -412 KeRegisterBugCheckCallback -413 KeReleaseMutant -414 KeReleaseMutex -415 KeReleaseSemaphore -416 KeReleaseSpinLockFromDpcLevel -417 KeRemoveByKeyDeviceQueue -418 KeRemoveDeviceQueue -419 KeRemoveEntryDeviceQueue -420 KeRemoveQueue -421 KeRemoveQueueDpc -422 KeResetEvent -423 KeRestoreFloatingPointState -424 KeRundownQueue -425 KeSaveFloatingPointState -426 KeServiceDescriptorTable -427 KeSetAffinityThread -428 KeSetBasePriorityThread -429 KeSetDmaIoCoherency -430 KeSetEvent -431 KeSetEventBoostPriority -432 KeSetIdealProcessorThread -433 KeSetImportanceDpc -434 KeSetKernelStackSwapEnable -435 KeSetPriorityThread -436 KeSetProfileIrql -437 KeSetTargetProcessorDpc -438 KeSetTimeIncrement -439 KeSetTimer -440 KeSetTimerEx -441 KeSynchronizeExecution -442 KeTerminateThread -443 KeTickCount -444 KeUpdateRunTime -445 KeUpdateSystemTime -446 KeUserModeCallback -447 KeWaitForMultipleObjects -448 KeWaitForMutexObject -449 KeWaitForSingleObject -450 KiBugCheckData -451 KiCoprocessorError -452 KiDeliverApc -453 KiDispatchInterrupt -454 KiIpiServiceRoutine -455 KiUnexpectedInterrupt -456 LdrAccessResource -457 LdrEnumResources -458 LdrFindResourceDirectory_U -459 LdrFindResource_U -460 LpcRequestPort -461 LsaCallAuthenticationPackage -462 LsaDeregisterLogonProcess -463 LsaFreeReturnBuffer -464 LsaLogonUser -465 LsaLookupAuthenticationPackage -466 LsaRegisterLogonProcess -467 MmAdjustWorkingSetSize -468 MmAllocateContiguousMemory -469 MmAllocateNonCachedMemory -470 MmBuildMdlForNonPagedPool -471 MmCanFileBeTruncated -472 MmCreateMdl -473 MmCreateSection -474 MmDbgTranslatePhysicalAddress -475 MmDisableModifiedWriteOfSection -476 MmFlushImageSection -477 MmForceSectionClosed -478 MmFreeContiguousMemory -479 MmFreeNonCachedMemory -480 MmGetPhysicalAddress -481 MmGrowKernelStack -482 MmIsAddressValid -483 MmIsNonPagedSystemAddressValid -484 MmIsRecursiveIoFault -485 MmIsThisAnNtAsSystem -486 MmLockPagableDataSection -487 MmLockPagableImageSection -488 MmLockPagableSectionByHandle -489 MmMapIoSpace -490 MmMapLockedPages -491 MmMapMemoryDumpMdl -492 MmMapVideoDisplay -493 MmMapViewInSystemSpace -494 MmMapViewOfSection -495 MmPageEntireDriver -496 MmProbeAndLockPages -497 MmQuerySystemSize -498 MmResetDriverPaging -499 MmSectionObjectType -500 MmSecureVirtualMemory -501 MmSetAddressRangeModified -502 MmSetBankedSection -503 MmSizeOfMdl -504 MmUnlockPagableImageSection -505 MmUnlockPages -506 MmUnmapIoSpace -507 MmUnmapLockedPages -508 MmUnmapVideoDisplay -509 MmUnmapViewInSystemSpace -510 MmUnmapViewOfSection -511 MmUnsecureVirtualMemory -512 NlsAnsiCodePage -513 NlsLeadByteInfo -514 NlsMbCodePageTag -515 NlsMbOemCodePageTag -516 NlsOemLeadByteInfo -517 NtAddAtom -518 NtAdjustPrivilegesToken -519 NtAllocateLocallyUniqueId -520 NtAllocateUuids -521 NtAllocateVirtualMemory -522 NtBuildNumber -523 NtClose -524 NtConnectPort -525 NtCreateEvent -526 NtCreateFile -527 NtCreateSection -528 NtDeleteAtom -529 NtDeleteFile -530 NtDeviceIoControlFile -531 NtDuplicateObject -532 NtDuplicateToken -533 NtFindAtom -534 NtFreeVirtualMemory -535 NtFsControlFile -536 NtGlobalFlag -537 NtLockFile -538 NtMapViewOfSection -539 NtNotifyChangeDirectoryFile -540 NtOpenFile -541 NtOpenProcess -542 NtOpenProcessToken -543 NtQueryDirectoryFile -544 NtQueryEaFile -545 NtQueryInformationAtom -546 NtQueryInformationFile -547 NtQueryInformationProcess -548 NtQueryInformationToken -549 NtQueryOleDirectoryFile -550 NtQuerySecurityObject -551 NtQueryVolumeInformationFile -552 NtReadFile -553 NtRequestPort -554 NtRequestWaitReplyPort -555 NtSetEvent -556 NtSetInformationFile -557 NtSetInformationProcess -558 NtSetInformationThread -559 NtSetSecurityObject -560 NtUnlockFile -561 NtVdmControl -562 NtWaitForSingleObject -563 NtWriteFile -564 ObAssignSecurity -565 ObCheckCreateObjectAccess -566 ObCheckObjectAccess -567 ObCreateObject -568 ObDereferenceObject -569 ObFindHandleForObject -570 ObGetObjectPointerCount -571 ObGetObjectSecurity -572 ObInsertObject -573 ObMakeTemporaryObject -574 ObOpenObjectByName -575 ObOpenObjectByPointer -576 ObQueryNameString -577 ObQueryObjectAuditingByHandle -578 ObReferenceObjectByHandle -579 ObReferenceObjectByName -580 ObReferenceObjectByPointer -581 ObReleaseObjectSecurity -582 ObSetSecurityDescriptorInfo -583 PfxFindPrefix -584 PfxInitialize -585 PfxInsertPrefix -586 PfxRemovePrefix -587 PoQueryPowerSequence -588 PoRequestPowerChange -589 PoSetDeviceIdleDetection -590 ProbeForWrite -591 PsAssignImpersonationToken -592 PsChargePoolQuota -593 PsCreateSystemProcess -594 PsCreateSystemThread -595 PsCreateWin32Process -596 PsEstablishWin32Callouts -597 PsGetCurrentProcessId -598 PsGetCurrentThreadId -599 PsGetProcessExitTime -600 PsGetVersion -601 PsImpersonateClient -602 PsInitialSystemProcess -603 PsIsThreadTerminating -604 PsLookupProcessByProcessId -605 PsLookupProcessThreadByCid -606 PsLookupThreadByThreadId -607 PsProcessType -608 PsReferenceImpersonationToken -609 PsReferencePrimaryToken -610 PsReturnPoolQuota -611 PsRevertToSelf -612 PsSetCreateProcessNotifyRoutine -613 PsSetCreateThreadNotifyRoutine -614 PsSetLegoNotifyRoutine -615 PsSetProcessPriorityByClass -616 PsTerminateSystemThread -617 PsThreadType -618 READ_REGISTER_BUFFER_UCHAR -619 READ_REGISTER_BUFFER_ULONG -620 READ_REGISTER_BUFFER_USHORT -621 READ_REGISTER_UCHAR -622 READ_REGISTER_ULONG -623 READ_REGISTER_USHORT -624 RtlAbsoluteToSelfRelativeSD -625 RtlAddAccessAllowedAce -626 RtlAddAce -627 RtlAddAtomToAtomTable -628 RtlAllocateAndInitializeSid -629 RtlAllocateHeap -630 RtlAnsiCharToUnicodeChar -631 RtlAnsiStringToUnicodeSize -632 RtlAnsiStringToUnicodeString -633 RtlAppendAsciizToString -634 RtlAppendStringToString -635 RtlAppendUnicodeStringToString -636 RtlAppendUnicodeToString -637 RtlAreAllAccessesGranted -638 RtlAreAnyAccessesGranted -639 RtlAreBitsClear -640 RtlAreBitsSet -641 RtlAssert -642 RtlCaptureStackBackTrace -643 RtlCharToInteger -644 RtlCheckRegistryKey -645 RtlClearAllBits -646 RtlClearBits -647 RtlCompareMemory -648 RtlCompareMemoryUlong -649 RtlCompareString -650 RtlCompareUnicodeString -651 RtlCompressBuffer -652 RtlCompressChunks -653 RtlConvertLongToLargeInteger -654 RtlConvertSidToUnicodeString -655 RtlConvertUlongToLargeInteger -656 RtlCopyLuid -657 RtlCopySid -658 RtlCopyString -659 RtlCopyUnicodeString -660 RtlCreateAcl -661 RtlCreateAtomTable -662 RtlCreateHeap -663 RtlCreateRegistryKey -664 RtlCreateSecurityDescriptor -665 RtlCreateUnicodeString -666 RtlCustomCPToUnicodeN -667 RtlDecompressBuffer -668 RtlDecompressChunks -669 RtlDecompressFragment -670 RtlDelete -671 RtlDeleteAtomFromAtomTable -672 RtlDeleteElementGenericTable -673 RtlDeleteNoSplay -674 RtlDeleteRegistryValue -675 RtlDescribeChunk -676 RtlDestroyAtomTable -677 RtlDestroyHeap -678 RtlDowncaseUnicodeString -679 RtlEmptyAtomTable -680 RtlEnlargedIntegerMultiply -681 RtlEnlargedUnsignedDivide -682 RtlEnlargedUnsignedMultiply -683 RtlEnumerateGenericTable -684 RtlEnumerateGenericTableWithoutSplaying -685 RtlEqualLuid -686 RtlEqualSid -687 RtlEqualString -688 RtlEqualUnicodeString -689 RtlExtendedIntegerMultiply -690 RtlExtendedLargeIntegerDivide -691 RtlExtendedMagicDivide -692 RtlFillMemory -693 RtlFillMemoryUlong -694 RtlFindClearBits -695 RtlFindClearBitsAndSet -696 RtlFindFirstRunClear -697 RtlFindFirstRunSet -698 RtlFindLongestRunClear -699 RtlFindLongestRunSet -700 RtlFindMessage -701 RtlFindSetBits -702 RtlFindSetBitsAndClear -703 RtlFindUnicodePrefix -704 RtlFormatCurrentUserKeyPath -705 RtlFreeAnsiString -706 RtlFreeHeap -707 RtlFreeOemString -708 RtlFreeUnicodeString -709 RtlGenerate8dot3Name -710 RtlGetCallersAddress -711 RtlGetCompressionWorkSpaceSize -712 RtlGetDaclSecurityDescriptor -713 RtlGetDefaultCodePage -714 RtlGetElementGenericTable -715 RtlGetGroupSecurityDescriptor -716 RtlGetOwnerSecurityDescriptor -717 RtlImageNtHeader -718 RtlInitAnsiString -719 RtlInitCodePageTable -720 RtlInitString -721 RtlInitUnicodeString -722 RtlInitializeBitMap -723 RtlInitializeGenericTable -724 RtlInitializeSid -725 RtlInitializeUnicodePrefix -726 RtlInsertElementGenericTable -727 RtlInsertUnicodePrefix -728 RtlIntegerToChar -729 RtlIntegerToUnicodeString -730 RtlIsNameLegalDOS8Dot3 -731 RtlLargeIntegerAdd -732 RtlLargeIntegerArithmeticShift -733 RtlLargeIntegerDivide -734 RtlLargeIntegerNegate -735 RtlLargeIntegerShiftLeft -736 RtlLargeIntegerShiftRight -737 RtlLargeIntegerSubtract -738 RtlLengthRequiredSid -739 RtlLengthSecurityDescriptor -740 RtlLengthSid -741 RtlLookupAtomInAtomTable -742 RtlLookupElementGenericTable -743 RtlMapGenericMask -744 RtlMoveMemory -745 RtlMultiByteToUnicodeN -746 RtlMultiByteToUnicodeSize -747 RtlNextUnicodePrefix -748 RtlNtStatusToDosError -749 RtlNtStatusToDosErrorNoTeb -750 RtlNumberGenericTableElements -751 RtlNumberOfClearBits -752 RtlNumberOfSetBits -753 RtlOemStringToCountedUnicodeString -754 RtlOemStringToUnicodeSize -755 RtlOemStringToUnicodeString -756 RtlOemToUnicodeN -757 RtlPinAtomInAtomTable -758 RtlPrefixString -759 RtlPrefixUnicodeString -760 RtlQueryAtomInAtomTable -761 RtlQueryRegistryValues -762 RtlQueryTimeZoneInformation -763 RtlRaiseException -764 RtlRandom -765 RtlRemoveUnicodePrefix -766 RtlReserveChunk -767 RtlSecondsSince1970ToTime -768 RtlSecondsSince1980ToTime -769 RtlSetAllBits -770 RtlSetBits -771 RtlSetDaclSecurityDescriptor -772 RtlSetGroupSecurityDescriptor -773 RtlSetOwnerSecurityDescriptor -774 RtlSetSaclSecurityDescriptor -775 RtlSetTimeZoneInformation -776 RtlSplay -777 RtlSubAuthorityCountSid -778 RtlSubAuthoritySid -779 RtlTimeFieldsToTime -780 RtlTimeToSecondsSince1970 -781 RtlTimeToSecondsSince1980 -782 RtlTimeToTimeFields -783 RtlUnicodeStringToAnsiSize -784 RtlUnicodeStringToAnsiString -785 RtlUnicodeStringToCountedOemString -786 RtlUnicodeStringToInteger -787 RtlUnicodeStringToOemSize -788 RtlUnicodeStringToOemString -789 RtlUnicodeToCustomCPN -790 RtlUnicodeToMultiByteN -791 RtlUnicodeToMultiByteSize -792 RtlUnicodeToOemN -793 RtlUnwind -794 RtlUpcaseUnicodeChar -795 RtlUpcaseUnicodeString -796 RtlUpcaseUnicodeStringToAnsiString -797 RtlUpcaseUnicodeStringToCountedOemString -798 RtlUpcaseUnicodeStringToOemString -799 RtlUpcaseUnicodeToCustomCPN -800 RtlUpcaseUnicodeToMultiByteN -801 RtlUpcaseUnicodeToOemN -802 RtlUpperChar -803 RtlUpperString -804 RtlValidSecurityDescriptor -805 RtlValidSid -806 RtlWriteRegistryValue -807 RtlZeroHeap -808 RtlZeroMemory -809 RtlxAnsiStringToUnicodeSize -810 RtlxOemStringToUnicodeSize -811 RtlxUnicodeStringToAnsiSize -812 RtlxUnicodeStringToOemSize -813 SeAccessCheck -814 SeAppendPrivileges -815 SeAssignSecurity -816 SeAuditingFileEvents -817 SeAuditingFileOrGlobalEvents -818 SeCaptureSecurityDescriptor -819 SeCaptureSubjectContext -820 SeCloseObjectAuditAlarm -821 SeCreateAccessState -822 SeCreateClientSecurity -823 SeDeassignSecurity -824 SeDeleteAccessState -825 SeDeleteObjectAuditAlarm -826 SeExports -827 SeFreePrivileges -828 SeImpersonateClient -829 SeLockSubjectContext -830 sionForTerminationNotification -831 SeOpenObjectAuditAlarm -832 SeOpenObjectForDeleteAuditAlarm -833 SePrivilegeCheck -834 SePrivilegeObjectAuditAlarm -835 SePublicDefaultDacl -836 SeQueryAuthenticationIdToken -837 SeQuerySecurityDescriptorInfo -838 SeRegisterLogonSessionTerminatedRoutine -839 SeReleaseSecurityDescriptor -840 SeReleaseSubjectContext -841 SeSetAccessStateGenericMapping -842 SeSetSecurityDescriptorInfo -843 SeSinglePrivilegeCheck -844 SeSystemDefaultDacl -845 SeTokenImpersonationLevel -846 SeTokenType -847 SeUnlockSubjectContext -848 SeUnregisterLogonSessionTerminatedRoutine -849 SeValidSecurityDescriptor -850 WRITE_REGISTER_BUFFER_UCHAR -851 WRITE_REGISTER_BUFFER_ULONG -852 WRITE_REGISTER_BUFFER_USHORT -853 WRITE_REGISTER_UCHAR -854 WRITE_REGISTER_ULONG -855 WRITE_REGISTER_USHORT -856 ZwAccessCheckAndAuditAlarm -857 ZwAlertThread -858 ZwAllocateVirtualMemory -859 ZwClearEvent -860 ZwClose -861 ZwCloseObjectAuditAlarm -862 ZwConnectPort -863 ZwCreateDirectoryObject -864 ZwCreateEvent -865 ZwCreateFile -866 ZwCreateKey -867 ZwCreateSection -868 ZwCreateSymbolicLinkObject -869 ZwDeleteFile -870 ZwDeleteKey -871 ZwDeleteValueKey -872 ZwDeviceIoControlFile -873 ZwDisplayString -874 ZwDuplicateObject -875 ZwDuplicateToken -876 ZwEnumerateKey -877 ZwEnumerateValueKey -878 ZwFlushInstructionCache -879 ZwFlushKey -880 ZwFreeVirtualMemory -881 ZwFsControlFile -882 ZwLoadDriver -883 ZwLoadKey -884 ZwMakeTemporaryObject -885 ZwMapViewOfSection -886 ZwNotifyChangeKey -887 ZwOpenDirectoryObject -888 ZwOpenEvent -889 ZwOpenFile -890 ZwOpenKey -891 ZwOpenProcess -892 ZwOpenProcessToken -893 ZwOpenSection -894 ZwOpenSymbolicLinkObject -895 ZwOpenThread -896 ZwOpenThreadToken -897 ZwPulseEvent -898 ZwQueryDefaultLocale -899 ZwQueryDirectoryFile -900 ZwQueryInformationFile -901 ZwQueryInformationProcess -902 ZwQueryInformationToken -903 ZwQueryKey -904 ZwQueryObject -905 ZwQuerySection -906 ZwQuerySecurityObject -907 ZwQuerySymbolicLinkObject -908 ZwQuerySystemInformation -909 ZwQueryValueKey -910 ZwQueryVolumeInformationFile -911 ZwReadFile -912 ZwReplaceKey -913 ZwRequestWaitReplyPort -914 ZwResetEvent -915 ZwSaveKey -916 ZwSetDefaultLocale -917 ZwSetEvent -918 ZwSetInformationFile -919 ZwSetInformationObject -920 ZwSetInformationProcess -921 ZwSetInformationThread -922 ZwSetSystemInformation -923 ZwSetSystemTime -924 ZwSetValueKey -925 ZwTerminateProcess -926 ZwUnloadDriver -927 ZwUnloadKey -928 ZwUnmapViewOfSection -929 ZwWaitForMultipleObjects -930 ZwWaitForSingleObject -931 ZwWriteFile -932 ZwYieldExecution -933 _abnormal_termination -934 _alldiv -935 _allmul -936 _allrem -937 _allshl -938 _allshr -939 _aulldiv -940 _aullrem -941 _aullshr -942 _except_handler2 -943 _global_unwind2 -944 _itoa -945 _local_unwind2 -946 _purecall -947 _snprintf -948 _snwprintf -949 _stricmp -950 _strlwr -951 _strnicmp -952 _strnset -953 _strrev -954 _strset -955 _strupr -956 _vsnprintf -957 _wcsicmp -958 _wcslwr -959 _wcsnicmp -960 _wcsnset -961 _wcsrev -962 _wcsupr -963 atoi -964 atol -965 isdigit -966 islower -967 isprint -968 isspace -969 isupper -970 isxdigit -971 mbstowcs -972 mbtowc -973 memchr -974 memcpy -975 memmove -976 memset -977 qsort -978 rand -979 sprintf -980 srand -981 strcat -982 strchr -983 strcmp -984 strcpy -985 strlen -986 strncat -987 strncmp -988 strncpy -989 strrchr -990 strspn -991 strstr -992 swprintf -993 tolower -994 toupper -995 towlower -996 towupper -997 vsprintf -998 wcscat -999 wcschr -1000 wcscmp -1001 wcscpy -1002 wcscspn -1003 wcslen -1004 wcsncat -1005 wcsncmp -1006 wcsncpy -1007 wcsrchr -1008 wcsspn -1009 wcsstr -1010 wcstombs -1011 wctomb - - -Import Name: hal.dll - -Hint Exported -Value: Name: -003E KdPortSave -0046 KeRaiseIrqlToDpcLevel -0001 ExReleaseFastMutex -0000 ExAcquireFastMutex -0002 ExTryToAcquireFastMutex -0022 HalRequestSoftwareInterrupt -0023 HalReturnToFirmware -000E HalDisplayString -001E HalQueryRealTimeClock -0029 HalSetRealTimeClock -002A HalSetTimeIncrement -0042 KeGetCurrentIrql -0044 KeQueryPerformanceCounter -0016 HalGetEnvironmentVariable -0027 HalSetEnvironmentVariable -004C KfRaiseIrql -0019 HalInitSystem -0020 HalReportResourceUsage -0005 HalAllProcessorsStarted -0006 HalAllocateAdapterChannel -0017 HalGetInterruptVector -002F HalTranslateBusAddress -0004 HalAdjustResourceList -0030 IoAssignDriveLetters -0035 IoReadPartitionTable -0007 HalAllocateCommonBuffer -003A KdPortInitialize -0039 KdPortGetByte -003C KdPortPutByte -003B KdPortPollByte -004B KfLowerIrql -003D KdPortRestore -0052 READ_PORT_ULONG -0053 READ_PORT_USHORT -0051 READ_PORT_UCHAR -0058 WRITE_PORT_ULONG -0059 WRITE_PORT_USHORT -0057 WRITE_PORT_UCHAR -001A HalInitializeProcessor -001C HalProcessorIdle -000C HalClearSoftwareInterrupt -0047 KeRaiseIrqlToSynchLevel -0018 HalHandleNMI -000A HalBeginSystemInterrupt -0010 HalEndSystemInterrupt -000F HalEnableSystemInterrupt -000D HalDisableSystemInterrupt -002E HalSystemVectorDispatchEntry -0045 KeRaiseIrql -0043 KeLowerIrql -0028 HalSetProfileInterval -002C HalStartProfileInterrupt -002D HalStopProfileInterrupt -001D HalQueryDisplayParameters -004D KfReleaseSpinLock -004A KfAcquireSpinLock -0041 KeFlushWriteBuffer -0049 KeStallExecutionProcessor - -These exported and imported functions might only correspond to Windows NT 4.0 diff --git a/reactos/ntoskrnl/vdm/vdmexec.c b/reactos/ntoskrnl/vdm/vdmexec.c new file mode 100644 index 00000000000..412f1b06d9f --- /dev/null +++ b/reactos/ntoskrnl/vdm/vdmexec.c @@ -0,0 +1,323 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/vdm/vdmexec.c + * PURPOSE: Support for executing VDM code and context swapping. + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +ULONG VdmBopCount; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NTAPI +VdmpGetVdmTib(OUT PVDM_TIB *VdmTib) +{ + PAGED_CODE(); + PVDM_TIB Tib; + + /* Assume vailure */ + *VdmTib = NULL; + + /* Get the current TIB */ + Tib = NtCurrentTeb()->Vdm; + if (!Tib) return STATUS_INVALID_SYSTEM_SERVICE; + + /* Validate the size */ + if (Tib->Size != sizeof(VDM_TIB)) return STATUS_INVALID_SYSTEM_SERVICE; + + /* Return it */ + *VdmTib = Tib; + return STATUS_SUCCESS; +} + +VOID +NTAPI +VdmSwapContext(IN PKTRAP_FRAME TrapFrame, + IN PCONTEXT OutContext, + IN PCONTEXT InContext) +{ + ULONG EFlags, OldEFlags; + + /* Make sure that we're at APC_LEVEL and that this is a valid frame */ + ASSERT_IRQL(APC_LEVEL); + ASSERT(TrapFrame->DbgArgMark = 0xBADB0D00); + + /* Check if this is a V86 frame */ + if (TrapFrame->EFlags & EFLAGS_V86_MASK) + { + /* Copy segment registers */ + OutContext->SegGs = TrapFrame->V86Gs; + OutContext->SegFs = TrapFrame->V86Fs; + OutContext->SegEs = TrapFrame->V86Es; + OutContext->SegDs = TrapFrame->V86Ds; + } + else if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK)) + { + /* This was user mode, copy segment registers */ + OutContext->SegGs = TrapFrame->SegGs; + OutContext->SegFs = TrapFrame->SegFs; + OutContext->SegEs = TrapFrame->SegEs; + OutContext->SegDs = TrapFrame->SegDs; + } + + /* Copy CS and SS */ + OutContext->SegCs = TrapFrame->SegCs; + OutContext->SegSs = TrapFrame->HardwareSegSs; + + /* Copy general purpose registers */ + OutContext->Eax = TrapFrame->Eax; + OutContext->Ebx = TrapFrame->Ebx; + OutContext->Ecx = TrapFrame->Ecx; + OutContext->Edx = TrapFrame->Edx; + OutContext->Esi = TrapFrame->Esi; + OutContext->Edi = TrapFrame->Edi; + + /* Copy stack and counter */ + OutContext->Ebp = TrapFrame->Ebp; + OutContext->Esp = TrapFrame->HardwareEsp; + OutContext->Eip = TrapFrame->Eip; + + /* Finally the flags */ + OutContext->EFlags = TrapFrame->EFlags; + + /* Now copy from the in frame to the trap frame */ + TrapFrame->SegCs = InContext->SegCs; + TrapFrame->HardwareSegSs = InContext->SegSs; + + /* Copy the general purpose registers */ + TrapFrame->Eax = InContext->Eax; + TrapFrame->Ebx = InContext->Ebx; + TrapFrame->Ecx = InContext->Ecx; + TrapFrame->Edx = InContext->Edx; + TrapFrame->Esi = InContext->Esi; + TrapFrame->Edi = InContext->Edi; + + /* Copy the stack and counter */ + TrapFrame->Ebp = InContext->Ebp; + TrapFrame->HardwareEsp = InContext->Esp; + TrapFrame->Eip = InContext->Eip; + + /* Check if the context is from V86 */ + EFlags = InContext->EFlags; + if (EFlags & EFLAGS_V86_MASK) + { + /* Sanitize the flags for V86 */ + EFlags &= KeI386EFlagsAndMaskV86; + EFlags |= KeI386EFlagsOrMaskV86; + } + else + { + /* Add RPL_MASK to segments */ + TrapFrame->SegCs |= RPL_MASK; + TrapFrame->HardwareSegSs |= RPL_MASK; + + /* Check for bogus CS */ + if (TrapFrame->SegCs < KGDT_R0_CODE) + { + /* Set user-mode */ + TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; + } + + /* Sanitize flags and add interrupt mask */ + EFlags &= EFLAGS_USER_SANITIZE; + EFlags |=EFLAGS_INTERRUPT_MASK; + } + + /* Save the new eflags */ + OldEFlags = TrapFrame->EFlags; + TrapFrame->EFlags = EFlags; + + /* Check if we need to fixup ESP0 */ + if ((OldEFlags ^ EFlags) & EFLAGS_V86_MASK) + { + /* Fix it up */ + Ki386AdjustEsp0(TrapFrame); + } + + /* Check if this is a V86 context */ + if (InContext->EFlags & EFLAGS_V86_MASK) + { + /* Copy VDM segments */ + TrapFrame->V86Gs = InContext->SegGs; + TrapFrame->V86Fs = InContext->SegFs; + TrapFrame->V86Es = InContext->SegEs; + TrapFrame->V86Ds = InContext->SegDs; + } + else + { + /* Copy monitor segments */ + TrapFrame->SegGs = InContext->SegGs; + TrapFrame->SegFs = InContext->SegFs; + TrapFrame->SegEs = InContext->SegEs; + TrapFrame->SegDs = InContext->SegDs; + } + + /* Clear the exception list and return */ + TrapFrame->ExceptionList = EXCEPTION_CHAIN_END; +} + +NTSTATUS +NTAPI +VdmpStartExecution(VOID) +{ + PETHREAD Thread = PsGetCurrentThread(); + PKTRAP_FRAME VdmFrame; + NTSTATUS Status; + PVDM_TIB VdmTib; + BOOLEAN Interrupts; + KIRQL OldIrql; + CONTEXT VdmContext; + PAGED_CODE(); + + /* Get the thread's VDM frame and TIB */ + VdmFrame = (PVOID)((ULONG_PTR)Thread->Tcb.InitialStack - + sizeof(FX_SAVE_AREA) - + sizeof(KTRAP_FRAME)); + Status = VdmpGetVdmTib(&VdmTib); + if (!NT_SUCCESS(Status)) return STATUS_INVALID_SYSTEM_SERVICE; + + /* Go to APC level */ + KeRaiseIrql(APC_LEVEL, &OldIrql); + + /* Check if interrupts are enabled */ + Interrupts = (BOOLEAN)(VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK); + + /* We don't support full VDM yet, this shouldn't happen */ + ASSERT(*VdmState == 0); + ASSERT(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK); + + /* Get the VDM context and make sure it's an edited frame */ + VdmContext = VdmTib->VdmContext; + if (!(VdmContext.SegCs & FRAME_EDITED)) + { + /* Fail */ + KeLowerIrql(OldIrql); + return STATUS_INVALID_SYSTEM_SERVICE; + } + + /* FIXME: Support VME */ + ASSERT(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK); + + /* Set interrupt state in the VDM State */ + if (VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK) + { + /* Enable them as well */ + InterlockedOr(VdmState, EFLAGS_INTERRUPT_MASK); + } + else + { + /* Disable them */ + InterlockedAnd(VdmState, ~EFLAGS_INTERRUPT_MASK); + } + + /* Enable the interrupt flag */ + VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK; + + /* Now do the VDM Swap */ + VdmSwapContext(VdmFrame, &VdmTib->MonitorContext, &VdmContext); + + /* Lower the IRQL and return EAX */ + KeLowerIrql(OldIrql); + return VdmFrame->Eax; +} + +VOID +NTAPI +VdmEndExecution(IN PKTRAP_FRAME TrapFrame, + IN PVDM_TIB VdmTib) +{ + KIRQL OldIrql; + CONTEXT Context; + PAGED_CODE(); + + /* Sanity check */ + ASSERT((TrapFrame->EFlags & EFLAGS_V86_MASK) || + (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK))); + + /* Raise to APC_LEVEL */ + KeRaiseIrql(APC_LEVEL, &OldIrql); + + /* Set success */ + VdmTib->MonitorContext.Eax = STATUS_SUCCESS; + + /* Make a copy of the monitor context */ + RtlMoveMemory(&Context, &VdmTib->MonitorContext, sizeof(CONTEXT)); + + /* Switch contexts */ + VdmSwapContext(TrapFrame, &VdmTib->VdmContext, &Context); + + /* FIXME: Support VME */ + + /* Set the EFLAGS */ + VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & + ~EFLAGS_INTERRUPT_MASK) | + (*VdmState & EFLAGS_INTERRUPT_MASK); + + /* Lower IRQL and reutrn */ + KeLowerIrql(OldIrql); +} + +BOOLEAN +NTAPI +VdmDispatchBop(IN PKTRAP_FRAME TrapFrame) +{ + PUCHAR Eip; + PVDM_TIB VdmTib; + + /* Check if this is from V86 mode */ + if (TrapFrame->EFlags & EFLAGS_V86_MASK) + { + /* Calculate flat EIP */ + Eip = (PUCHAR)((TrapFrame->Eip & 0xFFFF) + + ((TrapFrame->SegCs & 0xFFFF) << 4)); + + /* Check if this is a BOP */ + if (*(PUSHORT)Eip == 0xC4C4) + { + /* Check sure its the DOS Bop */ + if (Eip[2] == 0x50) + { + /* FIXME: No VDM Support */ + ASSERT(FALSE); + } + + /* Increase the number of BOP operations */ + VdmBopCount++; + + /* Get the TIB */ + VdmTib = NtCurrentTeb()->Vdm; + + /* Fill out a VDM Event */ + VdmTib->EventInfo.InstructionSize = 3; + VdmTib->EventInfo.BopNumber = Eip[2]; + VdmTib->EventInfo.Event = VdmBop; + + /* End VDM Execution */ + VdmEndExecution(TrapFrame, VdmTib); + } + else + { + /* Not a BOP */ + return FALSE; + } + } + else + { + /* FIXME: Shouldn't happen on ROS */ + ASSERT(FALSE); + } + + /* Return success */ + return TRUE; +} + diff --git a/reactos/ntoskrnl/vdm/vdmmain.c b/reactos/ntoskrnl/vdm/vdmmain.c new file mode 100644 index 00000000000..39bfbf359af --- /dev/null +++ b/reactos/ntoskrnl/vdm/vdmmain.c @@ -0,0 +1,131 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/vdm/vdmmain.c + * PURPOSE: VDM Support Services + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +static UCHAR OrigIVT[1024]; +static UCHAR OrigBDA[256]; + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +INIT_FUNCTION +NtEarlyInitVdm(VOID) +{ + /* GCC 3.4 hack */ + PVOID start = (PVOID)0x0; + + /* + * Save various BIOS data tables. At this point the lower 4MB memory + * map is still active so we can just copy the data from low memory. + * HACK HACK HACK: We should just map Physical Memory!!! + */ + memcpy(OrigIVT, start, 1024); + memcpy(OrigBDA, (PVOID)0x400, 256); +} + +VOID +NTAPI +Ki386VdmEnablePentiumExtentions(VOID) +{ + DPRINT1("VME detected but not yet supported\n"); +} + +VOID +NTAPI +KeI386VdmInitialize(VOID) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE RegHandle; + UNICODE_STRING Name; + UCHAR KeyValueInfo[sizeof(KEY_VALUE_BASIC_INFORMATION) + 30]; + ULONG ReturnLength; + + /* Make sure that there is a WOW key */ + RtlInitUnicodeString(&Name, + L"\\Registry\\Machine\\System\\CurrentControlSet\\" + "Control\\Wow"); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = ZwOpenKey(&RegHandle, KEY_READ, &ObjectAttributes); + if (!NT_SUCCESS(Status)) return; + + /* Check if VME is enabled */ + RtlInitUnicodeString(&Name, L"DisableVme"); + Status = ZwQueryValueKey(RegHandle, + &Name, + KeyValueBasicInformation, + &KeyValueInfo, + sizeof(KeyValueInfo), + &ReturnLength); + if (!NT_SUCCESS(Status)) + { + /* Not present, so check if the CPU supports VME */ + if (KeGetPcr()->Prcb->FeatureBits & X86_FEATURE_VME) + { + /* Enable them. FIXME: Use IPI */ + Ki386VdmEnablePentiumExtentions(); + KeI386VirtualIntExtensions = TRUE; + } + } + + /* Close the key */ + ZwClose(RegHandle); +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +NtVdmControl(IN ULONG ControlCode, + IN PVOID ControlData) +{ + NTSTATUS Status; + PAGED_CODE(); + + /* Check which control code this is */ + switch (ControlCode) + { + /* VDM Execution start */ + case VdmStartExecution: + + /* Call the sub-function */ + Status = VdmpStartExecution(); + break; + + case VdmInitialize: + + /* Pretty much a hack, since a lot more needs to happen */ + memcpy(ControlData, OrigIVT, 1024); + memcpy((PVOID)((ULONG_PTR)ControlData + 1024), OrigBDA, 256); + Status = STATUS_SUCCESS; + break; + + default: + + /* Unsupported */ + DPRINT1("Unknown VDM call: %lx\n", ControlCode); + Status = STATUS_INVALID_PARAMETER; + } + + /* Return the status */ + return Status; +} diff --git a/reactos/subsystems/win32/csrss/video.c b/reactos/subsystems/win32/csrss/video.c index fff97dc8597..99b02dd7971 100644 --- a/reactos/subsystems/win32/csrss/video.c +++ b/reactos/subsystems/win32/csrss/video.c @@ -19,8 +19,7 @@ InitializeVideoAddressSpace(VOID) PVOID NullAddress; LARGE_INTEGER Offset; ULONG ViewSize; - CHAR IVT[1024]; - CHAR BDA[256]; + CHAR IVTAndBda[1024+256]; /* * Open the physical memory section @@ -93,35 +92,21 @@ InitializeVideoAddressSpace(VOID) } /* - * Get the real mode IVT from the kernel + * Get the real mode IVT and BDA from the kernel */ - Status = NtVdmControl(0, IVT); - if (!NT_SUCCESS(Status)) + Status = NtVdmControl(VdmInitialize, IVTAndBda); + if (!NT_SUCCESS(Status)) { DbgPrint("NtVdmControl failed (status %x)\n", Status); return(0); } /* - * Copy the real mode IVT into the right place + * Copy the IVT and BDA into the right place */ NullAddress = (PVOID)0x0; /* Workaround for GCC 3.4 */ - memcpy(NullAddress, IVT, 1024); - - /* - * Get the BDA from the kernel - */ - Status = NtVdmControl(1, BDA); - if (!NT_SUCCESS(Status)) - { - DbgPrint("NtVdmControl failed (status %x)\n", Status); - return(0); - } - - /* - * Copy the BDA into the right place - */ - memcpy((PVOID)0x400, BDA, 256); + memcpy(NullAddress, IVTAndBda, 1024); + memcpy((PVOID)0x400, &IVTAndBda[1024], 256); return(1); }