windows-nt/Source/XPSP1/NT/base/busdrv/acpi/driver/amlinew/misc.c
2020-09-26 16:20:57 +08:00

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