/*** 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