mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
7.1 KiB
312 lines
7.1 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dpmiselr.c
|
|
|
|
Abstract:
|
|
|
|
This is the code for maintaining descriptor data for dpmi32.
|
|
|
|
Author:
|
|
|
|
Dave Hart (davehart) 11-Apr-1993
|
|
|
|
Notes:
|
|
|
|
|
|
Revision History:
|
|
|
|
09-Feb-1994 (daveh)
|
|
Moved here from not386.c.
|
|
31-Jul-1995 (neilsa)
|
|
Merged with x86 source
|
|
12-Dec-1995 (neilsa)
|
|
Wrote VdmAddDescriptorMapping(), GetDescriptorMapping
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "softpc.h"
|
|
#include "malloc.h"
|
|
|
|
#if DBG
|
|
USHORT CheckValue=0;
|
|
#endif
|
|
|
|
#ifndef i386
|
|
ULONG
|
|
GetDescriptorMapping(
|
|
USHORT Sel,
|
|
ULONG LdtBase
|
|
);
|
|
|
|
typedef struct _DESC_MAPPING {
|
|
USHORT Sel;
|
|
USHORT SelCount;
|
|
ULONG LdtBase;
|
|
ULONG FlatBase;
|
|
struct _DESC_MAPPING* pNext;
|
|
} DESC_MAPPING, *PDESC_MAPPING;
|
|
|
|
PDESC_MAPPING pDescMappingHead = NULL;
|
|
|
|
#endif // i386
|
|
|
|
|
|
|
|
//
|
|
// Imported functions from SoftPC world
|
|
//
|
|
extern VOID EnableEmulatorIretHooks(VOID);
|
|
extern VOID DisableEmulatorIretHooks(VOID);
|
|
|
|
BOOL
|
|
DpmiSetX86Descriptor(
|
|
LDT_ENTRY *Descriptors,
|
|
USHORT registerAX,
|
|
USHORT registerCX
|
|
);
|
|
|
|
VOID
|
|
DpmiSetDescriptorEntry(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is stolen from i386\dpmi386.c and brain-damaged to
|
|
only maintain the FlatAddress array.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
LDT_ENTRY UNALIGNED *Descriptors;
|
|
USHORT i;
|
|
ULONG Base;
|
|
ULONG Limit;
|
|
USHORT registerCX;
|
|
USHORT registerAX;
|
|
|
|
registerAX = getAX();
|
|
if (registerAX % 8){
|
|
return;
|
|
}
|
|
|
|
Descriptors = (PLDT_ENTRY)Sim32GetVDMPointer(((getES() << 16) | getBX()),
|
|
0,
|
|
(UCHAR) (getMSW() & MSW_PE));
|
|
|
|
|
|
registerCX = getCX();
|
|
for (i = 0; i < registerCX; i++) {
|
|
|
|
// form Base and Limit values
|
|
|
|
Base = Descriptors[i].BaseLow | (Descriptors[i].HighWord.Bytes.BaseMid << 16) |
|
|
(Descriptors[i].HighWord.Bytes.BaseHi << 24);
|
|
|
|
Limit = Descriptors[i].LimitLow | (Descriptors[i].HighWord.Bits.LimitHi << 16);
|
|
Limit = (Limit << (12 * Descriptors[i].HighWord.Bits.Granularity)) +
|
|
Descriptors[i].HighWord.Bits.Granularity * 0xFFF;
|
|
|
|
//
|
|
// Do NOT remove the following code. There are several apps that
|
|
// choose arbitrarily high limits for theirs selectors. This works
|
|
// under windows 3.1, but NT won't allow us to do that.
|
|
// The following code fixes the limits for such selectors.
|
|
// Note: if the base is > 0x7FFEFFFF, the selector set will fail
|
|
//
|
|
|
|
if ((Limit > 0x7FFEFFFF) || (Base + Limit > 0x7FFEFFFF)) {
|
|
Limit = 0x7FFEFFFF - (Base + 0xFFF);
|
|
if (!Descriptors[i].HighWord.Bits.Granularity) {
|
|
Descriptors[i].LimitLow = (USHORT)(Limit & 0x0000FFFF);
|
|
Descriptors[i].HighWord.Bits.LimitHi =
|
|
(Limit & 0x000f0000) >> 16;
|
|
} else {
|
|
Descriptors[i].LimitLow = (USHORT)((Limit >> 12) & 0xFFFF);
|
|
Descriptors[i].HighWord.Bits.LimitHi =
|
|
((Limit >> 12) & 0x000f0000) >> 16;
|
|
}
|
|
}
|
|
|
|
if ((registerAX >> 3) != 0) {
|
|
#ifndef i386
|
|
{
|
|
ULONG BaseOrig = Base;
|
|
Base = GetDescriptorMapping(registerAX+i*8, Base);
|
|
if (BaseOrig == Base) {
|
|
Base += (ULONG)IntelBase;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
FlatAddress[(registerAX >> 3) + i] = Base;
|
|
#if DBG
|
|
SelectorLimit[(registerAX >> 3) + i] = Limit;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#ifdef i386
|
|
if (!DpmiSetX86Descriptor(Descriptors, registerAX, registerCX)) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
setAX(0);
|
|
|
|
#ifndef i386
|
|
#if DBG
|
|
//
|
|
// debugbug
|
|
//
|
|
if (registerAX == CheckValue) {
|
|
force_yoda();
|
|
}
|
|
#endif
|
|
#endif // not i386
|
|
}
|
|
|
|
|
|
#ifndef i386
|
|
|
|
BOOL
|
|
VdmAddDescriptorMapping(
|
|
USHORT SelectorStart,
|
|
USHORT SelectorCount,
|
|
ULONG LdtBase,
|
|
ULONG Flat
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function was added to support the DIB.DRV implementation on RISC.
|
|
When an app uses DIB.DRV, then the situation arises where the Intel
|
|
linear base address + the flat address of the start of the Intel address
|
|
space does NOT equal the flat address of the memory. This happens when
|
|
the VdmAddVirtualMemory() api is used to set up an additional layer of
|
|
indirection for memory addressing in the emulator.
|
|
|
|
But there is more to the story. When app wants to use CreateDIBSection
|
|
via WinG we also need to map selectors, thus this routine should not
|
|
depend upon DpmiSetDesctriptorEntry being called afterwards. Thus, we go
|
|
and zap the flat address table with the new address.
|
|
|
|
Arguments:
|
|
|
|
SelectorStart, Count - range of selectors involved in the mapping
|
|
LdtBase - Intel base of start of range
|
|
Flat - True flat address base to be used for these selectors
|
|
|
|
Return Value:
|
|
|
|
This function returns TRUE on success, or FALSE for failure (out of mem)
|
|
|
|
--*/
|
|
|
|
{
|
|
PDESC_MAPPING pdm;
|
|
USHORT i;
|
|
|
|
if ((pdm = (PDESC_MAPPING) malloc(sizeof (DESC_MAPPING))) == NULL)
|
|
return FALSE;
|
|
|
|
pdm->Sel = SelectorStart &= ~7;
|
|
pdm->SelCount = SelectorCount;
|
|
pdm->LdtBase = LdtBase;
|
|
pdm->FlatBase = Flat;
|
|
pdm->pNext = pDescMappingHead;
|
|
pDescMappingHead = pdm;
|
|
|
|
// this code does what essentially desctribed in comment above
|
|
for (i = 0; i < SelectorCount; ++i) {
|
|
FlatAddress[(SelectorStart >> 3) + i] = Flat + 65536 * i;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ULONG
|
|
GetDescriptorMapping(
|
|
USHORT sel,
|
|
ULONG LdtBase
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
sel - the selector for which the base should be returned
|
|
LdtBase - the base for this selector as is set currently in the LDT
|
|
|
|
Return Value:
|
|
|
|
The true flat address for the specified selector.
|
|
|
|
--*/
|
|
{
|
|
PDESC_MAPPING pdm, pdmprev;
|
|
ULONG Base = LdtBase;
|
|
|
|
sel &= ~7; // and off lower 3 bits
|
|
pdm = pDescMappingHead;
|
|
|
|
while (pdm) {
|
|
|
|
if ((sel >= pdm->Sel) && (sel < (pdm->Sel + pdm->SelCount*8))) {
|
|
//
|
|
// We found a mapping for this selector. Now check to see if
|
|
// the ldt base still matches the base when the mapping was
|
|
// created.
|
|
//
|
|
if (LdtBase == (pdm->LdtBase + 65536*((sel-pdm->Sel)/8))) {
|
|
//
|
|
// The mapping appears still valid. Return the remapped address
|
|
//
|
|
return (pdm->FlatBase + 65536*((sel-pdm->Sel)/8));
|
|
|
|
} else {
|
|
//
|
|
// The ldt base doesn't match the mapping, so the mapping
|
|
// must be obselete. Free the mapping here.
|
|
//
|
|
if (pdm == pDescMappingHead) {
|
|
//
|
|
// mapping is the first in the list
|
|
//
|
|
pDescMappingHead = pdm->pNext;
|
|
|
|
} else {
|
|
pdmprev->pNext = pdm->pNext;
|
|
}
|
|
free(pdm);
|
|
}
|
|
|
|
break;
|
|
}
|
|
pdmprev = pdm;
|
|
pdm = pdm->pNext;
|
|
|
|
}
|
|
|
|
return Base;
|
|
}
|
|
|
|
#endif i386
|