From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/mvdm/v86/dirs | 24 + private/mvdm/v86/monitor/i386/fastpm.asm | 357 +++++++ private/mvdm/v86/monitor/i386/int.c | 454 +++++++++ private/mvdm/v86/monitor/i386/monitor.c | 1135 +++++++++++++++++++++ private/mvdm/v86/monitor/i386/monitorp.h | 221 ++++ private/mvdm/v86/monitor/i386/proflib.c | 930 +++++++++++++++++ private/mvdm/v86/monitor/i386/sas.c | 1551 +++++++++++++++++++++++++++++ private/mvdm/v86/monitor/i386/sources | 11 + private/mvdm/v86/monitor/i386/spcstubs.c | 109 ++ private/mvdm/v86/monitor/i386/thread.c | 338 +++++++ private/mvdm/v86/monitor/makefile | 6 + private/mvdm/v86/monitor/sources | 57 ++ private/mvdm/v86/scaffold/i386/fakebop.c | 502 ++++++++++ private/mvdm/v86/scaffold/i386/fakeinit.c | 123 +++ private/mvdm/v86/scaffold/i386/fakekbd.c | 281 ++++++ private/mvdm/v86/scaffold/i386/fakevid.c | 175 ++++ private/mvdm/v86/scaffold/i386/fun.h | 24 + private/mvdm/v86/scaffold/i386/softpc.c | 442 ++++++++ private/mvdm/v86/scaffold/i386/sources | 6 + private/mvdm/v86/scaffold/i386/stubs.c | 46 + private/mvdm/v86/scaffold/i386/x86.h | 418 ++++++++ private/mvdm/v86/scaffold/i386/xbios.h | 123 +++ private/mvdm/v86/scaffold/i386/xbiosdsk.h | 244 +++++ private/mvdm/v86/scaffold/i386/xbioskbd.h | 39 + private/mvdm/v86/scaffold/i386/xbiosvid.h | 65 ++ private/mvdm/v86/scaffold/i386/xguest.h | 459 +++++++++ private/mvdm/v86/scaffold/i386/xwincon.h | 186 ++++ private/mvdm/v86/scaffold/makefile | 6 + private/mvdm/v86/scaffold/ntvdm.def | 90 ++ private/mvdm/v86/scaffold/sources | 157 +++ private/mvdm/v86/scaffold/vdm.ico | Bin 0 -> 766 bytes private/mvdm/v86/scaffold/vdm.rc | 57 ++ private/mvdm/v86/scaffold/wow.ico | Bin 0 -> 766 bytes private/mvdm/v86/util/makefile | 56 ++ private/mvdm/v86/util/quit.asm | 40 + 35 files changed, 8732 insertions(+) create mode 100644 private/mvdm/v86/dirs create mode 100644 private/mvdm/v86/monitor/i386/fastpm.asm create mode 100644 private/mvdm/v86/monitor/i386/int.c create mode 100644 private/mvdm/v86/monitor/i386/monitor.c create mode 100644 private/mvdm/v86/monitor/i386/monitorp.h create mode 100644 private/mvdm/v86/monitor/i386/proflib.c create mode 100644 private/mvdm/v86/monitor/i386/sas.c create mode 100644 private/mvdm/v86/monitor/i386/sources create mode 100644 private/mvdm/v86/monitor/i386/spcstubs.c create mode 100644 private/mvdm/v86/monitor/i386/thread.c create mode 100644 private/mvdm/v86/monitor/makefile create mode 100644 private/mvdm/v86/monitor/sources create mode 100644 private/mvdm/v86/scaffold/i386/fakebop.c create mode 100644 private/mvdm/v86/scaffold/i386/fakeinit.c create mode 100644 private/mvdm/v86/scaffold/i386/fakekbd.c create mode 100644 private/mvdm/v86/scaffold/i386/fakevid.c create mode 100644 private/mvdm/v86/scaffold/i386/fun.h create mode 100644 private/mvdm/v86/scaffold/i386/softpc.c create mode 100644 private/mvdm/v86/scaffold/i386/sources create mode 100644 private/mvdm/v86/scaffold/i386/stubs.c create mode 100644 private/mvdm/v86/scaffold/i386/x86.h create mode 100644 private/mvdm/v86/scaffold/i386/xbios.h create mode 100644 private/mvdm/v86/scaffold/i386/xbiosdsk.h create mode 100644 private/mvdm/v86/scaffold/i386/xbioskbd.h create mode 100644 private/mvdm/v86/scaffold/i386/xbiosvid.h create mode 100644 private/mvdm/v86/scaffold/i386/xguest.h create mode 100644 private/mvdm/v86/scaffold/i386/xwincon.h create mode 100644 private/mvdm/v86/scaffold/makefile create mode 100644 private/mvdm/v86/scaffold/ntvdm.def create mode 100644 private/mvdm/v86/scaffold/sources create mode 100644 private/mvdm/v86/scaffold/vdm.ico create mode 100644 private/mvdm/v86/scaffold/vdm.rc create mode 100644 private/mvdm/v86/scaffold/wow.ico create mode 100644 private/mvdm/v86/util/makefile create mode 100644 private/mvdm/v86/util/quit.asm (limited to 'private/mvdm/v86') diff --git a/private/mvdm/v86/dirs b/private/mvdm/v86/dirs new file mode 100644 index 000000000..a9274c0f7 --- /dev/null +++ b/private/mvdm/v86/dirs @@ -0,0 +1,24 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dirs. + +Abstract: + + This file specifies the subdirectories of the current directory that + contain component makefiles. + + +Author: + + Steve Wood (stevewo) 17-Apr-1990 + Dave Hastings (daveh) 24-Apr-1991 + +NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl + +!ENDIF + +DIRS= monitor diff --git a/private/mvdm/v86/monitor/i386/fastpm.asm b/private/mvdm/v86/monitor/i386/fastpm.asm new file mode 100644 index 000000000..e42959d04 --- /dev/null +++ b/private/mvdm/v86/monitor/i386/fastpm.asm @@ -0,0 +1,357 @@ + title "Fast Protected Mode services" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; +; Module Name: +; +; fastpm.asm +; +; Abstract: +; +; This module implements a fast entry to and exit from protected mode +; +; Author: +; +; Dave Hastings (daveh) 26-Jul-91 +; +;-- +.386p + +include ks386.inc +include callconv.inc +include bop.inc +include vint.inc +include vdmtb.inc + +_TEXT SEGMENT PARA PUBLIC 'CODE' + ASSUME DS:NOTHING, ES:NOTHING, SS:FLAT, FS:NOTHING, GS:NOTHING +_TEXT ENDS + +_DATA SEGMENT DWORD PUBLIC 'DATA' + extrn _VdmTib:Dword + + public _NTVDMpLockPrefixTable +_NTVDMpLockPrefixTable label dword + dd offset FLAT:_ntvdmlock1 + dd offset FLAT:_ntvdmlock2 + dd 0 + +_DATA ENDS + +_TEXT SEGMENT + +; Interrupt type definitions +CPU_YODA_INT equ 4 +BIT_CPU_YODA_INT equ 0 +CPU_HW_RESET equ 0 +BIT_CPU_HW_RESET equ 1 +CPU_TIMER_TICK equ 1 +BIT_CPU_TIMER_TICK equ 2 +CPU_HW_INT equ 3 +BIT_CPU_HW_INT equ 3 + + page ,132 + subttl "FastEnterPm" +;++ +; +; Routine Description: +; +; This routine is a faster way to enter 16 bit vdm protected mode. +; Instead of making a system call, we just save the 32 bit state +; into the VdmTib, restore the Vdm state from the VdmTib, and do +; a far return to the application. +; +; Arguments: +; +; ss:sp + 4 = pointer to VdmTib +; +; Returns: +; +; nothing. +; + assume DS:FLAT +cPublicProc _FastEnterPm,0 + + push ebp + mov ebp,esp ; set up stack frame + + push ebx ; free up reg for pointer + lea ebx,_VdmTib + + ; translate the interrupt flag to the virtual interrupt flag + + test [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK + jz fe10 + +_ntvdmlock1: + lock or dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS + test dword ptr ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_INTERRUPT_PENDING + jz fe20 + + ; set up event info for an interrupt acknowlege + + mov word ptr [ebx].VtEventInfo.EiEvent,VdmIntAck + mov word ptr [ebx].VtEventInfo.EiInstructionSize,0 + mov word ptr [ebx].VtEventInfo.EiIntAckInfo,0 + + pop ebx + mov esp,ebp + pop ebp + stdRET _FastEnterPm + +fe10: +_ntvdmlock2: + lock and dword ptr ds:FIXED_NTVDMSTATE_LINEAR, NOT VDM_VIRTUAL_INTERRUPTS +fe20: + mov [ebx].VtMonitorContext.CsEax,eax + mov eax,[ebp - 4] + mov [ebx].VtMonitorContext.CsEbx,eax + mov [ebx].VtMonitorContext.CsEcx,ecx + mov [ebx].VtMonitorContext.CsEdx,edx + mov [ebx].VtMonitorContext.CsEsi,esi + mov [ebx].VtMonitorContext.CsEdi,edi + mov eax,[ebp] + mov [ebx].VtMonitorContext.CsEbp,eax + mov eax,ebp + + add eax,8 ; pop ebp and ret addr + + mov [ebx].VtMonitorContext.CsEsp,eax + mov eax,[ebp + 4] + mov [ebx].VtMonitorContext.CsEip,eax + mov eax,cs + mov [ebx].VtMonitorContext.CsSegCs,eax + mov eax,ss + mov [ebx].VtMonitorContext.CsSegSs,eax + mov eax,ds + mov [ebx].VtMonitorContext.CsSegDs,eax + mov eax,es + mov [ebx].VtMonitorContext.CsSegEs,eax + mov eax,fs + mov [ebx].VtMonitorContext.CsSegFs,eax + mov eax,gs + mov [ebx].VtMonitorContext.CsSegGs,eax + pushfd + pop eax + mov [ebx].VtMonitorContext.CsEflags,eax + + mov eax,[ebx].VtVdmContext.CsSegSs + mov es,eax + mov edi,[ebx].VtVdmContext.CsEsp ; es:edi -> stack + lar eax,eax + test eax,400000h ; big? + jnz fe30 + + movzx edi,di +fe30: mov eax,[ebx].VtVdmContext.CsEflags + sub edi,4 + mov es:[edi],eax ; push Eflags + mov eax,[ebx].VtVdmContext.CsSegCs + sub edi,4 + mov es:[edi],eax ; push cs + mov eax,[ebx].VtVdmContext.CsEip + sub edi,4 + mov es:[edi],eax ; push ip + sub edi,4 + mov eax,[ebx].VtVdmContext.CsEbp ; push ebp + mov es:[edi],eax + +fe40: push es + push edi ; push ss:esp for lss esp + mov eax,esp ; save sp for pushad + + ; simulate pushad + push dword ptr [ebx].VtVdmContext.CsEax + push dword ptr [ebx].VtVdmContext.CsEcx + push dword ptr [ebx].VtVdmContext.CsEdx + push dword ptr [ebx].VtVdmContext.CsEbx + push eax + push ebp ; save pointer to stack frame + push dword ptr [ebx].VtVdmContext.CsEsi + push dword ptr [ebx].VtVdmContext.CsEdi + + ; push seg regs + push dword ptr [ebx].VtVdmContext.CsSegFs + push dword ptr [ebx].VtVdmContext.CsSegGs + push dword ptr [ebx].VtVdmContext.CsSegDs + push dword ptr [ebx].VtVdmContext.CsSegEs + + ; set up VDM seg regs + pop es + pop ds + pop gs ; pop fs,gs of invalid selectors are trapped in ntoskrnl, + pop fs ; and handled by setting to zero + + ; set up VDM general regs + popad + + ; set up vdm stack + lss esp,[ebp - 12] + + ; restore ebp + pop ebp + + ; return to VDM + iretd +stdENDP _FastEnterPm + + page ,132 + subttl "GetFastBopEntry" +;++ +; +; Routine Description: +; +; This routine supplies the address of the routine that segmented +; protected mode code should call to switch to flat mode. +; +; Arguments: +; +; esp + 4 = pointer to VdmTib->VdmContext +; +; Returns: +; +; nothing. +; + assume DS:FLAT +cPublicProc _GetFastBopEntryAddress,1 + + push ebp + mov ebp,esp + push ebx + push eax + mov ebx,[ebp + 8] + mov [ebx].CsSegEs,cs + mov eax,offset FLAT:_FastLeavePm + mov word ptr [ebx].CsEbx,ax + shr eax,16 + mov word ptr [ebx].CsEdx,ax + pop eax + pop ebx + mov esp,ebp + pop ebp + stdRET _GetFastBopEntryAddress + +stdENDP _GetFastBopEntryAddress + + page ,132 + subttl "FastLeavePm" +;++ +; +; Routine Description: +; +; This routine switches from the VDM context to the monitor context. +; +; Arguments: +; +; none +; +; Returns: +; +; executing with monitor context +; + assume DS:Nothing,ES:Nothing,SS:Nothing +ALIGN 16 +cPublicProc _FastLeavePm,0 + + push ebx + + mov bx,ds + push bx ; so push and pop size same + mov bx,KGDT_R3_DATA OR RPL_MASK + mov ds,bx + assume ds:FLAT + lea ebx,_VdmTib ; get pointer to contexts + pushfd + mov dword ptr [ebx].VtVdmContext.CsEax,eax + pop eax + mov dword ptr [ebx].VtVdmContext.CsEFlags,eax + pop ax + mov word ptr [ebx].VtVdmContext.CsSegDs,ax + pop eax + mov dword ptr [ebx].VtVdmContext.CsEbx,eax + mov dword ptr [ebx].VtVdmContext.CsEcx,ecx + mov dword ptr [ebx].VtVdmContext.CsEdx,edx + mov dword ptr [ebx].VtVdmContext.CsEsi,esi + mov dword ptr [ebx].VtVdmContext.CsEdi,edi + mov dword ptr [ebx].VtVdmContext.CsEbp,ebp + mov word ptr [ebx].VtVdmContext.CsSegEs,es + mov word ptr [ebx].VtVdmContext.CsSegFs,fs + mov word ptr [ebx].VtVdmContext.CsSegGs,gs + pop eax + mov dword ptr [ebx].VtVdmContext.CsEip,eax + pop eax + mov word ptr [ebx].VtVdmContext.CsSegCs,ax + mov dword ptr [ebx].VtVdmContext.CsEsp,esp + mov word ptr [ebx].VtVdmContext.CsSegSs,ss + + ; switch Stacks +.errnz (CsEsp + 4 - CsSegSS) + lss esp, [ebx].VtMonitorContext.CsEsp + + ; Now running on Monitor stack + + ; set up event info + mov word ptr [ebx].VtEventInfo.EiEvent,VdmBop + mov dword ptr [ebx].VtEventInfo.EiInstructionSize,BOP_SIZE + mov ax,[ebx].VtVdmContext.CsSegCs + mov es,ax + ; BUGBUG 16 or 32 bit !!!!! + mov di,[ebx].VtVdmContext.CsEip + mov al,byte ptr es:[di] + movzx eax,al + mov [ebx].VtEventInfo.EiBopNumber,eax + sub di,2 + mov word ptr [ebx].VtVdmContext.CsEip,di ; set up bop bias + + ; set up for IRET + push dword ptr [ebx].VtMonitorContext.CsEFlags + push dword ptr [ebx].VtMonitorContext.CsSegCs + push dword ptr [ebx].VtMonitorContext.CsEip + + ; simulate pushad + mov eax,esp + push dword ptr [ebx].VtMonitorContext.CsEax + push dword ptr [ebx].VtMonitorContext.CsEcx + push dword ptr [ebx].VtMonitorContext.CsEdx + push dword ptr [ebx].VtMonitorContext.CsEbx + push eax + push dword ptr [ebx].VtMonitorContext.CsEbp + push dword ptr [ebx].VtMonitorContext.CsEsi + push dword ptr [ebx].VtMonitorContext.CsEdi + + ; push seg regs + push dword ptr [ebx].VtMonitorContext.CsSegFs + push dword ptr [ebx].VtMonitorContext.CsSegGs + push dword ptr [ebx].VtMonitorContext.CsSegDs + push dword ptr [ebx].VtMonitorContext.CsSegEs + + test ds:FIXED_NTVDMSTATE_LINEAR,dword ptr VDM_VIRTUAL_INTERRUPTS + jz fl10 + + or [ebx].VtVdmContext.CsEFlags,dword ptr EFLAGS_INTERRUPT_MASK + jmp fl20 + +fl10: and dword ptr [ebx].VtVdmContext.CsEFlags, NOT EFLAGS_INTERRUPT_MASK +fl20: + ; set up Monitor seg regs + pop es + pop ds + pop gs + pop fs + + ; set up Monitor general regs + popad + + xor eax,eax ; indicate success + ; return + iretd +stdENDP _FastLeavePm + +_TEXT ends + end + + + + + diff --git a/private/mvdm/v86/monitor/i386/int.c b/private/mvdm/v86/monitor/i386/int.c new file mode 100644 index 000000000..7912809da --- /dev/null +++ b/private/mvdm/v86/monitor/i386/int.c @@ -0,0 +1,454 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + int.c + +Abstract: + + This file contains interrupt support routines for the monitor + +Author: + + Dave Hastings (daveh) 18-Apr-1992 + +Notes: + + The code in this file split out from monitor.c (18-Apr-1992) + +Revision History: + +--*/ + +#include + +BOOL +DpmiHwIntHandler( + ULONG IntNumber + ); + +VOID +IRQ13_Eoi( + int IrqLine, + int CallCount + ); + +BOOLEAN IRQ13BeingHandled; // true until IRQ13 eoi'ed + + +VOID +InterruptInit( + VOID +) +/*++ + +Routine Description: + + This routine initializes the interrupt code for the monitor. + +Arguments: + + +Return Value: + + None. + +--*/ +{ + BOOL Bool; + + + + Bool = RegisterEOIHook( 13, IRQ13_Eoi); + if (!Bool) { +#if DBG + DbgPrint("NtVdm : Could not register IRQ 13 Eoi handler\n"); + DbgBreakPoint(); +#endif + TerminateVDM(); + } +} + +VOID +InterruptTerminate( + VOID + ) +/*++ + +Routine Description: + + This routine frees the resoures allocated by InterruptInit + +Arguments: + + +Return Value: + + None. + +--*/ +{ +} + + +VOID +cpu_interrupt( + IN int Type, + IN int Number + ) +/*++ + +Routine Description: + + This routine causes an interrupt of the specified type to be raised + at the appropriate time. + +Arguments: + + Type -- indicates the type of the interrupt. One of HARDWARE, TIMER, YODA, + or RESET + + YODA and RESET are ignored + +Return Value: + + None. + +Notes: + +--*/ +{ + NTSTATUS Status; + HANDLE MonitorThread; + + host_ica_lock(); + + if (Type == CPU_TIMER_TICK) { + + // + // Set the VDM State for timer tick int pending + // + _asm { + mov eax, FIXED_NTVDMSTATE_LINEAR + lock or dword ptr [eax], VDM_INT_TIMER + } + } else if (Type == CPU_HW_INT) { + + if (*pNtVDMState & VDM_INT_HARDWARE) { + goto EarlyExit; + } + + // + // Set the VDM State for Hardware Int pending + // + _asm { + mov eax, FIXED_NTVDMSTATE_LINEAR + lock or dword ptr [eax], VDM_INT_HARDWARE + } + } else { +#if DBG + DbgPrint("Monitor: Invalid Interrupt Type=%ld\n",Type); +#endif + goto EarlyExit; + } + + if (CurrentMonitorTeb != NtCurrentTeb()) { + + /* + * Look up the ThreadHandle and Queue and InterruptApc + * If no ThreadHandle found do nothing + * + * The CurrentMonitorTeb may not be in the ThreadHandle\Teb list + * because upon task termination the the CurrentMonitorTeb variable + * cannot be updated until a new task is activated by the + * non-preemptive scheduler. + */ + MonitorThread = ThreadLookUp(CurrentMonitorTeb); + if (MonitorThread) { + Status = NtVdmControl(VdmQueueInterrupt, (PVOID)MonitorThread); + // nothing much we can do if this fails +#if DBG + if (!NT_SUCCESS(Status) && Status != STATUS_UNSUCCESSFUL) { + DbgPrint("NtVdmControl.VdmQueueInterrupt Status=%lx\n",Status); + } +#endif + } + + } + +EarlyExit: + + host_ica_unlock(); +} + + + + +VOID +DispatchInterrupts( + ) +/*++ + +Routine Description: + + This routine dispatches interrupts to their appropriate handler routine + in priority order. The order is YODA, RESET, TIMER, HARDWARE. however + the YODA and RESET interrupts do nothing. Hardware interrupts are not + simulated unless the virtual interrupt enable flag is set. Flags + indicating which interrupts are pending appear in the pNtVDMState. + + +Arguments: + + None. + +Return Value: + + None. + +Notes: + +--*/ +{ + + host_ica_lock(); + + // If any delayed interrupts have expired + // call the ica to restart interrupts + if (UndelayIrqLine) { + ica_RestartInterrupts(UndelayIrqLine); + } + + + if (*pNtVDMState & VDM_INT_TIMER) { + *pNtVDMState &= ~VDM_INT_TIMER; + host_ica_unlock(); // maybe don't need to unlock ? Jonle + host_timer_event(); + host_ica_lock(); + } + + if ( getIF() && getMSW() & MSW_PE && *pNtVDMState & VDM_INT_HARDWARE) { + // + // Mark the vdm state as hw int dispatched. Must use the lock as + // kernel mode DelayedIntApcRoutine changes the bit as well + // + _asm { + mov eax,FIXED_NTVDMSTATE_LINEAR + lock and dword ptr [eax], NOT VDM_INT_HARDWARE + } + DispatchHwInterrupt(); + } + + host_ica_unlock(); +} + + + + +VOID +DispatchHwInterrupt( + ) +/*++ + +Routine Description: + + This routine dispatches hardware interrupts to the vdm in Protect Mode. + It calls the ICA to get the vector number and sets up the VDM stack + appropriately. Real Mode interrupt dispatching has been moved to the + kernel. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + int InterruptNumber; + ULONG IretHookAddress = 0L; + + InterruptNumber = ica_intack(&IretHookAddress); + if (InterruptNumber == -1) { // skip spurious ints + return; + } + + DpmiHwIntHandler(InterruptNumber); + + if (IretHookAddress) { + BOOL Frame32 = (BOOL) VdmTib.PmStackInfo.Flags; + BOOL Stack32; + USHORT SegSs, VdmCs; + ULONG VdmSp, VdmEip; + PUCHAR VdmStackPointer; + ULONG StackOffset; + + SegSs = getSS(); + VdmStackPointer = Sim32GetVDMPointer(((ULONG)SegSs) << 16, 1, TRUE); + + // + // Figure out how many bits of sp to use + // + + if (Ldt[(SegSs & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Default_Big) { + VdmSp = getESP(); + StackOffset = 12; + } else { + VdmSp = getSP(); + StackOffset = 6; + } + + (PCHAR)VdmStackPointer += VdmSp; + + // + // BUGBUG need to add stack limit checking 15-Nov-1993 Jonle + // + setESP(VdmSp - StackOffset); + + // + // Push info for Iret hook handler + // + VdmCs = (USHORT) ((IretHookAddress & 0xFFFF0000) >> 16); + VdmEip = (IretHookAddress & 0xFFFF); + + if (Frame32) { + *(PULONG)(VdmStackPointer - 4) = VdmTib.VdmContext.EFlags; + *(PULONG)(VdmStackPointer - 8) = (ULONG) VdmCs; + *(PULONG)(VdmStackPointer - 12) = VdmEip; + } else { + *(PUSHORT)(VdmStackPointer - 2) = (USHORT) VdmTib.VdmContext.EFlags; + *(PUSHORT)(VdmStackPointer - 4) = VdmCs; + *(PUSHORT)(VdmStackPointer - 6) = (USHORT) VdmEip; + } + } + +} + + +VOID +IRQ13_Eoi( + int IrqLine, + int CallCount + ) +{ + UNREFERENCED_PARAMETER(IrqLine); + UNREFERENCED_PARAMETER(CallCount); + + // + // if CallCount is less than Zero, then the interrupt request + // is being canceled. + // + if (CallCount < 0) { + return; + } + + IRQ13BeingHandled = FALSE; +} + + + + + + +VOID +MonitorEndIretHook( + VOID + ) +/*++ + +Routine Description: + + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + + PVOID VdmStackPointer; + + if (IntelMSW & MSW_PE) { + BOOL Frame32 = (BOOL) VdmTib.PmStackInfo.Flags; + ULONG FrameSize; + + if (Frame32) { + FrameSize = 12; + } else { + FrameSize = 6; + } + + VdmStackPointer = Sim32GetVDMPointer(((ULONG)getSS() << 16),2,TRUE); + + if (Ldt[(getSS() & ~0x7)/sizeof(LDT_ENTRY)].HighWord.Bits.Default_Big) { + (PCHAR)VdmStackPointer += getESP(); + setESP(getESP() + FrameSize); + } else { + (PCHAR)VdmStackPointer += getSP(); + setSP((USHORT) (getSP() + FrameSize)); + } + + if (Frame32) { + + VdmTib.VdmContext.EFlags = *(PULONG)((PCHAR)VdmStackPointer + 8); + setCS(*(PUSHORT)((PCHAR)VdmStackPointer + 4)); + VdmTib.VdmContext.Eip = *((PULONG)VdmStackPointer); + + } else { + + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & 0xFFFF0000) | + ((ULONG) *(PUSHORT)((PCHAR)VdmStackPointer + 4)); + setCS(*(PUSHORT)((PCHAR)VdmStackPointer + 2)); + VdmTib.VdmContext.Eip = (VdmTib.VdmContext.Eip & 0xFFFF0000) | + ((ULONG) *(PUSHORT)((PCHAR)VdmStackPointer)); + + } + + } else { + + VdmStackPointer = Sim32GetVDMPointer(((ULONG)getSS() << 16) | getSP(),2,FALSE); + + setSP((USHORT) (getSP() + 6)); + + (USHORT)(VdmTib.VdmContext.EFlags) = *((PUSHORT)((PCHAR)VdmStackPointer + 4)); + setCS(*((PUSHORT)((PCHAR)VdmStackPointer + 2))); + setIP(*((PUSHORT)VdmStackPointer)); + + } + + +} + +VOID +host_clear_hw_int() +/*++ + +Routine Description: + + This routine "forgets" a previously requested hardware interrupt. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + /* + * We do nothing here to save a kernel call, because the + * interrupt if it hasn't been intacked yet or dispatched, + * will produce a harmless spurious int, which is dropped + * in the i386 interrupt dispatching code anyhow. + */ +} diff --git a/private/mvdm/v86/monitor/i386/monitor.c b/private/mvdm/v86/monitor/i386/monitor.c new file mode 100644 index 000000000..fded8dac0 --- /dev/null +++ b/private/mvdm/v86/monitor/i386/monitor.c @@ -0,0 +1,1135 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + Monitor.c +Abstract: + + This module is the user mode portion of the x86 monitor + +Author: + + Dave Hastings (daveh) 16 Mar 1991 + +Environment: + + User mode only + +Revision History: + Sudeep Bharati (sudeepb) 31-Dec-1991 + + Converted all register manipulation interfaces to functions + from macros. This is to make ntvdm an exe as well as a dll, + and these register oriented routines are exported from ntvdm + for WOW32 and other installable VDDs. + + Dave Hastings (daveh) 18-Apr-1992 + + Split into multiple files. Track current monitor thread by + Teb pointer. Register initial thread. + + Sudeep Bharati (sudeepb) 22-Sep-1992 + + Added Page Fault Handling For installable VDD support + +--*/ + + +#include "monitorp.h" + + +// +// Internal functions +// + +VOID +EventVdmIo( + VOID + ); + +VOID +EventVdmStringIo( + VOID + ); + +VOID +EventVdmMemAccess( + VOID + ); + +VOID +EventVdmIntAck( + VOID + ); + +VOID +EventVdmBop( + VOID + ); + +VOID +EventVdmError( + VOID + ); + +VOID +EventVdmIrq13( + VOID + ); + +VOID +CreateProfile( + VOID + ); + +VOID +StartProfile( + VOID + ); + +VOID +StopProfile( + VOID + ); + +VOID +AnalyzeProfile( + VOID + ); + +// [LATER] how do you prevent a struct from straddling a page boundary? +VDM_TIB VdmTib; + +ULONG IntelBase; // base memory address +ULONG VdmSize; // Size of memory in VDM +ULONG IntelMSW; // Msw value (no msw in context) +ULONG VdmDebugLevel; // used to control debugging +PVOID CurrentMonitorTeb; // thread that is currently executing instructions. +ULONG InitialBreakpoint = FALSE; // if set, breakpoint at end of cpu_init +ULONG InitialVdmTibFlags = 0; // VdmTib flags picked up from here +CONTEXT InitialContext; // Initial context for all threads +BOOLEAN DebugContextActive = FALSE; +ULONG VdmFeatureBits = 0; // bit to indicate special features + +extern PVOID NTVDMpLockPrefixTable; + +IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // Reserved + 0, // GlobalFlagsClear + 0, // GlobalFlagsSet + 0, // CriticalSectionTimeout (milliseconds) + 0, // DeCommitFreeBlockThreshold + 0, // DeCommitTotalFreeThreshold + &NTVDMpLockPrefixTable, // LockPrefixTable, defined in FASTPM.ASM + 0, 0, 0, 0, 0, 0, 0 // Reserved +}; + +// Bop dispatch table + +extern void (*BIOS[])(); + +BOOLEAN ContinueExecution; + +// +// Event Dispatch table +// + +VOID (*EventDispatch[VdmMaxEvent])(VOID) = { + EventVdmIo, + EventVdmStringIo, + EventVdmMemAccess, + EventVdmIntAck, + EventVdmBop, + EventVdmError, + EventVdmIrq13 + }; + +// Debug control flags +BOOLEAN fShowBop = FALSE; +#if DBG +BOOLEAN fBreakInDebugger = FALSE; +LONG NumTasks = -1; +#endif + + + +EXPORT +VOID +cpu_init( + ) + +/*++ + +Routine Description: + + This routine is used to prepare the IEU for instruction simulation. + It will set the Intel registers to thier initial value, and perform + any implementation specific initialization necessary. + + +Arguments: + + +Return Value: + + None. + +--*/ + +{ + NTSTATUS Status; + + IntelMSW = 0x0; // bugbug use correct value for ET and MP + InitialVdmTibFlags |= RM_BIT_MASK; + + VdmTib.VdmContext.SegGs = 0; + VdmTib.VdmContext.SegFs = 0; + VdmTib.VdmContext.SegEs = 0; + VdmTib.VdmContext.SegDs = 0; + VdmTib.VdmContext.SegCs = 0; + VdmTib.VdmContext.Eip = 0xFFF0L; + VdmTib.VdmContext.EFlags = 0x02L | EFLAGS_INTERRUPT_MASK; + + VdmTib.MonitorContext.SegDs = KGDT_R3_DATA | RPL_MASK; + VdmTib.MonitorContext.SegEs = KGDT_R3_DATA | RPL_MASK; + VdmTib.MonitorContext.SegGs = 0; + VdmTib.MonitorContext.SegFs = KGDT_R3_TEB | RPL_MASK; + + VdmTib.PrinterInfo.prt_State = NULL; + VdmTib.PrinterInfo.prt_Control = NULL; + VdmTib.PrinterInfo.prt_Status = NULL; + VdmTib.PrinterInfo.prt_HostState = NULL; + ASSERT(VDM_NUMBER_OF_LPT == 3); + + VdmTib.PrinterInfo.prt_Mode[0] = + VdmTib.PrinterInfo.prt_Mode[1] = + VdmTib.PrinterInfo.prt_Mode[2] = PRT_MODE_NO_SIMULATION; + + VdmTib.Size = sizeof(VDM_TIB); + + // + // Find out if we are running with IOPL. We call the kernel + // rather than checking the registry ourselves, so that we can + // insure that both the kernel and ntvdm.exe agree. If they didn't, + // it would result in unnecssary trapping instructions. Whether or + // not Vdms run with IOPL only changes on reboot + // + Status = NtVdmControl(VdmFeatures, &VdmFeatureBits); + +#if DBG + if (!NT_SUCCESS(Status)) { + DbgPrint( + "NTVDM: Could not find out whether to use IOPL, %lx\n", + Status + ); + } +#endif + + // + // If we have fast v86 mode IF emulation set the bit that tells + // the 16 bit IF macros they know. + // + if (VdmFeatureBits & V86_VIRTUAL_INT_EXTENSIONS) { + InitialVdmTibFlags |= RI_BIT_MASK; + } + + *pNtVDMState = InitialVdmTibFlags; + + // Switch the npx back to 80 bit mode. Win32 apps start with + // 64-bit precision for compatibility across platforms, but + // DOS and Win16 apps expect 80 bit precision. + // + + _asm fninit; + + // + // We setup the InitialContext structure with the correct floating + // point and debug register configuration, and cpu_createthread + // uses this context to configure each 16-bit thread's floating + // point and debug registers. + // + + InitialContext.ContextFlags = CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; + + Status = NtGetContextThread( + NtCurrentThread(), + &InitialContext + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("NtVdm terminating : Could not get float/debug context for\n" + " initial thread, status %lx\n", Status); + DbgBreakPoint(); +#endif + TerminateVDM(); + } + + + // + // + // Turn OFF em bit so that dos apps will work correctly. + // + // On machines without 387's the floating point flag will have been + // cleared. + // + + InitialContext.ContextFlags = CONTEXT_FLOATING_POINT; + InitialContext.FloatSave.Cr0NpxState &= ~0x6; // CR0_EM | CR0_MP + + // + // Do the rest of thread initialization + // + cpu_createthread( NtCurrentThread() ); + + InterruptInit(); + + if (InitialBreakpoint) { + DbgBreakPoint(); + } + +} + +EXPORT +VOID +cpu_terminate( + ) +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ +{ + InterruptTerminate(); +} + +EXPORT +VOID +cpu_simulate( + ) + +/*++ + +Routine Description: + + This routine causes the simulation of intel instructions to start. + +Arguments: + +Return Value: + + None. + +--*/ + +{ + NTSTATUS Status; + VDMEVENTINFO OldEventInfo; + CONTEXT OldMonitorContext; + + OldEventInfo = VdmTib.EventInfo; + OldMonitorContext = VdmTib.MonitorContext; + + ContinueExecution = TRUE; + + CurrentMonitorTeb = NtCurrentTeb(); + + VdmTib.VdmContext.ContextFlags = CONTEXT_FULL; + + while (ContinueExecution) { + + ASSERT(CurrentMonitorTeb == NtCurrentTeb()); + ASSERT(InterlockedIncrement(&NumTasks) == 0); + + if (*pNtVDMState & VDM_INTERRUPT_PENDING) { + DispatchInterrupts(); + } + + // translate MSW bits into EFLAGS + if ( getMSW() & MSW_PE ) { + VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK; + Status = FastEnterPm(); + } else { + VdmTib.VdmContext.EFlags |= EFLAGS_V86_MASK; + Status = NtVdmControl(VdmStartExecution,NULL); + } + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("NTVDM: Could not start execution\n"); +#endif + return; + } + + ASSERT(InterlockedDecrement(&NumTasks) < 0); + +#if DBG + if (fBreakInDebugger) { + fBreakInDebugger = 0; + DbgBreakPoint(); + } +#endif + + // Translate Eflags value + ASSERT ((!((VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK) && + (getMSW() & MSW_PE)))); + + if ( VdmTib.VdmContext.EFlags & EFLAGS_V86_MASK ) { + VdmTib.VdmContext.EFlags &= ~EFLAGS_V86_MASK; + } + + // bugbug does cs:eip wrap cause some kind of fault? + VdmTib.VdmContext.Eip += VdmTib.EventInfo.InstructionSize; + + if (VdmTib.EventInfo.Event >= VdmMaxEvent) { +#if DBG + DbgPrint("NTVDM: Unknown event type\n"); + DbgBreakPoint(); +#endif + ContinueExecution = FALSE; + continue; + } + + (*EventDispatch[VdmTib.EventInfo.Event])(); + + } + + + // set this back to true incase we are nested + ContinueExecution = TRUE; + + // + // Restore the old Vdm tib info. This is necessary for the for the + // case where the application thread is suspended, and a host simulate is + // performed from another thread + // + + VdmTib.EventInfo = OldEventInfo; + VdmTib.MonitorContext = OldMonitorContext; +} + + +VOID +host_unsimulate( + ) + +/*++ + +Routine Description: + + This routine causes execution of instructions in a VDM to stop. + +Arguments: + + +Return Value: + + None. + +--*/ + +{ + + ContinueExecution = FALSE; + +} + + +VOID +EventVdmIo( + VOID + ) +/*++ + +Routine Description: + + This function calls the appropriate io simulation routine. + +Arguments: + + +Return Value: + + None. + +--*/ +{ + if (VdmTib.EventInfo.IoInfo.Size == 1) { + if (VdmTib.EventInfo.IoInfo.Read) { + inb(VdmTib.EventInfo.IoInfo.PortNumber,(half_word *)&(VdmTib.VdmContext.Eax)); + } else { + outb(VdmTib.EventInfo.IoInfo.PortNumber,getAL()); + } + } else if (VdmTib.EventInfo.IoInfo.Size == 2) { + if (VdmTib.EventInfo.IoInfo.Read) { + inw(VdmTib.EventInfo.IoInfo.PortNumber,(word *)&(VdmTib.VdmContext.Eax)); + } else { + outw(VdmTib.EventInfo.IoInfo.PortNumber,getAX()); + } + } +#if DBG + else { + DbgPrint( + "NtVdm: Unimplemented IO size %d\n", + VdmTib.EventInfo.IoInfo.Size + ); + DbgBreakPoint(); + } +#endif +} + +VOID +EventVdmStringIo( + VOID + ) +/*++ + +Routine Description: + + This function calls the appropriate io simulation routine. + +Arguments: + + +Return Value: + + None. + +--*/ +{ + PVDMSTRINGIOINFO pvsio; + PUSHORT pIndexRegister; + USHORT Index; + + // WARNING no 32 bit address support + + pvsio = &VdmTib.EventInfo.StringIoInfo; + + if (pvsio->Size == 1) { + if (pvsio->Read) { + insb((io_addr)pvsio->PortNumber, + (half_word *)Sim32GetVDMPointer(pvsio->Address, 1, ISPESET), + (word)pvsio->Count + ); + pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi; + } else { + outsb((io_addr)pvsio->PortNumber, + (half_word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET), + (word)pvsio->Count + ); + pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi; + } + } else if (pvsio->Size == 2) { + if (pvsio->Read) { + insw((io_addr)pvsio->PortNumber, + (word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET), + (word)pvsio->Count + ); + pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Edi; + } else { + outsw((io_addr)pvsio->PortNumber, + (word *)Sim32GetVDMPointer(pvsio->Address,1,ISPESET), + (word)pvsio->Count + ); + pIndexRegister = (PUSHORT)&VdmTib.VdmContext.Esi; + } + } else { +#if DBG + DbgPrint( + "NtVdm: Unimplemented IO size %d\n", + VdmTib.EventInfo.IoInfo.Size + ); + DbgBreakPoint(); +#endif + return; + } + + if (getDF()) { + Index = *pIndexRegister - (USHORT)(pvsio->Count * pvsio->Size); + } + else { + Index = *pIndexRegister + (USHORT)(pvsio->Count * pvsio->Size); + } + + *pIndexRegister = Index; + + if (pvsio->Rep) { + (USHORT)VdmTib.VdmContext.Ecx = 0; + } + + +} + +VOID +EventVdmIntAck( + VOID + ) +/*++ + +Routine Description: + + This routine is called each time we have returned to monitor context + to dispatch interrupts. Its function is to check for AutoEoi and call + the ica to do a nonspecific eoi, when the ica adapter is in AEOI mode. + +Arguments: + + +Return Value: + + None. + +--*/ +{ + int line; + int adapter; + + if (VdmTib.EventInfo.IntAckInfo) { + if (VdmTib.EventInfo.IntAckInfo & VDMINTACK_SLAVE) + adapter = 1; + else + adapter = 0; + line = -1; + + host_ica_lock(); + ica_eoi(adapter, + &line, + (int)(VdmTib.EventInfo.IntAckInfo & VDMINTACK_RAEOIMASK) + ); + host_ica_unlock(); + } +} + + +VOID +EventVdmBop( + VOID + ) +/*++ + +Routine Description: + + This routine dispatches to the appropriate bop handler + +Arguments: + + +Return Value: + + None. + +--*/ +{ + if (VdmTib.EventInfo.BopNumber > MAX_BOP) { +#if DBG + DbgPrint( + "NtVdm: Invalid BOP %lx\n", + VdmTib.EventInfo.BopNumber + ); +#endif + ContinueExecution = FALSE; + } else { +#if DBG + if (fShowBop) { + DbgPrint("Ntvdm cpu_simulate : bop dispatch %x,%x\n", + VdmTib.EventInfo.BopNumber, + (ULONG)(*((UCHAR *)Sim32GetVDMPointer( + (VdmTib.VdmContext.SegCs << 16) | VdmTib.VdmContext.Eip, + 1, + ISPESET))) + ); + } +#endif + (*BIOS[VdmTib.EventInfo.BopNumber])(); + CurrentMonitorTeb = NtCurrentTeb(); + } +} + +VOID +EventVdmError( + VOID + ) +/*++ + +Routine Description: + + This routine prints a message(debug only), and exits the vdm + +Arguments: + + +Return Value: + + None. + +--*/ +{ +#if DBG + DbgPrint( + "NtVdm: Error code %lx\n", + VdmTib.EventInfo.ErrorStatus + ); + DbgBreakPoint(); +#endif + TerminateVDM(); + ContinueExecution = FALSE; +} + +VOID +EventVdmIrq13( + VOID + ) +/*++ + +Routine Description: + + This routine simulates an IRQ 13 to the vdm + +Arguments: + + +Return Value: + + None. + +--*/ +{ + if (!IRQ13BeingHandled) { + IRQ13BeingHandled = TRUE; + ica_hw_interrupt( + ICA_SLAVE, + 5, + 1 + ); + } +} + + +VOID +EventVdmMemAccess( + VOID + ) +/*++ + +Routine Description: + + This routine will call the page fault handler routine which + is common to both x86 and mips. + +Arguments: + + +Return Value: + + None. + +--*/ +{ + + // RWMode is 0 if read fault or 1 if write fault. + + DispatchPageFault( + VdmTib.EventInfo.FaultInfo.FaultAddr, + VdmTib.EventInfo.FaultInfo.RWMode + ); + CurrentMonitorTeb = NtCurrentTeb(); +} + +// Get and Set routines for intel registers. + +ULONG getEAX (VOID) { return (VdmTib.VdmContext.Eax); } +USHORT getAX (VOID) { return ((USHORT)(VdmTib.VdmContext.Eax)); } +UCHAR getAL (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax)); } +UCHAR getAH (VOID) { return ((BYTE)(VdmTib.VdmContext.Eax >> 8)); } +ULONG getEBX (VOID) { return (VdmTib.VdmContext.Ebx); } +USHORT getBX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ebx)); } +UCHAR getBL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx)); } +UCHAR getBH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ebx >> 8)); } +ULONG getECX (VOID) { return (VdmTib.VdmContext.Ecx); } +USHORT getCX (VOID) { return ((USHORT)(VdmTib.VdmContext.Ecx)); } +UCHAR getCL (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx)); } +UCHAR getCH (VOID) { return ((BYTE)(VdmTib.VdmContext.Ecx >> 8)); } +ULONG getEDX (VOID) { return (VdmTib.VdmContext.Edx); } +USHORT getDX (VOID) { return ((USHORT)(VdmTib.VdmContext.Edx)); } +UCHAR getDL (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx)); } +UCHAR getDH (VOID) { return ((BYTE)(VdmTib.VdmContext.Edx >> 8)); } +ULONG getESP (VOID) { return (VdmTib.VdmContext.Esp); } +USHORT getSP (VOID) { return ((USHORT)VdmTib.VdmContext.Esp); } +ULONG getEBP (VOID) { return (VdmTib.VdmContext.Ebp); } +USHORT getBP (VOID) { return ((USHORT)VdmTib.VdmContext.Ebp); } +ULONG getESI (VOID) { return (VdmTib.VdmContext.Esi); } +USHORT getSI (VOID) { return ((USHORT)VdmTib.VdmContext.Esi); } +ULONG getEDI (VOID) { return (VdmTib.VdmContext.Edi); } +USHORT getDI (VOID) { return ((USHORT)VdmTib.VdmContext.Edi); } +ULONG getEIP (VOID) { return (VdmTib.VdmContext.Eip); } +USHORT getIP (VOID) { return ((USHORT)VdmTib.VdmContext.Eip); } +USHORT getCS (VOID) { return ((USHORT)VdmTib.VdmContext.SegCs); } +USHORT getSS (VOID) { return ((USHORT)VdmTib.VdmContext.SegSs); } +USHORT getDS (VOID) { return ((USHORT)VdmTib.VdmContext.SegDs); } +USHORT getES (VOID) { return ((USHORT)VdmTib.VdmContext.SegEs); } +USHORT getFS (VOID) { return ((USHORT)VdmTib.VdmContext.SegFs); } +USHORT getGS (VOID) { return ((USHORT)VdmTib.VdmContext.SegGs); } +ULONG getCF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_CARRY) ? 1 : 0); } +ULONG getPF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_PARITY) ? 1 : 0); } +ULONG getAF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_AUXILIARY) ? 1 : 0); } +ULONG getZF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_ZERO) ? 1 : 0); } +ULONG getSF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_SIGN) ? 1 : 0); } +ULONG getTF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_TRAP) ? 1 : 0); } +ULONG getIF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_INTERRUPT) ? 1 : 0); } +ULONG getDF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_DIRECTION) ? 1 : 0); } +ULONG getOF (VOID) { return ((VdmTib.VdmContext.EFlags & FLG_OVERFLOW) ? 1 : 0); } +USHORT getMSW (VOID) { return ((USHORT)IntelMSW); } +USHORT getSTATUS(VOID){ return (USHORT)VdmTib.VdmContext.EFlags; } +ULONG getEFLAGS(VOID) { return VdmTib.VdmContext.EFlags; } +USHORT getFLAGS(VOID) { return (USHORT)VdmTib.VdmContext.EFlags; } + +VOID setEAX (ULONG val) { + VdmTib.VdmContext.Eax = val; +} + +VOID setAX (USHORT val) { + VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setAH (UCHAR val) { + VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFF00FF) | + ((ULONG)(val << 8) & 0x0000FF00); +} + +VOID setAL (UCHAR val) { + VdmTib.VdmContext.Eax = (VdmTib.VdmContext.Eax & 0xFFFFFF00) | + ((ULONG)val & 0x000000FF); +} + +VOID setEBX (ULONG val) { + VdmTib.VdmContext.Ebx = val ; +} + +VOID setBX (USHORT val) { + VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setBH (UCHAR val) { + VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFF00FF) | + ((ULONG)(val << 8) & 0x0000FF00); +} + +VOID setBL (UCHAR val) { + VdmTib.VdmContext.Ebx = (VdmTib.VdmContext.Ebx & 0xFFFFFF00) | + ((ULONG)val & 0x000000FF); +} + +VOID setECX (ULONG val) { + VdmTib.VdmContext.Ecx = val ; +} + +VOID setCX (USHORT val) { + VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setCH (UCHAR val) { + VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFF00FF) | + ((ULONG)(val << 8) & 0x0000FF00); +} + +VOID setCL (UCHAR val) { + VdmTib.VdmContext.Ecx = (VdmTib.VdmContext.Ecx & 0xFFFFFF00) | + ((ULONG)val & 0x000000FF); +} + +VOID setEDX (ULONG val) { + VdmTib.VdmContext.Edx = val ; +} + +VOID setDX (USHORT val) { + VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setDH (UCHAR val) { + VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFF00FF) | + ((ULONG)(val << 8) & 0x0000FF00); +} + +VOID setDL (UCHAR val) { + VdmTib.VdmContext.Edx = (VdmTib.VdmContext.Edx & 0xFFFFFF00) | + ((ULONG)val & 0x000000FF); +} + +VOID setESP (ULONG val) { + VdmTib.VdmContext.Esp = val ; +} + +VOID setSP (USHORT val) { + VdmTib.VdmContext.Esp = (VdmTib.VdmContext.Esp & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setEBP (ULONG val) { + VdmTib.VdmContext.Ebp = val; +} + +VOID setBP (USHORT val) { + VdmTib.VdmContext.Ebp = (VdmTib.VdmContext.Ebp & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setESI (ULONG val) { + VdmTib.VdmContext.Esi = val ; +} + +VOID setSI (USHORT val) { + VdmTib.VdmContext.Esi = (VdmTib.VdmContext.Esi & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} +VOID setEDI (ULONG val) { + VdmTib.VdmContext.Edi = val ; +} + +VOID setDI (USHORT val) { + VdmTib.VdmContext.Edi = (VdmTib.VdmContext.Edi & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setEIP (ULONG val) { + VdmTib.VdmContext.Eip = val ; +} + +VOID setIP (USHORT val) { + VdmTib.VdmContext.Eip = (VdmTib.VdmContext.Eip & 0xFFFF0000) | + ((ULONG)val & 0x0000FFFF); +} + +VOID setCS (USHORT val) { + VdmTib.VdmContext.SegCs = (ULONG) val & 0x0000FFFF ; +} + +VOID setSS (USHORT val) { + VdmTib.VdmContext.SegSs = (ULONG) val & 0x0000FFFF ; +} + +VOID setDS (USHORT val) { + VdmTib.VdmContext.SegDs = (ULONG) val & 0x0000FFFF ; +} + +VOID setES (USHORT val) { + VdmTib.VdmContext.SegEs = (ULONG) val & 0x0000FFFF ; +} + +VOID setFS (USHORT val) { + VdmTib.VdmContext.SegFs = (ULONG) val & 0x0000FFFF ; +} + +VOID setGS (USHORT val) { + VdmTib.VdmContext.SegGs = (ULONG) val & 0x0000FFFF ; +} + +VOID setCF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_CARRY) | + (((ULONG)val << FLG_CARRY_BIT) & FLG_CARRY); +} + +VOID setPF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_PARITY) | + (((ULONG)val << FLG_PARITY_BIT) & FLG_PARITY); +} + +VOID setAF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_AUXILIARY) | + (((ULONG)val << FLG_AUXILIARY_BIT) & FLG_AUXILIARY); +} + +VOID setZF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_ZERO) | + (((ULONG)val << FLG_ZERO_BIT) & FLG_ZERO); +} + +VOID setSF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_SIGN) | + (((ULONG)val << FLG_SIGN_BIT) & FLG_SIGN); +} + +VOID setIF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_INTERRUPT) | + (((ULONG)val << FLG_INTERRUPT_BIT) & FLG_INTERRUPT); +} + +VOID setDF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_DIRECTION) | + (((ULONG)val << FLG_DIRECTION_BIT) & FLG_DIRECTION); +} + +VOID setOF (ULONG val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & ~FLG_OVERFLOW) | + (((ULONG)val << FLG_OVERFLOW_BIT) & FLG_OVERFLOW); +} + +VOID setMSW (USHORT val) { + IntelMSW = val ; +} + +VOID setSTATUS(USHORT val) { + VdmTib.VdmContext.EFlags = (VdmTib.VdmContext.EFlags & 0xFFFF0000) | val; +} +// +// The following is a private register function +// + +ULONG getPE(){ + return((IntelMSW & MSW_PE) ? 1 : 0); +} + + +PX86CONTEXT +getIntelRegistersPointer( + VOID + ) +/*++ + +Routine Description: + + Return Address on Intel Registers for WOW Fast Access + +Arguments: + + None + +Return Value: + + Pointer to Intel Registers x86 Context Record + + +--*/ +{ + return &(VdmTib.VdmContext); +} + + + +BOOLEAN MonitorInitializePrinterInfo( + WORD Ports, + PWORD PortTable, + PUCHAR State, + PUCHAR Control, + PUCHAR Status, + PUCHAR HostState) +{ + int i; + + ASSERT (Ports == 3); + ASSERT (Status != NULL); + + // only do this if the structure has not been initialized -- meaning + // the pointers can be set once. + if (NULL == VdmTib.PrinterInfo.prt_Status) { + + VdmTib.PrinterInfo.prt_PortAddr[0] = PortTable[0]; + VdmTib.PrinterInfo.prt_PortAddr[1] = PortTable[1]; + VdmTib.PrinterInfo.prt_PortAddr[2] = PortTable[2]; + + VdmTib.PrinterInfo.prt_Handle[0] = + VdmTib.PrinterInfo.prt_Handle[1] = + VdmTib.PrinterInfo.prt_Handle[2] = NULL; + + + // primarily for dongle + VdmTib.PrinterInfo.prt_BytesInBuffer[0] = + VdmTib.PrinterInfo.prt_BytesInBuffer[1] = + VdmTib.PrinterInfo.prt_BytesInBuffer[2] = 0; + + // primarily for simulating printer status read in kernel + VdmTib.PrinterInfo.prt_State = State; + VdmTib.PrinterInfo.prt_Control = Control; + VdmTib.PrinterInfo.prt_Status = Status; + VdmTib.PrinterInfo.prt_HostState = HostState; + + + // deal with mode carefully. VDD may have hooked printer ports + // before we get here. If the mode is undefined, we can + // safely initialize it to our default, otherwise, just leave + // it alone. + for (i = 0; i < 3; i++) { + if (PRT_MODE_NO_SIMULATION == VdmTib.PrinterInfo.prt_Mode[i]) + VdmTib.PrinterInfo.prt_Mode[i] = PRT_MODE_SIMULATE_STATUS_PORT; + } + + return TRUE; + } + else + return FALSE; +} + +BOOLEAN MonitorEnablePrinterDirectAccess(WORD adapter, HANDLE handle, BOOLEAN Enable) +{ + ASSERT(VDM_NUMBER_OF_LPT > adapter); + if (Enable) { + // if the adapter has been allocated by a third party VDD, + // can't do direct io. + if (PRT_MODE_VDD_CONNECTED != VdmTib.PrinterInfo.prt_Mode[adapter]) { + VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_DIRECT_IO; + VdmTib.PrinterInfo.prt_Handle[adapter] = handle; + // NtVdmControl(VdmPrinterDirectIoOpen, &adapter); + return TRUE; + } + else + return FALSE; + } + else { + // disabling direct i/o. reset it back to status port simulation + if (VdmTib.PrinterInfo.prt_Handle[adapter] == handle) { + NtVdmControl(VdmPrinterDirectIoClose, &adapter); + VdmTib.PrinterInfo.prt_Mode[adapter] = PRT_MODE_SIMULATE_STATUS_PORT; + VdmTib.PrinterInfo.prt_Handle[adapter] = NULL; + VdmTib.PrinterInfo.prt_BytesInBuffer[adapter] = 0; + return TRUE; + } + else + return FALSE; + } +} + +BOOLEAN MonitorVddConnectPrinter(WORD Adapter, HANDLE hVdd, BOOLEAN Connect) +{ + if (VDM_NUMBER_OF_LPT <= Adapter) + return FALSE; + if (Connect) { + VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_VDD_CONNECTED; + VdmTib.PrinterInfo.prt_Handle[Adapter] = hVdd; + return TRUE; + } + else { + if (hVdd == VdmTib.PrinterInfo.prt_Handle[Adapter]) { + VdmTib.PrinterInfo.prt_Mode[Adapter] = PRT_MODE_SIMULATE_STATUS_PORT; + VdmTib.PrinterInfo.prt_Handle[Adapter] = NULL; + return TRUE; + } + else return FALSE; + } +} + +BOOLEAN MonitorPrinterWriteData(WORD Adapter, BYTE Value) +{ + USHORT BytesInBuffer; + + ASSERT(VDM_NUMBER_OF_LPT > Adapter); + BytesInBuffer = VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter]; + VdmTib.PrinterInfo.prt_Buffer[Adapter][BytesInBuffer] = Value; + VdmTib.PrinterInfo.prt_BytesInBuffer[Adapter]++; + + return TRUE; +} diff --git a/private/mvdm/v86/monitor/i386/monitorp.h b/private/mvdm/v86/monitor/i386/monitorp.h new file mode 100644 index 000000000..721c01c13 --- /dev/null +++ b/private/mvdm/v86/monitor/i386/monitorp.h @@ -0,0 +1,221 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + Monitorp.h + +Abstract: + + This contains the function prototypes, constants, and types for + the monitor. + +Author: + + Dave Hastings (daveh) 16 Mar 1991 + +Revision History: + +--*/ + +#include +#include +#include +#include +#include +#include +#include "bop.h" +#include "softpc.h" +//bugbug +typedef unsigned int UINT; + +#include // for softpc base definitions +#include +#include +#include + +#define EFLAGS_INTERRUPT_MASK 0x00000200L +#define EFLAGS_V86_MASK 0x00020000L +#define VDM_BASE_ADDRESS 0x00000001L + + +#define RPL_MASK 3 +// Types borrowed from windef.h + +typedef unsigned char BYTE; + +// Memory type record + +typedef struct _Memory_Type { + struct _Memory_Type *Previous; + struct _Memory_Type *Next; + ULONG Start; + ULONG End; + half_word Type; +} MEMTYPE, *PMEMTYPE; + +// private flags + +#define VDM_IDLE 0x00000001L + +// external data + +extern ULONG VdmFlags; +extern ULONG VdmSize; +extern LDT_ENTRY *Ldt; +extern ULONG IntelBase; // base memory address +extern ULONG VdmDebugLevel; // used to control debugging +extern ULONG IntelMSW; // Msw value (no msw in context) +extern ULONG VdmSize; // Size of memory in VDM +extern PVOID CurrentMonitorTeb; // thread that is currently executing instructions. +extern BOOLEAN IRQ13BeingHandled; // true until IRQ13 eoi'ed +extern CONTEXT InitialContext; // Initial floating point context for all threads +extern BOOLEAN DebugContextActive; + +#define MAX_BOP 256 +VOID reset(VOID); +VOID dummy_int(VOID); +VOID unexpected_int(VOID); +VOID illegal_bop(VOID); +VOID illegal_op_int(VOID); +VOID print_screen(VOID); +VOID time_int(VOID); +VOID keyboard_int(VOID); +VOID diskette_int(VOID); +VOID video_io(VOID); +VOID equipment(VOID); +VOID memory_size(VOID); +VOID disk_io(VOID); +VOID rs232_io(VOID); +VOID cassette_io(VOID); +VOID keyboard_io(VOID); +VOID printer_io(VOID); +VOID rom_basic(VOID); +VOID bootstrap(VOID); +VOID time_of_day(VOID); +VOID critical_region(VOID); +VOID cmd_install(VOID); +VOID cmd_load(VOID); +VOID redirector(VOID); +VOID ega_video_io(VOID); +VOID MsBop0(VOID); +VOID MsBop1(VOID); +VOID MsBop2(VOID); +VOID MsBop3(VOID); +VOID MsBop4(VOID); +VOID MsBop5(VOID); +VOID MsBop6(VOID); +VOID MsBop7(VOID); +VOID MsBop8(VOID); +VOID MsBop9(VOID); +VOID MsBopA(VOID); +VOID MsBopB(VOID); +VOID MsBopC(VOID); +VOID MsBopD(VOID); +VOID MsBopE(VOID); +VOID MsBopF(VOID); +VOID emm_init(VOID); +VOID emm_io(VOID); +VOID return_from_call(VOID); +VOID rtc_int(VOID); +VOID re_direct(VOID); +VOID D11_int(VOID); +VOID int_287(VOID); +VOID worm_init(VOID); +VOID worm_io(VOID); +VOID ps_private_1(VOID); +VOID ps_private_2(VOID); +VOID ps_private_3(VOID); +VOID ps_private_4(VOID); +VOID ps_private_5(VOID); +VOID ps_private_6(VOID); +VOID ps_private_7(VOID); +VOID ps_private_8(VOID); +VOID ps_private_9(VOID); +VOID ps_private_10(VOID); +VOID ps_private_11(VOID); +VOID ps_private_12(VOID); +VOID ps_private_13(VOID); +VOID ps_private_14(VOID); +VOID ps_private_15(VOID); +VOID bootstrap1(VOID); +VOID bootstrap2(VOID); +VOID bootstrap3(VOID); +VOID ms_windows(VOID); +VOID msw_mouse(VOID); +VOID mouse_install1(VOID); +VOID mouse_install2(VOID); +VOID mouse_int1(VOID); +VOID mouse_int2(VOID); +VOID mouse_io_language(VOID); +VOID mouse_io_interrupt(VOID); +VOID mouse_video_io(VOID); +VOID switch_to_real_mode(VOID); +VOID control_bop(VOID); +VOID diskette_io(VOID); +VOID host_unsimulate(VOID); +VOID DispatchPageFault (ULONG,ULONG); + + +NTSTATUS +FastEnterPm( + ); + +VOID +DispatchInterrupts( + VOID + ); + +VOID +DispatchHwInterrupt( + ); + +ULONG +GetInterruptHandler( + ULONG InterruptNumber, + BOOLEAN ProtectedMode + ); + +PVOID +GetInterruptStack( + ULONG InterruptNumber, + PUSHORT StackSelector, + PUSHORT StackPointer, + BOOLEAN ProtectedMode + ); + + +VOID +CpuOnetimeInit( + VOID + ); + +VOID +CpuOnetimeTerm( + VOID + ); + +VOID +cpu_createthread(); + +VOID +cpu_exitthread(); + +HANDLE +ThreadLookUp( + PVOID + ); + +VOID +cpu_exit(); + +VOID +InterruptInit( + VOID + ); + +VOID +InterruptTerminate( + VOID + ); diff --git a/private/mvdm/v86/monitor/i386/proflib.c b/private/mvdm/v86/monitor/i386/proflib.c new file mode 100644 index 000000000..06276a820 --- /dev/null +++ b/private/mvdm/v86/monitor/i386/proflib.c @@ -0,0 +1,930 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + proflib.c + +Abstract: + + This module contains the implementation of a rudimentry user-mode + profiler. + +Usage: + + There are 4 routines, RtlInitializeProfile, RtlStartProfile, + RtlStopProfile, and RtlAnalyzeProfile. To initialize profiling + invoke RtlInitializeProfile, this routine is only called once and + goes through the address space looking for code regions of images + and DLLs. To start profiling call RtlStartProfile. To stop + profiling call RtlStopProfile. Note that RtlStartProfile and + RtlStopProfile can be called repeatedly to profile only key + "hot spots", For example: + RtlStartProfile (); + hot spot... + RtlStopProfile (); + .... + RtlStartProfile (); + hot spot... + RtlStopProfile (); + + To analyze the results call RtlAnalyzeProfile. This too can + be called repeatedly (it stops profiling during the analysis + phase and does NOT restart profiling). It also does not + zero out the values after reporting. + +Author: + + Lou Perazzoli (loup) 4-Oct-1990 + +Revision History: + +--*/ + +#include +#include +#include +#include +#include +#include <\nt\private\ntos\dll\ldrp.h> + +NTSTATUS +InitializeKernelProfile ( VOID ); + +#define PAGE_SIZE 4096 + +typedef struct _PROFILE_BLOCK { + HANDLE Handle; + PVOID ImageBase; //actual base in image header + PULONG CodeStart; + ULONG CodeLength; + PULONG Buffer; + ULONG BufferSize; + ULONG TextNumber; + ULONG BucketSize; + PVOID MappedImageBase; //actual base where mapped locally. + PSZ ImageName; +} PROFILE_BLOCK; + + +#define MAX_PROFILE_COUNT 50 + +PROFILE_BLOCK ProfileObject[MAX_PROFILE_COUNT]; + +ULONG NumberOfProfileObjects = 0; +PIMAGE_DEBUG_INFO KernelDebugInfo; + +// +// Image name to perform kernel mode analysis upon. +// + +#define IMAGE_NAME "\\SystemRoot\\ntoskrnl.exe" + +// +// Define map data file if the produced data file should be +// a mapped file (currently named "kernprof.dat"). +// + +// #define MAP_DATA_FILE + +// +// Define map as image if the image to be profiled should be mapped +// as an image rather than as data. +// + +// #define MAP_AS_IMAGE + +#define MAX_PROFILE_COUNT 50 + +extern ULONG ProfInt; + +NTSTATUS +RtlInitializeProfile ( + IN BOOLEAN KernelToo + ) + +/*++ + +Routine Description: + + This routine initializes profiling for the current process. + +Arguments: + + KernelToo - Set to TRUE if kernel code should be profiled as + well as user code. + +Return Value: + + Returns the status of the last NtCreateProfile. + +--*/ + +{ + + NTSTATUS status, LocalStatus; + HANDLE CurrentProcessHandle; + ULONG BufferSize; + PVOID ImageBase; + ULONG CodeLength; + PULONG Buffer; + PPEB Peb; + PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; + PSZ ImageName; + PLIST_ENTRY Next; + ULONG ExportSize, DebugSize; + PIMAGE_EXPORT_DIRECTORY ExportDirectory; + PIMAGE_DEBUG_DIRECTORY DebugDirectory; + PIMAGE_DEBUG_INFO DebugInfo; + BOOLEAN PreviousPrivState; + + // + // Locate all the executables in the address and create a + // seperate profile object for each one. + // + + CurrentProcessHandle = NtCurrentProcess(); + + Peb = NtCurrentPeb(); + + Next = Peb->Ldr->InMemoryOrderModuleList.Flink; + while ( Next != &Peb->Ldr->InMemoryOrderModuleList) { + LdrDataTableEntry + = (PLDR_DATA_TABLE_ENTRY) (CONTAINING_RECORD(Next,LDR_DATA_TABLE_ENTRY,InMemoryOrderLinks)); + + ImageBase = LdrDataTableEntry->DllBase; + if ( Peb->ImageBaseAddress == ImageBase ) { + ImageName = "TheApplication"; + } else { + ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData( + ImageBase, + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + + ImageName = (PSZ)((ULONG)ImageBase + ExportDirectory->Name); + } + if (NumberOfProfileObjects > MAX_PROFILE_COUNT) { + break; + } + + ProfileObject[NumberOfProfileObjects].ImageBase = ImageBase; + ProfileObject[NumberOfProfileObjects].ImageName = ImageName; + ProfileObject[NumberOfProfileObjects].MappedImageBase = ImageBase; + + // + // Locate the code range and start profiling. + // + + DebugDirectory = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData( + ImageBase, TRUE, IMAGE_DIRECTORY_ENTRY_DEBUG, &DebugSize); + + if (!DebugDirectory) { + DbgPrint ("RtlInitializeProfile : No debug directory\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + DebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)ImageBase + DebugDirectory->AddressOfRawData); + + ProfileObject[NumberOfProfileObjects].CodeStart = (PULONG)((ULONG)ImageBase + DebugInfo->RvaToFirstByteOfCode); + CodeLength = (DebugInfo->RvaToLastByteOfCode - DebugInfo->RvaToFirstByteOfCode) - 1; + ProfileObject[NumberOfProfileObjects].CodeLength = CodeLength; + + ProfileObject[NumberOfProfileObjects].TextNumber = 1; + + // + // Analyze the size of the code and create a reasonably sized + // profile object. + // + + BufferSize = (CodeLength >> 1) + 4; + Buffer = NULL; + + status = NtAllocateVirtualMemory (CurrentProcessHandle, + (PVOID *)&Buffer, + 0, + &BufferSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + + if (!NT_SUCCESS(status)) { + DbgPrint ("alloc VM failed %lx\n",status); + return status; + } + + + status = RtlAdjustPrivilege( + SE_PROF_SINGLE_PROCESS_PRIVILEGE, + TRUE, //Enable + FALSE, //not impersonating + &PreviousPrivState //Remember if it will need to be cleared + ); + + if (!NT_SUCCESS(status) || status == STATUS_NOT_ALL_ASSIGNED) { + DbgPrint("Enable system profile privilege failed - status 0x%lx\n", + status); + } + + + ProfileObject[NumberOfProfileObjects].Buffer = Buffer; + ProfileObject[NumberOfProfileObjects].BufferSize = BufferSize; + ProfileObject[NumberOfProfileObjects].BucketSize = 3; + + status = NtCreateProfile ( + &ProfileObject[NumberOfProfileObjects].Handle, + CurrentProcessHandle, + ProfileObject[NumberOfProfileObjects].CodeStart, + CodeLength, + ProfileObject[NumberOfProfileObjects].BucketSize, + ProfileObject[NumberOfProfileObjects].Buffer , + ProfileObject[NumberOfProfileObjects].BufferSize, + ProfileTime, + (KAFFINITY)-1); + + if (PreviousPrivState == FALSE) { + LocalStatus = RtlAdjustPrivilege( + SE_PROF_SINGLE_PROCESS_PRIVILEGE, + FALSE, //Disable + FALSE, //not impersonating + &PreviousPrivState //Don't care if it was already enabled + ); + if (!NT_SUCCESS(LocalStatus) || LocalStatus == STATUS_NOT_ALL_ASSIGNED) { + DbgPrint("Disable system profile privilege failed - status 0x%lx\n", + LocalStatus); + } + } + + if (status != STATUS_SUCCESS) { + DbgPrint("create profile %x failed - status %lx\n", + ProfileObject[NumberOfProfileObjects].ImageName,status); + return status; + } + + NumberOfProfileObjects += 1; + + Next = Next->Flink; + } + + if (KernelToo) { + + if (NumberOfProfileObjects > MAX_PROFILE_COUNT) { + return status; + } + status = InitializeKernelProfile(); + } + return status; + +} +NTSTATUS +InitializeKernelProfile ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes profiling for the kernel for the + current process. + +Arguments: + + None. + +Return Value: + + Returns the status of the last NtCreateProfile. + +--*/ + +{ + + //BUGBUG daveh I think that the new working set size calculation is + // generating the number of pages, when the api expects + // the number of bytes. + + STRING Name3; + IO_STATUS_BLOCK IoStatus; + HANDLE FileHandle, KernelSection; + OBJECT_ATTRIBUTES ObjectAttributes; + PVOID ImageBase; + ULONG ViewSize; + ULONG CodeLength; + NTSTATUS status, LocalStatus; + HANDLE CurrentProcessHandle; + QUOTA_LIMITS QuotaLimits; + PVOID Buffer; + ULONG Cells; + ULONG BucketSize; + UNICODE_STRING Unicode; + ULONG DebugSize; + PVOID KernelBase; + PIMAGE_NT_HEADERS KernelNtHeaders; + PIMAGE_DEBUG_DIRECTORY DebugDirectory; + BOOLEAN PreviousPrivState; + + RtlInitString (&Name3, IMAGE_NAME); + CurrentProcessHandle = NtCurrentProcess(); + + status = RtlAnsiStringToUnicodeString(&Unicode,(PANSI_STRING)&Name3,TRUE); + ASSERT(NT_SUCCESS(status)); + InitializeObjectAttributes( &ObjectAttributes, + &Unicode, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + // + // Open the file as readable and executable. + // + + status = NtOpenFile ( &FileHandle, + FILE_READ_DATA | FILE_EXECUTE, + &ObjectAttributes, + &IoStatus, + FILE_SHARE_READ, + 0L); + RtlFreeUnicodeString(&Unicode); + + if (!NT_SUCCESS(status)) { + DbgPrint("open file failed status %lx\n", status); + NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); + } + + InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); + + // + // For normal images they would be mapped as an image, but + // the kernel has no debug section (as yet) information, hence it + // must be mapped as a file. + // + + status = NtCreateSection (&KernelSection, + SECTION_MAP_EXECUTE, + &ObjectAttributes, + 0, + PAGE_READONLY, + SEC_IMAGE, + FileHandle); + + if (!NT_SUCCESS(status)) { + DbgPrint("create image section failed status %lx\n", status); + return(status); + } + + ViewSize = 0; + + // + // Map a view of the section into the address space. + // + + KernelBase = NULL; + + status = NtMapViewOfSection (KernelSection, + CurrentProcessHandle, + (PVOID *)&KernelBase, + 0L, + 0, + NULL, + &ViewSize, + ViewUnmap, + 0, + PAGE_EXECUTE); + + if (!NT_SUCCESS(status)) { + if (status != STATUS_IMAGE_NOT_AT_BASE) { + DbgPrint("map section status %lx base %lx size %lx\n", status, + KernelBase, ViewSize); + } + } + + KernelNtHeaders = (PIMAGE_NT_HEADERS)RtlImageNtHeader(KernelBase); + + ImageBase = (PVOID)KernelNtHeaders->OptionalHeader.ImageBase; + + DebugDirectory = (PIMAGE_DEBUG_DIRECTORY)RtlImageDirectoryEntryToData( + KernelBase, TRUE, IMAGE_DIRECTORY_ENTRY_DEBUG, &DebugSize); + + if (!DebugDirectory) { + DbgPrint("InitializeKernelProfile : No debug directory\n"); + return STATUS_INVALID_IMAGE_FORMAT; + } + + KernelDebugInfo = (PIMAGE_DEBUG_INFO)((ULONG)KernelBase + DebugDirectory->AddressOfRawData); + CodeLength = (KernelDebugInfo->RvaToLastByteOfCode - KernelDebugInfo->RvaToFirstByteOfCode) -1; + + // + // Just create a 512K byte buffer. + // + + ViewSize = 1024 * 512; + Buffer = NULL; + + status = NtAllocateVirtualMemory (CurrentProcessHandle, + (PVOID *)&Buffer, + 0, + &ViewSize, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + + if (!NT_SUCCESS(status)) { + DbgPrint ("alloc VM failed %lx\n",status); + NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); + } + + // + // Calculate the bucket size for the profile. + // + + Cells = ((CodeLength / (ViewSize >> 2)) >> 2); + BucketSize = 2; + + while (Cells != 0) { + Cells = Cells >> 1; + BucketSize += 1; + } + + ProfileObject[NumberOfProfileObjects].Buffer = Buffer; + ProfileObject[NumberOfProfileObjects].MappedImageBase = KernelBase; + ProfileObject[NumberOfProfileObjects].BufferSize = 1 + (CodeLength >> (BucketSize - 2)); + ProfileObject[NumberOfProfileObjects].CodeStart = (PULONG)((ULONG)ImageBase + KernelDebugInfo->RvaToFirstByteOfCode); + ProfileObject[NumberOfProfileObjects].CodeLength = CodeLength; + ProfileObject[NumberOfProfileObjects].TextNumber = 1; + ProfileObject[NumberOfProfileObjects].ImageBase = ImageBase; + ProfileObject[NumberOfProfileObjects].ImageName = "ntoskrnl"; + ProfileObject[NumberOfProfileObjects].BucketSize = BucketSize; + + + // + // Increase the working set to lock down a bigger buffer. + // + + status = NtQueryInformationProcess (CurrentProcessHandle, + ProcessQuotaLimits, + &QuotaLimits, + sizeof(QUOTA_LIMITS), + NULL ); + + if (!NT_SUCCESS(status)) { + DbgPrint ("query process info failed %lx\n",status); + NtTerminateProcess(NtCurrentProcess(),STATUS_SUCCESS); + } + + QuotaLimits.MaximumWorkingSetSize += ViewSize / PAGE_SIZE; + QuotaLimits.MinimumWorkingSetSize += ViewSize / PAGE_SIZE; + + status = NtSetInformationProcess (CurrentProcessHandle, + ProcessQuotaLimits, + &QuotaLimits, + sizeof(QUOTA_LIMITS)); + if (!NT_SUCCESS(status)) { + DbgPrint ("setting working set failed %lx\n",status); + return status; + } + + status = RtlAdjustPrivilege( + SE_PROF_SINGLE_PROCESS_PRIVILEGE, + TRUE, //Enable + FALSE, //not impersonating + &PreviousPrivState //Remember if it will need to be cleared + ); + + if (!NT_SUCCESS(status) || status == STATUS_NOT_ALL_ASSIGNED) { + DbgPrint("Enable process profile privilege failed - status 0x%lx\n", + status); + } + + status = NtCreateProfile ( + &ProfileObject[NumberOfProfileObjects].Handle, + CurrentProcessHandle, + ProfileObject[NumberOfProfileObjects].CodeStart, + CodeLength, + ProfileObject[NumberOfProfileObjects].BucketSize, + ProfileObject[NumberOfProfileObjects].Buffer , + ProfileObject[NumberOfProfileObjects].BufferSize, + ProfileTime, + (KAFFINITY)-1); + + if (PreviousPrivState == FALSE) { + LocalStatus = RtlAdjustPrivilege( + SE_PROF_SINGLE_PROCESS_PRIVILEGE, + FALSE, //Disable + FALSE, //not impersonating + &PreviousPrivState //Don't care if it was already enabled + ); + if (!NT_SUCCESS(LocalStatus) || LocalStatus == STATUS_NOT_ALL_ASSIGNED) { + DbgPrint("Disable system profile privilege failed - status 0x%lx\n", + LocalStatus); + } + } + + if (status != STATUS_SUCCESS) { + DbgPrint("create kernel profile %s failed - status %lx\n", + ProfileObject[NumberOfProfileObjects].ImageName,status); + } + + NumberOfProfileObjects += 1; + + return status; +} + + +VOID +RtlpWriteProfileLine( + IN HANDLE ProfileHandle, + IN PSZ Line, + IN int nbytes + ) +{ + IO_STATUS_BLOCK IoStatusBlock; + + NtWriteFile( + ProfileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, + Line, + (ULONG)nbytes, + NULL, + NULL + ); + +} + + +HANDLE +RtlpOpenProfileOutputFile() +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES Obja; + HANDLE Handle; + UNICODE_STRING FileName; + IO_STATUS_BLOCK IoStatusBlock; + BOOLEAN TranslationStatus; + RTL_RELATIVE_NAME RelativeName; + PVOID FreeBuffer; + + + TranslationStatus = RtlDosPathNameToNtPathName_U( + L"\\profile.out", + &FileName, + NULL, + &RelativeName + ); + + if ( !TranslationStatus ) { + return NULL; + } + FreeBuffer = FileName.Buffer; + + if ( RelativeName.RelativeName.Length ) { + FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; + } + else { + RelativeName.ContainingDirectory = NULL; + } + + InitializeObjectAttributes( + &Obja, + &FileName, + OBJ_CASE_INSENSITIVE, + RelativeName.ContainingDirectory, + NULL + ); + + Status = NtCreateFile( + &Handle, + FILE_APPEND_DATA | SYNCHRONIZE, + &Obja, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ, + FILE_OPEN_IF, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0L + ); + + RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer); + if ( !NT_SUCCESS(Status) ) { + return NULL; + } + + return Handle; +} + +VOID +RtlpDeleteProfileOutputFile() +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES Obja; + HANDLE Handle; + UNICODE_STRING FileName; + IO_STATUS_BLOCK IoStatusBlock; + FILE_DISPOSITION_INFORMATION Disposition; + BOOLEAN TranslationStatus; + RTL_RELATIVE_NAME RelativeName; + PVOID FreeBuffer; + + TranslationStatus = RtlDosPathNameToNtPathName_U( + L"\\profile.out", + &FileName, + NULL, + &RelativeName + ); + + if ( !TranslationStatus ) { + return; + } + + FreeBuffer = FileName.Buffer; + + if ( RelativeName.RelativeName.Length ) { + FileName = *(PUNICODE_STRING)&RelativeName.RelativeName; + } + else { + RelativeName.ContainingDirectory = NULL; + } + + InitializeObjectAttributes( + &Obja, + &FileName, + OBJ_CASE_INSENSITIVE, + RelativeName.ContainingDirectory, + NULL + ); + + // + // Open the file for delete access + // + + Status = NtOpenFile( + &Handle, + (ACCESS_MASK)DELETE | SYNCHRONIZE, + &Obja, + &IoStatusBlock, + FILE_SHARE_DELETE, + FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE + ); + RtlFreeHeap(RtlProcessHeap(),0,FreeBuffer); + if ( !NT_SUCCESS(Status) ) { + return; + } + + // + // Delete the file + // + Disposition.DeleteFile = TRUE; + + Status = NtSetInformationFile( + Handle, + &IoStatusBlock, + &Disposition, + sizeof(Disposition), + FileDispositionInformation + ); + + NtClose(Handle); +} + + + + +NTSTATUS +RtlStartProfile ( + VOID + ) +/*++ + +Routine Description: + + This routine starts all profile objects which have been initialized. + +Arguments: + + None. + +Return Value: + + Returns the status of the last NtStartProfile. + +--*/ + +{ + ULONG i; + NTSTATUS status; + QUOTA_LIMITS QuotaLimits; + + NtSetIntervalProfile(ProfInt,ProfileTime); + RtlpDeleteProfileOutputFile(); + + for (i = 0; i < NumberOfProfileObjects; i++) { + + status = NtStartProfile (ProfileObject[i].Handle); + + if (status == STATUS_WORKING_SET_QUOTA) { + + // + // Increase the working set to lock down a bigger buffer. + // + + status = NtQueryInformationProcess (NtCurrentProcess(), + ProcessQuotaLimits, + &QuotaLimits, + sizeof(QUOTA_LIMITS), + NULL ); + + if (!NT_SUCCESS(status)) { + DbgPrint ("query process info failed %lx\n",status); + return status; + + } + + QuotaLimits.MaximumWorkingSetSize += + 10 * PAGE_SIZE + ProfileObject[i].BufferSize; + QuotaLimits.MinimumWorkingSetSize += + 10 * PAGE_SIZE + ProfileObject[i].BufferSize; + + status = NtSetInformationProcess (NtCurrentProcess(), + ProcessQuotaLimits, + &QuotaLimits, + sizeof(QUOTA_LIMITS)); + if (!NT_SUCCESS(status)) { + DbgPrint ("setting working set failed %lx\n",status); + return status; + } + status = NtStartProfile (ProfileObject[i].Handle); + } + + if (status != STATUS_SUCCESS) { + DbgPrint("start profile %s failed - status %lx\n", + ProfileObject[i].ImageName, status); + return status; + } + } + return status; +} +NTSTATUS +RtlStopProfile ( + VOID + ) + +/*++ + +Routine Description: + + This routine stops all profile objects which have been initialized. + +Arguments: + + None. + +Return Value: + + Returns the status of the last NtStopProfile. + +--*/ + +{ + ULONG i; + NTSTATUS status; + + for (i = 0; i < NumberOfProfileObjects; i++) { + status = NtStopProfile (ProfileObject[i].Handle); + if (status != STATUS_SUCCESS) { + DbgPrint("stop profile %s failed - status %lx\n", + ProfileObject[i].ImageName,status); + return status; + } + } + return status; +} + +NTSTATUS +RtlAnalyzeProfile ( + VOID + ) + +/*++ + +Routine Description: + + This routine does the analysis of all the profile buffers and + correlates hits to the appropriate symbol table. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + + RTL_SYMBOL_INFORMATION ThisSymbol; + RTL_SYMBOL_INFORMATION LastSymbol; + ULONG CountAtSymbol; + NTSTATUS Status; + ULONG Va; + HANDLE ProfileHandle; + CHAR Line[512]; + int i,n; + PULONG Buffer, BufferEnd, Counter; + + + ProfileHandle = RtlpOpenProfileOutputFile(); + ASSERT(ProfileHandle); + + for (i = 0; i < NumberOfProfileObjects; i++) { + Status = NtStopProfile (ProfileObject[i].Handle); + } + + + // + // The new profiler + // + + for (i = 0; i < NumberOfProfileObjects; i++) { + + LastSymbol.Value = 0; + CountAtSymbol = 0; + + // + // Sum the total number of cells written. + // + + BufferEnd = ProfileObject[i].Buffer + ( + ProfileObject[i].BufferSize / sizeof(ULONG)); + Buffer = ProfileObject[i].Buffer; + + for ( Counter = Buffer; Counter < BufferEnd; Counter += 1 ) { + if ( *Counter ) { + + // + // Now we have an an address relative to the buffer + // base. + // + + Va = (ULONG)((PUCHAR)Counter - (PUCHAR)Buffer); + Va = Va * ( 1 << (ProfileObject[i].BucketSize - 2)); + + // + // Add in the image base and the base of the + // code to get the Va in the image + // + + Va = Va + (ULONG)ProfileObject[i].CodeStart; + + Status = RtlLookupSymbolByAddress( + ProfileObject[i].ImageBase, + NULL, + (PVOID)Va, + 0x4000, + &ThisSymbol, + NULL + ); + if ( NT_SUCCESS(Status) ) { + if ( LastSymbol.Value && LastSymbol.Value == ThisSymbol.Value ) { + CountAtSymbol += *Counter; + } + else { + if ( LastSymbol.Value ) { + if ( CountAtSymbol ) { + n= sprintf(Line,"%d,%s,%S\n", + CountAtSymbol, + ProfileObject[i].ImageName, + &LastSymbol.Name + ); + RtlpWriteProfileLine(ProfileHandle,Line,n); + } + } + CountAtSymbol = *Counter; + LastSymbol = ThisSymbol; + } + } + } + } + if ( CountAtSymbol ) { + n= sprintf(Line,"%d,%s,%S\n", + CountAtSymbol, + ProfileObject[i].ImageName, + &LastSymbol.Name + ); + RtlpWriteProfileLine(ProfileHandle,Line,n); + } + } + + for (i = 0; i < NumberOfProfileObjects; i++) { + Buffer = ProfileObject[i].Buffer; + RtlZeroMemory(Buffer,ProfileObject[i].BufferSize); + } + NtClose(ProfileHandle); + return Status; +} diff --git a/private/mvdm/v86/monitor/i386/sas.c b/private/mvdm/v86/monitor/i386/sas.c new file mode 100644 index 000000000..0549ad802 --- /dev/null +++ b/private/mvdm/v86/monitor/i386/sas.c @@ -0,0 +1,1551 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + Monitor.c +Abstract: + + This module is the user mode portion of the x86 monitor + +Author: + + Dave Hastings (daveh) 16 Mar 1991 + +Environment: + + User mode only + +Revision History: + William Hsieh 10-10-1992 Added A20 wrapping support +--*/ + +#define VDD_INTEG 1 +#include "monitorp.h" +#include +#include +#include + +// Tim Nov 92. +void sas_connect_memory( + IN sys_addr Low, + IN sys_addr High, + IN int Type + ); + +//BUGBUGBUGBUG Include file + +// from base\inc\sas.h +/* memory types for sas */ +#define SAS_RAM 0 +#define SAS_VIDEO 1 +#define SAS_ROM 2 +#define SAS_WRAP 3 +#define SAS_INACCESSIBLE 4 +#define SAS_MAX_TYPE SAS_INACCESSIBLE + +#define SIXTYFOURK 0x10000L +#define ONEMEGA 0x100000L + +void rom_init(); +void rom_checksum(); +void copyROM(); + +USHORT get_lim_backfill_segment(void); +BOOL HoldEMMBackfillMemory(ULONG Address, ULONG Size); + +#if DBG +extern unsigned short get_emm_page_size(void); +extern unsigned short get_intel_page_size(void); +#endif + +/* SYNC THESE DEFINITIONS WITH BASE\EMM.H, or sas_init will assert */ +#define EMM_PAGE_SIZE 0x4000 +#define INTEL_PAGE_SIZE 0x1000 + +typedef struct +{ + ULONG (*b_read) (); + ULONG (*w_read) (); + VOID (*str_read) (); +} READ_POINTERS; + +// Internal Data +PMEMTYPE MemType = NULL; + +// External Data +extern READ_POINTERS read_pointers; + +// M variables used by video.lib + +host_addr Start_of_M_area; /* host addr (char *) of start of M */ +sys_addr Length_of_M_area; /* sys addr (long) offset of end of M */ + +static HANDLE A20SectionHandle = NULL; +static BOOL A20IsON = FALSE; +static USHORT BackFillSegment; + + + +EXPORT +VOID +sas_init( + IN sys_addr Size + ) + +/*++ + +Routine Description: + + This routine initializes the SAS module, and allocates the linear + address space for the VDM, and loads the ROM + +Arguments: + + Size - Supplies the size of the VDMs linear address space. + +Return Value: + + None. + +--*/ + +{ + NTSTATUS Status; + ULONG ViewSize; + PVOID BaseAddress; + OBJECT_ATTRIBUTES A20ObjAttr; + LARGE_INTEGER SectionSize; + UCHAR SectionAnsiName[80]; + WCHAR SectionUnicodeName[80]; + UNICODE_STRING UnicodeString; + USHORT Pages; + ULONG BackFillBase; + +#define CONVENTIONAL_MEM_SECTION "\\BaseNamedObjects\\VdmConventionalMemory" + + // + // Create a name for the Convetional memory section + // + sprintf( + SectionAnsiName, + "%s%d", + CONVENTIONAL_MEM_SECTION, + GetCurrentProcessId() + ); + + if (MultiByteToWideChar(0, 0, SectionAnsiName, -1, SectionUnicodeName,80) + == 0 + ) { +#if DBG + DbgBreakPoint(); +#endif + // host_error(EG_MALLOC_FAILURE,ERR_QUIT,""); + TerminateVDM(); + } + + RtlInitUnicodeString(&UnicodeString, SectionUnicodeName); + + InitializeObjectAttributes( + &A20ObjAttr, + &UnicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + NULL + ); + + SectionSize.HighPart = 0L; + SectionSize.LowPart = 640 * 1024 + 64 * 1024; + + Status = NtCreateSection( + &A20SectionHandle, + SECTION_MAP_WRITE|SECTION_MAP_EXECUTE, + &A20ObjAttr, + &SectionSize, + PAGE_EXECUTE_READWRITE, + SEC_RESERVE, + NULL + ); + + if (!NT_SUCCESS(Status)) { + // bugbug -williamh + // we should pop up an approiate message before we + // terminate the vdm. +#if DBG + DbgPrint("sas_init: can not create himem section, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + VdmSize = Size; + + // + // N.B. We expect that process creation has reserved the first 16 MB + // for us already. If not, then this won't work worth a darn + + // free the first 640KB virtual address. + // This is done because it has been resevered before sas_init get called + BaseAddress = (PVOID)1; + ViewSize = 640 * 1024 - 1; + Status = NtFreeVirtualMemory( + NtCurrentProcess(), + &BaseAddress, + &ViewSize, + MEM_RELEASE + ); + + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("sas_init: cannot free 1st 640k virtual address, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + + BaseAddress =(PVOID) ONEMEGA; + ViewSize = SIXTYFOURK; + Status = NtFreeVirtualMemory( + NtCurrentProcess(), + &BaseAddress, + &ViewSize, + MEM_RELEASE + ); + + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("sas_init: can not free himem virtual address, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + + BaseAddress = (PVOID)VDM_BASE_ADDRESS; + ViewSize = SIXTYFOURK - (ULONG)VDM_BASE_ADDRESS; + SectionSize.HighPart = SectionSize.LowPart = 0; + + Status = NtMapViewOfSection( + A20SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + ViewSize, + &SectionSize, + &ViewSize, + ViewUnmap, + MEM_DOS_LIM, + PAGE_EXECUTE_READWRITE + ); + + if (!NT_SUCCESS(Status)){ +#if DBG + DbgPrint("sas_init: can not map view of 1st 64K, status = %ls\n", + Status); +#endif + TerminateVDM(); + } + BaseAddress = (PVOID) ONEMEGA; + ViewSize = SIXTYFOURK; + Status = NtMapViewOfSection(A20SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + ViewSize, + &SectionSize, + &ViewSize, + ViewUnmap, + MEM_DOS_LIM, + PAGE_EXECUTE_READWRITE + ); + + if (!NT_SUCCESS(Status)){ +#if DBG + DbgPrint("sas_init: can not map view of himem space, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + + // get emm back fill segment address from softpc + // we cut the backfill memory area into pieces in EMM_PAGE_SIZE unit. + // this is done so that EMM manager can grab the address space + // as EMM page frame. + // note that if EMM is disabled, the backfill segment will be + // (640 * 1024 / 16). + + BackFillSegment = get_lim_backfill_segment(); + + ASSERT(BackFillSegment <= 640 * 1024 / 16); + + // + // Map the rest of conventional memory + // only map up to the emm backfill segment. + BaseAddress = (PVOID) (64 * 1024); + ViewSize = BackFillSegment * 16 - 64 * 1024; + SectionSize.LowPart = 64 * 1024; + SectionSize.HighPart = 0; + Status = NtMapViewOfSection(A20SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + ViewSize, + &SectionSize, + &ViewSize, + ViewUnmap, + MEM_DOS_LIM, + PAGE_EXECUTE_READWRITE + ); + if (!NT_SUCCESS(Status)){ +#if DBG + DbgPrint("sas_init: can not map view of himem space, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + +// if there are any backfill memory, map it to our section initially + if (BackFillSegment < 640 * 1024 / 16) { + + /* make sure our constants are in sync with emm.h */ +#if DBG + ASSERT(EMM_PAGE_SIZE == get_emm_page_size()); + ASSERT(INTEL_PAGE_SIZE == get_intel_page_size()); +#endif + if (!HoldEMMBackFillMemory(BackFillSegment * 16, + (640 * 1024) - BackFillSegment * 16) + ) { + +#if DBG + DbgPrint("sas_init: can not map backfill space, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + } + + // + // Allocate ROM area + // + BaseAddress = (PVOID)(640 * 1024); + ViewSize = 384 * 1024; + Status = NtAllocateVirtualMemory( + NtCurrentProcess(), + &BaseAddress, + 0L, + &ViewSize, + MEM_COMMIT, + PAGE_READWRITE + ); + if (!NT_SUCCESS(Status)){ +#if DBG + DbgPrint("sas_init: can not map view of himem space, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + + A20IsON = FALSE; + + Start_of_M_area = 0; + Length_of_M_area = VdmSize; + sas_connect_memory(0, VdmSize + 2*SIXTYFOURK -1, SAS_RAM); +} + +#if VDD_INTEG + +EXPORT +VOID +sas_term( + VOID + ) +/*++ + +Routine Description: + + Free memory prior to reallocing it + +Arguments: + + None. + +Return Value: + + None. +--*/ +{ + PVOID BaseAddress; + NTSTATUS Status; + ULONG Size; + + BaseAddress = (PVOID)VDM_BASE_ADDRESS; + Size = VdmSize; + Status = NtFreeVirtualMemory( + NtCurrentProcess(), + &BaseAddress, + &Size, + MEM_DECOMMIT); + + if (!NT_SUCCESS(Status)) { + VDprint(VDP_LEVEL_ERROR, + ("SoftPc: NtDeCommitVirtualMemory failed !!!! Status = %lx\n", + Status)); + VDbreak(VDB_LEVEL_ERROR); + } +} + + +EXPORT +sys_addr +sas_memory_size( + VOID + ) +/*++ + +Routine Description: + + This routine returns the size of Intel memory + +Arguments: + + none + +Return Value: + + size of intel memory + +--*/ +{ + return(VdmSize); +} + + +EXPORT +VOID +sas_connect_memory( + IN sys_addr Low, + IN sys_addr High, + IN int Type + ) +/*++ + +Routine Description: + + This routine sets up a type record for the specified address region. + If the specified address region was a different type, it is changed to + the new type. + +Arguments: + + Low -- the starting address of the region + High -- the ending address of the region + Type -- the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM, + SAS_WRAP, SAS_INACCESSIBLE + +Return Value: + + None. +--*/ +{ + //bugbug do we handle new block contained in old block correctly? + PMEMTYPE Current, Previous, New, Temp; + + if (!MemType) { + MemType = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE)); + MemType->Previous = NULL; + MemType->Next = NULL; + MemType->Start = Low; + MemType->End = High; + MemType->Type = (half_word)Type; + return; + } + + Current = MemType; + while (Current && (Low > Current->Start)) { + Previous = Current; + Current = Current->Next; + } + + if ((Current) && (Low == Current->Start) && (High == Current->End)) { + Current->Type = (half_word)Type; + return; + } + + if (!Current) { + // Block goes at end of list + New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE)); + Previous->Next = New; + New->Previous = Previous; + New->Start = Low; + New->End = High; + New->Type = (half_word)Type; + New->Next = NULL; + } else { + // Block goes in front of Current + New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE)); + New->Start = Low; + New->Type = (half_word)Type; + New->End = High; + New->Previous = Current->Previous; + New->Next = Current; + Current->Previous = New; + if (!New->Previous) { + MemType = New; + } else { + New->Previous->Next = New; + } + } + + + // Block overlaps one or more existing blocks + + if (New->Previous) { + if (New->Previous->End > New->End) { + // block contained in exising block + Temp = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE)); + Temp->Previous = New; + Temp->Next = New->Next; + New->Next = Temp; + if (Temp->Next) { + Temp->Next->Previous = Temp; + } + Temp->End = New->Previous->End; + New->Previous->End = New->Start - 1; + Temp->Start = New->End + 1; + Temp->Type = New->Previous->Type; + return; + } else if (New->Previous->End >= New->Start){ + // block overlaps end of exising block + New->Previous->End = New->Start - 1; + } + } + + // remove all blocks entirely contained in new block + while ((New->Next) && (New->Next->End <= New->End)) { + Temp = New->Next; + New->Next = New->Next->Next; + if (New->Next) { + New->Next->Previous = New; + } + free(Temp); + } + + // remove portion of next block overlapping new block + if ((New->Next) && (New->Next->Start <= New->End)) { + New->Next->Start = New->End + 1; + } + +} + + +EXPORT +half_word +sas_memory_type( + IN sys_addr Address + ) +/*++ + +Routine Description: + + This routine returns the type of memory at a specific address + +Arguments: + + Address -- linear address to return type for. + +Return Value: + + the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM, + SAS_WRAP, SAS_INACCESSIBLE +--*/ +{ + PMEMTYPE Current; + + if (Address > VdmSize) { + return SAS_INACCESSIBLE; + } + + Current = MemType; + while (Current && !((Address >= Current->Start) && + (Address <= Current->End))) { + Current = Current->Next; + } + if (!Current) { + return SAS_INACCESSIBLE; + } + return Current->Type; +} + + + +EXPORT +VOID +sas_enable_20_bit_wrapping( + VOID + ) +/*++ + +Routine Description: + + This routine causes memory addresses to wrap at 1MB + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + NTSTATUS Status; + PVOID BaseAddress; + ULONG Size; + LARGE_INTEGER SectionOffset; + // if A20 line is off already do nothing + if (A20IsON == FALSE){ + return; + } + BaseAddress = (PVOID)ONEMEGA; + Size = SIXTYFOURK; + Status = NtUnmapViewOfSection(NtCurrentProcess(), + BaseAddress + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("A20OFF: Unable to unmap view of section, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + SectionOffset.HighPart = SectionOffset.LowPart = 0; + Status = NtMapViewOfSection(A20SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + Size, + &SectionOffset, + &Size, + ViewUnmap, + MEM_DOS_LIM, + PAGE_EXECUTE_READWRITE + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("A20OFF: Unable to map view of section, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + A20IsON = FALSE; +} + +EXPORT +VOID +sas_disable_20_bit_wrapping( + VOID + ) +/*++ + +Routine Description: + + This routine causes addressing to NOT wrap at 1MB + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + NTSTATUS Status; + PVOID BaseAddress; + ULONG Size; + LARGE_INTEGER SectionOffset; + + // if A20 line is on already do nothing + if (A20IsON == TRUE){ + return; + } + BaseAddress = (PVOID)ONEMEGA; + Size = SIXTYFOURK; + + Status = NtUnmapViewOfSection(NtCurrentProcess(), + BaseAddress + ); + + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("A20ON: Unable to unmap view of section, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + SectionOffset.HighPart = 0; + SectionOffset.LowPart = 640 * 1024; + Status = NtMapViewOfSection(A20SectionHandle, + NtCurrentProcess(), + &BaseAddress, + 0, + Size, + &SectionOffset, + &Size, + ViewUnmap, + MEM_DOS_LIM, + PAGE_EXECUTE_READWRITE + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("A20ON: Unable to map view of section, status = %lx\n", + Status); +#endif + TerminateVDM(); + } + A20IsON = TRUE; +} + + + +EXPORT +half_word +sas_hw_at( + IN sys_addr Address + ) +/*++ + +Routine Description: + + This routine returns the byte at the specified address + +Arguments: + + Address -- address of byte to return + +Return Value: + + value of byte at specified address + +--*/ +{ + half_word RetVal; + + if (Address > VdmSize) { + return 0xFE; + } + + RetVal = *((half_word *)Address); + return RetVal; +} + + +EXPORT +word +sas_w_at( + IN sys_addr Address + ) +/*++ + +Routine Description: + + This routine returns the word at the specified address + +Arguments: + + Address -- address of word to return + +Return Value: + + value of word at specified address + +--*/ +{ + word RetVal; + +// DbgPrint("NtVdm : sas_w_at \n"); + if (Address > VdmSize) { + return 0xFEFE; + } + + RetVal = *((word *)Address); + return RetVal; +} + + +EXPORT +double_word +sas_dw_at( + IN sys_addr Address + ) +/*++ + +Routine Description: + + This routine returns the dword at the specified address + +Arguments: + + Address -- address of dword to return + +Return Value: + + value of dword at specified address + +--*/ +{ + double_word RetVal; + + //DbgPrint("NtVdm : sas_dw_at \n"); + RetVal = (double_word)(((ULONG)sas_w_at(Address + 2) << 16) + + sas_w_at(Address)); + return RetVal; +} + + +EXPORT +VOID +sas_load( + IN sys_addr Address, + IN half_word *Value + ) +/*++ + +Routine Description: + + This routine stores the byte at the specified address in the supplied + variable + +Arguments: + + Address -- address of byte to return + Value -- Variable to store the value in + +Return Value: + + None. +--*/ +{ + //DbgPrint("NtVdm : sas_load \n"); + if (Address > VdmSize) { + *Value = 0xFE; + return; + } + + *Value = *((half_word *)Address); + return; +} + + +EXPORT +VOID +sas_loadw( + IN sys_addr Address, + IN word *Value + ) +/*++ + +Routine Description: + + This routine stores the word at the specified address in the supplied + variable + +Arguments: + + Address -- address of word to return + Value -- Variable to store the value in + +Return Value: + + None. +--*/ +{ + //DbgPrint("NtVdm : sas_loadw\n"); + if (Address > VdmSize) { + *Value = 0xFEFE; + return; + } + + *Value = *((word *)Address); + //DbgPrint("NtVdm : sas_loadw word at address %lx is %x (Not video)\n",Address,*Value); + return; +} + + + +EXPORT +VOID +sas_store( + IN sys_addr Address, + IN half_word Value + ) +/*++ + +Routine Description: + + This routine stores the specified byte at the specified address + +Arguments: + + Address -- address of word to return + Value -- value to store + +Return Value: + + None. +--*/ +{ + half_word Type; + //DbgPrint("NtVdm : sas_store\n"); + if (Address <= VdmSize) { + Type = sas_memory_type(Address); + switch (Type) { + case SAS_ROM: + break; + + default: + *((half_word *)Address) = Value; + //DbgPrint("NtVdm : sas_store put byte %x at address %lx\n",Value,Address); + break; + } + } +} + + + +EXPORT +VOID +sas_storew( + IN sys_addr Address, + IN word Value + ) +/*++ + +Routine Description: + + This routine stores the specified word at the specified address + +Arguments: + + Address -- address of word to return + Value -- value to store at the specified address + +Return Value: + + None. +--*/ +{ + + //DbgPrint("NtVdm : sas_storew\n"); + if (Address + 1 <= VdmSize) { + switch (sas_memory_type(Address)) { + + case SAS_ROM: + break; + + default: + *((word *)Address) = Value; + //DbgPrint("NtVdm : sas_storew put word %x at address %lx\n",Value,Address); + break; + } + } +} + + + +EXPORT +VOID +sas_storedw( + IN sys_addr Address, + IN double_word Value + ) +/*++ + +Routine Description: + + This routine stores the specified dword at the specified address + +Arguments: + + Address -- address of word to return + Value -- value to store at the specified address + +Return Value: + + None. +--*/ +{ + //_asm int 3; + sas_storew(Address, (word)(Value & 0xFFFF)); + sas_storew(Address + 2, (word)((Value >> 16) & 0xFFFF)); +} + + +EXPORT +VOID +sas_loads( + IN sys_addr Source, + IN host_addr Destination, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine copies the string from the specified intel address to the + specified host address + +Arguments: + + Source -- Intel address to copy from + Destination -- host address to copy the string to + Length -- length of the string to copy + +Return Value: + + None. +--*/ +{ + + //DbgPrint("NtVdm : sas_loads\n"); + RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length); +} + + + +EXPORT +VOID +sas_stores( + IN sys_addr Destination, + IN host_addr Source, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine copies the string from the specified host address to the + specified intel address + +Arguments: + + Destination -- intel address to copy the string to + Source -- host address to copy from + Length -- length of the string to copy + +Return Value: + + None. +--*/ +{ + + //DbgPrint("NtVdm : sas_stores\n"); + switch (sas_memory_type(Destination)) { + + case SAS_ROM: + break; + + default: + RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length); + break; + } +} + + +EXPORT +VOID +sas_move_bytes_forward( + IN sys_addr Source, + IN sys_addr Destination, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine copies one region of intel memory to another. + +Arguments: + + Source -- source intel address + Destination -- destination intel address + Length -- length of region to copy (in bytes) + +Return Value: + + None. +--*/ +{ + //DbgPrint("NtVdm : sas_move_bytes_forward\n"); + switch (sas_memory_type(Destination)) { + + case SAS_ROM: + break; + + default: + RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length); + break; + } +} + + + +EXPORT +VOID +sas_move_words_forward( + IN sys_addr Source, + IN sys_addr Destination, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine copies one region of intel memory to another. + +Arguments: + + Source -- source intel address + Destination -- destination intel address + Length -- length of region to copy (in words) + +Return Value: + + None. +--*/ +{ + //_asm int 3; + Length <<= 1; + switch (sas_memory_type(Destination)) { + + case SAS_ROM: + break; + + default: + RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length); + break; + } +} + + + +EXPORT +VOID +sas_move_bytes_backward( + IN sys_addr Source, + IN sys_addr Destination, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine copies one region of intel memory to another. + +Arguments: + + Source -- source intel address + Destination -- destination intel address + Length -- length of region to copy (in bytes) + +Return Value: + + None. +--*/ +{ + //_asm int 3; + switch (sas_memory_type(Destination)) { + + case SAS_ROM: + break; + + default: + RtlCopyMemory((PVOID) (Destination - Length + 1), + (PVOID) (Source - Length + 1), + Length); + break; + } +} + + + +EXPORT +VOID +sas_move_words_backward( + IN sys_addr Source, + IN sys_addr Destination, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine copies one region of intel memory to another. + +Arguments: + + Source -- source intel address + Destination -- destination intel address + Length -- length of region to copy (in words) + +Return Value: + + None. +--*/ +{ + //_asm int 3; + Length <<= 1; + switch (sas_memory_type(Destination)) { + + case SAS_ROM: + break; + + default: + RtlCopyMemory((PVOID) (Destination - Length + 1), + (PVOID) (Source - Length + 1), + Length); + break; + } +} + +EXPORT +VOID +sas_fills( + IN sys_addr Address, + IN half_word Value, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine fills a specified region of intel memory with a byte value + +Arguments: + + Address -- address to fill at + Value -- value to fill with + Length -- length of region to fill + +Return Value: + + None. +--*/ +{ + half_word Type; + + //DbgPrint("NtVdm : sas_fills\n"); + Type = sas_memory_type(Address); + switch (Type) { + + case SAS_ROM: + break; + + default: + RtlFillMemory((PVOID) Address, Length, Value); + break; + } +} + +EXPORT +VOID +sas_fillsw( + IN sys_addr Address, + IN word Value, + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine fills a specified region of intel memory with a word value + +Arguments: + + Address -- address to fill at + Value -- value to fill with + Length -- length of region to fill + +Return Value: + + None. +--*/ +{ + + word *p; + half_word Type; + + //DbgPrint("NtVdm : sas_fillsw\n"); + Type = sas_memory_type(Address); + switch (Type) { + + case SAS_ROM: + break; + + default: + p = (word *)Address; + while (Length--) { + *p++ = Value; + } + break; + } +} + +host_addr scratch = NULL; + +EXPORT +host_addr +sas_scratch_address( + IN sys_addr Length + ) +/*++ + +Routine Description: + + This routine supplies a scratch buffer for short term use + +Arguments + + Length -- length of buffer needed + +Return Value: + + None. + +NOTE: Sudeepb 31-Oct-1993 Converted scratch to be allocated dynamically rather + than as a static array. +--*/ +{ + //DbgPrint("NtVdm : sas_scratch_address\n"); + if (Length > 64 * 1024) { + //DbgPrint("SoftPc: sas_scratch_address requet for buffer larger than 64K\n"); + return NULL; + } + + if (scratch) + return scratch; + + if ((scratch = (host_addr) malloc (64 * 1024)) == NULL) + return NULL; + + return scratch; +} + +EXPORT +half_word +sas_hw_at_no_check( + sys_addr addr + ) +// bugbug comment +{ + //DbgPrint("NtVdm : sas_hw_at_no_check\n"); + //DbgPrint("NtVdm : sas_hw_at_no_check byte at %lx is %x\n",addr,*((half_word *)addr)); + return *((half_word *)addr); +} + +EXPORT +word +sas_w_at_no_check( + sys_addr addr + ) +// bugbug comment +{ + //DbgPrint("NtVdm : sas_w_at_no_check\n"); + //DbgPrint("NtVdm : sas_w_at_no_check word at %lx is %x\n",addr,*((word *)addr)); + return *((word *)addr); +} +EXPORT +double_word +sas_dw_at_no_check( + sys_addr addr + ) +// bugbug comment +{ + //DbgPrint("NtVdm : sas_dw_at_no_check\n"); + //DbgPrint("NtVdm : sas_dw_at_no_check double word at %lx is %lx\n",addr,*((double_word *)addr)); + return *((double_word *)addr); +} + + +EXPORT +VOID +sas_store_no_check( + sys_addr addr, + half_word val + ) +// bugbug comment +{ + //DbgPrint("NtVdm : sas_store_no_check\n"); + *((half_word *)addr) = val; + //DbgPrint("NtVdm : sas_store_no_check stored byte %x at %lx\n",val,addr); +} + +EXPORT +VOID +sas_storew_no_check( + sys_addr addr, + word val + ) +// bugbug comment +{ + //DbgPrint("NtVdm : sas_storew_no_check\n"); + *((word *)addr) = val; +} +EXPORT +double_word +effective_addr( + IN word Segment, + IN word Offset + ) +/*++ + +Routine Description: + + This routine maps effective_addr to Sim32GetVdmPointer + +Arguments: + + Segment -- segment of address + Offset -- offset of address + +Return Value: + + Actual Intel address corresponding to the address supplied +--*/ +{ + //DbgPrint("NtVdm : effective_addr\n"); + return (ULONG)Sim32GetVDMPointer(((((ULONG)Segment) << 16) | Offset), 1, + (UCHAR) (getMSW() & MSW_PE ? TRUE : FALSE)); +} + +typedef enum +{ + RAM, + VIDEO, + ROM, + IN_FRAGMENT, + NEXT_FRAGMENT +} mem_type; + +typedef struct +{ + VOID (*b_write)(); + VOID (*w_write)(); + VOID (*b_fill)(); + VOID (*w_fill)(); + VOID (*b_move)(); + VOID (*w_move)(); +} MEM_HANDLERS; +#define TYPE_RANGE ((int)SAS_INACCESSIBLE) +#define write_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) ) +#define write_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) ) +#define write_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) ) +#define write_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) ) +#define init_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) ) +#define init_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) ) +#define init_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) ) +#define init_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) ) +#define read_b_write_ptrs( offset ) ( b_write_ptrs[(offset)] ) +#define read_w_write_ptrs( offset ) ( w_write_ptrs[(offset)] ) +#define read_b_page_ptrs( offset ) ( b_move_ptrs[(offset)] ) +#define read_w_page_ptrs( offset ) ( w_move_ptrs[(offset)] ) +#define read_b_move_ptrs( offset ) ( b_move_ptrs[(offset)] ) +#define read_w_move_ptrs( offset ) ( w_move_ptrs[(offset)] ) +#define read_b_fill_ptrs( offset ) ( b_fill_ptrs[(offset)] ) +#define read_w_fill_ptrs( offset ) ( w_fill_ptrs[(offset)] ) + +/* +* The main gmi data structures are defined here +*/ +void (*(b_write_ptrs[TYPE_RANGE]))() ; /* byte write function */ +void (*(w_write_ptrs[TYPE_RANGE]))() ; /* word write function */ +void (*(b_fill_ptrs[TYPE_RANGE]))() ; /* byte str fill func */ +void (*(w_fill_ptrs[TYPE_RANGE]))() ; /* word str fill func */ +void (*(b_move_ptrs[TYPE_RANGE]))() ; /* byte str write func */ +void (*(w_move_ptrs[TYPE_RANGE]))() ; /* word str write func */ + +void gmi_define_mem(type,handlers) +mem_type type; +MEM_HANDLERS *handlers; +{ + int int_type = (int)(type); + init_b_write_ptrs(int_type, (void(*)())(handlers->b_write)); + init_w_write_ptrs(int_type, (void(*)())(handlers->w_write)); + b_move_ptrs[int_type] = (void(*)())(handlers->b_move); + w_move_ptrs[int_type] = (void(*)())(handlers->w_move); + b_fill_ptrs[int_type] = (void(*)())(handlers->b_fill); + w_fill_ptrs[int_type] = (void(*)())(handlers->w_fill); +} +#endif +BOOL sas_twenty_bit_wrapping_enabled() { + return (!A20IsON); +} + +VOID sas_part_enable_20_bit_wrapping(){ +} +VOID sas_part_disable_20_bit_wrapping(){ +} + + +/* + * This function maps the given EMM backfill memory to DOS conventional + * memory. The function is provided to EMM manager to put back + * unmapped backfill memory(hold its contents while it is not mapped). + * + * NOTE: The very first caller will be sas_init. + * + * Input: ULONG BaseAddress -- the starting address, must be in INTEL page + * boundary + * ULONG Size -- size of the range, must be a multiple of + * EMM_PAGE_SIZE. + * + * According to LouP, a view costs about 400 bytes of memory. This is why + * I make these function strictly to work on EMM_PAGE_SIZE instead of 4KB. + */ + + +BOOL +HoldEMMBackFillMemory(ULONG BaseAddress, ULONG Size) +{ + ULONG NewBase, Pages, i; + LARGE_INTEGER SectionOffset; + ULONG ViewSize; + NTSTATUS Status; + + /* this function can only be called if there is backfill at all */ + ASSERT(BackFillSegment < 640 * 1024 / 16); + + // size must be EMM_PAGE_SIZE multiple + ASSERT((Size % EMM_PAGE_SIZE) == 0); + + // address must be on INTEL page boundary + ASSERT((BaseAddress & (INTEL_PAGE_SIZE - 1)) == 0); + + for (Pages = Size / EMM_PAGE_SIZE; Pages; Pages--) { + SectionOffset.LowPart = BaseAddress; + SectionOffset.HighPart = 0; + ViewSize = EMM_PAGE_SIZE; + Status = NtMapViewOfSection(A20SectionHandle, + NtCurrentProcess(), + (PVOID *)&BaseAddress, + 0, + ViewSize, + &SectionOffset, + &ViewSize, + ViewUnmap, + MEM_DOS_LIM, + PAGE_EXECUTE_READWRITE + ); + if (!NT_SUCCESS(Status)) + break; + BaseAddress += EMM_PAGE_SIZE; + } + return (NT_SUCCESS(Status)); +} diff --git a/private/mvdm/v86/monitor/i386/sources b/private/mvdm/v86/monitor/i386/sources new file mode 100644 index 000000000..826099cfc --- /dev/null +++ b/private/mvdm/v86/monitor/i386/sources @@ -0,0 +1,11 @@ +i386_SOURCES=i386\monitor.c \ + i386\fastpm.asm\ + i386\sas.c \ + i386\spcstubs.c \ + i386\thread.c \ + i386\int.c +!IF 0 +Note: to build with profiling support, add the following to the i386_sources + + i386\proflib.c \ +!ENDIF diff --git a/private/mvdm/v86/monitor/i386/spcstubs.c b/private/mvdm/v86/monitor/i386/spcstubs.c new file mode 100644 index 000000000..c2bb4fcce --- /dev/null +++ b/private/mvdm/v86/monitor/i386/spcstubs.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +//Tim Nov 92 #include +#include //Tim Nov 92, so it builds... + + +ULONG cpu_calc_q_ev_inst_for_time(ULONG time){ + return(time); +} + +ULONG q_ev_count; + +VOID cpu_q_ev_set_count(ULONG time){ + q_ev_count = time; +} +ULONG cpu_q_ev_get_count() { + return(q_ev_count); +} + +char szYodaWarn[]="NtVdm : Using Yoda on an x86 may be hazardous to your systems' health\n"; + +unsigned char *GDP; + +int getCPL(){ + OutputDebugString(szYodaWarn); + return(0); +} + +int getEM(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getGDT_BASE(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getGDT_LIMIT(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getIDT_BASE(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getIDT_LIMIT(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getIOPL(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getLDT_BASE(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getLDT_LIMIT(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getLDT_SELECTOR(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getMP(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getNT(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getTR_BASE(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getTR_LIMIT(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getTR_SELECTOR(){ + OutputDebugString(szYodaWarn); + return(0); +} +int getTS(){ + OutputDebugString(szYodaWarn); + return(0); +} +void setPE(int dummy1){ + OutputDebugString(szYodaWarn); +} +boolean selector_outside_table(word foo, double_word *bar){ + UNREFERENCED_PARAMETER(foo); + UNREFERENCED_PARAMETER(bar); + OutputDebugString("NtVdm : Using Yoda on an x86 may be hazardous to your systems' health\n"); + return(0); +} + +VOID +EnterIdle(){ +} + +VOID +LeaveIdle(){ +} diff --git a/private/mvdm/v86/monitor/i386/thread.c b/private/mvdm/v86/monitor/i386/thread.c new file mode 100644 index 000000000..41d3b50e5 --- /dev/null +++ b/private/mvdm/v86/monitor/i386/thread.c @@ -0,0 +1,338 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + Thread.c + +Abstract: + + This file contains functions for tracking and manipulating threads + +Author: + + Dave Hastings (daveh) 18-Apr-1992 + +Revision History: + +--*/ + +#include +#include + +// +// Local Types +// + +typedef struct _MonitorThread { + struct _MonitorThread *Previous; + struct _MonitorThread *Next; + PVOID Teb; + HANDLE Thread; +} MONITORTHREAD, *PMONITORTHREAD; + +// +// Local Variables +// + +PMONITORTHREAD ThreadList = NULL; // List of all threads registered + +VOID +cpu_createthread( + HANDLE Thread + ) +/*++ + +Routine Description: + + This routine adds a thread to the list of threads that could be executing + in application mode. + +Arguments: + + Thread -- Supplies a thread handle + +Return Value: + + None. + +--*/ +{ + PMONITORTHREAD NewThread, CurrentThread; + THREAD_BASIC_INFORMATION ThreadInfo; + HANDLE MonitorThreadHandle; + NTSTATUS Status; + + // + // Correctly initialize the floating point context for the thread + // + InitialContext.ContextFlags = CONTEXT_FLOATING_POINT; + + if (DebugContextActive) + InitialContext.ContextFlags |= CONTEXT_DEBUG_REGISTERS; + + Status = NtSetContextThread( + Thread, + &InitialContext + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("NtVdm terminating : Could not set float context for\n" + " thread handle 0x%x, status %lx\n", Thread, Status); + DbgBreakPoint(); +#endif + TerminateVDM(); + } + + // + // Set up a structure to keep track of the new thread + // + NewThread = malloc(sizeof(MONITORTHREAD)); + + if (!NewThread) { +#if DBG + DbgPrint("NTVDM: Could not allocate space for new thread\n"); + DbgBreakPoint(); +#endif + TerminateVDM(); + } + + // + // Create a handle for the monitor to use + // + + Status = NtDuplicateObject( + NtCurrentProcess(), + Thread, + NtCurrentProcess(), + &MonitorThreadHandle, + 0, + 0, + DUPLICATE_SAME_ACCESS + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("NTVDM: Could not duplicate thread handle\n"); + DbgBreakPoint(); +#endif + TerminateVDM(); + } + + NewThread->Thread = MonitorThreadHandle; + + Status = NtQueryInformationThread( + MonitorThreadHandle, + ThreadBasicInformation, + &ThreadInfo, + sizeof(THREAD_BASIC_INFORMATION), + NULL + ); + + if (!NT_SUCCESS(Status)) { +#if DBG + DbgPrint("NTVDM: Could not get thread information\n"); + DbgBreakPoint(); +#endif + TerminateVDM(); + } + + NewThread->Teb = ThreadInfo.TebBaseAddress; + ((PTEB)(NewThread->Teb))->Vdm = &VdmTib; + + // + // Insert the new thread in the list. The list is sorted in ascending + // order of Teb address + // + if (!ThreadList) { + ThreadList = NewThread; + NewThread->Next = NULL; + NewThread->Previous = NULL; + return; + } + + CurrentThread = ThreadList; + while ((CurrentThread->Next) && (CurrentThread->Teb < NewThread->Teb)) { + CurrentThread = CurrentThread->Next; + } + + if (NewThread->Teb > CurrentThread->Teb) { + CurrentThread->Next = NewThread; + NewThread->Previous = CurrentThread; + NewThread->Next = NULL; + } else { + ASSERT((CurrentThread->Teb != NewThread->Teb)); + NewThread->Previous = CurrentThread->Previous; + NewThread->Next = CurrentThread; + CurrentThread->Previous = NewThread; + if (NewThread->Previous) { + NewThread->Previous->Next = NewThread; + } else { + ThreadList = NewThread; + } + } +} + +VOID +cpu_exitthread( + VOID + ) +/*++ + +Routine Description: + + This routine frees the thread tracking information, and closes the thread + handle + +Arguments: + + +Return Value: + + None. + +--*/ +{ + PVOID CurrentTeb; + NTSTATUS Status; + PMONITORTHREAD ThreadInfo; + + CurrentTeb = NtCurrentTeb(); + + ThreadInfo = ThreadList; + + // + // Find this thread in the list + // + while ((ThreadInfo) && (ThreadInfo->Teb != CurrentTeb)) { + ThreadInfo = ThreadInfo->Next; + } + + if (!ThreadInfo) { +#if DBG + DbgPrint("NTVDM: Could not find thread in list\n"); + DbgBreakPoint(); +#endif + return; + } + + // + // Close our handle to this thread + // + Status = NtClose(ThreadInfo->Thread); +#if DBG + if (!NT_SUCCESS(Status)) { + DbgPrint("NTVDM: Could not close thread handle\n"); + } +#endif + + // + // Remove this thread from the list + // + if (ThreadInfo->Previous) { + ThreadInfo->Previous->Next = ThreadInfo->Next; + } else { + ThreadList = ThreadInfo->Next; + } + + if (ThreadInfo->Next) { + ThreadInfo->Next->Previous = ThreadInfo->Previous; + } + + free(ThreadInfo); +} + +HANDLE +ThreadLookUp( + PVOID Teb + ) +/*++ + +Routine Description: + + This routine returns the handle for the specified thread. + +Arguments: + + Teb -- Supplies the teb pointer of the thread + +Return Value: + + Returns the handle of the thread, or NULL + +--*/ +{ + PMONITORTHREAD Thread; + + Thread = ThreadList; + + while ((Thread) && (Thread->Teb != Teb)) { + Thread = Thread->Next; + } + + if (Thread) { + return Thread->Thread; + } else { + return NULL; + } +} + +BOOL +ThreadSetDebugContext( + PULONG pDebugRegisters + ) +/*++ + +Routine Description: + + This routine sets the debug registers for all the threads that the + monitor knows about. + +Arguments: + + pDebugRegisters -- Pointer to 6 dwords containing the requested debug + register contents. + +Return Value: + + none + +--*/ +{ + PMONITORTHREAD Thread; + NTSTATUS Status; + + Thread = ThreadList; + InitialContext.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + InitialContext.Dr0 = *pDebugRegisters++; + InitialContext.Dr1 = *pDebugRegisters++; + InitialContext.Dr2 = *pDebugRegisters++; + InitialContext.Dr3 = *pDebugRegisters++; + InitialContext.Dr6 = *pDebugRegisters++; + InitialContext.Dr7 = *pDebugRegisters++; + + while (Thread) { + + Status = NtSetContextThread( + Thread->Thread, + &InitialContext + ); + + if (!NT_SUCCESS(Status)) + break; + + Thread = Thread->Next; + } + + if (!NT_SUCCESS(Status)) + return (FALSE); + else { + DebugContextActive = ((InitialContext.Dr7 & 0x0f) != 0); + return (TRUE); + } + +} + diff --git a/private/mvdm/v86/monitor/makefile b/private/mvdm/v86/monitor/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/mvdm/v86/monitor/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/mvdm/v86/monitor/sources b/private/mvdm/v86/monitor/sources new file mode 100644 index 000000000..cb21ac27d --- /dev/null +++ b/private/mvdm/v86/monitor/sources @@ -0,0 +1,57 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + Dave Hastings (daveh) 24-Apr-1991 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + + +MAJORCOMP=v86 +MINORCOMP=monitor +TARGETNAME=monitor + + +TARGETPATH=\nt\public\sdk\lib + +TARGETTYPE=LIBRARY + + +TARGETLIBS= + + +INCLUDES=..\..\inc;..\..\softpc.new\base\inc;..\..\softpc.new\host\inc;..\..\..\inc + + +NTPROFILEINPUT=YES + +SOURCES= + +!IFDEF PROFILE +C_DEFINES=-DCPU_30_STYLE -DMONITOR -DPROFILE +!ELSE +!IFDEF OLDBUILD +C_DEFINES=-DCPU_30_STYLE -DMONITOR -DOLDBUILD +!ELSE +C_DEFINES=-DCPU_30_STYLE -DMONITOR +!ENDIF +!ENDIF + +UMTYPE=console diff --git a/private/mvdm/v86/scaffold/i386/fakebop.c b/private/mvdm/v86/scaffold/i386/fakebop.c new file mode 100644 index 000000000..b9430dd30 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/fakebop.c @@ -0,0 +1,502 @@ +#include +#include +#include +#include "demexp.h" +#include "cmdsvc.h" +#include "rdrexp.h" +#include "dbgexp.h" +#include "softpc.h" +#include "fun.h" +// +// This module contains the fake function definitions for bop functions +// + +extern CONTEXT IntelRegisters; +extern VOID switch_to_real_mode(); +extern VOID host_unsimulate(); + + +HANDLE hWOWDll; + +FARPROC WOWDispatchEntry; +FARPROC WOWInitEntry; + +void DBGDispatch( void ); + +void reset(){} +void dummy_int(){} +void unexpected_int(){} +void illegal_bop(){} +void print_screen(){} +void time_int(){} +void keyboard_int(){} +void diskette_int(){} +void video_io(){} +void equipment(){} +void memory_size(){} +void disk_io(){} +void rs232_io(){} +void cassette_io(){} +void keyboard_io(){} +void printer_io(){} +void rom_basic(){} +void bootstrap(){} +void time_of_day(){} +void critical_region(){} +void cmd_install(){} +void cmd_load(){} +void redirector(){} +void ega_video_io(){} +void MsBop0(){ + + DemDispatch((ULONG)(*Sim32GetVDMPointer( + ((ULONG)getCS() << 16) + (getIP()), 1, FALSE))); + setIP(getIP() + 1); + +} +void MsBop1(){ + + + static WowModeInitialized = FALSE; + + if (!WowModeInitialized) { + + // Load the WOW DLL + if ((hWOWDll = LoadLibrary ("WOW32")) == NULL){ + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing WOW\n") + ); + TerminateVDM(); + return; + } + + // Get the init entry point and dispatch entry point + if ((WOWInitEntry = GetProcAddress (hWOWDll, "W32Init")) == NULL) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing WOW\n") + ); + FreeLibrary (hWOWDll); + TerminateVDM(); + return; + } + + if ((WOWDispatchEntry = GetProcAddress (hWOWDll, "W32Dispatch")) == NULL) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing WOW\n") + ); + FreeLibrary (hWOWDll); + TerminateVDM(); + return; + } + + // Call the Init Routine + if ((*WOWInitEntry)() == FALSE) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing WOW\n") + ); + TerminateVDM(); + return; + } + + WowModeInitialized = TRUE; + } + + (*WOWDispatchEntry)(); +} + +void MsBop2(){ + + XMSDispatch((ULONG)(*Sim32GetVDMPointer( + ((ULONG)getCS() << 16) + (getIP()), 1, FALSE))); + setIP(getIP() + 1); + +} +void MsBop3(){ + DpmiDispatch(); +} + + + +void MsBop4(){ + CmdDispatch((ULONG)(*Sim32GetVDMPointer( + ((ULONG)getCS() << 16) + (getIP()), 1, FALSE))); + setIP(getIP() + 1); +} + + + +// +// MsBop5 - used to dispatch to Vdm Redir (Vr) support functions +// + +void MsBop5() +{ +#ifdef NTVDM_NET_SUPPORT + VrDispatch((ULONG)(*Sim32GetVDMPointer( + ((ULONG)getCS() << 16) + (getIP()), 1, FALSE))); + setIP(getIP() + 1); +#endif +} + +// +// MsBop6 - used to dispatch to debugger support functions +// + +void MsBop6() +{ + /* + ** All of the parameters for the debugger support + ** should be on the VDMs stack. + */ + DBGDispatch(); +} +void MsBop7(){} +void MsBop8(){} +void MsBop9(){} +void MsBopA(){} +void MsBopB(){ + + switch (getAH()) { + + case 0 : + setAH(0); + while (!tkbhit()); + setAL((BYTE)tgetch()); + break; + + case 1 : + tputch(getAL()); + break; + } +} +void MsBopC(){ + + BiosKbd(); + +} +void MsBopD(){ + + BiosVid(); + +} +void MsBopE(){} + + +void MsBopF(){ + UCHAR *Instruction; + USHORT i; + + // Unimplemented interrupt bop + + Instruction = RMSEGOFFTOLIN(getSS(), getSP()); + Instruction = RMSEGOFFTOLIN(*((PWORD)Instruction + 1), + *(PWORD)(Instruction)); + i = (USHORT)(*(Instruction - 1)); + VDprint( + VDP_LEVEL_WARNING, + ("SoftPC Bop Support: Unimplemented Interrupt %x\n", + i) + ); + +} +void emm_init(){} +void emm_io(){} +void return_from_call(){} +void rtc_int(){} +void re_direct(){} +void D11_int(){} +void int_287(){} +void worm_init(){} +void worm_io(){} +void ps_private_1(){} +void ps_private_2(){} +void ps_private_3(){} +void ps_private_4(){} +void ps_private_5(){} +void ps_private_6(){} +void ps_private_7(){} +void ps_private_8(){} +void ps_private_9(){} +void ps_private_10(){} +void ps_private_11(){} +void ps_private_12(){} +void ps_private_13(){} +void ps_private_14(){} +void ps_private_15(){} +void bootstrap1(){} +void bootstrap2(){} +void bootstrap3(){} +void ms_windows(){} +void msw_mouse(){} +void mouse_install1(){} +void mouse_install2(){} +void mouse_int1(){} +void mouse_int2(){} +void mouse_io_language(){} +void mouse_io_interrupt(){} +void mouse_video_io(){} +void control_bop(){} +void diskette_io(){} +void illegal_op_int(){} + +VOID (*BIOS[])(VOID) = { reset, + dummy_int, + unexpected_int, + illegal_bop, + illegal_bop, + print_screen, + illegal_op_int, + illegal_bop, + time_int, + keyboard_int, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + diskette_int, + illegal_bop, + video_io, + equipment, + memory_size, + disk_io, + rs232_io, + cassette_io, + keyboard_io, + printer_io, + rom_basic, + bootstrap, + time_of_day, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + critical_region, + cmd_install, + cmd_load, + illegal_bop, + illegal_bop, + redirector, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + diskette_io, + illegal_bop, + ega_video_io, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + MsBop0, + MsBop1, + MsBop2, + MsBop3, + MsBop4, + MsBop5, + MsBop6, + MsBop7, + MsBop8, + MsBop9, + MsBopA, + MsBopB, + MsBopC, + MsBopD, + MsBopE, + MsBopF, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + emm_init, + emm_io, + return_from_call, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + rtc_int, + re_direct, + D11_int, + D11_int, + D11_int, + int_287, + D11_int, + D11_int, + worm_init, + worm_io, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + ps_private_1, + ps_private_2, + ps_private_3, + ps_private_4, + ps_private_5, + ps_private_6, + ps_private_7, + ps_private_8, + ps_private_9, + ps_private_10, + ps_private_11, + ps_private_12, + ps_private_13, + ps_private_14, + ps_private_15, + illegal_bop, + bootstrap1, + bootstrap2, + bootstrap3, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + ms_windows, + msw_mouse, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + mouse_install1, + mouse_install2, + mouse_int1, + mouse_int2, + mouse_io_language, + mouse_io_interrupt, + mouse_video_io, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + illegal_bop, + switch_to_real_mode, + host_unsimulate, + control_bop }; + diff --git a/private/mvdm/v86/scaffold/i386/fakeinit.c b/private/mvdm/v86/scaffold/i386/fakeinit.c new file mode 100644 index 000000000..ae5d586de --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/fakeinit.c @@ -0,0 +1,123 @@ +// +// Fake Bios support initialization. +// +// This file provides interrim support for rom bios services initialization. +// It is only intended for use until Insignia produces proper rom support +// for NTVDM +// + +#include +#include +#include +#include +#include "softpc.h" +#include "bop.h" +#include "xguest.h" +#include "xbios.h" +#include "xbiosdsk.h" +#include "fun.h" + +#define SERVICE_LENGTH 4 +static BYTE ServiceRoutine[] = { 0xC4 , 0xC4, BOP_UNIMPINT, 0xCF }; + +#define RESET_LENGTH 16 +static BYTE ResetRoutine[] = { 0xEA, 0x00, 0x00, 0x00, 0xE0, // jmpf E000:0 + BIOSDATE_MINE, + 0, 0xFE, 0 }; + +static BYTE WarmBoot[] = { + OPX_MOVAX, BYTESOFFSET(0x30), + OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_SS,REG_AX), + OPX_MOVSP, BYTESOFFSET(0x100), + OPX_MOVAX, 0x00, 0x00, + OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_DS,REG_AX), + OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_ES,REG_AX), + OPX_MOVDX, DRIVE_FD0, 0x00, // WARNING: sync with BIOSBOOT_DRIVE + OPX_MOVCX, 0x01, 0x00, + OPX_MOVBX, BYTESOFFSET(BIOSDATA_BOOT), + OPX_MOVAX, 0x01, DSKFUNC_READSECTORS, + OPX_INT, BIOSINT_DSK, + OPX_JB, -7, + OPX_JMPF, BYTESCOMPOSITE(0, BIOSDATA_BOOT) +}; +#define WARMBOOT_LENGTH sizeof(WarmBoot) + +static BYTE EquipmentRoutine[] = { // INT 11h code + OPX_PUSHDS, + OPX_MOVAX, 0x00, 0x00, + OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_DS,REG_AX), + OPX_MOVAXOFF, BYTESOFFSET(BIOSDATA_EQUIP_FLAG), + OPX_POPDS, + OPX_IRET +}; +#define EQUIPMENT_LENGTH sizeof(EquipmentRoutine) + +static BYTE MemoryRoutine[] = { // INT 12h code + OPX_PUSHDS, + OPX_MOVAX, 0x00, 0x00, + OPX_MOV2SEG, MODREGRM(MOD_REGISTER,REG_DS,REG_AX), + OPX_MOVAXOFF, BYTESOFFSET(BIOSDATA_MEMORY_SIZE), + OPX_POPDS, + OPX_IRET +}; +#define MEMORY_LENGTH sizeof(MemoryRoutine) + + +VOID BiosInit(int argc, char *argv[]) { + + PVOID Address, RomAddress; + + // set up IVT with unimplemented interrupt handler + + for (Address = NULL; Address < (PVOID)(0x1D * 4); (PCHAR)Address += 4) { + *(PWORD)Address = 0x100; + *(((PWORD)Address) + 1) = 0xF000; + } + + RomAddress = (PVOID)(0xE000 << 4); + + // set up warm boot handler + memcpy(RomAddress, WarmBoot, WARMBOOT_LENGTH); + Address = RMSEGOFFTOLIN(0, BIOSINT_WBOOT * 4); + *((PWORD)Address) = 0; + *((PWORD)Address + 1) = 0xE000; + (PCHAR)RomAddress += WARMBOOT_LENGTH; + + // set up equipment interrupt handler + memcpy(RomAddress, EquipmentRoutine, EQUIPMENT_LENGTH); + Address = RMSEGOFFTOLIN(0, BIOSINT_EQUIP * 4); + *((PWORD)Address) = RMOFF(RomAddress); + *((PWORD)Address + 1) = RMSEG(RomAddress); + (PCHAR)RomAddress += EQUIPMENT_LENGTH; + + // set up memory size interrupt handler + memcpy(RomAddress, MemoryRoutine, MEMORY_LENGTH); + Address = RMSEGOFFTOLIN(0, BIOSINT_MEMORY * 4); + *((PWORD)Address) = RMOFF(RomAddress); + *((PWORD)Address + 1) = RMSEG(RomAddress); + + RomAddress = (PVOID)((0xF000 << 4) + 0x100); + + Address = (PBYTE)RomAddress + 0xFE53; + *(PCHAR)Address = 0xCF; // IRET at f000:ff53 + + // set up unimplemented interrupt handler + + memcpy(RomAddress, ServiceRoutine, SERVICE_LENGTH); + (PCHAR)RomAddress += SERVICE_LENGTH; + + // set up reset code + memcpy(RMSEGOFFTOLIN(BIOSROM_SEG, BIOSROM_RESET), ResetRoutine, RESET_LENGTH); + + // set up equipment byte and memory size + + *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG) = + BIOSEQUIP_32KPLANAR; + *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_MEMORY_SIZE) = + 640; + + // Initialize individual rom modules + + BiosKbdInit(argc, argv, &RomAddress); + BiosVidInit(argc, argv, &RomAddress); +} diff --git a/private/mvdm/v86/scaffold/i386/fakekbd.c b/private/mvdm/v86/scaffold/i386/fakekbd.c new file mode 100644 index 000000000..8e807548e --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/fakekbd.c @@ -0,0 +1,281 @@ + +// +// Fake Keyboard rom support +// +// This file provides interrim support for keyboard rom bios services. +// It is only intended for use until Insignia produces proper rom support +// for NTVDM +// +// Note: portions of this code were lifted from the following source. + +/* x86 v1.0 + * + * XBIOSKBD.C + * Guest ROM BIOS keyboard emulation + * + * History + * Created 20-Oct-90 by Jeff Parsons + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + +#include +#include +#include +#include +#include "softpc.h" +#include "bop.h" +#include "xbios.h" +#include "xbioskbd.h" +#include "xwincon.h" +#include "fun.h" +#include + +extern HANDLE InputHandle; + +#define MAX_KBD_BUFFER 256 +CHAR KbdBuffer[MAX_KBD_BUFFER]; +ULONG Head=0,Tail=0; +HANDLE KbdSyncEvent; +CRITICAL_SECTION csKbd; +CRITICAL_SECTION csConsole; +CRITICAL_SECTION csCtrlc; +BOOL fEventThreadBlock = FALSE; +HANDLE hConsoleWait; +ULONG nCtrlc=0; + +HANDLE StdIn; + +static BYTE ServiceRoutine[] = { 0xC4, 0xC4, BOP_KBD, 0x50, 0x55, 0x8B, + 0xEC, 0x9C, 0x58, 0x89, 0x46, 0x08, 0x5d, 0x58, 0xCF }; +#define SERVICE_LENGTH sizeof(ServiceRoutine) + +/* BiosKbdInit - Initialize ROM BIOS keyboard support + * + * ENTRY + * argc - # of command-line options + * argv - pointer to first option pointer + * ServiceAddress - linear address to put service routine at + * + * EXIT + * TRUE if successful, FALSE if not + */ + +BOOL BiosKbdInit(int argc, char *argv[], PVOID *ServiceAddress) +{ + PVOID Address; + + argc, argv; + + memcpy(*ServiceAddress, ServiceRoutine, SERVICE_LENGTH); + + Address = (PVOID)(BIOSINT_KBD * 4); + *((PWORD)Address) = RMOFF(*ServiceAddress); + *(((PWORD)Address) + 1) = RMSEG(*ServiceAddress); + (PCHAR)*ServiceAddress += SERVICE_LENGTH; + + StdIn = GetStdHandle(STD_INPUT_HANDLE); + + KbdSyncEvent = CreateEvent( NULL, TRUE, FALSE,NULL ); + + InitializeCriticalSection (&csKbd); + InitializeCriticalSection(&csConsole); + InitializeCriticalSection(&csCtrlc); + + hConsoleWait = CreateEvent (NULL,TRUE,FALSE,NULL); + + return TRUE; +} + + +/* BiosKbd - Emulate ROM BIOS keyboard functions + * + * ENTRY + * None (x86 registers contain parameters) + * + * EXIT + * None (x86 registers/memory updated appropriately) + * + * This function receives control on INT 16h, routes control to the + * appropriate subfunction based on the function # in AH, and + * then simulates an IRET and returns back to the instruction emulator. + */ + +VOID BiosKbdReadLoop (VOID) +{ +ULONG Temp; + + while (1) { + + Temp = Head + 1; + if(Temp >= MAX_KBD_BUFFER) + Temp =0; + if(Temp == Tail){ + Sleep (20); + continue; + } + + KbdBuffer[Head] = getche(); + + EnterCriticalSection(&csConsole); + if(fEventThreadBlock == TRUE){ + LeaveCriticalSection(&csConsole); + WaitForSingleObject(hConsoleWait,-1); + ResetEvent(hConsoleWait); + continue; + } + else{ + LeaveCriticalSection(&csConsole); + } + + EnterCriticalSection(&csKbd); + Head = Temp; + LeaveCriticalSection(&csKbd); + SetEvent(KbdSyncEvent); + } +} + +BOOL tkbhit(VOID) +{ + + if (Tail != Head || nCtrlc) + return TRUE; + return FALSE; +} + + +CHAR tgetch(VOID) +{ +CHAR ch; + + while(TRUE) { + EnterCriticalSection(&csCtrlc); + if (nCtrlc){ + nCtrlc--; + LeaveCriticalSection(&csCtrlc); + return (CHAR)0x3; // return ctrlc + } + LeaveCriticalSection(&csCtrlc); + + if (Tail != Head) { + EnterCriticalSection(&csKbd); + ch = KbdBuffer[Tail++]; + if (Tail >= MAX_KBD_BUFFER) + Tail = 0; + LeaveCriticalSection(&csKbd); + return ch; + } + WaitForSingleObject(KbdSyncEvent, -1); + ResetEvent(KbdSyncEvent); + } +} + + + + +VOID BiosKbd() +{ + static ULONG ulch; + DWORD nRead=0; + + switch(getAH()) { + + case KBDFUNC_READCHAR: + if (ulch) { + setAL(ulch & 0xff); + setAH(ulch & 0xFF00); + ulch = 0; + } + else { + setAH(0); // zero scan code field for now + setAL((BYTE)tgetch()); + if (getAL() == 0 || getAL() == 0xE0) { + setAL(0); + setAH((BYTE)tgetch()); + } + } + break; + + case KBDFUNC_PEEKCHAR: + setZF(1); + if (ulch) { + setAL(ulch & 0xFF); + setAH(ulch & 0xFF00); + setZF(0); + } + else if(tkbhit()) { + setAH(0); // zero scan code field for now + setAL((BYTE)tgetch()); + if (getAL() == 0 || getAL() == 0xE0) { + setAL(0); + setAH((BYTE)tgetch()); + } + ulch = getAL() | getAH()<<8 | 0x10000; + setZF(0); + } + break; + } +} + + +void nt_block_event_thread(void) +{ + INPUT_RECORD InputRecord; + DWORD nRecordsWritten; + + InputRecord.EventType = 1; + InputRecord.Event.KeyEvent.bKeyDown = 1; + InputRecord.Event.KeyEvent.wRepeatCount = 1; + InputRecord.Event.KeyEvent.wVirtualKeyCode = 32; + InputRecord.Event.KeyEvent.wVirtualScanCode = 41; + InputRecord.Event.KeyEvent.uChar.AsciiChar = ' '; + InputRecord.Event.KeyEvent.dwControlKeyState = 32; + EnterCriticalSection(&csConsole); + WriteConsoleInput(InputHandle,&InputRecord,1,&nRecordsWritten); + InputRecord.EventType = 1; + InputRecord.Event.KeyEvent.bKeyDown = 0; + InputRecord.Event.KeyEvent.wRepeatCount = 1; + InputRecord.Event.KeyEvent.wVirtualKeyCode = 32; + InputRecord.Event.KeyEvent.wVirtualScanCode = 41; + InputRecord.Event.KeyEvent.uChar.AsciiChar = ' '; + InputRecord.Event.KeyEvent.dwControlKeyState = 32; + WriteConsoleInput(InputHandle,&InputRecord,1,&nRecordsWritten); + fEventThreadBlock = TRUE; + LeaveCriticalSection(&csConsole); + return; + +} + +void nt_resume_event_thread(void) +{ + fEventThreadBlock = FALSE; + SetEvent (hConsoleWait); + return; +} + +// TEMP Till we have proper multitasking in WOW +extern BOOL VDMForWOW; +extern ULONG iWOWTaskId; + + +VOID VDMCtrlCHandler(ULONG ulCtrlType) +{ +// DebugBreak(); + if(ulCtrlType == SYSTEM_ROOT_CONSOLE_EVENT) { + if(VDMForWOW) + // Kill everything for WOW VDM + ExitVDM(VDMForWOW,(ULONG)-1); + else + ExitVDM(FALSE,0); + ExitProcess(0); + return; + } + EnterCriticalSection(&csCtrlc); + nCtrlc++; + LeaveCriticalSection(&csCtrlc); + SetEvent(KbdSyncEvent); +} diff --git a/private/mvdm/v86/scaffold/i386/fakevid.c b/private/mvdm/v86/scaffold/i386/fakevid.c new file mode 100644 index 000000000..450737c80 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/fakevid.c @@ -0,0 +1,175 @@ + +// +// Fake video rom support +// +// This file provides interrim support for video rom bios services. +// It is only intended for use until Insignia produces proper rom support +// for NTVDM +// +// Note: portions of this code were lifted from the following source. + + +/* x86 v1.0 + * + * XBIOSVID.C + * Guest ROM BIOS video emulation + * + * History + * Created 20-Oct-90 by Jeff Parsons + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + +#include +#include +#include +#include +#include "softpc.h" +#include "bop.h" +#include "xbios.h" +#include "xbiosvid.h" +#include "xwincon.h" +#include "fun.h" +#include "cmdsvc.h" + +static BYTE ServiceRoutine[] = { 0xC4, 0xC4, BOP_VIDEO, 0x50, 0x55, 0x8B, + 0xEC, 0x9C, 0x58, 0x89, 0x46, 0x08, 0x5d, 0x58, 0xCF }; +#define SERVICE_LENGTH sizeof(ServiceRoutine) + +extern HANDLE OutputHandle; +extern HANDLE InputHandle; + +/* BiosVidInit - Initialize ROM BIOS video support + * + * ENTRY + * argc - # of command-line options + * argv - pointer to first option pointer + * ServicAddress - pointer to linear address to put interrupt service + * routine at + * + * EXIT + * TRUE if successful, FALSE if not + */ + +BOOL BiosVidInit(int argc, char *argv[], PVOID *ServiceAddress) +{ + USHORT usEquip; + + static BYTE abVidInit[] = {VIDMODE_MONO, // VIDDATA_CRT_MODE + 0x80, 0, // VIDDATA_CRT_COLS + 00, 0x10, // VIDDATA_CRT_LEN + 0, 0, // VIDDATA_CRT_START + 0,0,0,0,0,0,0,0, // VIDDATA_CURSOR_POSN + 0,0,0,0,0,0,0,0, // + 7, 6, // VIDDATA_CURSOR_MODE + 0, // VIDDATA_ACTIVE_PAGE + 0xD4, 0x03, // VIDDATA_ADDR_6845 + 0, // VIDDATA_CRT_MODE_SET + 0, // VIDDATA_CRT_PALETTE + }; + PVOID Address; + + argv, argc; + memcpy(*ServiceAddress, ServiceRoutine, SERVICE_LENGTH); + + Address = (PVOID)(BIOSINT_VID * 4); + *((PWORD)Address) = RMOFF(*ServiceAddress); + *(((PWORD)Address) + 1) = RMSEG(*ServiceAddress); + (PCHAR)*ServiceAddress += SERVICE_LENGTH; + + usEquip = *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG); + usEquip |= BIOSEQUIP_MONOVIDEO; + *(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, BIOSDATA_EQUIP_FLAG) = usEquip; + + // Initialize ROM BIOS video data to defaults + Address = RMSEGOFFTOLIN(BIOSDATA_SEG, VIDDATA_CRT_MODE); + memcpy(Address, abVidInit, sizeof(abVidInit)); + +#if 0 +#ifdef WIN + clearconsole(hwndGuest); +#endif +#endif + return TRUE; +} + + +/* BiosVid - Emulate ROM BIOS video functions + * + * ENTRY + * None (x86 registers contain parameters) + * + * EXIT + * None (x86 registers/memory updated appropriately) + * + * This function receives control on INT 10h, routes control to the + * appropriate subfunction based on the function # in AH, and + * then simulates an IRET and returns back to the instruction emulator. + */ + +VOID BiosVid() +{ +COORD coord; +CHAR ch; + + if (fEnableInt10 == FALSE) + return; + + switch(getAH()) { + case VIDFUNC_SETCURSORPOS: + coord.X = getDL(); + coord.Y = getDH(); + if(SetConsoleCursorPosition(OutputHandle, coord) == FALSE) + VDprint( + VDP_LEVEL_WARNING, + ("SetCursorPosition Failed X=%d Y=%d\n", + coord.X,coord.Y) + ); + break; + case VIDFUNC_QUERYCURSORPOS: + VDprint( + VDP_LEVEL_WARNING, + ("Query Cursor Position Not Yet Implemented\n") + ); + break; + case VIDFUNC_SCROLLUP: + VDprint( + VDP_LEVEL_WARNING, + ("ScrollUp Not Yet Implemented\n") + ); + break; + case VIDFUNC_WRITECHARATTR: + VDprint( + VDP_LEVEL_WARNING, + ("WRITECHARATTR Not Yet Implemented\n") + ); + break; + case VIDFUNC_WRITETTY: + ch = getAL(); + putch(ch); + break; + + case VIDFUNC_QUERYMODE: + setAX(*(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, VIDDATA_CRT_MODE)); + setBX(*(PWORD)RMSEGOFFTOLIN(BIOSDATA_SEG, VIDDATA_ACTIVE_PAGE)); + break; + + default: + VDprint( + VDP_LEVEL_WARNING, + ("SoftPC Video Support: Unimplemented function %x\n", + getAX()) + ); + } +} + + +INT tputch(INT i) +{ + putch((CHAR)i); + return i; +} diff --git a/private/mvdm/v86/scaffold/i386/fun.h b/private/mvdm/v86/scaffold/i386/fun.h new file mode 100644 index 000000000..d83a72a0c --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/fun.h @@ -0,0 +1,24 @@ +// +// function definitions for scaffolding code +// + +VOID BiosInit(int argc, char *argv[]); +BOOL WinInit(); +VOID DbgPrint(); +VOID DbgBreakPoint(); +BOOL W32Init(); +VOID main(); +VOID exit(); +BOOL BiosKbdInit(int argc, char *argv[], PVOID *ServiceAddress); +BOOL BiosDskInit(int argc, char *argv[], PVOID *ServiceAddress); +BOOL BiosVidInit(int argc, char *argv[], PVOID *ServiceAddress); +VOID W32Dispatch(); +VOID XMSDispatch(); +VOID BiosVid(); +VOID BiosKbd(); +VOID BiosDsk(); +VOID BiosKbdReadLoop (VOID); +BOOL tkbhit(VOID); +CHAR tgetch(VOID); +INT tputch(INT); +VOID FixConfigFile (PSZ,BOOL); diff --git a/private/mvdm/v86/scaffold/i386/softpc.c b/private/mvdm/v86/scaffold/i386/softpc.c new file mode 100644 index 000000000..b97ee53a9 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/softpc.c @@ -0,0 +1,442 @@ +#include +#include +#include +#include +#include +#include +#include "demexp.h" +#include "softpc.h" +#include +#include +#include +#include "xwincon.h" +#include "fun.h" +#include + +#define VDM_VIRTUAL_INTERRUPTS 0x00000200L +extern CONTEXT IntelRegisters; + +VOID DumpIntelRegs(); +VOID ParseSwitches( int, char**); +VOID usage(); +BOOL ConInit (VOID); +extern VOID VDMCtrlCHandler(ULONG); + +INT flOptions; + +HANDLE OutputHandle; +HANDLE InputHandle; +HANDLE SCSCreateEvent; +char *EmDirectory; +BOOL scaffMin = FALSE; +BOOL scaffWow = FALSE; +BOOL VDMForWOW = FALSE; +CHAR BootLetter; + + +void main (argc, argv) +int argc; +char *argv[]; +{ + + PSZ psz,pszNULL; + HANDLE hfile; + DWORD BytesRead; + int i; + PCHAR FileAddress; + BOOL IsFirst; + int temp_argc = argc; + char **temp_argv = argv; + +// DebugBreak(); + + if(SetConsoleCtrlHandler((PHANDLER_ROUTINE)VDMCtrlCHandler,TRUE) + == FALSE) { + VDprint( + VDP_LEVEL_INFO, + ("CtrlC Handler Could'nt be installed\n") + ); + } + + // Tell the console that we want the last event (i.e when the + // window is just to be destroyed. + SetLastConsoleEventActive(); + + // Check if the VDM Is for WOW + while (--temp_argc > 0) { + psz = *++temp_argv; + if (*psz == '-' || *psz == '/') { + psz++; + if(tolower(*psz) == 'w'){ + VDMForWOW = TRUE; + break; + } + } + } + + // This following API is required for recovery purposes. This + // tells the basesrv that VDM has hooked ctrlc event. After + // this it will always get the termination notification. If + // the window is killed before we hook ctrl-c then basesrv + // will know that data structures for this VDM has to be + // freed. This should be the first call to base.dll. + + VDMOperationStarted (VDMForWOW); + + EmDirectory = NULL; + + // Hide the cmd window of WOWVDM + if(VDMForWOW) + VDMConsoleOperation((DWORD)VDM_HIDE_WINDOW); + + ParseSwitches( argc, argv ); + + IsFirst = GetNextVDMCommand(NULL); + + for (i = 0; i < argc; i++) { + VDprint( + VDP_LEVEL_INFO, + ("%s\n", argv[i]) + ); + } + + VDbreak(VDB_LEVEL_INFO); + + if (EmDirectory == NULL) { + usage(); + TerminateVDM(); + } + + // Sudeepb 26-Dec-1991 Temporary code to make + // the life easy for WOW's internal users such that they dont have + // to change the config.sys as per their setup. + + FixConfigFile (EmDirectory,IsFirst); + + pszNULL = strchr(EmDirectory,'\0'); + psz = EmDirectory; + while(*psz == ' ' || *psz == '\t') + psz++; + + BootLetter = *psz; + + host_cpu_init(); + sas_init(1024L * 1024L + 64L * 1024L); + + // Initialize ROM support + + BiosInit(argc, argv); + + // Initialize console support + + if (!ConInit()) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing console\n") + ); + TerminateVDM(); + } + + // Initialize WOW + + + CMDInit (argc,argv); + + // Initialize DOSEm + + if(!DemInit (argc,argv,EmDirectory)) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing DOSEm\n") + ); + TerminateVDM(); + } + + // Initialize XMS + + if(!XMSInit (argc,argv)) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing XMS\n") + ); + TerminateVDM(); + } + + // Initialize DBG + + if(!DBGInit (argc,argv)) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: error initializing DBG\n") + ); + TerminateVDM(); + } + + // Prepare to load ntio.sys + strcat (EmDirectory,"\\ntio.sys"); + hfile = CreateFile(EmDirectory, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + + if (hfile == (HANDLE)0xffffffff) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: could not open file %s. Error %d\n", + EmDirectory, + GetLastError()) + ); + TerminateVDM(); + } + + FileAddress = (PCHAR)0x700; + BytesRead = 1; + while (BytesRead) { + if (!ReadFile(hfile, FileAddress, 16384, &BytesRead, NULL)) { + VDprint( + VDP_LEVEL_ERROR, + ("SoftPC: read failure on file %s. Error %d\n", + EmDirectory, + GetLastError()) + ); + TerminateVDM(); + } + + VDprint(VDP_LEVEL_INFO, + ("SoftPC: read a block of file %s\n", + EmDirectory) + ); + FileAddress = (PCHAR)FileAddress + BytesRead; + } + + VDprint(VDP_LEVEL_WARNING, + ("SoftPC: using Emulation file %s\n", + EmDirectory) + ); + + VDbreak(VDB_LEVEL_INFO); + + CloseHandle (hfile); + + // restore the emulation directory + *pszNULL = 0; + + + IntelRegisters.Eip = 0x0; + IntelRegisters.SegCs = 0x70; + IntelRegisters.EFlags = VDM_VIRTUAL_INTERRUPTS; + + host_simulate(); + + if (IntelRegisters.EFlags & VDM_VIRTUAL_INTERRUPTS) { + VDprint(VDP_LEVEL_INFO, ("Virtual ints enabled\n")); + } else { + VDprint(VDP_LEVEL_INFO, ("Virtual ints disabled\n")); + } + + DumpIntelRegs(); +} + +#define MAX_CONFIG_SIZE 1024 + +VOID FixConfigFile (pszBin86Dir,IsFirstVDM) +PSZ pszBin86Dir; +BOOL IsFirstVDM; +{ + + // Temporary code. To be thrown out once we have full configuration + // and installation. + +CHAR ConfigFile[]="?:\\config.vdm"; +CHAR Buffer [MAX_CONFIG_SIZE]; +DWORD len,i; +DWORD BytesRead,BytesWritten; +HANDLE hfile; + + if (IsFirstVDM == FALSE) + return; + + ConfigFile[0] = *pszBin86Dir; + hfile = CreateFile( ConfigFile, + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + if (hfile == (HANDLE)0xffffffff) { + DbgPrint ("config.vdm is'nt found on the root drive of yout NT trre\n"); + return; + } + + + if (!ReadFile(hfile, Buffer, MAX_CONFIG_SIZE, &BytesRead, NULL)){ + DbgPrint ("config.vdm could'nt be read\n, %x\n",GetLastError ()); + CloseHandle (hfile); + return; + } + + if (BytesRead == MAX_CONFIG_SIZE) { + DbgPrint ("config.vdm is too big, could'nt perform macro substitution\n"); + CloseHandle (hfile); + return; + } + + SetFilePointer (hfile, + 0, + NULL, + FILE_BEGIN); + + len = strlen (pszBin86Dir); + + for (i=0; i < BytesRead; i++) { + if (Buffer [i] != '@'){ + WriteFile (hfile, + &Buffer[i], + 1, + &BytesWritten, + NULL); + } + else { + WriteFile (hfile, + pszBin86Dir, + len, + &BytesWritten, + NULL); + } + } + + CloseHandle (hfile); + return; +} + +VOID DumpIntelRegs() +{ + + VDprint(VDP_LEVEL_ERROR,("EAX = %lx\n",IntelRegisters.Eax)); + VDprint(VDP_LEVEL_ERROR,("Ebx = %lx\n",IntelRegisters.Ebx)); + VDprint(VDP_LEVEL_ERROR,("Ecx = %lx\n",IntelRegisters.Ecx)); + VDprint(VDP_LEVEL_ERROR,("Edx = %lx\n",IntelRegisters.Edx)); + VDprint(VDP_LEVEL_ERROR,("Esi = %lx\n",IntelRegisters.Esi)); + VDprint(VDP_LEVEL_ERROR,("Edi = %lx\n",IntelRegisters.Edi)); + VDprint(VDP_LEVEL_ERROR,("Ebp = %lx\n",IntelRegisters.Ebp)); + VDprint(VDP_LEVEL_ERROR,("SegDs = %lx\n",IntelRegisters.SegDs)); + VDprint(VDP_LEVEL_ERROR,("SegEs = %lx\n",IntelRegisters.SegEs)); + VDprint(VDP_LEVEL_ERROR,("SegFs = %lx\n",IntelRegisters.SegFs)); + VDprint(VDP_LEVEL_ERROR,("SegGs = %lx\n",IntelRegisters.SegGs)); + VDprint(VDP_LEVEL_ERROR,("EFlags = %lx\n",IntelRegisters.EFlags)); + VDprint(VDP_LEVEL_ERROR,("SS:Esp = %lx:",IntelRegisters.SegSs)); + VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Esp)); + VDprint(VDP_LEVEL_ERROR,("CS:Eip = %lx:",IntelRegisters.SegCs)); + VDprint(VDP_LEVEL_ERROR,("%lx\n",IntelRegisters.Eip)); +} + +VOID ParseSwitches( + int argc, + char **argv + ) +{ + int i; + + for (i = 1; i < argc; i++){ + if ((argv[i][0] == '-') || (argv[i][0] == '/')) { + + switch (argv[i][1]) { + + case 's' : + case 'S' : + sscanf(&argv[i][2], "%x", &VdmDebugLevel); + VDprint( + VDP_LEVEL_WARNING, + ("VdmDebugLevel = %x\n", + VdmDebugLevel) + ); + break; + + case 'f' : + case 'F' : + // Note this memory is freed by DEM. + if((EmDirectory = (PCHAR)malloc (strlen (&argv[i][2]) + + 1 + + sizeof("\\ntdos.sys") + + 1 + )) == NULL){ + DbgPrint("SoftPC: Not Enough Memory \n"); + TerminateVDM(); + } + strcpy(EmDirectory,&argv[i][2]); + break; + + case 't' : + case 'T' : + flOptions |= OPT_TERMINAL; + break; + case 'm' : + case 'M' : + scaffMin = TRUE; + break; + case 'w' : + case 'W' : + scaffWow = TRUE; + } + } else { + break; + } + } +} + +VOID usage() +{ + DbgPrint("SoftPC Usage: softpc -F [-D#] [:=] [dos command line]\n"); +} + + +VOID TerminateVDM(void) +{ + + if(VDMForWOW) + // Kill everything for WOW VDM + ExitVDM(VDMForWOW,(ULONG)-1); + else + ExitVDM(FALSE,0); + ExitProcess (0); +} + + +DWORD SCSConsoleThread(LPVOID lp) +{ + + + SetEvent(SCSCreateEvent); + BiosKbdReadLoop(); + return TRUE; +} + + +BOOL ConInit (VOID) +{ + DWORD SCSThreadId; + HANDLE InputThread; + OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE); + InputHandle = GetStdHandle(STD_INPUT_HANDLE); + + SCSCreateEvent = CreateEvent( NULL, TRUE, FALSE,NULL ); + + InputThread = CreateThread( + (LPSECURITY_ATTRIBUTES)0, + 8192, + (LPTHREAD_START_ROUTINE)SCSConsoleThread, + (LPVOID)0, + STANDARD_RIGHTS_REQUIRED, + &SCSThreadId + ); + + WaitForSingleObject(SCSCreateEvent, -1); + + CloseHandle(SCSCreateEvent); + + return TRUE; +} diff --git a/private/mvdm/v86/scaffold/i386/sources b/private/mvdm/v86/scaffold/i386/sources new file mode 100644 index 000000000..af03d8fa3 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/sources @@ -0,0 +1,6 @@ +i386_SOURCES=i386\softpc.c \ + i386\fakeinit.c \ + i386\fakekbd.c \ + i386\fakevid.c \ + i386\fakebop.c \ + i386\stubs.c diff --git a/private/mvdm/v86/scaffold/i386/stubs.c b/private/mvdm/v86/scaffold/i386/stubs.c new file mode 100644 index 000000000..4ba53b52e --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/stubs.c @@ -0,0 +1,46 @@ +void check_I(){ +} + +void copyROM(){ +} + +void generic_insb(){ +} +void generic_insw(){ +} +void generic_outsb(){ +} +void generic_outsw(){ +} + +void host_timer_event(){ +} +int ica_intack(){ + return 7; +} +void inb(){ +} +void inw(){ +} +void outb(){ +} +void outw(){ +} +unsigned long *read_pointers; + +void rom_checksum(){ +} + +void rom_init(){ +} + + +host_simulate(){ + cpu_simulate(); +} + +host_cpu_init(){ + cpu_init(); +} + +void (*ica_hw_interrupt_func)() = rom_init; diff --git a/private/mvdm/v86/scaffold/i386/x86.h b/private/mvdm/v86/scaffold/i386/x86.h new file mode 100644 index 000000000..eb4772e82 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/x86.h @@ -0,0 +1,418 @@ +// +// This is temporary code, and should be removed when Insignia supplies rom +// support +// + +/* x86 v1.0 + * + * X86.H + * Constants, macros, and common types + * for the x86 emulator and related components + * + * History + * Created 19-Oct-90 by Jeff Parsons + * 17-Apr-91 by Dave Hastings trimmed for use in softpc (temprorary) + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + +#ifdef DOS +#define SIGNALS +#endif + +#ifdef OS2_16 +#define OS2 +#define SIGNALS +#endif + +#ifdef OS2_32 +#define OS2 +#define FLAT_32 +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef WIN_16 +#define WIN +#define API16 +#endif + +#ifdef WIN_32 +#ifndef WIN +#define WIN +#endif +#define FLAT_32 +#define TRUE_IF_WIN32 1 +#define FIXHWND(h) ((HWND)((INT)(h) & 0x00ffffff)) +#include +#include +#include +#else +#define TRUE_IF_WIN32 0 +#define FIXHWND(h) (h) +#endif + +#ifdef FLAT_32 +#ifndef i386 +#define ALIGN_32 +#else +#define NOALIGN_32 +#endif +#endif + +#ifdef WIN +#define _WINDOWS +#include +#endif + +#ifdef SIGNALS +#include +#include +#endif + +#ifdef OS2_32 +#include +#define XCPT_SIGNAL 0xC0010003 +#endif +#define SIGHIT(flChk) ((iSigCheck++ & 0x7FF)?(flSignals & (flChk)):(kbhit(),(flSignals & (flChk)))) + +#ifndef CONST +#define CONST const +#endif +#ifndef CDECL +#define CDECL _cdecl +#endif +#ifndef PASCAL +#define PASCAL +#endif + +#ifdef FLAT_32 +#ifndef WIN +#define FAR +#endif +#define HUGE +#define HALLOC(n,s) malloc((n)*(s)) +#define HLOCK(h) h +#define HUNLOCK(h) 0 +#define HFREE(h) free(h) +#else +#ifndef WIN +#define FAR _far +#define HUGE _huge +#define HALLOC(n,s) halloc(n,s) +#define HLOCK(h) h +#define HUNLOCK(h) 0 +#define HFREE(h) hfree(h) +#else +#define HUGE _huge +#define HALLOC(n,s) GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,(n)*(s)) +#define HLOCK(h) (HPVOID)GlobalLock(h) +#define HUNLOCK(h) GlobalUnlock(h) +#define HFREE(h) GlobalFree(h) +#endif +#endif + +#define BYTEOF(i,n) (((PBYTE)&(i))[n]) +#define LOB(i) BYTEOF(i,0) +#define HIB(i) BYTEOF(i,1) +#define WORDOF(i,n) (((PWORD)&(i))[n]) +#define LOW(l) WORDOF(l,0) +#define HIW(l) WORDOF(l,1) +#define INTOF(i,n) (((PINT)&(i))[n]) +#define UINTOF(i,n) (((PUINT)&(i))[n]) +#ifndef WIN +#define LOWORD(l) ((WORD)(l)) +#define HIWORD(l) ((WORD)(((DWORD)(l) >> 16) & 0xFFFF)) +#define LOBYTE(w) ((BYTE)(w)) +#define HIBYTE(w) ((BYTE)(((WORD)(w) >> 8) & 0xFF)) +#endif +#ifndef MAKEWORD +#define MAKEWORD(l,h) ((WORD)((BYTE)(l)|((BYTE)(h)<<8))) +#endif +#define MAKEDWORD(l0,h0,l1,h1) ((DWORD)MAKEWORD(l0,h0)|((DWORD)MAKEWORD(l1,h1)<<16)) +#define GETBYTE(p) *((PBYTE)p)++ +#define GETBYTEPTR(p) ((PBYTE)p)++ +#define GETWORDPTR(pb) ((PWORD)pb)++ +#define GETDWORDPTR(pb) ((PDWORD)pb)++ +#ifndef ALIGN_32 +#define GETWORD(pb) (*((PWORD)pb)++) +#define GETDWORD(pb) (*((PDWORD)pb)++) +#define FETCHWORD(s) ((WORD)(s)) +#define FETCHDWORD(s) ((DWORD)(s)) +#define STOREWORD(d,s) (WORD)d=(WORD)s +#define STOREDWORD(d,s) (DWORD)d=(DWORD)s +#else +#define GETWORD(pb) (pb+=2,MAKEWORD(*(pb-2),*(pb-1))) +#define GETDWORD(pb) (pb+=4,MAKEDWORD(*(pb-4),*(pb-3),*(pb-2),*(pb-1))) +#define FETCHWORD(s) MAKEWORD(LOB(s),HIB(s)) +#define FETCHDWORD(s) MAKEDWORD(BYTEOF(s,0),BYTEOF(s,1),BYTEOF(s,2),BYTEOF(s,3)) +#define STOREWORD(d,s) {BYTEOF(d,0)=LOBYTE(s);BYTEOF(d,1)=HIBYTE(s);} +#define STOREDWORD(d,s) {BYTEOF(d,0)=LOBYTE(LOWORD(s));BYTEOF(d,1)=HIBYTE(LOWORD(s));BYTEOF(d,2)=LOBYTE(HIWORD(s));BYTEOF(d,3)=HIBYTE(HIWORD(s));} +#endif +#define SWAP(x,y) {INT t; t=y; y=x; x=t;} +#define SWAPS(x,y) {SHORT t; t=y; y=x; x=t;} +#define SWAPL(x,y) {LONG t; t=y; y=x; x=t;} +#define SWAPBYTE(x,y) {BYTE t; t=y; y=x; x=t;} +#define SWAPWORD(x,y) {WORD t; t=FETCHWORD(y); STOREWORD(y,FETCHWORD(x)); STOREWORD(x,t);} +#define SWAPDWORD(x,y) {DWORD t; t=FETCHDWORD(y); STOREDWORD(y,FETCHDWORD(x)); STOREDWORD(x,t);} +#define NUMEL(a) ((sizeof a)/(sizeof a[0])) + +#define SXBYTE(i) ((LONG)(SBYTE)(i)) +#define SXWORD(i) ((LONG)(SHORT)(i)) +#define SXSHORT(i) ((LONG)(SHORT)(i)) +#define ZXBYTE(i) ((ULONG)(BYTE)(i)) +#define ZXWORD(i) ((ULONG)(USHORT)(i)) +#define ZXSHORT(i) ((ULONG)(USHORT)(i)) + +#define _Z2(m) ((m)&1?0:(m)&2?1:2) +#define _Z4(m) ((m)&3?_Z2(m):_Z2((m)>>2)+2) +#define _Z8(m) ((m)&15?_Z4(m):_Z4((m)>>4)+4) +#define _Z16(m) ((m)&255?_Z8(m):_Z8((m)>>8)+8) +#define _Z32(m) ((m)&65535?_Z16(m):_Z16((m)>>16)+16) +#define SHIFTLEFT(i,m) (((i)<<_Z32(m))&(m)) +#define SHIFTRIGHT(i,m) (((i)&(m))>>_Z32(m)) + +#define OFFSETOF(t,f) ((INT)&(((t *)0)->f)) + + +/* Universal constants + */ +#define K 1024L +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif +#define UNDEFINED -1 + +#define CTRL_A 1 // used by gets to repeat last line +#define CTRL_C 3 // break in debug window +#define CTRL_Q 17 // flow control +#define CTRL_S 19 // flow control +#define BELL 7 // +#define BS 8 // backspace +#define TAB 9 // +#define LF 10 // linefeed +#define CR 13 // return +#define ESCAPE 27 // + + +/* Program options + */ +#define OPT_FONT 0x0004 // use small OEM font if available (/s) +#define OPT_DOUBLE 0x0020 // use 50-line debug window w/small font (/50) +#define OPT_CAPS 0x0002 // map ctrl keys to caps-lock (/c) +#define OPT_TERMINAL 0x0010 // redirect all window output to terminal (/t) +#define OPT_FLUSH 0x0100 // flush prefetch after every jump (/f) +#define OPT_NOXLATE 0x0200 // disable built-in translations (/n) +#define OPT_DEBUG 0x0008 // shadow all log output on debug terminal (/d) +#define OPT_GO 0x0001 // do an initial "go" (/g) + + +/* Signal flags + */ +#define SIGNAL_BREAK 0x0001 // set whenever break has occurred +#define SIGNAL_UNWIND 0x0002 // set whenever unwind has occurred +#define SIGNAL_REBOOT 0x0004 // set whenever reboot has occurred +#define SIGNAL_RUN 0x0008 // set whenever emulator is "running" +#define SIGNAL_TRACE 0x0010 // set whenever debugger tracing +#define SIGNAL_BRKPT 0x0020 // set whenever debugger breakpoints enabled +#define SIGNAL_SSTEP 0x0040 // set whenever emulator single-step on + +#undef SIG_IGN // fix broken definition in (old) signal.h +#define SIG_IGN (VOID (CDECL *)())1 + + +/* Exec flags (for HostInput/GuestInput) + */ +#define EXEC_INPUT 0x0000 // wait for input +#define EXEC_GO 0x0001 // execute immediately +#define EXEC_FREEZE 0x0002 // execution frozen (guest only) + + +/* Standard types + */ +#ifndef WIN +typedef void VOID; +typedef unsigned char BYTE; +typedef unsigned short WORD; // confusing - use where 16-bit req. only +typedef unsigned long DWORD; // confusing - use where 32-bit req. only +typedef long LONG; // use where 32-bit req. only +typedef int BOOL; +#endif +typedef char CHAR; +typedef signed char SBYTE; +typedef short SHORT; // use where 16-bit req. only +typedef unsigned short USHORT; // use where 16-bit req. only +typedef int INT; // ints preferred +typedef unsigned int UINT; // ints preferred +typedef unsigned long ULONG; // use where 32-bit req. only + +#ifndef WIN +typedef BYTE *PBYTE; // native pointers +typedef WORD *PWORD; +typedef DWORD *PDWORD; +typedef INT *PINT; +typedef LONG *PLONG; +typedef CHAR *PSTR; +#endif +typedef PBYTE *PPBYTE; +typedef PWORD *PPWORD; +typedef PDWORD *PPDWORD; +typedef CHAR SZ[]; +typedef VOID *PVOID; +typedef CHAR *PCHAR; +typedef SHORT *PSHORT; +typedef USHORT *PUSHORT; +typedef PUSHORT *PPUSHORT; +typedef UINT *PUINT; +typedef ULONG *PULONG; +typedef PULONG *PPULONG; +typedef BOOL *PBOOL; +typedef CHAR *PSZ; +typedef PSZ *PPSZ; + +typedef VOID FAR *FPVOID; // "far" (or "long" in Windows) pointers +typedef CHAR FAR *FPCHAR; +typedef BYTE FAR *FPBYTE; +typedef SHORT FAR *FPSHORT; +typedef USHORT FAR *FPUSHORT; +typedef LONG FAR *FPLONG; +typedef ULONG FAR *FPULONG; +typedef CHAR FAR *FPSTR; +typedef CHAR FAR *FPSZ; + +typedef VOID HUGE *HPVOID; // "huge" pointers +typedef CHAR HUGE *HPCHAR; +typedef BYTE HUGE *HPBYTE; +typedef SHORT HUGE *HPSHORT; +typedef USHORT HUGE *HPUSHORT; +typedef LONG HUGE *HPLONG; +typedef ULONG HUGE *HPULONG; +typedef CHAR HUGE *HPSTR; +typedef CHAR HUGE *HPSZ; + +#ifndef WIN +typedef HPVOID HANDLE; +#endif + +#ifdef WIN +typedef INT (FAR PASCAL *INTPROC)(HWND, UINT, UINT, LONG); +#endif +#ifdef WIN_16 +typedef LONG (FAR PASCAL *WNDPROC)(HWND, WORD, UINT, LONG); +#endif + + +/* Global data + */ +extern FILE *hfLog; +extern INT flOptions; // command-line options (see OPT_*) +extern INT flSignals; // signal flags (see SIGNAL_*) +extern INT iSigCheck; // counter indicating when to make next check +extern INT iSigLevel; // counter indicating whether to take default action +extern INT iLogLevel; // logging level; 0 implies none +extern BOOL fReinit; // set once first initialization has completed + + +/* String macros + */ +#define STRSKIP(psz,sz) psz += strspn(psz, sz) +#define STRSKIPTO(psz,sz) psz += strcspn(psz, sz) +#define STRSKIPNEXT(psz,sz) psz += strspn(psz+=strcspn(psz, sz), sz) + +#define ATOI(psz) (INT)szTOul(psz, 10, -1) + + +/* Logging macros + */ +#define IFLOG(l) if (l==iLogLevel && (iLogLevel&1) || l<=iLogLevel && !(iLogLevel&1)) + +#define OPENLOG() (hfLog?hfLog:(hfLog=fopen("log", "w"))) +#define APPENDLOG() (hfLog?hfLog:(hfLog=fopen("log", "a"))) +#define CLOSELOG() if (hfLog) {fclose(hfLog); hfLog=NULL;} + +#ifdef NOLOG +#define LOG(l,args) +#else +#define LOG(l,args) IFLOG(l) logprintf args; else +#endif + + +/* Debugging macros + */ +#define MODNAME(module) static char szModule[] = __FILE__ +#define X86ERROR() terminate(ERR_ASSERT, szModule, __LINE__) + +#ifdef DEBUG + +#define STATIC +#define INT3() _asm int 3 +#define IFDEBUG(f) if (f) +#define ELSEDEBUG else +#define LOGDEBUG(l,args) LOG(l,args) +#define X86ASSERT(exp) if (!(exp)) X86ERROR() + +#else + +#define STATIC static +#define INT3() +#define IFDEBUG(f) +#define ELSEDEBUG +#define LOGDEBUG(l,args) +#define X86ASSERT(exp) + +#endif // DEBUG + + +/* Other common local include files + */ +#ifdef X86 +#include "xerr.h" +#include "xlib.h" +#endif + + +/* Windows goop + */ +#define SZ_APP "x86" +#define SZ_TITLE "x86 emulator v0.17" +#define SZ_AUTHOR "by Jeff Parsons, (C) 1991" +#define SZ_PCTITLE "x86 pc" + +#define IDM_DBBRK 100 +#define IDM_ABOUT 101 + +/* Standard color definitions + */ +#define CLR_BLACK 0x00000000 +#define CLR_RED 0x007F0000 +#define CLR_GREEN 0x00007F00 +#define CLR_BROWN 0x007F7F00 +#define CLR_BLUE 0x0000007F +#define CLR_MAGENTA 0x007F007F +#define CLR_CYAN 0x00007F7F +#define CLR_LT_GRAY 0x00BFBFBF + +#define CLR_DK_GRAY 0x007F7F7F +#define CLR_BR_RED 0x00FF0000 +#define CLR_BR_GREEN 0x0000FF00 +#define CLR_YELLOW 0x00FFFF00 +#define CLR_BR_BLUE 0x000000FF +#define CLR_BR_MAGENTA 0x00FF00FF +#define CLR_BR_CYAN 0x0000FFFF +#define CLR_WHITE 0x00FFFFFF + + +extern HANDLE hHostInstance; diff --git a/private/mvdm/v86/scaffold/i386/xbios.h b/private/mvdm/v86/scaffold/i386/xbios.h new file mode 100644 index 000000000..253f6e1e3 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/xbios.h @@ -0,0 +1,123 @@ +// +// This code is temporary. When Insignia supplies rom support, it should +// be removed. +// + +/* x86 v1.0 + * + * XBIOS.H + * Guest ROM BIOS support + * + * History + * Created 20-Oct-90 by Jeff Parsons + * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + + +/* BIOS interrupts + */ +#define BIOSINT_DIVZERO 0x00 // +#define BIOSINT_SSTEP 0x01 // +#define BIOSINT_NMI 0x02 // for parity errors, too +#define BIOSINT_BRKPT 0x03 // +#define BIOSINT_OVFL 0x04 // +#define BIOSINT_PRTSC 0x05 // +#define BIOSINT_TMRINT 0x08 // +#define BIOSINT_KBDINT 0x09 // +#define BIOSINT_COM2INT 0x0B // +#define BIOSINT_COM1INT 0x0C // +#define BIOSINT_LPT2INT 0x0D // +#define BIOSINT_FLPYINT 0x0E // +#define BIOSINT_LPT1INT 0x0F // +#define BIOSINT_VID 0x10 // +#define BIOSINT_EQUIP 0x11 // +#define BIOSINT_MEMORY 0x12 // +#define BIOSINT_DSK 0x13 // +#define BIOSINT_COM 0x14 // +#define BIOSINT_OSHOOK 0x15 // +#define BIOSINT_KBD 0x16 // +#define BIOSINT_PRT 0x17 // +#define BIOSINT_BASIC 0x18 // +#define BIOSINT_WBOOT 0x19 // +#define BIOSINT_TIME 0x1A // +#define BIOSINT_CTRLBRK 0x1B // +#define BIOSINT_TICK 0x1C // +#define BIOSINT_VIDPARMS 0x1D // +#define BIOSINT_FDSKPARMS 0x1E // +#define BIOSINT_VIDGRAPH 0x1F // +#define BIOSINT_OLDDISKIO 0x40 // +#define BIOSINT_HDSK1PARMS 0x41 // +#define BIOSINT_OLDVID 0x42 // +#define BIOSINT_EXTVIDGRAPH 0x43 // +#define BIOSINT_HDSK2PARMS 0x46 // + + +/* BIOS Data Area locations + * + * So that all low-memory references are relative to the same segment + * (ie, 0), we use 0:400 instead of 40:0 as the base address of this area. + * + * Note that as more individual BIOS modules are created (eg, xbiosvid, + * xbiosdsk, etc), many of these BIOS data definitions should be moved to the + * appropriate individual header file. + */ +#define BIOSDATA_SEG 0 + +#define BIOSDATA_BEGIN 0x400 +#define BIOSDATA_RS232_BASE 0x400 // 4 COM adapter addresses +#define BIOSDATA_PRINTER_BASE 0x408 // 4 LPT adapter addresses +#define BIOSDATA_EQUIP_FLAG 0x410 // equipment flag (1 word) + +#define BIOSEQUIP_FLOPPY 0x0001 // machine has a floppy +#define BIOSEQUIP_X87 0x0002 // X87=1 if coprocessor installed +#define BIOSEQUIP_16KPLANAR 0x0000 // +#define BIOSEQUIP_32KPLANAR 0x0004 // +#define BIOSEQUIP_48KPLANAR 0x0008 // +#define BIOSEQUIP_64KPLANAR 0x000C // +#define BIOSEQUIP_PLANARMASK 0x000C // +#define BIOSEQUIP_VIDEOMASK 0x0030 // video configuration bits +#define BIOSEQUIP_COLOR40VIDEO 0x0010 // +#define BIOSEQUIP_COLOR80VIDEO 0x0020 // +#define BIOSEQUIP_MONOVIDEO 0x0030 // +#define BIOSEQUIP_FLOPPYMASK 0x00C0 // # floppies-1 (if FLOPPY=1) +#define BIOSEQUIP_COMMASK 0x0E00 // # COM ports +#define BIOSEQUIP_PRINTERMASK 0xC000 // # LPT ports + +#define BIOSDATA_MFG_TST 0x412 // initialization flag (1 byte) +#define BIOSDATA_MEMORY_SIZE 0x413 // memory size in K bytes (1 word) +#define BIOSDATA_MFG_ERR_FLG 0x415 // mfg error codes (2 bytes) + +#define BIOSDATA_END 0x4FF + +#define BIOSDATA_BOOT 0x7C00 + + +/* BIOS ROM locations (assumed segment BIOSROM_SEG) + */ +#define BIOSROM_SEG 0xF000 + +#define BIOSROM_WBOOT 0xE6F2 +#define BIOSROM_DSK 0xEC59 +#define BIOSROM_MEMORY 0xF841 +#define BIOSROM_EQUIP 0xF84D +#define BIOSROM_IRET 0xFF53 // 1 byte IRET +#define BIOSROM_RESET 0xFFF0 // 5 byte jmp +#define BIOSROM_DATE 0xFFF5 // 8 byte date (eg, 04/24/81) +#define BIOSROM_UNUSED1 0xFFFD +#define BIOSROM_SIG 0xFFFE // PC ID byte +#define BIOSROM_GBP 0xFFFF // location of GBP opcode (non-standard) + +#define BIOSSIG_PC 0xFF +#define BIOSSIG_XT 0xFE +#define BIOSSIG_JR 0xFD +#define BIOSSIG_AT 0xFC // and many more... + +#define BIOSDATE_MINE '0','4','/','1','7','/','9','1' + + diff --git a/private/mvdm/v86/scaffold/i386/xbiosdsk.h b/private/mvdm/v86/scaffold/i386/xbiosdsk.h new file mode 100644 index 000000000..ecfa6540b --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/xbiosdsk.h @@ -0,0 +1,244 @@ +// +// This code is temporary. When Insignia supplies rom support, it should +// be removed. +// + +/* x86 v1.0 + * + * XBIOSDSK.H + * Guest ROM BIOS disk emulation + * + * History + * Created 20-Oct-90 by Jeff Parsons + * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + + +#define MAX_FD 2 // # supported floppy drives +#define MAX_HD 2 // # supported hard disk drives +#define MAX_DRIVES (MAX_FD+MAX_HD) + +#define DRIVE_FD0 0x00 // first floppy disk drive # +#define DRIVE_FD1 0x01 // +#define DRIVE_HD0 0x80 // first hard disk drive # +#define DRIVE_HD1 0x81 // + + +/* Drive types for QUERYDRVPARMS + */ +#define DRVTYPE_360KB 1 +#define DRVTYPE_1200KB 2 +#define DRVTYPE_720KB 3 +#define DRVTYPE_1440KB 4 + + +/* BIOS disk functions + */ +#define DSKFUNC_DISKRESET 0x00 +#define DSKFUNC_DISKSTATUS 0x01 +#define DSKFUNC_READSECTORS 0x02 +#define DSKFUNC_WRITESECTORS 0x03 +#define DSKFUNC_VERIFYSECTORS 0x04 +#define DSKFUNC_FORMATTRACK 0x05 +#define DSKFUNC_QUERYDRVPARMS 0x08 +#define DSKFUNC_QUERYDASDTYPE 0x15 +#define DSKFUNC_QUERYCHANGE 0x16 +#define DSKFUNC_SETDISKTYPE 0x17 +#define DSKFUNC_SETMEDIATYPE 0x18 + + +/* BIOS disk status codes + */ +#define DSKSTAT_SUCCESS 0x00 // successful completion +#define DSKSTAT_BADCMD 0x01 // bad command +#define DSKSTAT_BADADDRMARK 0x02 // address mark not found +#define DSKSTAT_WRITEPROTECT 0x03 // write on write-protected disk +#define DSKSTAT_RECNOTFOUND 0x04 // sector not found +#define DSKSTAT_BADRESET 0x05 // reset failed (HD) +#define DSKSTAT_MEDIACHANGE 0x06 // media changed +#define DSKSTAT_INITFAIL 0x07 // parm. act. failed (HD) +#define DSKSTAT_BADDMA 0x08 // DMA overrun +#define DSKSTAT_DMABOUNDARY 0x09 // DMA across 64K boundary +#define DSKSTAT_BADSECTOR 0x0A // bad sector detected (HD) +#define DSKSTAT_BADTRACK 0x0B // bad track detected (HD) +#define DSKSTAT_BADMEDIATYPE 0x0C // unsupported track (HD) +#define DSKSTAT_BADFMTSECNUM 0x0D // bad # of sectors on format (HD) +#define DSKSTAT_ADDRMARKDET 0x0E // ctrl data addr mark detected (HD +#define DSKSTAT_DMAARBERR 0x0F // DMA arbitration error (HD) +#define DSKSTAT_BADCRCECC 0x10 // bad CRC/ECC +#define DSKSTAT_DATACORRECT 0x11 // data ECC corrected +#define DSKSTAT_BADCNTLR 0x20 // controller failure +#define DSKSTAT_BADSEEK 0x40 // seek failed +#define DSKSTAT_TIMEOUT 0x80 // time out +#define DSKSTAT_DRVNOTREADY 0xAA // drive not ready (HD) +#define DSKSTAT_UNDEFERR 0xBB // undefined error (HD) +#define DSKSTAT_WRITEFAULT 0xCC // write fault (HD) +#define DSKSTAT_STATUSERROR 0xE0 // status register error (HD) +#define DSKSTAT_SENSEFAIL 0xFF // sense operation failed (HD) + + +/* BIOS Data Area disk locations + */ +#define DSKDATA_SEEKSTATUS 0x43E // drive recal. status (1 byte) +#define DSKDATA_MOTORSTATUS 0x43F // motor status (1 byte) +#define DSKDATA_MOTORCOUNT 0x440 // time-out count for motor (1 byte) +#define DSKDATA_DISKETTESTATUS 0x441 // return code status (1 byte) +#define DSKDATA_NECSTATUS 0x442 // controller status bytes (7 bytes) + +#define DSKDATA_DISKSTATUS1 0x474 // return code status (1 byte) + + +/* Floppy Diskette Parameter Table + * (pointed by vector BIOSINT_FDSKPARMS (1Eh)) + */ +typedef struct fdp_s { + BYTE bSpecify1; // step-rate, head-unload + BYTE bSpecify2; // head-load, DMA mode + BYTE bMotorOff; // motor-off delay + BYTE bSectorSize; // bytes/sec (0=128,1=256,2=512,3=1024) + BYTE nLastSector; // (or think of it as # sectors/track) + BYTE lenGapRW; // + BYTE lenData; // + BYTE lenGapFormat; // + BYTE bFormatData; // format initialization byte + BYTE bSettle; // head settle time + BYTE bMotorOn; // motor start-up time +} FDP; +typedef FDP *PFDP; // pointer to diskette parameter table + + +/* Hard Disk Parameter Table + */ +typedef struct hdp_s { + USHORT usMaxCylinders; // maximum number of cylinders + BYTE bMaxHeads; // maximum number of heads + USHORT usReserve1; // reserved (not used) + USHORT usWritePrecompCyl; // starting write precompensation cyl. + BYTE bMaxECCDataBurstLen; // maximum ECC data burst length + BYTE bControl; // control byte + BYTE abReserve2[3]; // reserved (not used) + USHORT usLandingZone; // landing zone for head parking + BYTE bSectorsPerTrack; // number of sectors per track + BYTE bReserve3; // reserved for future use +} HDP; +typedef HDP *PHDP; // pointer to hard disk parameter table + + +/* Hard Disk Parameter Table control byte bit definitions + */ +#define HDPCTRL_DISABLERETRY 0xC0 // disable retries +#define HDPCTRL_EXCEED8HEADS 0x08 // more than 8 heads + + +/* Boot sector structures (more DOS-defined than BIOS-defined however -JTP) + */ +#define PARTITION_ACTIVE 0x80 // status values + +#define PARTITION_12BITFAT 1 // type valus +#define PARTITION_16BITFAT 4 +#define PARTITION_LARGEFAT 6 + +typedef struct mbr_s { // Master Boot Record + BYTE boot_code[0x1BE]; + BYTE partition_status; + BYTE starting_head; + USHORT starting_sec_cyl; + BYTE partition_type; + BYTE ending_head; + USHORT ending_sec_cyl; + ULONG starting_abs_sector; + ULONG total_sectors; +} MBR; +typedef MBR *PMBR; + +typedef struct bpb_s { // BIOS Parameter Block (from sysbloks.h) + BYTE boot_code[0x0B]; + USHORT bytes_per_sector; // sector size + BYTE sectors_per_cluster; // sectors per allocation unit + USHORT reserved_sectors; // number of reserved sectors + BYTE nbr_fats; // number of fats + USHORT root_entries; // number of directory entries + USHORT total_sectors; // number of sectors + BYTE media_type; // fatid byte + USHORT sectors_per_fat; // sectors in a copy of the FAT + USHORT sectors_per_track; // number of sectors per track + USHORT number_of_heads; // number of heads + ULONG hidden_sectors; // number of hidden sectors + ULONG large_total_sectors; // large total sectors + BYTE reserved[6]; // 6 reserved bytes +} BPB; +typedef BPB *PBPB; + + +/* Virtual disk mapping info + * + * VIRTDISK is the header of a virtual disk file. Following the header + * is an optional track table, and TRACKINFO is the format of each entry + * in that table. The track table is only present if the last two + * fields in the header (nsecTrack and nbSector) are zero, indicating a + * non-homogeneous disk structure. + * + * Currently, a max of 4 DRIVEMAP structures are supported. The first two + * entries are for physical drives 0 and 1 (specified in the command-line + * options as drives A: and B:), and subsequent entries are for physical + * hard drives 0x80 and up (specified as drives C: and up). Each DRIVEMAP + * describes the remapping that should occur, if any, and for virtual disk + * files, it also contains the virtual disk file header (which is read in + * during initialization). + * + * When a request comes in for one of those drives, we check the flags in + * corresponding DRIVEMAP structure. If no flags are set, no remapping + * or virtualization occurs (drive behaves normally). This is the default. + * If the drive is disabled (eg, "A:=*"), then all requests are returned + * with an error. If the drive is remapped to another physical drive (eg, + * "A:=B:") then the request is routed to the mapped drive. Finally, if + * the drive is remapped to a virtual disk file, the appropriate file I/O + * is performed. + * + * NOTE: Contrary to comments above, access to physical drives is not + * currently supported, so mapping to a virtual drive is all you can do + * right now.... (24-Nov-90 JTP) + */ + +#define VDFLAGS_WRITEPROTECT 0x01 // virtual disk is "write-protected" + +typedef struct virtdisk_s { + BYTE fbVirt; // flags + BYTE nHeads; // # heads + USHORT nCyls; // # cylinders + USHORT nsecTrack; // # sectors per track + USHORT nbSector; // # bytes per sector +} VIRTDISK; +typedef VIRTDISK *PVIRTDISK; + +typedef struct trackinfo_s { + USHORT nsecTrack; // # sectors per track + USHORT nbSector; // # bytes per sector + ULONG offVirtDisk; // offset within virtual disk file +} TRACKINFO; +typedef TRACKINFO *PTRACKINFO; + +#define DMFLAGS_VIRTUAL 0x01 // physical remapped to virtual +#define DMFLAGS_DISABLED 0x02 // physical remapped to disabled +#define DMFLAGS_PHYSICAL 0x04 // physical remapped to physical +#define DMFLAGS_LOGICAL 0x08 // physical remapped to logical + +typedef struct drivemap_s { + BYTE fbMap; // flags + BYTE iPhysical; // # of remapped drive, if any + FILE *hfVirtDisk; // handle to virtual disk, if any + VIRTDISK vdInfo; // virtual disk info, if any + #ifdef LOGICAL_DRIVE_SUPPORT + ULONG nsecHidden; // from BPB, if any (logical disks only) + BYTE type; // disk type, if any (logical disks only) + #endif +} DRIVEMAP; +typedef DRIVEMAP *PDRIVEMAP; + + diff --git a/private/mvdm/v86/scaffold/i386/xbioskbd.h b/private/mvdm/v86/scaffold/i386/xbioskbd.h new file mode 100644 index 000000000..d416b4069 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/xbioskbd.h @@ -0,0 +1,39 @@ +// +// This code is temporary. When Insignia supplies rom support, it should +// be removed. +// + +/* x86 v1.0 + * + * XBIOSKBD.H + * Guest ROM BIOS keyboard emulation + * + * History + * Created 20-Oct-90 by Jeff Parsons + * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + + +/* BIOS keyboard functions + */ +#define KBDFUNC_READCHAR 0x00 +#define KBDFUNC_PEEKCHAR 0x01 +#define KBDFUNC_QUERYSHIFT 0x02 +#define KBDFUNC_SETDELAYS 0x03 +#define KBDFUNC_WRITECHAR 0x05 +#define KBDFUNC_READEXTCHAR 0x10 +#define KBDFUNC_PEEKEXTCHAR 0x11 +#define KBDFUNC_QUERYEXTSHIFT 0x12 + + +/* BIOS Data Area keyboard locations + */ +#define KBDDATA_KBDSHIFT 0x417 + + diff --git a/private/mvdm/v86/scaffold/i386/xbiosvid.h b/private/mvdm/v86/scaffold/i386/xbiosvid.h new file mode 100644 index 000000000..8a8a64ddb --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/xbiosvid.h @@ -0,0 +1,65 @@ +// +// This code is temporary. When Insignia supplies rom support, it should +// be removed. +// + +/* x86 v1.0 + * + * XBIOSVID.H + * Guest ROM BIOS video emulation + * + * History + * Created 20-Oct-90 by Jeff Parsons + * 17-Apr-91 Trimmed by Dave Hastings for use in temp. softpc + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + + +/* BIOS video functions + */ +#define VIDFUNC_SETMODE 0x00 +#define VIDFUNC_SETCURSORTYPE 0x01 +#define VIDFUNC_SETCURSORPOS 0x02 +#define VIDFUNC_QUERYCURSORPOS 0x03 +#define VIDFUNC_QUERYLPEN 0x04 +#define VIDFUNC_SETACTIVEPAGE 0x05 +#define VIDFUNC_SCROLLUP 0x06 +#define VIDFUNC_SCROLLDOWN 0x07 +#define VIDFUNC_READCHARATTR 0x08 +#define VIDFUNC_WRITECHARATTR 0x09 +#define VIDFUNC_WRITECHAR 0x0A +#define VIDFUNC_SETPALETTE 0x0B +#define VIDFUNC_WRITEPIXEL 0x0C +#define VIDFUNC_READPIXEL 0x0D +#define VIDFUNC_WRITETTY 0x0E +#define VIDFUNC_QUERYMODE 0x0F +#define VIDFUNC_EGASETPALETTE 0x10 +#define VIDFUNC_EGASELECTFONT 0x11 +#define VIDFUNC_EGASELECTMISC 0x12 +#define VIDFUNC_EGAWRITESTRING 0x13 +#define VIDFUNC_VGADISPLAYCODES 0x1A +#define VIDFUNC_VGAQUERYSTATE 0x1B +#define VIDFUNC_VGASAVERESTORE 0x1C + +#define VIDMODE_MONO 7 + + +/* BIOS Data Area video locations + */ +#define VIDDATA_CRT_MODE 0x449 +#define VIDDATA_CRT_COLS 0x44A +#define VIDDATA_CRT_LEN 0x44C +#define VIDDATA_CRT_START 0x44E +#define VIDDATA_CURSOR_POSN 0x450 +#define VIDDATA_CURSOR_MODE 0x460 +#define VIDDATA_ACTIVE_PAGE 0x462 +#define VIDDATA_ADDR_6845 0x463 +#define VIDDATA_CRT_MODE_SET 0x465 +#define VIDDATA_CRT_PALETTE 0x466 + + diff --git a/private/mvdm/v86/scaffold/i386/xguest.h b/private/mvdm/v86/scaffold/i386/xguest.h new file mode 100644 index 000000000..38e963365 --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/xguest.h @@ -0,0 +1,459 @@ +/* x86 v1.0 + * + * XGUEST.H + * Guest processor definitions/conventions + * + * History + * Created 20-Oct-90 by Jeff Parsons + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + + +#define GUESTMEM_SIZE (640*K) + +#define GUESTMEM_MIN (32*K) // smallest PC size ever +#define GUESTMEM_MAX (960*K) // uses all but the last 64k ROM block + +#define GUESTVID_SIZE (4*K) // for MONO emulation +#define GUESTVID_SEG (USHORT)0xB000 + +#define GUESTROM_SIZE (64*K) +#define GUESTROM_SEG (USHORT)0xF000 + +#define FLATMEM_SIZE ((1024+64)*K) + + +/* Processor-defined stuff + */ +#define IVT_BEGIN 0x0000 // IVT table +#define IVT_END 0x03FF + +#define RESET_SEG (USHORT)0xFFFF // processor reset address +#define RESET_OFF 0x0000 + + +/* Useful macros + */ +#define LINEAR(seg,off) (((((ULONG)(seg)<<4)+(off))) & ulWrapMask) +#define LINEAR2(seg,off) (((ULONG)(seg)<<4)+(off)) +#define COMPOSITE(seg,off) (((ULONG)(seg)<<16)|(off)) +#define OFFCOMPOSITE(ul) WORDOF(ul,0) +#define SEGCOMPOSITE(ul) WORDOF(ul,1) + +#define BYTESOFFSET(off) LOBYTE(off), HIBYTE(off) +#define BYTESCOMPOSITE(seg,off) LOBYTE(off), HIBYTE(off), LOBYTE(seg), HIBYTE(seg) + +/* x86 opcodes (the really useful ones anyway) + */ +#define OPX_ADDAXI 0x05 +#define OPX_PUSHDS 0x1E +#define OPX_POPDS 0x1F +#define OPX_ES 0x26 +#define OPX_CS 0x2E +#define OPX_SS 0x36 +#define OPX_DS 0x3E +#define OPX_PUSHAX 0x50 +#define OPX_POPAX 0x58 +#define OPX_JO 0x70 +#define OPX_JNO 0x71 +#define OPX_JB 0x72 +#define OPX_JNB 0x73 +#define OPX_JZ 0x74 +#define OPX_JNZ 0x75 +#define OPX_JBE 0x76 +#define OPX_JNBE 0x77 +#define OPX_JS 0x78 +#define OPX_JNS 0x79 +#define OPX_JP 0x7A +#define OPX_JNP 0x7B +#define OPX_JL 0x7C +#define OPX_JGE 0x7D +#define OPX_JLE 0x7E +#define OPX_JG 0x7F +#define OPX_MOVSEG2 0x8C +#define OPX_LEA 0x8D +#define OPX_MOV2SEG 0x8E +#define OPX_CBW 0x98 +#define OPX_CWD 0x99 +#define OPX_MOVALOFF 0xA0 +#define OPX_MOVAXOFF 0xA1 +#define OPX_MOVSB 0xA4 +#define OPX_MOVSW 0xA5 +#define OPX_MOVAL 0xB0 +#define OPX_MOVCL 0xB1 +#define OPX_MOVDL 0xB2 +#define OPX_MOVBL 0xB3 +#define OPX_MOVAH 0xB4 +#define OPX_MOVCH 0xB5 +#define OPX_MOVDH 0xB6 +#define OPX_MOVBH 0xB7 +#define OPX_MOVAX 0xB8 +#define OPX_MOVCX 0xB9 +#define OPX_MOVDX 0xBA +#define OPX_MOVBX 0xBB +#define OPX_MOVSP 0xBC +#define OPX_MOVBP 0xBD +#define OPX_MOVSI 0xBE +#define OPX_MOVDI 0xBF +#define OPX_RETNV 0xC2 +#define OPX_RETN 0xC3 +#define OPX_LES 0xC4 +#define OPX_LDS 0xC5 +#define OPX_RETFV 0xCA +#define OPX_RETF 0xCB +#define OPX_INT3 0xCC +#define OPX_INT 0xCD +#define OPX_INTO 0xCE +#define OPX_IRET 0xCF +#define OPX_GBP 0xD6 // invalid opcode used for guest breakpoints +#define OPX_XLAT 0xD7 +#define OPX_JCXZ 0xE3 +#define OPX_JMPR16 0xE9 +#define OPX_JMPF 0xEA +#define OPX_JMPR8 0xEB +#define OPX_LOCK 0xF0 +#define OPX_REPNZ 0xF2 +#define OPX_REPZ 0xF3 +#define OPX_CLC 0xF8 +#define OPX_STC 0xF9 +#define OPX_CLI 0xFA +#define OPX_STI 0xFB +#define OPX_GRP5 0xFF + +/* Mnemonic ordinals (indexes into apszMnemonic) + */ +#define M_NONE 0 +#define M_AAA 1 +#define M_AAD 2 +#define M_AAM 3 +#define M_AAS 4 +#define M_ADC 5 +#define M_ADD 6 +#define M_AND 7 +#define M_ARPL 8 +#define M_ASIZE 9 +#define M_BOUND 10 +#define M_BSF 11 +#define M_BSR 12 +#define M_BT 13 +#define M_BTC 14 +#define M_BTR 15 +#define M_BTS 16 +#define M_CALL 17 +#define M_CBW 18 +#define M_CLC 19 +#define M_CLD 20 +#define M_CLI 21 +#define M_CLTS 22 +#define M_CMC 23 +#define M_CMP 24 +#define M_CMPSB 25 +#define M_CMPSW 26 +#define M_CS 27 +#define M_CWD 28 +#define M_DAA 29 +#define M_DAS 30 +#define M_DEC 31 +#define M_DIV 32 +#define M_DS 33 +#define M_ENTER 34 +#define M_ES 35 +#define M_ESC 36 +#define M_FADD 37 +#define M_FBLD 38 +#define M_FBSTP 39 +#define M_FCOM 40 +#define M_FCOMP 41 +#define M_FDIV 42 +#define M_FDIVR 43 +#define M_FIADD 44 +#define M_FICOM 45 +#define M_FICOMP 46 +#define M_FIDIV 47 +#define M_FIDIVR 48 +#define M_FILD 49 +#define M_FIMUL 50 +#define M_FIST 51 +#define M_FISTP 52 +#define M_FISUB 53 +#define M_FISUBR 54 +#define M_FLD 55 +#define M_FLDCW 56 +#define M_FLDENV 57 +#define M_FMUL 58 +#define M_FNSAVE 59 +#define M_FNSTCW 60 +#define M_FNSTENV 61 +#define M_FNSTSW 62 +#define M_FRSTOR 63 +#define M_FS 64 +#define M_FST 65 +#define M_FSTP 66 +#define M_FSUB 67 +#define M_FSUBR 68 +#define M_GBP 69 +#define M_GS 70 +#define M_HLT 71 +#define M_IDIV 72 +#define M_IMUL 73 +#define M_IN 74 +#define M_INC 75 +#define M_INS 76 +#define M_INT 77 +#define M_INT3 78 +#define M_INTO 79 +#define M_IRET 80 +#define M_JBE 81 +#define M_JB 82 +#define M_JCXZ 83 +#define M_JG 84 +#define M_JGE 85 +#define M_JL 86 +#define M_JLE 87 +#define M_JMP 88 +#define M_JNBE 89 +#define M_JNB 90 +#define M_JNO 91 +#define M_JNP 92 +#define M_JNS 93 +#define M_JNZ 94 +#define M_JO 95 +#define M_JP 96 +#define M_JS 97 +#define M_JZ 98 +#define M_LAHF 99 +#define M_LAR 100 +#define M_LDS 101 +#define M_LEA 102 +#define M_LEAVE 103 +#define M_LES 104 +#define M_LFS 105 +#define M_LGDT 106 +#define M_LGS 107 +#define M_LIDT 108 +#define M_LLDT 109 +#define M_LMSW 110 +#define M_LOCK 111 +#define M_LODSB 112 +#define M_LODSW 113 +#define M_LOOP 114 +#define M_LOOPNZ 115 +#define M_LOOPZ 116 +#define M_LSL 117 +#define M_LSS 118 +#define M_LTR 119 +#define M_MOV 120 +#define M_MOVSB 121 +#define M_MOVSW 122 +#define M_MOVSX 123 +#define M_MOVZX 124 +#define M_MUL 125 +#define M_NEG 126 +#define M_NOP 127 +#define M_NOT 128 +#define M_OR 129 +#define M_OSIZE 130 +#define M_OUT 131 +#define M_OUTS 132 +#define M_POP 133 +#define M_POPA 134 +#define M_POPF 135 +#define M_PUSH 136 +#define M_PUSHA 137 +#define M_PUSHF 138 +#define M_RCL 139 +#define M_RCR 140 +#define M_REPNZ 141 +#define M_REPZ 142 +#define M_RET 143 +#define M_RETF 144 +#define M_ROL 145 +#define M_ROR 146 +#define M_SAHF 147 +#define M_SAR 148 +#define M_SBB 149 +#define M_SCASB 150 +#define M_SCASW 151 +#define M_SETBE 152 +#define M_SETC 153 +#define M_SETG 154 +#define M_SETGE 155 +#define M_SETL 156 +#define M_SETLE 157 +#define M_SETNBE 158 +#define M_SETNC 159 +#define M_SETNO 160 +#define M_SETNP 161 +#define M_SETNS 162 +#define M_SETNZ 163 +#define M_SETO 164 +#define M_SETP 165 +#define M_SETS 166 +#define M_SETZ 167 +#define M_SGDT 156 +#define M_SHL 169 +#define M_SHLD 170 +#define M_SHR 171 +#define M_SHRD 172 +#define M_SIDT 173 +#define M_SLDT 174 +#define M_SMSW 175 +#define M_SS 176 +#define M_STC 177 +#define M_STD 178 +#define M_STI 179 +#define M_STOSB 180 +#define M_STOSW 181 +#define M_STR 182 +#define M_SUB 183 +#define M_TEST 184 +#define M_VERR 185 +#define M_VERW 186 +#define M_WAIT 187 +#define M_XCHG 188 +#define M_XLAT 189 +#define M_XOR 190 +#define MTOTAL 191 + + +/* ModRegRM masks and definitions + */ +#define REG_AL 0x00 // bits 0-2 are standard Reg encodings +#define REG_CL 0x01 // +#define REG_DL 0x02 // +#define REG_BL 0x03 // +#define REG_AH 0x04 // +#define REG_CH 0x05 // +#define REG_DH 0x06 // +#define REG_BH 0x07 // +#define REG_AX 0x08 // +#define REG_CX 0x09 // +#define REG_DX 0x0A // +#define REG_BX 0x0B // +#define REG_SP 0x0C // +#define REG_BP 0x0D // +#define REG_SI 0x0E // +#define REG_DI 0x0F // + +#define REG_ES 0x00 // bits 0-1 are standard SegReg encodings +#define REG_CS 0x01 // +#define REG_SS 0x02 // +#define REG_DS 0x03 // +#define REG_FS 0x04 // +#define REG_GS 0x05 // + +#define MODMASK 0xC0 // mod/reg/rm definitions +#define MODSHIFT 6 // +#define MOD(m) (((m)&MODMASK)>>MODSHIFT) +#define REGMASK 0x38 // +#define REGSHIFT 3 // +#define REG(r) (((r)®MASK)>>REGSHIFT) +#define RMMASK 0x07 // +#define RMSHIFT 0 // +#define RM(b) (((b)&RMMASK)>>RMSHIFT) +#define MODREGRM(m,r,b) ((BYTE)((((m)<= TYPE_MODRM (clever, eh?) + +#define TYPE_IMM 0x0000 // (I) immediate data +#define TYPE_ONE 0x0010 // implicit 1 (eg, shifts/rotates) +#define TYPE_IMMOFF 0x0020 // (A) immediate offset +#define TYPE_IMMREL 0x0030 // (J) immediate relative +#define TYPE_DSSI 0x0040 // (X) memory addressed by DS:SI +#define TYPE_ESDI 0x0050 // (Y) memory addressed by ES:DI +#define TYPE_IMPREG 0x0060 // implicit register in TYPE_IREG +#define TYPE_IMPSEG 0x0070 // implicit seg. register in TYPE_IREG +#define TYPE_MODRM 0x0080 // (E) standard ModRM decoding +#define TYPE_MEM 0x0090 // (M) ModRM refers to memory only +#define TYPE_REG 0x00A0 // (G) standard Reg decoding +#define TYPE_SEGREG 0x00B0 // (S) Reg selects segment register +#define TYPE_MODREG 0x00C0 // (R) Mod refers to register only +#define TYPE_CTLREG 0x00D0 // (C) Reg selects control register +#define TYPE_DBGREG 0x00E0 // (D) Reg selects debug register +#define TYPE_TSTREG 0x00F0 // (T) Reg selects test register + +// TYPE_IREG values, based on the REG_* constants. +// For convenience, they include TYPE_IMPREG or TYPE_IMPSEG as appropriate. + +#define TYPE_AL (REG_AL<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_CL (REG_CL<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_DL (REG_DL<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_BL (REG_BL<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_AH (REG_AH<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_CH (REG_CH<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_DH (REG_DH<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_BH (REG_BH<<8|TYPE_IMPREG|TYPE_BYTE) +#define TYPE_AX (REG_AX<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_CX (REG_CX<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_DX (REG_DX<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_BX (REG_BX<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_SP (REG_SP<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_BP (REG_BP<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_SI (REG_SI<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_DI (REG_DI<<8|TYPE_IMPREG|TYPE_WORD) +#define TYPE_ES (REG_ES<<8|TYPE_IMPSEG|TYPE_WORD) +#define TYPE_CS (REG_CS<<8|TYPE_IMPSEG|TYPE_WORD) +#define TYPE_SS (REG_SS<<8|TYPE_IMPSEG|TYPE_WORD) +#define TYPE_DS (REG_DS<<8|TYPE_IMPSEG|TYPE_WORD) +#define TYPE_FS (REG_FS<<8|TYPE_IMPSEG|TYPE_WORD) +#define TYPE_GS (REG_GS<<8|TYPE_IMPSEG|TYPE_WORD) + +// TYPE_OTHER bit definitions + +#define TYPE_IN 0x1000 // operand is input +#define TYPE_OUT 0x2000 // operand is output +#define TYPE_BOTH (TYPE_IN|TYPE_OUT) +#define TYPE_86 (CPU_86 << 14) +#define TYPE_186 (CPU_186 << 14) +#define TYPE_286 (CPU_286 << 14) +#define TYPE_386 (CPU_386 << 14) + diff --git a/private/mvdm/v86/scaffold/i386/xwincon.h b/private/mvdm/v86/scaffold/i386/xwincon.h new file mode 100644 index 000000000..c3880146d --- /dev/null +++ b/private/mvdm/v86/scaffold/i386/xwincon.h @@ -0,0 +1,186 @@ +// +// borrowed for temprorary softpc console support +// + + +/*++ BUILD Version: 0001 + * + * x86 v1.0 + * + * XWINCON.H + * Windows support functions for console windows + * + * History + * Created 27-Dec-90 by Jeff Parsons + * + * COPYRIGHT NOTICE + * This source file may not be distributed, modified or incorporated into + * another product without prior approval from the author, Jeff Parsons. + * This file may be copied to designated servers and machines authorized to + * access those servers, but that does not imply any form of approval. + */ + + +typedef unsigned int UINT; // ints preferred +typedef int INT; // ints preferred +typedef CHAR *NPSZ; +typedef INT (FAR PASCAL *INTPROC)(HWND, UINT, UINT, LONG); + +#define DEF_CCHIN 16 // default input buffer size +#define DEF_CCHXOUT 80 // default output buffer width +#define DEF_CCHYOUT 25 // default output buffer height + +#define CON_SCROLL_LOCK 0x0010 // console has SCROLL-LOCK set +#define CON_NUM_LOCK 0x0020 // console has NUM-LOCK set +#define CON_CAPS_LOCK 0x0040 // console has CAPS-LOCK set +#define CON_LEDS_MASK 0x0070 // +#define CON_FOCUS 0x0100 // console has focus + +#ifndef VK_OEM_SCROLL +#define VK_OEM_SCROLL 0x91 // left out of windows.h for some reason... +#endif + +#define INVALIDATE_SCROLL 2 + +#define IDM_DBBRK 100 +#define IDM_ABOUT 101 + +#define CLR_BLACK 0x00000000 +#define CLR_RED 0x007F0000 +#define CLR_GREEN 0x00007F00 +#define CLR_BROWN 0x007F7F00 +#define CLR_BLUE 0x0000007F +#define CLR_MAGENTA 0x007F007F +#define CLR_CYAN 0x00007F7F +#define CLR_LT_GRAY 0x00BFBFBF + +#define CLR_DK_GRAY 0x007F7F7F +#define CLR_BR_RED 0x00FF0000 +#define CLR_BR_GREEN 0x0000FF00 +#define CLR_YELLOW 0x00FFFF00 +#define CLR_BR_BLUE 0x000000FF +#define CLR_BR_MAGENTA 0x00FF00FF +#define CLR_BR_CYAN 0x0000FFFF +#define CLR_WHITE 0x00FFFFFF + +#define OPT_FONT 0x0004 // use small OEM font if available (/s) +#define OPT_DOUBLE 0x0020 // use 50-line debug window w/small font (/50) +#define OPT_CAPS 0x0002 // map ctrl keys to caps-lock (/c) +#define OPT_TERMINAL 0x0010 // redirect all window output to terminal (/t) +#define OPT_FLUSH 0x0100 // flush prefetch after every jump (/f) +#define OPT_NOXLATE 0x0200 // disable built-in translations (/n) +#define OPT_DEBUG 0x0008 // shadow all log output on debug terminal (/d) +#define OPT_GO 0x0001 // do an initial "go" (/g) + +#define CTRL_A 1 // used by gets to repeat last line +#define CTRL_C 3 // break in debug window +#define CTRL_Q 17 // flow control +#define CTRL_S 19 // flow control +#define BELL 7 // +#define BS 8 // backspace +#define TAB 9 // +#define LF 10 // linefeed +#define CR 13 // return +#define ESCAPE 27 // + +#define SIGNAL_EMULATE 1 +#define ERR_NONE 0x0 + +#define TRUE_IF_WIN32 1 + +/* Per-window information + */ +#ifdef WIN_16 +#define GETPCONSOLE(hwnd) (PCONSOLE)GetWindowWord(hwnd,0) +#define SETPCONSOLE(hwnd,p) (PCONSOLE)SetWindowWord(hwnd,0,(INT)p) +#endif +#ifdef WIN_32 +#define GETPCONSOLE(hwnd) (PCONSOLE)GetWindowLong(hwnd,0) +#define SETPCONSOLE(hwnd,p) (PCONSOLE)SetWindowLong(hwnd,0,(LONG)p) +#endif +#ifdef PM +#define GETPCONSOLE(hwnd) (PCONSOLE)WinQueryWindowUShort(hwnd,0) +#define SETPCONSOLE(hwnd,p) (PCONSOLE)WinSetWindowUShort(hwnd,0,(USHORT)p) +#endif + +#define GETICARET(pcon) (pcon->chyCaret*pcon->cchxOut+pcon->chxCaret) +#define GETPCARET(pcon) (pcon->pchOut+GETICARET(pcon)) +#define GETXCARET(pcon) (pcon->chxCaret*pcon->cxChar) +#ifdef WIN +#define GETYCARET(pcon) (pcon->chyCaret*pcon->cyChar) +#else +#define GETYCARET(pcon) (pcon->cyOut - pcon->chyCaret*pcon->cyChar) +#endif + +#define GETILINE(pcon,chy) ((chy)*pcon->cchxOut) +#define GETPLINE(pcon,chy) (pcon->pchOut+GETILINE(pcon,chy)) + +#define GETICHAR(pcon,chx,chy) ((chy)*pcon->cchxOut+(chx)) +#define GETPCHAR(pcon,chx,chy) (pcon->pchOut+GETICHAR(pcon,chx,chy)) +#define GETXCHAR(pcon,chx) (pcon->cxChar*(chx)) +#ifdef WIN +#define GETYCHAR(pcon,chy) (pcon->cyChar*(chy)) +#else +#define GETYCHAR(pcon,chy) (pcon->cyOut - pcon->cyChar*(chy)) +#endif + +#define WORDOF(i,n) (((PWORD)&(i))[n]) +#define LOW(l) WORDOF(l,0) +#define NPVOID(p) ((VOID *)(p)) + +typedef struct key_s { + INT iKey; + LONG lKeyType; +} KEY, *PKEY; + +typedef struct console_s { + INT flCon; // console flags (see CON_*) + PKEY pkIn; // pointer to input buffer + HANDLE hkEvent; // handle to key event + INT ikHead; // input head (where to store next key) + INT ikTail; // input tail (where to retrieve next key) + INT ikMax; // maximum input index + HFONT hFont; // font identifier + INT cxChar; // character width, in pixels + INT cyChar; // character height, in pixels + INT cxOut; // buffer width, in pixels + INT cyOut; // buffer height, in pixels + INT cchxOut; // buffer width, in chars + INT cchyOut; // buffer height, in chars + UINT cbOut; // buffer size, in bytes + PCHAR pchOut; // pointer to output buffer + INT chxCaret; // caret x location, in char coordinates + INT chyCaret; // caret y location, in char coordinates +} CONSOLE, *PCONSOLE; + + +/* Function prototypes + */ +PCONSOLE initconsole(HWND hwnd, INT cchIn, INT cchxOut, INT cchyOut, INT iFont); +VOID freeconsole(HWND hwnd); +VOID clearconsole(HWND hwnd); +VOID invalidateconsole(HWND hwnd, PRECT prc, BOOL fUpdate); + +INT wprint(HWND hwnd, NPSZ psz, INT n); +INT wgetch(HWND hwnd); +BOOL wkbhit(HWND hwnd); +VOID wyield(HANDLE); +INT wputch(HWND hwnd, INT i); + +VOID setcaret(HWND hwnd, INT x, INT y); +VOID getcaret(HWND hwnd, PINT px, PINT py); +VOID writechar(HWND hwnd, CHAR ch, INT n); +VOID scrollrect(HWND hwndGuest, PRECT prc, INT n); + +extern HWND hwndGuest; +extern HANDLE hHostInstance; +extern INT flOptions; // command-line options (see OPT_*) +extern INT flSignals; // signal flags (see SIGNAL_*) + +LONG FAR PASCAL VDMWndProc(HWND hwnd, UINT wMsg, UINT uParam, LONG lParam); +BOOL FAR PASCAL VDMAbout(HWND hDlg, UINT wMsg, UINT uParam, LONG lParam); + +VOID processmessages(HWND hwnd); +INT getkbdleds(VOID); +VOID setkbdleds(INT flCon); +VOID mapkbdkeys(PCONSOLE pcon, UINT iParam, BOOL fDown); diff --git a/private/mvdm/v86/scaffold/makefile b/private/mvdm/v86/scaffold/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/mvdm/v86/scaffold/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/mvdm/v86/scaffold/ntvdm.def b/private/mvdm/v86/scaffold/ntvdm.def new file mode 100644 index 000000000..6cc3fd979 --- /dev/null +++ b/private/mvdm/v86/scaffold/ntvdm.def @@ -0,0 +1,90 @@ +NAME ntvdm.exe + +EXPORTS + getEAX + getAX + getAL + getAH + getEBX + getBX + getBL + getBH + getECX + getCX + getCL + getCH + getEDX + getDX + getDL + getDH + getESP + getSP + getEBP + getBP + getESI + getSI + getEDI + getDI + getEIP + getIP + getCS + getSS + getDS + getES + getFS + getGS + getCF + getPF + getAF + getZF + getSF + getIF + getDF + getOF + getMSW + setEAX + setAX + setAH + setAL + setEBX + setBX + setBH + setBL + setECX + setCX + setCH + setCL + setEDX + setDX + setDH + setDL + setESP + setSP + setEBP + setBP + setESI + setSI + setEDI + setDI + setEIP + setIP + setCS + setSS + setDS + setES + setFS + setGS + setCF + setPF + setAF + setZF + setSF + setIF + setDF + setOF + setMSW + MGetVdmPointer + host_simulate + EnterIdle + LeaveIdle + getIntelRegistersPointer diff --git a/private/mvdm/v86/scaffold/sources b/private/mvdm/v86/scaffold/sources new file mode 100644 index 000000000..d0cde5f5b --- /dev/null +++ b/private/mvdm/v86/scaffold/sources @@ -0,0 +1,157 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + Dave Hastings (daveh) 24-Apr-1991 + Sudeep Bharati (sudeepb) 31-Dec-1991 - deleted wow32 related stuff and + converted .EXE to (.EXE/.EXP/.LIB) + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + + +# +# The MAJORCOMP and MINORCOMP variables are defined +# so that $(MAJORCOMP)$(MINORCOMP)filename can be used in +# cross compiling to provide unique filenames in a flat namespace. +# + +MAJORCOMP=v86 +MINORCOMP=scaffold + +# +# The TARGETNAME variable is defined by the developer. It is the name of +# the target (component) that is being built by this makefile. It +# should NOT include any path or file extension information. +# + +TARGETNAME=ntvdm + + +# +# The TARGETPATH and TARGETTYPE variables are defined by the developer. +# The first specifies where the target is to be build. The second specifies +# the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or +# BOOTPGM). UMAPPL_NOLIB is used when you're only building user-mode +# apps and don't need to build a library. +# + +TARGETPATH=\nt\public\sdk\lib + +# PROGLIB is a new target type which allows ntvdm to be an exe and +# at the same time exports interfaces like a dll. +TARGETTYPE=PROGLIB + + +# +# The TARGETLIBS specifies additional libraries to link with you target +# image. Each library path specification should contain an asterisk (*) +# where the machine specific subdirectory name should go. +# + +!IFNDEF NTVDM_NET_PATH +NTVDM_NET_PATH=..\..\..\net +!ENDIF + +!IFDEF NTLIBPATH +TARGETLIBS=\nt\public\sdk\lib\*\monitor.lib \ + \nt\public\sdk\lib\*\xms.lib \ + \nt\public\sdk\lib\*\dbg.lib \ + \nt\public\sdk\lib\*\dem.lib \ + \nt\public\sdk\lib\*\command.lib \ +!IFDEF NTVDM_NET_SUPPORT + ..\..\dos\command\obj\*\command.lib \ + ..\..\vdmredir\obj\*\vdmredir.lib +!ELSE + ..\..\dos\command\obj\*\command.lib +!ENDIF +!ELSE +TARGETLIBS=\nt\public\sdk\lib\*\monitor.lib \ + \nt\public\sdk\lib\*\dem.lib \ + \nt\public\sdk\lib\*\xms.lib \ + \nt\public\sdk\lib\*\dbg.lib \ + \nt\public\sdk\lib\*\command.lib \ +!IFDEF NTVDM_NET_SUPPORT + ..\..\vdmredir\obj\*\vdmredir.lib \ + \nt\public\sdk\lib\*\netapi32.lib \ + \nt\public\sdk\lib\*\xactsrv.lib \ + $(BASEDIR)\Public\SDK\Lib\*\rxcommon.lib \ + $(NTVDM_NET_PATH)\netlib\obj\*\netlib.lib \ +!ENDIF + \nt\public\sdk\lib\*\gdi32.lib \ +!ENDIF + +# +# The INCLUDES variable specifies any include paths that are specific to +# this source directory. Separate multiple directory paths with single +# semicolons. Relative path specifications are okay. +# + +INCLUDES=..\..\inc;..\..\..\windows\inc + + +# +# The SOURCES variable is defined by the developer. It is a list of all the +# source files for this component. Each source file should be on a separate +# line using the line continuation character. This will minimize merge +# conflicts if two developers adding source files to the same component. +# + +SOURCES=vdm.rc + +# +# Next specify options for the compiler. +# + +!IFDEF NTVDM_NET_SUPPORT +C_DEFINES=-DWIN_32 -DWOW -DNTVDM_NET_SUPPORT +!ELSE +C_DEFINES=-DWIN_32 -DWOW +!ENDIF + +# +# Next specify a kernel mode test (valid only in NTOS tree) +# + +NTTEST= + +# +# Next specify one or more user mode test programs and their type +# UMTEST is used for optional test programs. UMAPPL is used for +# programs that always get built when the directory is built. +# + +UMTYPE=console +UMTEST= +UMAPPL= +UMBASE=0x1000000 +UMLIBS= + +# +# Defining either (or both) the variables NTTARGETFILE0 and/or NTTARGETFILES +# will cause MAKEFILE.DEF to include .\makefile.inc immediately after it +# specifies the top level targets (all, clean and loc) and their dependencies. +# MAKEFILE.DEF also expands NTTARGETFILE0 as the first dependent for the +# "all" target and NTTARGETFILES as the last dependent for the "all" target. +# Useful for specifying additional targets and dependencies that don't fit the +# general case covered by MAKEFILE.DEF +# + +# NTTARGETFILE0= +# NTTARGETFILES= diff --git a/private/mvdm/v86/scaffold/vdm.ico b/private/mvdm/v86/scaffold/vdm.ico new file mode 100644 index 000000000..6b2416d64 Binary files /dev/null and b/private/mvdm/v86/scaffold/vdm.ico differ diff --git a/private/mvdm/v86/scaffold/vdm.rc b/private/mvdm/v86/scaffold/vdm.rc new file mode 100644 index 000000000..1d354879c --- /dev/null +++ b/private/mvdm/v86/scaffold/vdm.rc @@ -0,0 +1,57 @@ +#ifndef DOS // Gross hack to account for the +#ifndef OS2_16 // fact that C_DEFINES in "sources" isn't +#ifndef OS2_32 // passed to the resource compiler when building +#ifndef WIN_16 // for MIPS. Since MIPS is a WIN_32 build, +#ifndef WIN_32 // I try to innocuously define WIN_32 here... -JTP +#define WIN_32 +#endif +#endif +#endif +#endif +#endif + +#define _NTIMAGE_ // This will force ntimage not to include nt.h +#define _NTXCAPI_ // forces ntxcapi.h unincluded +#include "i386\x86.h" + +VDMIcon ICON vdm.ico + + +SoftPC MENU +BEGIN + POPUP "&Help" + BEGIN + MENUITEM "&DebugBreak", IDM_DBBRK + MENUITEM "&About NT VDM...", IDM_ABOUT + END +END + + +VDMAbout DIALOG 22, 17, 131, 83 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About NT VDM" +BEGIN + CTEXT "NT VDMs are " -1, 32, 5, 65, 12 + CTEXT "Brought to you by the NTVDM Team" -1, 0, 19, 131, 10 + CTEXT "Some code adapted from:" -1, 0, 27, 131, 9 + CTEXT "x86 emulator v0.17" -1, 0, 38, 131, 8 + CTEXT "by Jeff Parsons, (C) 1991" -1, 0, 45, 131, 8 + CONTROL "Text", -1, "static", SS_BLACKFRAME | WS_CHILD, 17, 36, 99, 27 + DEFPUSHBUTTON "OK" IDOK, 51, 66, 32, 14, WS_GROUP +END + + +#ifdef WOW + +WOW32About DIALOG 22, 17, 144, 55 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About WOW" +BEGIN + CTEXT "Just say WOW!" -1, 0, 5, 144, 8 + CTEXT "This Win16-on-Win32 app" -1, 0, 18, 144, 8 + CTEXT "brought to you by the MVDM Team" -1, 0, 27, 144, 8 + DEFPUSHBUTTON "OK" IDOK, 32, 39, 32, 14, WS_GROUP + PUSHBUTTON "Debug" 100, 80, 39, 32, 14, WS_GROUP +END + +#endif diff --git a/private/mvdm/v86/scaffold/wow.ico b/private/mvdm/v86/scaffold/wow.ico new file mode 100644 index 000000000..936ab5c5e Binary files /dev/null and b/private/mvdm/v86/scaffold/wow.ico differ diff --git a/private/mvdm/v86/util/makefile b/private/mvdm/v86/util/makefile new file mode 100644 index 000000000..31b26fc0b --- /dev/null +++ b/private/mvdm/v86/util/makefile @@ -0,0 +1,56 @@ +!IF 0 +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + makefile + +Abstract: + + This file controls the creation of the utilities + +Author: + + Dave Hastings (daveh) 25-Apr-1991 + +!ENDIF + +########## Path definition so we find 16 bit tools ########## +# Also works around stupid bug in RC 3.1 that doesn't allow rcpp.err to be +# in a directory that is greater than 128 chars down the path, even if +# rc 3.1 is running as an OS/2 app. + +PATH = $(_NTBINDIR)\private\mvdm\tools16;$(PATH) + +.SUFFIXES: +.SUFFIXES: .asm .inc .obj .lst .exe .com .map .sym + +MASM = masm +AINC = -I. -I..\inc -I..\..\inc +AFLAGS = -Ml + +LFLAGS = +LIB = + +RELOC = reloc + +# rules + +.asm.obj : + $(MASM) $(AFLAGS) $(AINC) $*.asm, $*.obj; + +.asm.lst : + $(MASM) $(AFLAGS) $(AINC) -l $*.asm, $*.obj; + +.obj.exe : + link16 $(LFLAGS) $*,,,$(LIB); + +.exe.com : + $(RELOC) $*.exe $*.com + +# dependencies + +all: quit.com + +quit.com : quit.exe +quit.obj : quit.asm ..\..\inc\bop.inc diff --git a/private/mvdm/v86/util/quit.asm b/private/mvdm/v86/util/quit.asm new file mode 100644 index 000000000..664fd2880 --- /dev/null +++ b/private/mvdm/v86/util/quit.asm @@ -0,0 +1,40 @@ + title "Terminate execution of an NT VDM" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; +; Module Name: +; +; quit.asm +; +; Abstract: +; +; This module is a simple dos executable that will terminate a +; Vdm. +; +; Author: +; +; Dave Hastings (daveh) 25-Apr-1991 +; +; Environment: +; +; V86 mode only!! +; +; Revision History: +; +;-- +.386 + + +.xlist +include bop.inc +.list + +code segment + ASSUME CS:code +quit proc near + BOP BOP_UNSIMULATE +quit endp + +code ends + end -- cgit v1.2.3