2227 lines
60 KiB
C
2227 lines
60 KiB
C
/*** misc.c - Miscellaneous functions
|
|
*
|
|
* Copyright (c) 1996,1997 Microsoft Corporation
|
|
* Author: Michael Tsang (MikeTs)
|
|
* Created 11/18/96
|
|
*
|
|
* MODIFICATION HISTORY
|
|
*/
|
|
|
|
#include "pch.h"
|
|
|
|
#ifdef LOCKABLE_PRAGMA
|
|
#pragma ACPI_LOCKABLE_DATA
|
|
#pragma ACPI_LOCKABLE_CODE
|
|
#endif
|
|
|
|
/***LP InitializeMutex - initialize mutex
|
|
*
|
|
* ENTRY
|
|
* pmut -> MUTEX
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL InitializeMutex(PMUTEX pmut)
|
|
{
|
|
TRACENAME("INITIALIZEMUTEX")
|
|
|
|
ENTER(3, ("InitializeMutex(pmut=%x)\n", pmut));
|
|
|
|
KeInitializeSpinLock(&pmut->SpinLock);
|
|
pmut->OldIrql = PASSIVE_LEVEL;
|
|
|
|
EXIT(3, ("InitializeMutex!\n"));
|
|
} //InitializeMutex
|
|
|
|
/***LP AcquireMutex - acquire mutex
|
|
*
|
|
* ENTRY
|
|
* pmut -> MUTEX
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TRUE
|
|
* EXIT-FAILURE
|
|
* returns FALSE
|
|
*
|
|
* NOTE
|
|
* AcquireMutex can be called at DISPATCH_LEVEL as long as the mutex
|
|
* is unowned or owned by the same thread. If the mutex is owned by
|
|
* some other thread, this thread cannot block if we are at
|
|
* DISPATCH_LEVEL and therefore would fail to acquire the mutex.
|
|
*/
|
|
|
|
BOOLEAN LOCAL AcquireMutex(PMUTEX pmut)
|
|
{
|
|
TRACENAME("ACQUIREMUTEX")
|
|
BOOLEAN rc = TRUE;
|
|
|
|
ENTER(3, ("AcquireMutex(pmut=%x)\n", pmut));
|
|
|
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
|
KeAcquireSpinLock(&pmut->SpinLock, &pmut->OldIrql);
|
|
|
|
EXIT(3, ("AcquireMutex=%x\n", rc));
|
|
return rc;
|
|
} //AcquireMutex
|
|
|
|
/***LP ReleaseMutex - release mutex
|
|
*
|
|
* ENTRY
|
|
* pmut -> MUTEX
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TRUE
|
|
* EXIT-FAILURE
|
|
* returns FALSE
|
|
*/
|
|
|
|
BOOLEAN LOCAL ReleaseMutex(PMUTEX pmut)
|
|
{
|
|
TRACENAME("RELEASEMUTEX")
|
|
BOOLEAN rc = TRUE;
|
|
|
|
ENTER(3, ("ReleaseMutex(pmut=%x)\n", pmut));
|
|
|
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
|
KeReleaseSpinLock(&pmut->SpinLock, pmut->OldIrql);
|
|
|
|
EXIT(3, ("ReleaseMutex!\n"));
|
|
return rc;
|
|
} //ReleaseMutex
|
|
|
|
/***LP FindOpcodeTerm - find the AMLTERM for the given opcode
|
|
*
|
|
* ENTRY
|
|
* dwOp - opcode
|
|
* pOpTable -> opcode table
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns pointer to the opcode's AMLTERM
|
|
* EXIT-FAILURE
|
|
* returns NULL
|
|
*/
|
|
|
|
PAMLTERM LOCAL FindOpcodeTerm(ULONG dwOp, POPCODEMAP pOpTable)
|
|
{
|
|
TRACENAME("FINDOPCODETERM")
|
|
PAMLTERM pamlterm = NULL;
|
|
|
|
ENTER(3, ("FindOpcodeTerm(Op=%x,pOpTable=%x)\n", dwOp, pOpTable));
|
|
|
|
while (pOpTable->pamlterm != NULL)
|
|
{
|
|
if (dwOp == pOpTable->dwOpcode)
|
|
{
|
|
pamlterm = pOpTable->pamlterm;
|
|
break;
|
|
}
|
|
else
|
|
pOpTable++;
|
|
}
|
|
|
|
EXIT(3, ("FindOpcodeTerm=%x\n", pamlterm));
|
|
return pamlterm;
|
|
} //FindOpcodeTerm
|
|
|
|
/***LP GetHackFlags - Get the hack flags from the registry
|
|
*
|
|
* ENTRY
|
|
* pdsdt -> AML table
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns the hack flags read
|
|
* EXIT-FAILURE
|
|
* returns zero
|
|
*/
|
|
|
|
ULONG LOCAL GetHackFlags(PDSDT pdsdt)
|
|
{
|
|
TRACENAME("GETHACKFLAGS")
|
|
ULONG dwfHacks = 0, dwcb;
|
|
static PSZ pszHackFlags = "AMLIHackFlags";
|
|
|
|
ENTER(3, ("GetHackFlags(pdsdt=%x)\n", pdsdt));
|
|
|
|
if (pdsdt == NULL)
|
|
{
|
|
dwcb = sizeof(dwfHacks);
|
|
OSReadRegValue(pszHackFlags, (HANDLE)NULL, &dwfHacks, &dwcb);
|
|
}
|
|
else
|
|
{
|
|
ULONG dwLen, i;
|
|
PSZ pszRegPath;
|
|
HANDLE hRegKey;
|
|
NTSTATUS status;
|
|
|
|
dwLen = STRLEN(ACPI_PARAMETERS_REGISTRY_KEY) +
|
|
ACPI_MAX_TABLE_STRINGS +
|
|
8 + 5;
|
|
|
|
if ((pszRegPath = ExAllocatePool(PagedPool, dwLen)) != NULL)
|
|
{
|
|
STRCPY(pszRegPath, ACPI_PARAMETERS_REGISTRY_KEY);
|
|
STRCAT(pszRegPath, "\\");
|
|
STRCATN(pszRegPath, (PSZ)&pdsdt->Header.Signature,
|
|
ACPI_MAX_SIGNATURE);
|
|
STRCAT(pszRegPath, "\\");
|
|
STRCATN(pszRegPath, (PSZ)pdsdt->Header.OEMID, ACPI_MAX_OEM_ID);
|
|
STRCAT(pszRegPath, "\\");
|
|
STRCATN(pszRegPath, (PSZ)pdsdt->Header.OEMTableID, ACPI_MAX_TABLE_ID);
|
|
STRCAT(pszRegPath, "\\");
|
|
ULTOA(pdsdt->Header.OEMRevision, &pszRegPath[STRLEN(pszRegPath)],
|
|
16);
|
|
dwLen = STRLEN(pszRegPath);
|
|
for (i = 0; i < dwLen; i++)
|
|
{
|
|
if (pszRegPath[i] == ' ')
|
|
{
|
|
pszRegPath[i] = '_';
|
|
}
|
|
}
|
|
|
|
status = OSOpenHandle(pszRegPath, NULL, &hRegKey);
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
dwcb = sizeof(dwfHacks);
|
|
OSReadRegValue(pszHackFlags, hRegKey, &dwfHacks, &dwcb);
|
|
}
|
|
ExFreePool(pszRegPath);
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("GetHackFlags=%x\n", dwfHacks));
|
|
return dwfHacks;
|
|
} //GetHackFlags
|
|
|
|
/***LP GetBaseObject - If object type is OBJALIAS, follow the chain to the base
|
|
*
|
|
* ENTRY
|
|
* pnsObj -> object
|
|
*
|
|
* EXIT
|
|
* returns the base object
|
|
*/
|
|
|
|
PNSOBJ LOCAL GetBaseObject(PNSOBJ pnsObj)
|
|
{
|
|
TRACENAME("GETBASEOBJECT")
|
|
|
|
ENTER(3, ("GetBaseObject(pnsObj=%s)\n", GetObjectPath(pnsObj)));
|
|
|
|
while (pnsObj->ObjData.dwDataType == OBJTYPE_OBJALIAS)
|
|
{
|
|
pnsObj = pnsObj->ObjData.pnsAlias;
|
|
}
|
|
|
|
EXIT(3, ("GetBaseObject=%s\n", GetObjectPath(pnsObj)));
|
|
return pnsObj;
|
|
} //GetBaseObject
|
|
|
|
/***LP GetBaseData - If object type is DATAALIAS, follow the chain to the base
|
|
*
|
|
* ENTRY
|
|
* pdataObj -> object
|
|
*
|
|
* EXIT
|
|
* returns the base object
|
|
*/
|
|
|
|
POBJDATA LOCAL GetBaseData(POBJDATA pdataObj)
|
|
{
|
|
TRACENAME("GETBASEDATA")
|
|
|
|
ENTER(3, ("GetBaseData(pdataObj=%x)\n", pdataObj));
|
|
|
|
ASSERT(pdataObj != NULL);
|
|
for (;;)
|
|
{
|
|
if (pdataObj->dwDataType == OBJTYPE_OBJALIAS)
|
|
{
|
|
pdataObj = &pdataObj->pnsAlias->ObjData;
|
|
}
|
|
else if (pdataObj->dwDataType == OBJTYPE_DATAALIAS)
|
|
{
|
|
pdataObj = pdataObj->pdataAlias;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("GetBaseData=%x\n", pdataObj));
|
|
return pdataObj;
|
|
} //GetBaseData
|
|
|
|
/***LP NewObjOwner - create a new object owner
|
|
*
|
|
* ENTRY
|
|
* pheap -> HEAP
|
|
* ppowner -> to hold new owner pointer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL NewObjOwner(PHEAP pheap, POBJOWNER *ppowner)
|
|
{
|
|
TRACENAME("NEWOBJOWNER")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("NewObjOwner(pheap=%x,ppowner=%x)\n", pheap, ppowner));
|
|
|
|
if ((*ppowner = NEWOOOBJ(pheap, sizeof(OBJOWNER))) == NULL)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
|
|
("NewObjOwner: failed to allocate object owner"));
|
|
}
|
|
else
|
|
{
|
|
|
|
MEMZERO(*ppowner, sizeof(OBJOWNER));
|
|
(*ppowner)->dwSig = SIG_OBJOWNER;
|
|
|
|
AcquireMutex(&gmutOwnerList);
|
|
ListInsertTail(&(*ppowner)->list, &gplistObjOwners);
|
|
ReleaseMutex(&gmutOwnerList);
|
|
|
|
}
|
|
|
|
EXIT(3, ("NewObjOwner=%x (powern=%x)\n", rc, *ppowner));
|
|
return rc;
|
|
} //NewObjOwner
|
|
|
|
/***LP FreeObjOwner - free object owner
|
|
*
|
|
* ENTRY
|
|
* powner -> OBJOWNER
|
|
* fUnload - if TRUE, the caller is unloading a DDB
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL FreeObjOwner(POBJOWNER powner, BOOLEAN fUnload)
|
|
{
|
|
TRACENAME("FREEOBJOWNER")
|
|
KIRQL oldIrql;
|
|
PNSOBJ pns;
|
|
PNSOBJ pnsNext = NULL;
|
|
PNSOBJ pnsPrev = NULL;
|
|
PNSOBJ pnsDeviceList = NULL;
|
|
PNSOBJ pnsChild = NULL;
|
|
|
|
ENTER(3, ("FreeObjOwner(powner=%x,fUnload=%x)\n", powner,fUnload));
|
|
|
|
ASSERT(powner != NULL);
|
|
|
|
AcquireMutex(&gmutOwnerList);
|
|
ListRemoveEntry(&powner->list, &gplistObjOwners);
|
|
ReleaseMutex(&gmutOwnerList);
|
|
|
|
if (fUnload && (ghDestroyObj.pfnHandler != NULL))
|
|
{
|
|
|
|
//
|
|
// First we have to tell the driver that we are about to
|
|
// do walk the owner list so that we can seek and destroy
|
|
// the objects
|
|
//
|
|
((PFNDOBJ)ghDestroyObj.pfnHandler)(DESTROYOBJ_START, &oldIrql, 0);
|
|
|
|
//
|
|
// First pass, mark the objects defunc'd.
|
|
//
|
|
for (pns = powner->pnsObjList; pns != NULL; pns = pns->pnsOwnedNext) {
|
|
|
|
pns->ObjData.dwfData |= DATAF_NSOBJ_DEFUNC;
|
|
|
|
}
|
|
|
|
//
|
|
// Second pass, find the device in the list to be removed
|
|
//
|
|
for (pns = powner->pnsObjList; pns != NULL; pns = pnsNext) {
|
|
|
|
pnsNext = pns->pnsOwnedNext;
|
|
if (pns->ObjData.dwDataType == OBJTYPE_DEVICE ||
|
|
pns->ObjData.dwDataType == OBJTYPE_POWERRES ||
|
|
pns->ObjData.dwDataType == OBJTYPE_THERMALZONE ||
|
|
pns->ObjData.dwDataType == OBJTYPE_PROCESSOR) {
|
|
|
|
if (pnsPrev) {
|
|
|
|
pnsPrev->pnsOwnedNext = pns->pnsOwnedNext;
|
|
|
|
} else {
|
|
|
|
powner->pnsObjList = pns->pnsOwnedNext;
|
|
|
|
}
|
|
pns->pnsOwnedNext = pnsDeviceList;
|
|
pnsDeviceList = pns;
|
|
|
|
//
|
|
// Detach the device from its parent
|
|
//
|
|
if (pns->pnsParent != NULL) {
|
|
|
|
ListRemoveEntry(
|
|
&pns->list,
|
|
(PPLIST)&pns->pnsParent->pnsFirstChild
|
|
);
|
|
pns->pnsParent = NULL;
|
|
|
|
}
|
|
|
|
//
|
|
// Make sure that all of the device's children have been
|
|
// marked as being unloaded
|
|
//
|
|
if (pns->pnsFirstChild) {
|
|
|
|
pnsChild = pns->pnsFirstChild;
|
|
do {
|
|
|
|
if (!(pnsChild->ObjData.dwfData & DATAF_NSOBJ_DEFUNC) ) {
|
|
|
|
((PFNDOBJ)ghDestroyObj.pfnHandler)(
|
|
DESTROYOBJ_CHILD_NOT_FREED,
|
|
pnsChild,
|
|
0
|
|
);
|
|
|
|
}
|
|
pnsChild = (PNSOBJ) pnsChild->list.plistNext;
|
|
|
|
} while (pnsChild != pns->pnsFirstChild);
|
|
|
|
}
|
|
//
|
|
// Not that if we don't put this continue in here, then
|
|
// it becomes possible for pnsPrev to point to a device,
|
|
// which would corrupt the list
|
|
continue;
|
|
|
|
} else if (pns->pnsParent == NULL ||
|
|
!(pns->pnsParent->ObjData.dwfData & DATAF_NSOBJ_DEFUNC)) {
|
|
|
|
((PFNDOBJ)ghDestroyObj.pfnHandler)(
|
|
DESTROYOBJ_BOGUS_PARENT,
|
|
pns,
|
|
0
|
|
);
|
|
|
|
}
|
|
pnsPrev = pns;
|
|
|
|
}
|
|
|
|
//
|
|
// Chain the two lists back together
|
|
//
|
|
if (powner->pnsObjList == NULL) {
|
|
|
|
powner->pnsObjList = pnsDeviceList;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Find a pointer to the last element in the list
|
|
//
|
|
pns = powner->pnsObjList;
|
|
|
|
while ( pns->pnsOwnedNext != NULL )
|
|
{
|
|
|
|
//
|
|
// Next element in the list
|
|
//
|
|
pns = pns->pnsOwnedNext;
|
|
|
|
}
|
|
|
|
pns->pnsOwnedNext = pnsDeviceList;
|
|
}
|
|
|
|
// //
|
|
// Third pass pass, do callback for each device that is going away
|
|
//
|
|
for (pns = pnsDeviceList; pns != NULL; pns = pnsNext) {
|
|
|
|
//
|
|
// Remember what the next point is because we might nuke
|
|
// the current object in the callback (if there is no
|
|
// device extension associated with it
|
|
//
|
|
pnsNext = pns->pnsOwnedNext;
|
|
|
|
//
|
|
// Issue the callback. This might nuke the pnsObject
|
|
//
|
|
((PFNDOBJ)ghDestroyObj.pfnHandler)(
|
|
DESTROYOBJ_REMOVE_OBJECT,
|
|
pns,
|
|
pns->ObjData.dwDataType
|
|
);
|
|
|
|
}
|
|
|
|
//
|
|
// We end by tell the ACPI driver that we have finished looking
|
|
// at the list
|
|
//
|
|
((PFNDOBJ)ghDestroyObj.pfnHandler)(DESTROYOBJ_END, &oldIrql, 0 );
|
|
|
|
}
|
|
else
|
|
{
|
|
for (pns = powner->pnsObjList; pns != NULL; pns = pnsNext)
|
|
{
|
|
pnsNext = pns->pnsOwnedNext;
|
|
FreeNameSpaceObjects(pns);
|
|
}
|
|
}
|
|
powner->pnsObjList = NULL;
|
|
FREEOOOBJ(powner);
|
|
|
|
EXIT(3, ("FreeObjOwner!\n"));
|
|
} //FreeObjOwner
|
|
|
|
/***LP InsertOwnerObjList - Insert the new object into the owner's object list
|
|
*
|
|
* ENTRY
|
|
* powner -> owner
|
|
* pnsObj -> new object
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL InsertOwnerObjList(POBJOWNER powner, PNSOBJ pnsObj)
|
|
{
|
|
TRACENAME("INSERTOWNEROBJLIST")
|
|
|
|
ENTER(3, ("InsertOwnerObjList(powner=%x,pnsObj=%x)\n",
|
|
powner, pnsObj));
|
|
|
|
pnsObj->hOwner = (HANDLE)powner;
|
|
if (powner != NULL)
|
|
{
|
|
pnsObj->pnsOwnedNext = powner->pnsObjList;
|
|
powner->pnsObjList = pnsObj;
|
|
}
|
|
|
|
EXIT(3, ("InsertOwnerObjList!\n"));
|
|
} //InsertOwnerObjList
|
|
|
|
/***LP FreeDataBuffs - Free any buffers attached to OBJDATA array
|
|
*
|
|
* ENTRY
|
|
* adata -> OBJDATA array
|
|
* icData - number of data object in array
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL FreeDataBuffs(POBJDATA adata, int icData)
|
|
{
|
|
TRACENAME("FREEDATABUFFS")
|
|
int i;
|
|
|
|
ENTER(3, ("FreeDataBuffs(adata=%x,icData=%d)\n", adata, icData));
|
|
|
|
for (i = 0; i < icData; ++i)
|
|
{
|
|
if (adata[i].pbDataBuff != NULL)
|
|
{
|
|
if (adata[i].dwfData & DATAF_BUFF_ALIAS)
|
|
{
|
|
//
|
|
// decrement the base object's reference count.
|
|
//
|
|
adata[i].pdataBase->dwRefCount--;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We cannot free a base object buffer that has aliases on it.
|
|
//
|
|
ASSERT(adata[i].dwRefCount == 0);
|
|
if (adata[i].dwDataType == OBJTYPE_PKGDATA)
|
|
{
|
|
PPACKAGEOBJ ppkg = (PPACKAGEOBJ)adata[i].pbDataBuff;
|
|
|
|
FreeDataBuffs(ppkg->adata, ppkg->dwcElements);
|
|
}
|
|
ENTER(4, ("FreeData(i=%d,Buff=%x,Flags=%x)\n",
|
|
i, adata[i].pbDataBuff, adata[i].dwfData));
|
|
FREEOBJDATA(&adata[i]);
|
|
EXIT(4, ("FreeData!\n"));
|
|
}
|
|
}
|
|
|
|
MEMZERO(&adata[i], sizeof(OBJDATA));
|
|
}
|
|
|
|
EXIT(3, ("FreeDataBuff!\n"));
|
|
} //FreeDataBuffs
|
|
|
|
/***LP PutIntObjData - put integer data into data object
|
|
*
|
|
* ENTRY
|
|
* pctxt -> CTXT
|
|
* pdataObj -> data object
|
|
* dwData -> data to be written
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL PutIntObjData(PCTXT pctxt, POBJDATA pdataObj, ULONG dwData)
|
|
{
|
|
TRACENAME("PUTINTOBJDATA")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
OBJDATA data;
|
|
|
|
ENTER(3, ("PutIntObjData(pctxt=%x,pdataObj=%x,dwData=%x)\n",
|
|
pctxt, pdataObj, dwData));
|
|
|
|
MEMZERO(&data, sizeof(OBJDATA));
|
|
data.dwDataType = OBJTYPE_INTDATA;
|
|
data.uipDataValue = (ULONG_PTR)dwData;
|
|
|
|
rc = WriteObject(pctxt, pdataObj, &data);
|
|
|
|
EXIT(3, ("PutIntObjData=%x\n", rc));
|
|
return rc;
|
|
} //PutIntObjData
|
|
|
|
/***LP GetFieldUnitRegionObj - Get the OperationRegion object of FieldUnit
|
|
*
|
|
* ENTRY
|
|
* pfu -> FIELDUNITOBJ
|
|
* ppns -> to hold OperationRegion object
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL GetFieldUnitRegionObj(PFIELDUNITOBJ pfu, PPNSOBJ ppns)
|
|
{
|
|
TRACENAME("GETFIELDUNITREGIONOBJ")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
PNSOBJ pns;
|
|
|
|
ENTER(3, ("GetFieldUnitRegionObj(pfu=%x,ppns=%x)\n", pfu, ppns));
|
|
|
|
pns = pfu->pnsFieldParent;
|
|
switch (pns->ObjData.dwDataType)
|
|
{
|
|
case OBJTYPE_BANKFIELD:
|
|
*ppns = ((PBANKFIELDOBJ)pns->ObjData.pbDataBuff)->pnsBase;
|
|
break;
|
|
|
|
case OBJTYPE_FIELD:
|
|
*ppns = ((PFIELDOBJ)pns->ObjData.pbDataBuff)->pnsBase;
|
|
break;
|
|
|
|
case OBJTYPE_INDEXFIELD:
|
|
pns = ((PINDEXFIELDOBJ)pns->ObjData.pbDataBuff)->pnsData;
|
|
ASSERT(pns->ObjData.dwDataType == OBJTYPE_FIELDUNIT);
|
|
rc = GetFieldUnitRegionObj((PFIELDUNITOBJ)pns->ObjData.pbDataBuff,
|
|
ppns);
|
|
break;
|
|
|
|
default:
|
|
rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
|
|
("GetFieldUnitRegionObj: unknown field unit parent object type - %x",
|
|
(*ppns)->ObjData.dwDataType));
|
|
}
|
|
|
|
if ((*ppns != NULL) && ((*ppns)->ObjData.dwDataType != OBJTYPE_OPREGION))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
|
|
("GetFieldUnitRegionObj: base object of field unit is not OperationRegion (BaseObj=%s,Type=%x)",
|
|
GetObjectPath(*ppns), (*ppns)->ObjData.dwDataType));
|
|
}
|
|
|
|
EXIT(3, ("GetFieldUnitRegionObj=%x (RegionObj=%x:%s)\n",
|
|
rc, *ppns, GetObjectPath(*ppns)));
|
|
return rc;
|
|
} //GetFieldUnitRegionObj
|
|
|
|
/***LP CopyObjData - Copy object data
|
|
*
|
|
* ENTRY
|
|
* pdataDst -> target object
|
|
* pdataSrc -> source object
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL CopyObjData(POBJDATA pdataDst, POBJDATA pdataSrc)
|
|
{
|
|
TRACENAME("COPYOBJDATA")
|
|
|
|
ENTER(3, ("CopyObjData(Dest=%x,Src=%x)\n", pdataDst, pdataSrc));
|
|
|
|
ASSERT(pdataDst != NULL);
|
|
ASSERT(pdataSrc != NULL);
|
|
if (pdataDst != pdataSrc)
|
|
{
|
|
MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
|
|
if (pdataSrc->dwfData & DATAF_BUFF_ALIAS)
|
|
{
|
|
//
|
|
// Source is an alias, so we need to increment the base object
|
|
// reference count.
|
|
//
|
|
ASSERT(pdataSrc->pdataBase != NULL);
|
|
pdataSrc->pdataBase->dwRefCount++;
|
|
}
|
|
else if (pdataSrc->pbDataBuff != NULL)
|
|
{
|
|
//
|
|
// Source is a base object with buffer, increment its reference
|
|
// count.
|
|
//
|
|
pdataSrc->dwRefCount++;
|
|
pdataDst->dwfData |= DATAF_BUFF_ALIAS;
|
|
pdataDst->pdataBase = pdataSrc;
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("CopyObjData!\n"));
|
|
} //CopyObjData
|
|
|
|
/***LP MoveObjData - Move object data
|
|
*
|
|
* ENTRY
|
|
* pdataDst -> target object
|
|
* pdataSrc -> source object
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL MoveObjData(POBJDATA pdataDst, POBJDATA pdataSrc)
|
|
{
|
|
TRACENAME("MOVEOBJDATA")
|
|
|
|
ENTER(3, ("MoveObjData(Dest=%x,Src=%x)\n", pdataDst, pdataSrc));
|
|
|
|
ASSERT(pdataDst != NULL);
|
|
ASSERT(pdataSrc != NULL);
|
|
if (pdataDst != pdataSrc)
|
|
{
|
|
//
|
|
// We can only move an alias object or a base object with zero
|
|
// reference count or a base object with no data buffer.
|
|
//
|
|
ASSERT((pdataSrc->dwfData & DATAF_BUFF_ALIAS) ||
|
|
(pdataSrc->pbDataBuff == NULL) ||
|
|
(pdataSrc->dwRefCount == 0));
|
|
|
|
MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
|
|
MEMZERO(pdataSrc, sizeof(OBJDATA));
|
|
}
|
|
|
|
EXIT(3, ("MoveObjData!\n"));
|
|
} //MoveObjData
|
|
|
|
/***LP DupObjData - Duplicate object data
|
|
*
|
|
* ENTRY
|
|
* pheap -> HEAP
|
|
* pdataDst -> target object
|
|
* pdataSrc -> source object
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL DupObjData(PHEAP pheap, POBJDATA pdataDst, POBJDATA pdataSrc)
|
|
{
|
|
TRACENAME("DUPOBJDATA")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("DupObjData(pheap=%x,Dest=%x,Src=%x)\n",
|
|
pheap, pdataDst, pdataSrc));
|
|
|
|
ASSERT(pdataDst != NULL);
|
|
ASSERT(pdataSrc != NULL);
|
|
if (pdataDst != pdataSrc)
|
|
{
|
|
MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
|
|
if (pdataSrc->pbDataBuff != NULL)
|
|
{
|
|
if ((pdataDst->pbDataBuff = NEWOBJDATA(pheap, pdataSrc)) == NULL)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
|
|
("DupObjData: failed to allocate destination buffer"));
|
|
}
|
|
else if (pdataSrc->dwDataType == OBJTYPE_PKGDATA)
|
|
{
|
|
PPACKAGEOBJ ppkgSrc = (PPACKAGEOBJ)pdataSrc->pbDataBuff,
|
|
ppkgDst = (PPACKAGEOBJ)pdataDst->pbDataBuff;
|
|
int i;
|
|
|
|
ppkgDst->dwcElements = ppkgSrc->dwcElements;
|
|
for (i = 0; i < (int)ppkgSrc->dwcElements; ++i)
|
|
{
|
|
if ((rc = DupObjData(pheap, &ppkgDst->adata[i],
|
|
&ppkgSrc->adata[i])) != STATUS_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MEMCPY(pdataDst->pbDataBuff, pdataSrc->pbDataBuff,
|
|
pdataSrc->dwDataLen);
|
|
}
|
|
pdataDst->dwfData &= ~DATAF_BUFF_ALIAS;
|
|
pdataDst->dwRefCount = 0;
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("DupObjData=%x\n", rc));
|
|
return rc;
|
|
} //DupObjData
|
|
|
|
/***LP CopyObjBuffer - Copy object data to a buffer
|
|
*
|
|
* ENTRY
|
|
* pbBuff -> buffer
|
|
* dwLen - buffer size
|
|
* pdata -> object
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL CopyObjBuffer(PUCHAR pbBuff, ULONG dwLen, POBJDATA pdata)
|
|
{
|
|
TRACENAME("COPYOBJBUFFER")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
PUCHAR pb = NULL;
|
|
ULONG dwcb = 0;
|
|
|
|
ENTER(3, ("CopyObjBuffer(pbBuff=%x,Len=%d,pdata=%x)\n",
|
|
pbBuff, dwLen, pdata));
|
|
|
|
switch (pdata->dwDataType)
|
|
{
|
|
case OBJTYPE_INTDATA:
|
|
pb = (PUCHAR)&pdata->uipDataValue;
|
|
dwcb = sizeof(ULONG);
|
|
break;
|
|
|
|
case OBJTYPE_STRDATA:
|
|
pb = pdata->pbDataBuff;
|
|
dwcb = pdata->dwDataLen - 1;
|
|
break;
|
|
|
|
case OBJTYPE_BUFFDATA:
|
|
pb = pdata->pbDataBuff;
|
|
dwcb = pdata->dwDataLen;
|
|
break;
|
|
|
|
default:
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
|
|
("CopyObjBuffer: invalid source object type (type=%s)",
|
|
GetObjectTypeName(pdata->dwDataType)));
|
|
}
|
|
|
|
if ((rc == STATUS_SUCCESS) && (pbBuff != pb))
|
|
{
|
|
MEMZERO(pbBuff, dwLen);
|
|
dwcb = MIN(dwLen, dwcb);
|
|
MEMCPY(pbBuff, pb, dwcb);
|
|
}
|
|
|
|
EXIT(3, ("CopyObjBuffer=%x (CopyLen=%d)\n", rc, dwcb));
|
|
return rc;
|
|
} //CopyObjBuffer
|
|
|
|
/***LP AcquireGL - acquire global lock
|
|
*
|
|
* ENTRY
|
|
* pctxt -> CTXT
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL AcquireGL(PCTXT pctxt)
|
|
{
|
|
TRACENAME("ACQUIREGL")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("AcquireGL(pctxt=%x)\n", pctxt));
|
|
|
|
if (ghGlobalLock.pfnHandler != NULL)
|
|
{
|
|
ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
|
|
rc = ((PFNGL)ghGlobalLock.pfnHandler)(EVTYPE_ACQREL_GLOBALLOCK,
|
|
GLOBALLOCK_ACQUIRE,
|
|
ghGlobalLock.uipParam,
|
|
RestartCtxtCallback,
|
|
&pctxt->CtxtData);
|
|
if (rc == STATUS_PENDING)
|
|
{
|
|
rc = AMLISTA_PENDING;
|
|
}
|
|
else if (rc != STATUS_SUCCESS)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_ACQUIREGL_FAILED,
|
|
("AcquireGL: failed to acquire global lock"));
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("AcquireGL=%x\n", rc));
|
|
return rc;
|
|
} //AcquireGL
|
|
|
|
/***LP ReleaseGL - release global lock if acquired
|
|
*
|
|
* ENTRY
|
|
* pctxt -> CTXT
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL ReleaseGL(PCTXT pctxt)
|
|
{
|
|
TRACENAME("RELEASEGL")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("ReleaseGL(pctxt=%x)\n", pctxt));
|
|
|
|
if (ghGlobalLock.pfnHandler != NULL)
|
|
{
|
|
rc = ((PFNGL)ghGlobalLock.pfnHandler)(EVTYPE_ACQREL_GLOBALLOCK,
|
|
GLOBALLOCK_RELEASE,
|
|
ghGlobalLock.uipParam, NULL,
|
|
&pctxt->CtxtData);
|
|
}
|
|
|
|
EXIT(3, ("ReleaseGL=%x\n", rc));
|
|
return rc;
|
|
} //ReleaseGL
|
|
|
|
/***LP MapUnmapPhysMem - Map/Unmap physical memory
|
|
*
|
|
* ENTRY
|
|
* pctxt -> CTXT (can be NULL if cannot handle STATUS_PENDING)
|
|
* uipAddr - physical address
|
|
* dwLen - length of memory range
|
|
* puipMappedAddr -> to hold memory address mapped (NULL if unmap)
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL MapUnmapPhysMem(PCTXT pctxt, ULONG_PTR uipAddr, ULONG dwLen,
|
|
PULONG_PTR puipMappedAddr)
|
|
{
|
|
TRACENAME("MAPUNMAPPHYSMEM")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("MapUnmapPhysMem(pctxt=%x,Addr=%x,Len=%d,pMappedAddr=%x)\n",
|
|
pctxt, uipAddr, dwLen, puipMappedAddr));
|
|
|
|
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
|
|
{
|
|
if (puipMappedAddr != NULL)
|
|
{
|
|
*puipMappedAddr = MapPhysMem(uipAddr, dwLen);
|
|
}
|
|
else
|
|
{
|
|
MmUnmapIoSpace((PVOID)uipAddr, dwLen);
|
|
}
|
|
}
|
|
else if (pctxt != NULL)
|
|
{
|
|
PPASSIVEHOOK pph;
|
|
|
|
if ((pph = NEWPHOBJ(sizeof(PASSIVEHOOK))) == NULL)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
|
|
("MapUnmapPhysMem: failed to allocate passive hook"));
|
|
}
|
|
else
|
|
{
|
|
pph->pctxt = pctxt;
|
|
pph->uipAddr = uipAddr;
|
|
pph->dwLen = dwLen;
|
|
pph->puipMappedAddr = puipMappedAddr;
|
|
ExInitializeWorkItem(&pph->WorkItem, MapUnmapCallBack, pph);
|
|
OSQueueWorkItem(&pph->WorkItem);
|
|
|
|
rc = AMLISTA_PENDING;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_FATAL,
|
|
("MapUnmapPhysMem: IRQL is not at PASSIVE (IRQL=%x)",
|
|
KeGetCurrentIrql()));
|
|
}
|
|
|
|
EXIT(3, ("MapUnmapPhysMem=%x (MappedAddr=%x)\n",
|
|
rc, puipMappedAddr? *puipMappedAddr: 0));
|
|
return rc;
|
|
} //MapUnmapPhysMem
|
|
|
|
/***LP MapPhysMem - Map physical memory
|
|
*
|
|
* ENTRY
|
|
* uipAddr - physical memory address
|
|
* dwLen - length of memory block
|
|
*
|
|
* EXIT
|
|
* returns mapped address
|
|
*/
|
|
|
|
ULONG_PTR LOCAL MapPhysMem(ULONG_PTR uipAddr, ULONG dwLen)
|
|
{
|
|
TRACENAME("MAPPHYSMEM")
|
|
ULONG_PTR uipMappedAddr = 0;
|
|
PHYSICAL_ADDRESS phyaddr = {0, 0}, XlatedAddr;
|
|
ULONG dwAddrSpace;
|
|
|
|
ENTER(3, ("MapPhysMem(Addr=%x,Len=%d)\n", uipAddr, dwLen));
|
|
|
|
phyaddr.HighPart = 0;
|
|
phyaddr.QuadPart = uipAddr;
|
|
dwAddrSpace = 0;
|
|
if (HalTranslateBusAddress(Internal, 0, phyaddr, &dwAddrSpace, &XlatedAddr))
|
|
{
|
|
uipMappedAddr = (ULONG_PTR)MmMapIoSpace(XlatedAddr, dwLen, FALSE);
|
|
}
|
|
|
|
EXIT(3, ("MapPhysMem=%x", uipMappedAddr));
|
|
return uipMappedAddr;
|
|
} //MapPhysMem
|
|
|
|
/***LP MapUnmapCallBack - Map/Unmap physical memory callback
|
|
*
|
|
* ENTRY
|
|
* pph -> PASSIVEHOOK
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID MapUnmapCallBack(PPASSIVEHOOK pph)
|
|
{
|
|
TRACENAME("MAPUNMAPCALLBACK")
|
|
|
|
ENTER(3, ("MapUnmapCallBack(pph=%x,pctxt=%x,Addr=%x,Len=%d,pdwMappedAddr=%x)\n",
|
|
pph, pph->pctxt, pph->uipAddr, pph->dwLen, pph->puipMappedAddr));
|
|
|
|
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
|
|
|
if (pph->puipMappedAddr != NULL)
|
|
{
|
|
*pph->puipMappedAddr = MapPhysMem(pph->uipAddr, pph->dwLen);
|
|
}
|
|
else
|
|
{
|
|
MmUnmapIoSpace((PVOID)pph->uipAddr, pph->dwLen);
|
|
}
|
|
|
|
RestartContext(pph->pctxt,
|
|
(BOOLEAN)((pph->pctxt->dwfCtxt & CTXTF_ASYNC_EVAL) == 0));
|
|
|
|
FREEPHOBJ(pph);
|
|
|
|
EXIT(3, ("MapUnmapCallBack!\n"));
|
|
} //MapUnmapCallBack
|
|
|
|
/***LP MatchObjType - match object type
|
|
*
|
|
* ENTRY
|
|
* dwObjType - object type
|
|
* dwExpected - expected type
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TRUE - type matched
|
|
* EXIT-FAILURE
|
|
* returns FALSE - type mismatch
|
|
*/
|
|
|
|
BOOLEAN LOCAL MatchObjType(ULONG dwObjType, ULONG dwExpectedType)
|
|
{
|
|
TRACENAME("MATCHOBJTYPE")
|
|
BOOLEAN rc = FALSE;
|
|
|
|
ENTER(3, ("MatchObjType(ObjType=%s,Expected=%s)\n",
|
|
GetObjectTypeName(dwObjType), GetObjectTypeName(dwExpectedType)));
|
|
//
|
|
// OBJTYPE_BUFFFIELD is essentially OBJTYPE_INTDATA, so we'll let
|
|
// it pass the check.
|
|
//
|
|
if ((dwObjType == OBJTYPE_BUFFFIELD) &&
|
|
(dwExpectedType == OBJTYPE_INTDATA))
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
else if ((dwExpectedType == OBJTYPE_UNKNOWN) ||
|
|
(dwObjType == OBJTYPE_UNKNOWN) ||
|
|
(dwObjType == dwExpectedType))
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if ((dwObjType == OBJTYPE_INTDATA) ||
|
|
(dwObjType == OBJTYPE_STRDATA) ||
|
|
(dwObjType == OBJTYPE_BUFFDATA) ||
|
|
(dwObjType == OBJTYPE_PKGDATA))
|
|
{
|
|
dwObjType = OBJTYPE_DATA;
|
|
}
|
|
else if ((dwObjType == OBJTYPE_FIELDUNIT) ||
|
|
(dwObjType == OBJTYPE_BUFFFIELD))
|
|
{
|
|
dwObjType = OBJTYPE_DATAFIELD;
|
|
}
|
|
|
|
if ((dwObjType == dwExpectedType) ||
|
|
(dwExpectedType == OBJTYPE_DATAOBJ) &&
|
|
((dwObjType == OBJTYPE_DATA) || (dwObjType == OBJTYPE_DATAFIELD)))
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("MatchObjType=%x\n", rc));
|
|
return rc;
|
|
} //MatchObjType
|
|
|
|
/***LP ValidateTarget - Validate target object type
|
|
*
|
|
* ENTRY
|
|
* pdataTarget -> target object data
|
|
* dwExpectedType - expected target object type
|
|
* ppdata -> to hold base target object data pointer
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL ValidateTarget(POBJDATA pdataTarget, ULONG dwExpectedType,
|
|
POBJDATA *ppdata)
|
|
{
|
|
TRACENAME("VALIDATETARGET")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("ValidateTarget(pdataTarget=%x,ExpectedType=%s,ppdata=%x)\n",
|
|
pdataTarget, GetObjectTypeName(dwExpectedType), ppdata));
|
|
|
|
ASSERT(pdataTarget != NULL);
|
|
if (pdataTarget->dwDataType == OBJTYPE_OBJALIAS)
|
|
{
|
|
*ppdata = &pdataTarget->pnsAlias->ObjData;
|
|
}
|
|
else if (pdataTarget->dwDataType == OBJTYPE_DATAALIAS)
|
|
{
|
|
*ppdata = pdataTarget->pdataAlias;
|
|
}
|
|
else if ((pdataTarget->dwDataType == OBJTYPE_UNKNOWN) ||
|
|
(pdataTarget->dwDataType == OBJTYPE_BUFFFIELD) ||
|
|
(pdataTarget->dwDataType == OBJTYPE_DEBUG))
|
|
{
|
|
*ppdata = pdataTarget;
|
|
}
|
|
else
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_TARGETTYPE,
|
|
("ValidateTarget: target is not a supername (Type=%s)",
|
|
GetObjectTypeName(pdataTarget->dwDataType)));
|
|
}
|
|
|
|
if ((rc == STATUS_SUCCESS) &&
|
|
(pdataTarget->dwDataType == OBJTYPE_OBJALIAS) &&
|
|
!MatchObjType((*ppdata)->dwDataType, dwExpectedType))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_TARGETTYPE,
|
|
("ValidateTarget: unexpected target type (Type=%s,Expected=%s)",
|
|
GetObjectTypeName((*ppdata)->dwDataType),
|
|
GetObjectTypeName(dwExpectedType)));
|
|
}
|
|
|
|
if ((rc == STATUS_SUCCESS) &&
|
|
(pdataTarget->dwDataType != OBJTYPE_OBJALIAS) &&
|
|
MatchObjType((*ppdata)->dwDataType, OBJTYPE_DATA))
|
|
{
|
|
FreeDataBuffs(*ppdata, 1);
|
|
}
|
|
|
|
EXIT(3, ("ValidateTarget=%x (pdataTarget=%x)\n", rc, *ppdata));
|
|
return rc;
|
|
} //ValidateTarget
|
|
|
|
/***LP ValidateArgTypes - Validate argument types
|
|
*
|
|
* ENTRY
|
|
* pArgs -> argument array
|
|
* pszExpectedTypes -> expected argument types string
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL ValidateArgTypes(POBJDATA pArgs, PSZ pszExpectedTypes)
|
|
{
|
|
TRACENAME("VALIDATEARGTYPES")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
int icArgs, i;
|
|
|
|
ENTER(3, ("ValidateArgTypes(pArgs=%x,ExpectedTypes=%s)\n",
|
|
pArgs, pszExpectedTypes));
|
|
|
|
ASSERT(pszExpectedTypes != NULL);
|
|
|
|
icArgs = STRLEN(pszExpectedTypes);
|
|
for (i = 0; (rc == STATUS_SUCCESS) && (i < icArgs); ++i)
|
|
{
|
|
switch (pszExpectedTypes[i])
|
|
{
|
|
case ARGOBJ_UNKNOWN:
|
|
break;
|
|
|
|
case ARGOBJ_INTDATA:
|
|
if (pArgs[i].dwDataType != OBJTYPE_INTDATA)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type Integer (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_STRDATA:
|
|
if (pArgs[i].dwDataType != OBJTYPE_STRDATA)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type String (Type-%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_BUFFDATA:
|
|
if (pArgs[i].dwDataType != OBJTYPE_BUFFDATA)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type Buffer (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_PKGDATA:
|
|
if (pArgs[i].dwDataType != OBJTYPE_PKGDATA)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type Package (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_FIELDUNIT:
|
|
if (pArgs[i].dwDataType != OBJTYPE_FIELDUNIT)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type FieldUnit (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_OBJALIAS:
|
|
if (pArgs[i].dwDataType != OBJTYPE_OBJALIAS)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type ObjAlias (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_DATAALIAS:
|
|
if (pArgs[i].dwDataType != OBJTYPE_DATAALIAS)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type DataAlias (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_BASICDATA:
|
|
if ((pArgs[i].dwDataType != OBJTYPE_INTDATA) &&
|
|
(pArgs[i].dwDataType != OBJTYPE_STRDATA) &&
|
|
(pArgs[i].dwDataType != OBJTYPE_BUFFDATA))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type int/str/buff (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_COMPLEXDATA:
|
|
if ((pArgs[i].dwDataType != OBJTYPE_BUFFDATA) &&
|
|
(pArgs[i].dwDataType != OBJTYPE_PKGDATA))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type buff/pkg (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
case ARGOBJ_REFERENCE:
|
|
if ((pArgs[i].dwDataType != OBJTYPE_OBJALIAS) &&
|
|
(pArgs[i].dwDataType != OBJTYPE_DATAALIAS) &&
|
|
(pArgs[i].dwDataType != OBJTYPE_BUFFFIELD))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
|
|
("ValidateArgTypes: expected Arg%d to be type reference (Type=%s)",
|
|
i,
|
|
GetObjectTypeName(pArgs[i].dwDataType)));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
|
|
("ValidateArgTypes: internal error (invalid type - %c)",
|
|
pszExpectedTypes[i]));
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("ValidateArgTypes=%x\n", rc));
|
|
return rc;
|
|
} //ValidateArgTypes
|
|
|
|
/***LP RegEventHandler - register event handler
|
|
*
|
|
* ENTRY
|
|
* peh -> EVHANDLE
|
|
* pfnHandler -> handler entry point
|
|
* uipParam - parameter pass to handler
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL RegEventHandler(PEVHANDLE peh, PFNHND pfnHandler,
|
|
ULONG_PTR uipParam)
|
|
{
|
|
TRACENAME("REGEVENTHANDLER")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("RegEventHandler(peh=%x,pfnHandler=%x,Param=%x)\n",
|
|
peh, pfnHandler, uipParam));
|
|
|
|
if ((peh->pfnHandler != NULL) && (pfnHandler != NULL))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
|
|
("RegEventHandler: event handler already exist"));
|
|
}
|
|
else
|
|
{
|
|
peh->pfnHandler = pfnHandler;
|
|
peh->uipParam = uipParam;
|
|
}
|
|
|
|
EXIT(3, ("RegEventHandler=%x\n", rc));
|
|
return rc;
|
|
} //RegEventHandler
|
|
|
|
/***LP RegOpcodeHandler - register an opcode callback handler
|
|
*
|
|
* The callback handler will be called after the opcode finishes its
|
|
* execution. If an opcode has a variable list, the opcode handler
|
|
* will be called at the point of processing the closing brace.
|
|
*
|
|
* ENTRY
|
|
* dwOpcode - opcode event to hook
|
|
* pfnHandler -> handler entry point
|
|
* uipParam - parameter pass to handler
|
|
* dwfOpcode - opcode flags
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL RegOpcodeHandler(ULONG dwOpcode, PFNOH pfnHandler,
|
|
ULONG_PTR uipParam, ULONG dwfOpcode)
|
|
{
|
|
TRACENAME("REGOPCODEHANDLER")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
PAMLTERM pamlterm;
|
|
|
|
ENTER(3, ("RegOpcodeHandler(Opcode=%x,pfnHandler=%x,Param=%x,dwfOpcode=%x)\n",
|
|
dwOpcode, pfnHandler, uipParam, dwfOpcode));
|
|
|
|
if ((dwOpcode & 0xff) == OP_EXT_PREFIX)
|
|
pamlterm = FindOpcodeTerm(dwOpcode >> 8, ExOpcodeTable);
|
|
else
|
|
pamlterm = OpcodeTable[dwOpcode];
|
|
|
|
if (pamlterm == NULL)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_REGHANDLER_FAILED,
|
|
("RegOpcodeHandler: either invalid opcode or "
|
|
"opcode does not allow callback"));
|
|
}
|
|
else if ((pamlterm->pfnCallBack != NULL) && (pfnHandler != NULL))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
|
|
("RegOpcodeHandler: opcode or opcode class already "
|
|
"has a handler"));
|
|
}
|
|
else
|
|
{
|
|
pamlterm->pfnCallBack = pfnHandler;
|
|
pamlterm->dwCBData = (ULONG)uipParam;
|
|
pamlterm->dwfOpcode |= dwfOpcode;
|
|
}
|
|
|
|
EXIT(3, ("RegOpcodeHandler=%x\n", rc));
|
|
return rc;
|
|
} //RegOpcodeHandler
|
|
|
|
/***LP RegRSAccess - register region space cook/raw access handler
|
|
*
|
|
* ENTRY
|
|
* dwRegionSpace - specifying the region space to handle
|
|
* pfnHandler -> handler entry point
|
|
* uipParam - parameter pass to handler
|
|
* fRaw - TRUE if registering raw access handler
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns STATUS_SUCCESS
|
|
* EXIT-FAILURE
|
|
* returns AMLIERR_ code
|
|
*/
|
|
|
|
NTSTATUS LOCAL RegRSAccess(ULONG dwRegionSpace, PFNHND pfnHandler,
|
|
ULONG_PTR uipParam, BOOLEAN fRaw)
|
|
{
|
|
TRACENAME("REGRSACCESS")
|
|
NTSTATUS rc = STATUS_SUCCESS;
|
|
|
|
ENTER(3, ("RegRSAccess(RegionSpace=%x,pfnHandler=%x,Param=%x,fRaw=%x)\n",
|
|
dwRegionSpace, pfnHandler, uipParam, fRaw));
|
|
|
|
if ((dwRegionSpace != REGSPACE_MEM) && (dwRegionSpace != REGSPACE_IO))
|
|
{
|
|
PRSACCESS prsa;
|
|
|
|
if ((prsa = FindRSAccess(dwRegionSpace)) == NULL)
|
|
{
|
|
if ((prsa = NEWRSOBJ(sizeof(RSACCESS))) == NULL)
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
|
|
("RegRSAccess: failed to allocate handler structure"));
|
|
}
|
|
else
|
|
{
|
|
MEMZERO(prsa, sizeof(RSACCESS));
|
|
prsa->dwRegionSpace = dwRegionSpace;
|
|
prsa->prsaNext = gpRSAccessHead;
|
|
gpRSAccessHead = prsa;
|
|
}
|
|
}
|
|
|
|
if (rc == STATUS_SUCCESS)
|
|
{
|
|
if (fRaw)
|
|
{
|
|
if ((prsa->pfnRawAccess != NULL) && (pfnHandler != NULL))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
|
|
("RegRSAccess: RawAccess for RegionSpace %x "
|
|
"already have a handler", dwRegionSpace));
|
|
}
|
|
else
|
|
{
|
|
prsa->pfnRawAccess = (PFNRA)pfnHandler;
|
|
prsa->uipRawParam = uipParam;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((prsa->pfnCookAccess != NULL) && (pfnHandler != NULL))
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
|
|
("RegRSAccess: CookAccess for RegionSpace %x "
|
|
"already have a handler", dwRegionSpace));
|
|
}
|
|
else
|
|
{
|
|
prsa->pfnCookAccess = (PFNCA)pfnHandler;
|
|
prsa->uipCookParam = uipParam;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = AMLI_LOGERR(AMLIERR_INVALID_REGIONSPACE,
|
|
("RegRSAccess: illegal region space - %x",
|
|
dwRegionSpace));
|
|
}
|
|
|
|
EXIT(3, ("RegRSAccess=%x\n", rc));
|
|
return rc;
|
|
} //RegRSAccess
|
|
|
|
/***LP FindRSAccess - Find RSACCESS structure with a given RegionSpace
|
|
*
|
|
* ENTRY
|
|
* dwRegionSpace - region space
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns the pointer to the structure found
|
|
* EXIT-FAILURE
|
|
* returns NULL
|
|
*/
|
|
|
|
PRSACCESS LOCAL FindRSAccess(ULONG dwRegionSpace)
|
|
{
|
|
TRACENAME("FINDRSACCESS")
|
|
PRSACCESS prsa;
|
|
|
|
ENTER(3, ("FindRSAccess(RegionSpace=%x)\n", dwRegionSpace));
|
|
|
|
for (prsa = gpRSAccessHead; prsa != NULL; prsa = prsa->prsaNext)
|
|
{
|
|
if (prsa->dwRegionSpace == dwRegionSpace)
|
|
break;
|
|
}
|
|
|
|
EXIT(3, ("FindRSAccess=%x\n", prsa));
|
|
return prsa;
|
|
} //FindRSAccess
|
|
|
|
/***LP FreeRSAccessList - free the RSACCESS structure list
|
|
*
|
|
* ENTRY
|
|
* prsa -> RSACCESS list
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL FreeRSAccessList(PRSACCESS prsa)
|
|
{
|
|
TRACENAME("FREERSACCESSLIST")
|
|
PRSACCESS prsaNext;
|
|
|
|
ENTER(3, ("FreeRSAccessList(prsa=%x)\n", prsa));
|
|
|
|
while (prsa != NULL)
|
|
{
|
|
prsaNext = prsa->prsaNext;
|
|
FREERSOBJ(prsa);
|
|
prsa = prsaNext;
|
|
}
|
|
|
|
EXIT(3, ("FreeRSAccessList!\n"));
|
|
} //FreeRSAccessList
|
|
|
|
/***LP GetObjectPath - get object namespace path
|
|
*
|
|
* ENTRY
|
|
* pns -> object
|
|
*
|
|
* EXIT
|
|
* returns name space path
|
|
*/
|
|
|
|
PSZ LOCAL GetObjectPath(PNSOBJ pns)
|
|
{
|
|
TRACENAME("GETOBJECTPATH")
|
|
static char szPath[MAX_NAME_LEN + 1] = {0};
|
|
int i;
|
|
|
|
ENTER(4, ("GetObjectPath(pns=%x)\n", pns));
|
|
|
|
if (pns != NULL)
|
|
{
|
|
if (pns->pnsParent == NULL)
|
|
STRCPY(szPath, "\\");
|
|
else
|
|
{
|
|
GetObjectPath(pns->pnsParent);
|
|
if (pns->pnsParent->pnsParent != NULL)
|
|
STRCAT(szPath, ".");
|
|
STRCATN(szPath, (PSZ)&pns->dwNameSeg, sizeof(NAMESEG));
|
|
}
|
|
|
|
|
|
for (i = STRLEN(szPath) - 1; i >= 0; --i)
|
|
{
|
|
if (szPath[i] == '_')
|
|
szPath[i] = '\0';
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szPath[0] = '\0';
|
|
}
|
|
|
|
EXIT(4, ("GetObjectPath=%s\n", szPath));
|
|
return szPath;
|
|
} //GetObjectPath
|
|
|
|
#ifdef DEBUGGER
|
|
|
|
/***LP NameSegString - convert a NameSeg to an ASCIIZ string
|
|
*
|
|
* ENTRY
|
|
* dwNameSeg - NameSeg
|
|
*
|
|
* EXIT
|
|
* returns string
|
|
*/
|
|
|
|
PSZ LOCAL NameSegString(ULONG dwNameSeg)
|
|
{
|
|
TRACENAME("NAMESEGSTRING")
|
|
static char szNameSeg[sizeof(NAMESEG) + 1] = {0};
|
|
|
|
ENTER(5, ("NameSegString(dwNameSeg=%x)\n", dwNameSeg));
|
|
|
|
STRCPYN(szNameSeg, (PSZ)&dwNameSeg, sizeof(NAMESEG));
|
|
|
|
EXIT(5, ("NameSegString=%s\n", szNameSeg));
|
|
return szNameSeg;
|
|
} //NameSegString
|
|
|
|
|
|
/***LP GetObjectTypeName - get object type name
|
|
*
|
|
* ENTRY
|
|
* dwObjType - object type
|
|
*
|
|
* EXIT
|
|
* return object type name
|
|
*/
|
|
|
|
PSZ LOCAL GetObjectTypeName(ULONG dwObjType)
|
|
{
|
|
TRACENAME("GETOBJECTTYPENAME")
|
|
PSZ psz = NULL;
|
|
int i;
|
|
static struct
|
|
{
|
|
ULONG dwObjType;
|
|
PSZ pszObjTypeName;
|
|
} ObjTypeTable[] =
|
|
{
|
|
OBJTYPE_UNKNOWN, "Unknown",
|
|
OBJTYPE_INTDATA, "Integer",
|
|
OBJTYPE_STRDATA, "String",
|
|
OBJTYPE_BUFFDATA, "Buffer",
|
|
OBJTYPE_PKGDATA, "Package",
|
|
OBJTYPE_FIELDUNIT, "FieldUnit",
|
|
OBJTYPE_DEVICE, "Device",
|
|
OBJTYPE_EVENT, "Event",
|
|
OBJTYPE_METHOD, "Method",
|
|
OBJTYPE_MUTEX, "Mutex",
|
|
OBJTYPE_OPREGION, "OpRegion",
|
|
OBJTYPE_POWERRES, "PowerResource",
|
|
OBJTYPE_PROCESSOR, "Processor",
|
|
OBJTYPE_THERMALZONE,"ThermalZone",
|
|
OBJTYPE_BUFFFIELD, "BuffField",
|
|
OBJTYPE_DDBHANDLE, "DDBHandle",
|
|
OBJTYPE_DEBUG, "Debug",
|
|
OBJTYPE_OBJALIAS, "ObjAlias",
|
|
OBJTYPE_DATAALIAS, "DataAlias",
|
|
OBJTYPE_BANKFIELD, "BankField",
|
|
OBJTYPE_FIELD, "Field",
|
|
OBJTYPE_INDEXFIELD, "IndexField",
|
|
OBJTYPE_DATA, "Data",
|
|
OBJTYPE_DATAFIELD, "DataField",
|
|
OBJTYPE_DATAOBJ, "DataObject",
|
|
0, NULL
|
|
};
|
|
|
|
ENTER(4, ("GetObjectTypeName(Type=%x)\n", dwObjType));
|
|
|
|
for (i = 0; ObjTypeTable[i].pszObjTypeName != NULL; ++i)
|
|
{
|
|
if (dwObjType == ObjTypeTable[i].dwObjType)
|
|
{
|
|
psz = ObjTypeTable[i].pszObjTypeName;
|
|
break;
|
|
}
|
|
}
|
|
|
|
EXIT(4, ("GetObjectTypeName=%s\n", psz? psz: "NULL"));
|
|
return psz;
|
|
} //GetObjectTypeName
|
|
|
|
/***LP GetRegionSpaceName - get region space name
|
|
*
|
|
* ENTRY
|
|
* bRegionSpace - region space
|
|
*
|
|
* EXIT
|
|
* return object type name
|
|
*/
|
|
|
|
PSZ LOCAL GetRegionSpaceName(UCHAR bRegionSpace)
|
|
{
|
|
TRACENAME("GETREGIONSPACENAME")
|
|
PSZ psz = NULL;
|
|
int i;
|
|
static PSZ pszVendorDefined = "VendorDefined";
|
|
static struct
|
|
{
|
|
UCHAR bRegionSpace;
|
|
PSZ pszRegionSpaceName;
|
|
} RegionNameTable[] =
|
|
{
|
|
REGSPACE_MEM, "SystemMemory",
|
|
REGSPACE_IO, "SystemIO",
|
|
REGSPACE_PCICFG, "PCIConfigSpace",
|
|
REGSPACE_EC, "EmbeddedController",
|
|
REGSPACE_SMB, "SMBus",
|
|
0, NULL
|
|
};
|
|
|
|
ENTER(4, ("GetRegionSpaceName(RegionSpace=%x)\n", bRegionSpace));
|
|
|
|
for (i = 0; RegionNameTable[i].pszRegionSpaceName != NULL; ++i)
|
|
{
|
|
if (bRegionSpace == RegionNameTable[i].bRegionSpace)
|
|
{
|
|
psz = RegionNameTable[i].pszRegionSpaceName;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (psz == NULL)
|
|
{
|
|
psz = pszVendorDefined;
|
|
}
|
|
|
|
EXIT(4, ("GetRegionSpaceName=%s\n", psz? psz: "NULL"));
|
|
return psz;
|
|
} //GetRegionSpaceName
|
|
#endif //ifdef DEBUGGER
|
|
|
|
/***LP ValidateTable - Validate the table creator and revision
|
|
*
|
|
* ENTRY
|
|
* pdsdt -> DSDT
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns TRUE
|
|
* EXIT-FAILURE
|
|
* returns FALSE
|
|
*/
|
|
|
|
BOOLEAN LOCAL ValidateTable(PDSDT pdsdt)
|
|
{
|
|
TRACENAME("VALIDATETABLE")
|
|
BOOLEAN rc = TRUE;
|
|
|
|
ENTER(3, ("ValidateTable(pdsdt=%x)\n", pdsdt));
|
|
|
|
if (!(gdwfAMLIInit & AMLIIF_NOCHK_TABLEVER) &&
|
|
(STRCMPN((PSZ)pdsdt->Header.CreatorID, CREATORID_MSFT,
|
|
sizeof(pdsdt->Header.CreatorID)) == 0))
|
|
{
|
|
if (pdsdt->Header.CreatorRev < MIN_CREATOR_REV)
|
|
{
|
|
rc = FALSE;
|
|
}
|
|
}
|
|
|
|
EXIT(3, ("ValidateTable=%x\n", rc));
|
|
return rc;
|
|
} //ValidateTable
|
|
|
|
/***LP NewObjData - allocate new object data identical to a given old object
|
|
*
|
|
* ENTRY
|
|
* pheap -> HEAP
|
|
* pdata -> old object
|
|
*
|
|
* EXIT-SUCCESS
|
|
* returns pointer to the new data
|
|
* EXIT-FAILURE
|
|
* returns NULL
|
|
*/
|
|
|
|
PVOID LOCAL NewObjData(PHEAP pheap, POBJDATA pdata)
|
|
{
|
|
PVOID pv = NULL;
|
|
|
|
switch (pdata->dwDataType)
|
|
{
|
|
case OBJTYPE_STRDATA:
|
|
pv = NEWSDOBJ(gpheapGlobal, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFDATA:
|
|
pv = NEWBDOBJ(gpheapGlobal, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_PKGDATA:
|
|
pv = NEWPKOBJ(gpheapGlobal, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_FIELDUNIT:
|
|
pv = NEWFUOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_EVENT:
|
|
pv = NEWEVOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_METHOD:
|
|
pv = NEWMEOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_MUTEX:
|
|
pv = NEWMTOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_OPREGION:
|
|
pv = NEWOROBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_POWERRES:
|
|
pv = NEWPROBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_PROCESSOR:
|
|
pv = NEWPCOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFFIELD:
|
|
pv = NEWBFOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_BANKFIELD:
|
|
pv = NEWKFOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_FIELD:
|
|
pv = NEWFOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
case OBJTYPE_INDEXFIELD:
|
|
pv = NEWIFOBJ(pheap, pdata->dwDataLen);
|
|
break;
|
|
|
|
default:
|
|
AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
|
|
("NewObjData: invalid object type %s",
|
|
GetObjectTypeName(pdata->dwDataType)));
|
|
}
|
|
|
|
return pv;
|
|
} //NewObjData
|
|
|
|
/***LP FreeObjData - Free object data
|
|
*
|
|
* ENTRY
|
|
* pdata -> object which its data is to be freed
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL FreeObjData(POBJDATA pdata)
|
|
{
|
|
switch (pdata->dwDataType)
|
|
{
|
|
case OBJTYPE_STRDATA:
|
|
FREESDOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFDATA:
|
|
FREEBDOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_PKGDATA:
|
|
FREEPKOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_FIELDUNIT:
|
|
FREEFUOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_EVENT:
|
|
FREEEVOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_METHOD:
|
|
FREEMEOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_MUTEX:
|
|
FREEMTOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_OPREGION:
|
|
FREEOROBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_POWERRES:
|
|
FREEPROBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_PROCESSOR:
|
|
FREEPCOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_BUFFFIELD:
|
|
FREEBFOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_BANKFIELD:
|
|
FREEKFOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_FIELD:
|
|
FREEFOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
case OBJTYPE_INDEXFIELD:
|
|
FREEIFOBJ(pdata->pbDataBuff);
|
|
break;
|
|
|
|
default:
|
|
AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
|
|
("FreeObjData: invalid object type %s",
|
|
GetObjectTypeName(pdata->dwDataType)));
|
|
}
|
|
} //FreeObjData
|
|
|
|
/*** LP InitializeRegOverrideFlags - Get override flags from
|
|
* the registry.
|
|
*
|
|
* ENTRY
|
|
* None
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
VOID LOCAL InitializeRegOverrideFlags(VOID)
|
|
{
|
|
TRACENAME("InitializeRegOverrideFlags")
|
|
HANDLE hRegKey=NULL;
|
|
NTSTATUS status;
|
|
ULONG argSize;
|
|
|
|
ENTER(3, ("InitializeRegOverrideFlags\n"));
|
|
|
|
status = OSOpenHandle(ACPI_PARAMETERS_REGISTRY_KEY, NULL, &hRegKey);
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
argSize = sizeof(gOverrideFlags);
|
|
OSReadRegValue(AMLI_ATTRIBUTES, hRegKey, &gOverrideFlags, &argSize);
|
|
}
|
|
else
|
|
{
|
|
gOverrideFlags = 0;
|
|
}
|
|
|
|
EXIT(3, ("InitializeRegOverrideFlags\n"));
|
|
return;
|
|
}
|
|
|
|
|
|
/*** LP ValidateMemoryOpregionRange - Validate the memory range that is
|
|
* required for the memory opregion.
|
|
*
|
|
* ENTRY
|
|
* uipAddr - physical memory address
|
|
* dwLen - length of memory block
|
|
*
|
|
* EXIT
|
|
* returns TRUE iff the memory is in the legal range.
|
|
*/
|
|
BOOLEAN LOCAL ValidateMemoryOpregionRange(ULONG_PTR uipAddr, ULONG dwLen)
|
|
{
|
|
BOOLEAN Ret = FALSE;
|
|
NTSTATUS status;
|
|
PACPI_BIOS_MULTI_NODE e820Info;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartialDesc;
|
|
PCM_PARTIAL_RESOURCE_LIST cmPartialList;
|
|
PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 keyInfo;
|
|
ULONGLONG i;
|
|
ULONGLONG absMin;
|
|
ULONGLONG absMax;
|
|
|
|
|
|
//
|
|
// Read the key for the AcpiConfigurationData
|
|
//
|
|
status = OSReadAcpiConfigurationData( &keyInfo );
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
PRINTF("ValidateMemoryOpregionRange: Cannot get E820 Information %08lx\n",
|
|
status
|
|
);
|
|
Ret = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Crack the structure to get the E820Table entry
|
|
//
|
|
cmPartialList = (PCM_PARTIAL_RESOURCE_LIST) (keyInfo->Data);
|
|
cmPartialDesc = &(cmPartialList->PartialDescriptors[0]);
|
|
e820Info = (PACPI_BIOS_MULTI_NODE) ( (PUCHAR) cmPartialDesc + sizeof(CM_PARTIAL_RESOURCE_LIST) );
|
|
|
|
//
|
|
// Calculate absmin and absmax for the incoming address
|
|
//
|
|
absMin = (ULONGLONG)uipAddr;
|
|
absMax = absMin + dwLen;
|
|
|
|
//
|
|
// walk the E820 list
|
|
//
|
|
for(i = 0; i < e820Info->Count; i++)
|
|
{
|
|
if (e820Info->E820Entry[i].Type == AcpiAddressRangeMemory)
|
|
{
|
|
if(absMax < (ULONGLONG)PAGE_SIZE)
|
|
{
|
|
Ret = TRUE;
|
|
PRINTF("ValidateMemoryOpregionRange: Memory OpRegion (Base = 0x%I64x, Length = 0x%x) is in first physical page, skipping check.\n",
|
|
absMin,
|
|
dwLen
|
|
);
|
|
}
|
|
else
|
|
{
|
|
if((absMax < (ULONGLONG) e820Info->E820Entry[i].Base.QuadPart)
|
|
||(absMin >= (ULONGLONG) (e820Info->E820Entry[i].Base.QuadPart + e820Info->E820Entry[i].Length.QuadPart)))
|
|
{
|
|
Ret = TRUE;
|
|
PRINTF("ValidateMemoryOpregionRange: Memory OpRegion (Base = 0x%I64x, Length = 0x%x) is not in AcpiAddressRangeMemory (Base = 0x%I64x, Length = 0x%I64x)\n",
|
|
absMin,
|
|
dwLen,
|
|
e820Info->E820Entry[i].Base.QuadPart,
|
|
e820Info->E820Entry[i].Length.QuadPart
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This opregion is mapping memory that belongs to the OS.
|
|
// Log a error in the event log.
|
|
//
|
|
|
|
PWCHAR illegalMemoryAddress[5];
|
|
WCHAR AMLIName[6];
|
|
WCHAR addressBuffer[64];
|
|
WCHAR addressLengthBuffer[64];
|
|
WCHAR OSaddressBufferRangeMin[64];
|
|
WCHAR OSaddressBufferRangeMax[64];
|
|
|
|
//
|
|
// Turn the address into a string
|
|
//
|
|
swprintf( AMLIName, L"AMLI");
|
|
swprintf( addressBuffer, L"0x%I64x", absMin );
|
|
swprintf( addressLengthBuffer, L"0x%lx", dwLen );
|
|
swprintf( OSaddressBufferRangeMin, L"0x%I64x", e820Info->E820Entry[i].Base.QuadPart );
|
|
swprintf( OSaddressBufferRangeMax, L"0x%I64x", e820Info->E820Entry[i].Base.QuadPart + e820Info->E820Entry[i].Length.QuadPart);
|
|
|
|
|
|
//
|
|
// Build the list of arguments to pass to the function that will write the
|
|
// error log to the registry
|
|
//
|
|
illegalMemoryAddress[0] = AMLIName;
|
|
illegalMemoryAddress[1] = addressBuffer;
|
|
illegalMemoryAddress[2] = addressLengthBuffer;
|
|
illegalMemoryAddress[3] = OSaddressBufferRangeMin;
|
|
illegalMemoryAddress[4] = OSaddressBufferRangeMax;
|
|
|
|
//
|
|
// Log error to event log
|
|
//
|
|
ACPIWriteEventLogEntry(ACPI_ERR_AMLI_ILLEGAL_MEMORY_OPREGION_FATAL,
|
|
&illegalMemoryAddress,
|
|
5,
|
|
NULL,
|
|
0);
|
|
|
|
|
|
PRINTF("ValidateMemoryOpregionRange: Memory OpRegion (Base = 0x%I64x, Length = 0x%x) is in AcpiAddressRangeMemory (Base = 0x%I64x, Length = 0x%I64x)\n",
|
|
absMin,
|
|
dwLen,
|
|
e820Info->E820Entry[i].Base.QuadPart,
|
|
e820Info->E820Entry[i].Length.QuadPart
|
|
);
|
|
Ret = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Free the E820 info
|
|
//
|
|
ExFreePool( keyInfo );
|
|
|
|
return Ret;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/*** LP FreeMem - Free memory object
|
|
*
|
|
* ENTRY
|
|
* pv -> memory object to be freed
|
|
* pdwcObjs -> object counter to be decremented
|
|
*
|
|
* EXIT
|
|
* None
|
|
*/
|
|
|
|
VOID LOCAL FreeMem(PVOID pv, PULONG pdwcObjs)
|
|
{
|
|
if (*pdwcObjs != 0)
|
|
{
|
|
ExFreePool(pv);
|
|
(*pdwcObjs)--;
|
|
}
|
|
else
|
|
{
|
|
AMLI_ERROR(("FreeMem: Unbalanced MemFree"));
|
|
}
|
|
} //FreeMem
|
|
|
|
/*** LP CheckGlobalHeap - Make sure that the global heap has not become
|
|
* corrupted
|
|
*
|
|
* ENTRY
|
|
* None
|
|
*
|
|
* Exit
|
|
* None
|
|
*/
|
|
VOID LOCAL CheckGlobalHeap()
|
|
{
|
|
KIRQL oldIrql;
|
|
|
|
//
|
|
// We don't care about this is we are loading a DDB
|
|
//
|
|
if (gdwfAMLI & AMLIF_LOADING_DDB) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
// Must have spinlock protection...
|
|
//
|
|
KeAcquireSpinLock( &gdwGHeapSpinLock, &oldIrql );
|
|
|
|
//
|
|
// We only care if they don't match...
|
|
//
|
|
if (gdwGlobalHeapSize == gdwGHeapSnapshot) {
|
|
|
|
goto CheckGlobalHeapExit;
|
|
|
|
}
|
|
|
|
//
|
|
// If the new heap size is smaller than the current size, then
|
|
// we shrunk the heap and that is good...
|
|
//
|
|
if (gdwGlobalHeapSize < gdwGHeapSnapshot) {
|
|
|
|
//
|
|
// Remember the new "snapshot size"
|
|
//
|
|
gdwGHeapSnapshot = gdwGlobalHeapSize;
|
|
goto CheckGlobalHeapExit;
|
|
|
|
}
|
|
|
|
if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON) {
|
|
|
|
AMLI_WARN(("CheckGlobalHeap: "
|
|
"potential memory leak "
|
|
"detected (CurrentHeapSize=%d,"
|
|
"ReferenceSize=%d)",
|
|
gdwGlobalHeapSize,
|
|
gdwGHeapSnapshot));
|
|
|
|
}
|
|
if (gdwGlobalHeapSize - gdwGHeapSnapshot > 8192) {
|
|
|
|
AMLI_WARN(("CheckGlobalHeap: detected memory leak"));
|
|
KdBreakPoint();
|
|
|
|
}
|
|
|
|
CheckGlobalHeapExit:
|
|
|
|
//
|
|
// Release the lock and we are done
|
|
//
|
|
KeReleaseSpinLock( &gdwGHeapSpinLock, oldIrql );
|
|
}
|
|
#endif //ifdef DEBUG
|