Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2226 lines
60 KiB

  1. /*** misc.c - Miscellaneous functions
  2. *
  3. * Copyright (c) 1996,1997 Microsoft Corporation
  4. * Author: Michael Tsang (MikeTs)
  5. * Created 11/18/96
  6. *
  7. * MODIFICATION HISTORY
  8. */
  9. #include "pch.h"
  10. #ifdef LOCKABLE_PRAGMA
  11. #pragma ACPI_LOCKABLE_DATA
  12. #pragma ACPI_LOCKABLE_CODE
  13. #endif
  14. /***LP InitializeMutex - initialize mutex
  15. *
  16. * ENTRY
  17. * pmut -> MUTEX
  18. *
  19. * EXIT
  20. * None
  21. */
  22. VOID LOCAL InitializeMutex(PMUTEX pmut)
  23. {
  24. TRACENAME("INITIALIZEMUTEX")
  25. ENTER(3, ("InitializeMutex(pmut=%x)\n", pmut));
  26. KeInitializeSpinLock(&pmut->SpinLock);
  27. pmut->OldIrql = PASSIVE_LEVEL;
  28. EXIT(3, ("InitializeMutex!\n"));
  29. } //InitializeMutex
  30. /***LP AcquireMutex - acquire mutex
  31. *
  32. * ENTRY
  33. * pmut -> MUTEX
  34. *
  35. * EXIT-SUCCESS
  36. * returns TRUE
  37. * EXIT-FAILURE
  38. * returns FALSE
  39. *
  40. * NOTE
  41. * AcquireMutex can be called at DISPATCH_LEVEL as long as the mutex
  42. * is unowned or owned by the same thread. If the mutex is owned by
  43. * some other thread, this thread cannot block if we are at
  44. * DISPATCH_LEVEL and therefore would fail to acquire the mutex.
  45. */
  46. BOOLEAN LOCAL AcquireMutex(PMUTEX pmut)
  47. {
  48. TRACENAME("ACQUIREMUTEX")
  49. BOOLEAN rc = TRUE;
  50. ENTER(3, ("AcquireMutex(pmut=%x)\n", pmut));
  51. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  52. KeAcquireSpinLock(&pmut->SpinLock, &pmut->OldIrql);
  53. EXIT(3, ("AcquireMutex=%x\n", rc));
  54. return rc;
  55. } //AcquireMutex
  56. /***LP ReleaseMutex - release mutex
  57. *
  58. * ENTRY
  59. * pmut -> MUTEX
  60. *
  61. * EXIT-SUCCESS
  62. * returns TRUE
  63. * EXIT-FAILURE
  64. * returns FALSE
  65. */
  66. BOOLEAN LOCAL ReleaseMutex(PMUTEX pmut)
  67. {
  68. TRACENAME("RELEASEMUTEX")
  69. BOOLEAN rc = TRUE;
  70. ENTER(3, ("ReleaseMutex(pmut=%x)\n", pmut));
  71. ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
  72. KeReleaseSpinLock(&pmut->SpinLock, pmut->OldIrql);
  73. EXIT(3, ("ReleaseMutex!\n"));
  74. return rc;
  75. } //ReleaseMutex
  76. /***LP FindOpcodeTerm - find the AMLTERM for the given opcode
  77. *
  78. * ENTRY
  79. * dwOp - opcode
  80. * pOpTable -> opcode table
  81. *
  82. * EXIT-SUCCESS
  83. * returns pointer to the opcode's AMLTERM
  84. * EXIT-FAILURE
  85. * returns NULL
  86. */
  87. PAMLTERM LOCAL FindOpcodeTerm(ULONG dwOp, POPCODEMAP pOpTable)
  88. {
  89. TRACENAME("FINDOPCODETERM")
  90. PAMLTERM pamlterm = NULL;
  91. ENTER(3, ("FindOpcodeTerm(Op=%x,pOpTable=%x)\n", dwOp, pOpTable));
  92. while (pOpTable->pamlterm != NULL)
  93. {
  94. if (dwOp == pOpTable->dwOpcode)
  95. {
  96. pamlterm = pOpTable->pamlterm;
  97. break;
  98. }
  99. else
  100. pOpTable++;
  101. }
  102. EXIT(3, ("FindOpcodeTerm=%x\n", pamlterm));
  103. return pamlterm;
  104. } //FindOpcodeTerm
  105. /***LP GetHackFlags - Get the hack flags from the registry
  106. *
  107. * ENTRY
  108. * pdsdt -> AML table
  109. *
  110. * EXIT-SUCCESS
  111. * returns the hack flags read
  112. * EXIT-FAILURE
  113. * returns zero
  114. */
  115. ULONG LOCAL GetHackFlags(PDSDT pdsdt)
  116. {
  117. TRACENAME("GETHACKFLAGS")
  118. ULONG dwfHacks = 0, dwcb;
  119. static PSZ pszHackFlags = "AMLIHackFlags";
  120. ENTER(3, ("GetHackFlags(pdsdt=%x)\n", pdsdt));
  121. if (pdsdt == NULL)
  122. {
  123. dwcb = sizeof(dwfHacks);
  124. OSReadRegValue(pszHackFlags, (HANDLE)NULL, &dwfHacks, &dwcb);
  125. }
  126. else
  127. {
  128. ULONG dwLen, i;
  129. PSZ pszRegPath;
  130. HANDLE hRegKey;
  131. NTSTATUS status;
  132. dwLen = STRLEN(ACPI_PARAMETERS_REGISTRY_KEY) +
  133. ACPI_MAX_TABLE_STRINGS +
  134. 8 + 5;
  135. if ((pszRegPath = ExAllocatePool(PagedPool, dwLen)) != NULL)
  136. {
  137. STRCPY(pszRegPath, ACPI_PARAMETERS_REGISTRY_KEY);
  138. STRCAT(pszRegPath, "\\");
  139. STRCATN(pszRegPath, (PSZ)&pdsdt->Header.Signature,
  140. ACPI_MAX_SIGNATURE);
  141. STRCAT(pszRegPath, "\\");
  142. STRCATN(pszRegPath, (PSZ)pdsdt->Header.OEMID, ACPI_MAX_OEM_ID);
  143. STRCAT(pszRegPath, "\\");
  144. STRCATN(pszRegPath, (PSZ)pdsdt->Header.OEMTableID, ACPI_MAX_TABLE_ID);
  145. STRCAT(pszRegPath, "\\");
  146. ULTOA(pdsdt->Header.OEMRevision, &pszRegPath[STRLEN(pszRegPath)],
  147. 16);
  148. dwLen = STRLEN(pszRegPath);
  149. for (i = 0; i < dwLen; i++)
  150. {
  151. if (pszRegPath[i] == ' ')
  152. {
  153. pszRegPath[i] = '_';
  154. }
  155. }
  156. status = OSOpenHandle(pszRegPath, NULL, &hRegKey);
  157. if (NT_SUCCESS(status))
  158. {
  159. dwcb = sizeof(dwfHacks);
  160. OSReadRegValue(pszHackFlags, hRegKey, &dwfHacks, &dwcb);
  161. }
  162. ExFreePool(pszRegPath);
  163. }
  164. }
  165. EXIT(3, ("GetHackFlags=%x\n", dwfHacks));
  166. return dwfHacks;
  167. } //GetHackFlags
  168. /***LP GetBaseObject - If object type is OBJALIAS, follow the chain to the base
  169. *
  170. * ENTRY
  171. * pnsObj -> object
  172. *
  173. * EXIT
  174. * returns the base object
  175. */
  176. PNSOBJ LOCAL GetBaseObject(PNSOBJ pnsObj)
  177. {
  178. TRACENAME("GETBASEOBJECT")
  179. ENTER(3, ("GetBaseObject(pnsObj=%s)\n", GetObjectPath(pnsObj)));
  180. while (pnsObj->ObjData.dwDataType == OBJTYPE_OBJALIAS)
  181. {
  182. pnsObj = pnsObj->ObjData.pnsAlias;
  183. }
  184. EXIT(3, ("GetBaseObject=%s\n", GetObjectPath(pnsObj)));
  185. return pnsObj;
  186. } //GetBaseObject
  187. /***LP GetBaseData - If object type is DATAALIAS, follow the chain to the base
  188. *
  189. * ENTRY
  190. * pdataObj -> object
  191. *
  192. * EXIT
  193. * returns the base object
  194. */
  195. POBJDATA LOCAL GetBaseData(POBJDATA pdataObj)
  196. {
  197. TRACENAME("GETBASEDATA")
  198. ENTER(3, ("GetBaseData(pdataObj=%x)\n", pdataObj));
  199. ASSERT(pdataObj != NULL);
  200. for (;;)
  201. {
  202. if (pdataObj->dwDataType == OBJTYPE_OBJALIAS)
  203. {
  204. pdataObj = &pdataObj->pnsAlias->ObjData;
  205. }
  206. else if (pdataObj->dwDataType == OBJTYPE_DATAALIAS)
  207. {
  208. pdataObj = pdataObj->pdataAlias;
  209. }
  210. else
  211. {
  212. break;
  213. }
  214. }
  215. EXIT(3, ("GetBaseData=%x\n", pdataObj));
  216. return pdataObj;
  217. } //GetBaseData
  218. /***LP NewObjOwner - create a new object owner
  219. *
  220. * ENTRY
  221. * pheap -> HEAP
  222. * ppowner -> to hold new owner pointer
  223. *
  224. * EXIT-SUCCESS
  225. * returns STATUS_SUCCESS
  226. * EXIT-FAILURE
  227. * returns AMLIERR_ code
  228. */
  229. NTSTATUS LOCAL NewObjOwner(PHEAP pheap, POBJOWNER *ppowner)
  230. {
  231. TRACENAME("NEWOBJOWNER")
  232. NTSTATUS rc = STATUS_SUCCESS;
  233. ENTER(3, ("NewObjOwner(pheap=%x,ppowner=%x)\n", pheap, ppowner));
  234. if ((*ppowner = NEWOOOBJ(pheap, sizeof(OBJOWNER))) == NULL)
  235. {
  236. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  237. ("NewObjOwner: failed to allocate object owner"));
  238. }
  239. else
  240. {
  241. MEMZERO(*ppowner, sizeof(OBJOWNER));
  242. (*ppowner)->dwSig = SIG_OBJOWNER;
  243. AcquireMutex(&gmutOwnerList);
  244. ListInsertTail(&(*ppowner)->list, &gplistObjOwners);
  245. ReleaseMutex(&gmutOwnerList);
  246. }
  247. EXIT(3, ("NewObjOwner=%x (powern=%x)\n", rc, *ppowner));
  248. return rc;
  249. } //NewObjOwner
  250. /***LP FreeObjOwner - free object owner
  251. *
  252. * ENTRY
  253. * powner -> OBJOWNER
  254. * fUnload - if TRUE, the caller is unloading a DDB
  255. *
  256. * EXIT
  257. * None
  258. */
  259. VOID LOCAL FreeObjOwner(POBJOWNER powner, BOOLEAN fUnload)
  260. {
  261. TRACENAME("FREEOBJOWNER")
  262. KIRQL oldIrql;
  263. PNSOBJ pns;
  264. PNSOBJ pnsNext = NULL;
  265. PNSOBJ pnsPrev = NULL;
  266. PNSOBJ pnsDeviceList = NULL;
  267. PNSOBJ pnsChild = NULL;
  268. ENTER(3, ("FreeObjOwner(powner=%x,fUnload=%x)\n", powner,fUnload));
  269. ASSERT(powner != NULL);
  270. AcquireMutex(&gmutOwnerList);
  271. ListRemoveEntry(&powner->list, &gplistObjOwners);
  272. ReleaseMutex(&gmutOwnerList);
  273. if (fUnload && (ghDestroyObj.pfnHandler != NULL))
  274. {
  275. //
  276. // First we have to tell the driver that we are about to
  277. // do walk the owner list so that we can seek and destroy
  278. // the objects
  279. //
  280. ((PFNDOBJ)ghDestroyObj.pfnHandler)(DESTROYOBJ_START, &oldIrql, 0);
  281. //
  282. // First pass, mark the objects defunc'd.
  283. //
  284. for (pns = powner->pnsObjList; pns != NULL; pns = pns->pnsOwnedNext) {
  285. pns->ObjData.dwfData |= DATAF_NSOBJ_DEFUNC;
  286. }
  287. //
  288. // Second pass, find the device in the list to be removed
  289. //
  290. for (pns = powner->pnsObjList; pns != NULL; pns = pnsNext) {
  291. pnsNext = pns->pnsOwnedNext;
  292. if (pns->ObjData.dwDataType == OBJTYPE_DEVICE ||
  293. pns->ObjData.dwDataType == OBJTYPE_POWERRES ||
  294. pns->ObjData.dwDataType == OBJTYPE_THERMALZONE ||
  295. pns->ObjData.dwDataType == OBJTYPE_PROCESSOR) {
  296. if (pnsPrev) {
  297. pnsPrev->pnsOwnedNext = pns->pnsOwnedNext;
  298. } else {
  299. powner->pnsObjList = pns->pnsOwnedNext;
  300. }
  301. pns->pnsOwnedNext = pnsDeviceList;
  302. pnsDeviceList = pns;
  303. //
  304. // Detach the device from its parent
  305. //
  306. if (pns->pnsParent != NULL) {
  307. ListRemoveEntry(
  308. &pns->list,
  309. (PPLIST)&pns->pnsParent->pnsFirstChild
  310. );
  311. pns->pnsParent = NULL;
  312. }
  313. //
  314. // Make sure that all of the device's children have been
  315. // marked as being unloaded
  316. //
  317. if (pns->pnsFirstChild) {
  318. pnsChild = pns->pnsFirstChild;
  319. do {
  320. if (!(pnsChild->ObjData.dwfData & DATAF_NSOBJ_DEFUNC) ) {
  321. ((PFNDOBJ)ghDestroyObj.pfnHandler)(
  322. DESTROYOBJ_CHILD_NOT_FREED,
  323. pnsChild,
  324. 0
  325. );
  326. }
  327. pnsChild = (PNSOBJ) pnsChild->list.plistNext;
  328. } while (pnsChild != pns->pnsFirstChild);
  329. }
  330. //
  331. // Not that if we don't put this continue in here, then
  332. // it becomes possible for pnsPrev to point to a device,
  333. // which would corrupt the list
  334. continue;
  335. } else if (pns->pnsParent == NULL ||
  336. !(pns->pnsParent->ObjData.dwfData & DATAF_NSOBJ_DEFUNC)) {
  337. ((PFNDOBJ)ghDestroyObj.pfnHandler)(
  338. DESTROYOBJ_BOGUS_PARENT,
  339. pns,
  340. 0
  341. );
  342. }
  343. pnsPrev = pns;
  344. }
  345. //
  346. // Chain the two lists back together
  347. //
  348. if (powner->pnsObjList == NULL) {
  349. powner->pnsObjList = pnsDeviceList;
  350. } else {
  351. //
  352. // Find a pointer to the last element in the list
  353. //
  354. pns = powner->pnsObjList;
  355. while ( pns->pnsOwnedNext != NULL )
  356. {
  357. //
  358. // Next element in the list
  359. //
  360. pns = pns->pnsOwnedNext;
  361. }
  362. pns->pnsOwnedNext = pnsDeviceList;
  363. }
  364. // //
  365. // Third pass pass, do callback for each device that is going away
  366. //
  367. for (pns = pnsDeviceList; pns != NULL; pns = pnsNext) {
  368. //
  369. // Remember what the next point is because we might nuke
  370. // the current object in the callback (if there is no
  371. // device extension associated with it
  372. //
  373. pnsNext = pns->pnsOwnedNext;
  374. //
  375. // Issue the callback. This might nuke the pnsObject
  376. //
  377. ((PFNDOBJ)ghDestroyObj.pfnHandler)(
  378. DESTROYOBJ_REMOVE_OBJECT,
  379. pns,
  380. pns->ObjData.dwDataType
  381. );
  382. }
  383. //
  384. // We end by tell the ACPI driver that we have finished looking
  385. // at the list
  386. //
  387. ((PFNDOBJ)ghDestroyObj.pfnHandler)(DESTROYOBJ_END, &oldIrql, 0 );
  388. }
  389. else
  390. {
  391. for (pns = powner->pnsObjList; pns != NULL; pns = pnsNext)
  392. {
  393. pnsNext = pns->pnsOwnedNext;
  394. FreeNameSpaceObjects(pns);
  395. }
  396. }
  397. powner->pnsObjList = NULL;
  398. FREEOOOBJ(powner);
  399. EXIT(3, ("FreeObjOwner!\n"));
  400. } //FreeObjOwner
  401. /***LP InsertOwnerObjList - Insert the new object into the owner's object list
  402. *
  403. * ENTRY
  404. * powner -> owner
  405. * pnsObj -> new object
  406. *
  407. * EXIT
  408. * None
  409. */
  410. VOID LOCAL InsertOwnerObjList(POBJOWNER powner, PNSOBJ pnsObj)
  411. {
  412. TRACENAME("INSERTOWNEROBJLIST")
  413. ENTER(3, ("InsertOwnerObjList(powner=%x,pnsObj=%x)\n",
  414. powner, pnsObj));
  415. pnsObj->hOwner = (HANDLE)powner;
  416. if (powner != NULL)
  417. {
  418. pnsObj->pnsOwnedNext = powner->pnsObjList;
  419. powner->pnsObjList = pnsObj;
  420. }
  421. EXIT(3, ("InsertOwnerObjList!\n"));
  422. } //InsertOwnerObjList
  423. /***LP FreeDataBuffs - Free any buffers attached to OBJDATA array
  424. *
  425. * ENTRY
  426. * adata -> OBJDATA array
  427. * icData - number of data object in array
  428. *
  429. * EXIT
  430. * None
  431. */
  432. VOID LOCAL FreeDataBuffs(POBJDATA adata, int icData)
  433. {
  434. TRACENAME("FREEDATABUFFS")
  435. int i;
  436. ENTER(3, ("FreeDataBuffs(adata=%x,icData=%d)\n", adata, icData));
  437. for (i = 0; i < icData; ++i)
  438. {
  439. if (adata[i].pbDataBuff != NULL)
  440. {
  441. if (adata[i].dwfData & DATAF_BUFF_ALIAS)
  442. {
  443. //
  444. // decrement the base object's reference count.
  445. //
  446. adata[i].pdataBase->dwRefCount--;
  447. }
  448. else
  449. {
  450. //
  451. // We cannot free a base object buffer that has aliases on it.
  452. //
  453. ASSERT(adata[i].dwRefCount == 0);
  454. if (adata[i].dwDataType == OBJTYPE_PKGDATA)
  455. {
  456. PPACKAGEOBJ ppkg = (PPACKAGEOBJ)adata[i].pbDataBuff;
  457. FreeDataBuffs(ppkg->adata, ppkg->dwcElements);
  458. }
  459. ENTER(4, ("FreeData(i=%d,Buff=%x,Flags=%x)\n",
  460. i, adata[i].pbDataBuff, adata[i].dwfData));
  461. FREEOBJDATA(&adata[i]);
  462. EXIT(4, ("FreeData!\n"));
  463. }
  464. }
  465. MEMZERO(&adata[i], sizeof(OBJDATA));
  466. }
  467. EXIT(3, ("FreeDataBuff!\n"));
  468. } //FreeDataBuffs
  469. /***LP PutIntObjData - put integer data into data object
  470. *
  471. * ENTRY
  472. * pctxt -> CTXT
  473. * pdataObj -> data object
  474. * dwData -> data to be written
  475. *
  476. * EXIT-SUCCESS
  477. * returns STATUS_SUCCESS
  478. * EXIT-FAILURE
  479. * returns AMLIERR_ code
  480. */
  481. NTSTATUS LOCAL PutIntObjData(PCTXT pctxt, POBJDATA pdataObj, ULONG dwData)
  482. {
  483. TRACENAME("PUTINTOBJDATA")
  484. NTSTATUS rc = STATUS_SUCCESS;
  485. OBJDATA data;
  486. ENTER(3, ("PutIntObjData(pctxt=%x,pdataObj=%x,dwData=%x)\n",
  487. pctxt, pdataObj, dwData));
  488. MEMZERO(&data, sizeof(OBJDATA));
  489. data.dwDataType = OBJTYPE_INTDATA;
  490. data.uipDataValue = (ULONG_PTR)dwData;
  491. rc = WriteObject(pctxt, pdataObj, &data);
  492. EXIT(3, ("PutIntObjData=%x\n", rc));
  493. return rc;
  494. } //PutIntObjData
  495. /***LP GetFieldUnitRegionObj - Get the OperationRegion object of FieldUnit
  496. *
  497. * ENTRY
  498. * pfu -> FIELDUNITOBJ
  499. * ppns -> to hold OperationRegion object
  500. *
  501. * EXIT-SUCCESS
  502. * returns STATUS_SUCCESS
  503. * EXIT-FAILURE
  504. * returns AMLIERR_ code
  505. */
  506. NTSTATUS LOCAL GetFieldUnitRegionObj(PFIELDUNITOBJ pfu, PPNSOBJ ppns)
  507. {
  508. TRACENAME("GETFIELDUNITREGIONOBJ")
  509. NTSTATUS rc = STATUS_SUCCESS;
  510. PNSOBJ pns;
  511. ENTER(3, ("GetFieldUnitRegionObj(pfu=%x,ppns=%x)\n", pfu, ppns));
  512. pns = pfu->pnsFieldParent;
  513. switch (pns->ObjData.dwDataType)
  514. {
  515. case OBJTYPE_BANKFIELD:
  516. *ppns = ((PBANKFIELDOBJ)pns->ObjData.pbDataBuff)->pnsBase;
  517. break;
  518. case OBJTYPE_FIELD:
  519. *ppns = ((PFIELDOBJ)pns->ObjData.pbDataBuff)->pnsBase;
  520. break;
  521. case OBJTYPE_INDEXFIELD:
  522. pns = ((PINDEXFIELDOBJ)pns->ObjData.pbDataBuff)->pnsData;
  523. ASSERT(pns->ObjData.dwDataType == OBJTYPE_FIELDUNIT);
  524. rc = GetFieldUnitRegionObj((PFIELDUNITOBJ)pns->ObjData.pbDataBuff,
  525. ppns);
  526. break;
  527. default:
  528. rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
  529. ("GetFieldUnitRegionObj: unknown field unit parent object type - %x",
  530. (*ppns)->ObjData.dwDataType));
  531. }
  532. if ((*ppns != NULL) && ((*ppns)->ObjData.dwDataType != OBJTYPE_OPREGION))
  533. {
  534. rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
  535. ("GetFieldUnitRegionObj: base object of field unit is not OperationRegion (BaseObj=%s,Type=%x)",
  536. GetObjectPath(*ppns), (*ppns)->ObjData.dwDataType));
  537. }
  538. EXIT(3, ("GetFieldUnitRegionObj=%x (RegionObj=%x:%s)\n",
  539. rc, *ppns, GetObjectPath(*ppns)));
  540. return rc;
  541. } //GetFieldUnitRegionObj
  542. /***LP CopyObjData - Copy object data
  543. *
  544. * ENTRY
  545. * pdataDst -> target object
  546. * pdataSrc -> source object
  547. *
  548. * EXIT
  549. * None
  550. */
  551. VOID LOCAL CopyObjData(POBJDATA pdataDst, POBJDATA pdataSrc)
  552. {
  553. TRACENAME("COPYOBJDATA")
  554. ENTER(3, ("CopyObjData(Dest=%x,Src=%x)\n", pdataDst, pdataSrc));
  555. ASSERT(pdataDst != NULL);
  556. ASSERT(pdataSrc != NULL);
  557. if (pdataDst != pdataSrc)
  558. {
  559. MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
  560. if (pdataSrc->dwfData & DATAF_BUFF_ALIAS)
  561. {
  562. //
  563. // Source is an alias, so we need to increment the base object
  564. // reference count.
  565. //
  566. ASSERT(pdataSrc->pdataBase != NULL);
  567. pdataSrc->pdataBase->dwRefCount++;
  568. }
  569. else if (pdataSrc->pbDataBuff != NULL)
  570. {
  571. //
  572. // Source is a base object with buffer, increment its reference
  573. // count.
  574. //
  575. pdataSrc->dwRefCount++;
  576. pdataDst->dwfData |= DATAF_BUFF_ALIAS;
  577. pdataDst->pdataBase = pdataSrc;
  578. }
  579. }
  580. EXIT(3, ("CopyObjData!\n"));
  581. } //CopyObjData
  582. /***LP MoveObjData - Move object data
  583. *
  584. * ENTRY
  585. * pdataDst -> target object
  586. * pdataSrc -> source object
  587. *
  588. * EXIT
  589. * None
  590. */
  591. VOID LOCAL MoveObjData(POBJDATA pdataDst, POBJDATA pdataSrc)
  592. {
  593. TRACENAME("MOVEOBJDATA")
  594. ENTER(3, ("MoveObjData(Dest=%x,Src=%x)\n", pdataDst, pdataSrc));
  595. ASSERT(pdataDst != NULL);
  596. ASSERT(pdataSrc != NULL);
  597. if (pdataDst != pdataSrc)
  598. {
  599. //
  600. // We can only move an alias object or a base object with zero
  601. // reference count or a base object with no data buffer.
  602. //
  603. ASSERT((pdataSrc->dwfData & DATAF_BUFF_ALIAS) ||
  604. (pdataSrc->pbDataBuff == NULL) ||
  605. (pdataSrc->dwRefCount == 0));
  606. MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
  607. MEMZERO(pdataSrc, sizeof(OBJDATA));
  608. }
  609. EXIT(3, ("MoveObjData!\n"));
  610. } //MoveObjData
  611. /***LP DupObjData - Duplicate object data
  612. *
  613. * ENTRY
  614. * pheap -> HEAP
  615. * pdataDst -> target object
  616. * pdataSrc -> source object
  617. *
  618. * EXIT-SUCCESS
  619. * returns STATUS_SUCCESS
  620. * EXIT-FAILURE
  621. * returns AMLIERR_ code
  622. */
  623. NTSTATUS LOCAL DupObjData(PHEAP pheap, POBJDATA pdataDst, POBJDATA pdataSrc)
  624. {
  625. TRACENAME("DUPOBJDATA")
  626. NTSTATUS rc = STATUS_SUCCESS;
  627. ENTER(3, ("DupObjData(pheap=%x,Dest=%x,Src=%x)\n",
  628. pheap, pdataDst, pdataSrc));
  629. ASSERT(pdataDst != NULL);
  630. ASSERT(pdataSrc != NULL);
  631. if (pdataDst != pdataSrc)
  632. {
  633. MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
  634. if (pdataSrc->pbDataBuff != NULL)
  635. {
  636. if ((pdataDst->pbDataBuff = NEWOBJDATA(pheap, pdataSrc)) == NULL)
  637. {
  638. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  639. ("DupObjData: failed to allocate destination buffer"));
  640. }
  641. else if (pdataSrc->dwDataType == OBJTYPE_PKGDATA)
  642. {
  643. PPACKAGEOBJ ppkgSrc = (PPACKAGEOBJ)pdataSrc->pbDataBuff,
  644. ppkgDst = (PPACKAGEOBJ)pdataDst->pbDataBuff;
  645. int i;
  646. ppkgDst->dwcElements = ppkgSrc->dwcElements;
  647. for (i = 0; i < (int)ppkgSrc->dwcElements; ++i)
  648. {
  649. if ((rc = DupObjData(pheap, &ppkgDst->adata[i],
  650. &ppkgSrc->adata[i])) != STATUS_SUCCESS)
  651. {
  652. break;
  653. }
  654. }
  655. }
  656. else
  657. {
  658. MEMCPY(pdataDst->pbDataBuff, pdataSrc->pbDataBuff,
  659. pdataSrc->dwDataLen);
  660. }
  661. pdataDst->dwfData &= ~DATAF_BUFF_ALIAS;
  662. pdataDst->dwRefCount = 0;
  663. }
  664. }
  665. EXIT(3, ("DupObjData=%x\n", rc));
  666. return rc;
  667. } //DupObjData
  668. /***LP CopyObjBuffer - Copy object data to a buffer
  669. *
  670. * ENTRY
  671. * pbBuff -> buffer
  672. * dwLen - buffer size
  673. * pdata -> object
  674. *
  675. * EXIT-SUCCESS
  676. * returns STATUS_SUCCESS
  677. * EXIT-FAILURE
  678. * returns AMLIERR_ code
  679. */
  680. NTSTATUS LOCAL CopyObjBuffer(PUCHAR pbBuff, ULONG dwLen, POBJDATA pdata)
  681. {
  682. TRACENAME("COPYOBJBUFFER")
  683. NTSTATUS rc = STATUS_SUCCESS;
  684. PUCHAR pb = NULL;
  685. ULONG dwcb = 0;
  686. ENTER(3, ("CopyObjBuffer(pbBuff=%x,Len=%d,pdata=%x)\n",
  687. pbBuff, dwLen, pdata));
  688. switch (pdata->dwDataType)
  689. {
  690. case OBJTYPE_INTDATA:
  691. pb = (PUCHAR)&pdata->uipDataValue;
  692. dwcb = sizeof(ULONG);
  693. break;
  694. case OBJTYPE_STRDATA:
  695. pb = pdata->pbDataBuff;
  696. dwcb = pdata->dwDataLen - 1;
  697. break;
  698. case OBJTYPE_BUFFDATA:
  699. pb = pdata->pbDataBuff;
  700. dwcb = pdata->dwDataLen;
  701. break;
  702. default:
  703. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  704. ("CopyObjBuffer: invalid source object type (type=%s)",
  705. GetObjectTypeName(pdata->dwDataType)));
  706. }
  707. if ((rc == STATUS_SUCCESS) && (pbBuff != pb))
  708. {
  709. MEMZERO(pbBuff, dwLen);
  710. dwcb = MIN(dwLen, dwcb);
  711. MEMCPY(pbBuff, pb, dwcb);
  712. }
  713. EXIT(3, ("CopyObjBuffer=%x (CopyLen=%d)\n", rc, dwcb));
  714. return rc;
  715. } //CopyObjBuffer
  716. /***LP AcquireGL - acquire global lock
  717. *
  718. * ENTRY
  719. * pctxt -> CTXT
  720. *
  721. * EXIT-SUCCESS
  722. * returns STATUS_SUCCESS
  723. * EXIT-FAILURE
  724. * returns AMLIERR_ code
  725. */
  726. NTSTATUS LOCAL AcquireGL(PCTXT pctxt)
  727. {
  728. TRACENAME("ACQUIREGL")
  729. NTSTATUS rc = STATUS_SUCCESS;
  730. ENTER(3, ("AcquireGL(pctxt=%x)\n", pctxt));
  731. if (ghGlobalLock.pfnHandler != NULL)
  732. {
  733. ASSERT(!(pctxt->dwfCtxt & CTXTF_READY));
  734. rc = ((PFNGL)ghGlobalLock.pfnHandler)(EVTYPE_ACQREL_GLOBALLOCK,
  735. GLOBALLOCK_ACQUIRE,
  736. ghGlobalLock.uipParam,
  737. RestartCtxtCallback,
  738. &pctxt->CtxtData);
  739. if (rc == STATUS_PENDING)
  740. {
  741. rc = AMLISTA_PENDING;
  742. }
  743. else if (rc != STATUS_SUCCESS)
  744. {
  745. rc = AMLI_LOGERR(AMLIERR_ACQUIREGL_FAILED,
  746. ("AcquireGL: failed to acquire global lock"));
  747. }
  748. }
  749. EXIT(3, ("AcquireGL=%x\n", rc));
  750. return rc;
  751. } //AcquireGL
  752. /***LP ReleaseGL - release global lock if acquired
  753. *
  754. * ENTRY
  755. * pctxt -> CTXT
  756. *
  757. * EXIT-SUCCESS
  758. * returns STATUS_SUCCESS
  759. * EXIT-FAILURE
  760. * returns AMLIERR_ code
  761. */
  762. NTSTATUS LOCAL ReleaseGL(PCTXT pctxt)
  763. {
  764. TRACENAME("RELEASEGL")
  765. NTSTATUS rc = STATUS_SUCCESS;
  766. ENTER(3, ("ReleaseGL(pctxt=%x)\n", pctxt));
  767. if (ghGlobalLock.pfnHandler != NULL)
  768. {
  769. rc = ((PFNGL)ghGlobalLock.pfnHandler)(EVTYPE_ACQREL_GLOBALLOCK,
  770. GLOBALLOCK_RELEASE,
  771. ghGlobalLock.uipParam, NULL,
  772. &pctxt->CtxtData);
  773. }
  774. EXIT(3, ("ReleaseGL=%x\n", rc));
  775. return rc;
  776. } //ReleaseGL
  777. /***LP MapUnmapPhysMem - Map/Unmap physical memory
  778. *
  779. * ENTRY
  780. * pctxt -> CTXT (can be NULL if cannot handle STATUS_PENDING)
  781. * uipAddr - physical address
  782. * dwLen - length of memory range
  783. * puipMappedAddr -> to hold memory address mapped (NULL if unmap)
  784. *
  785. * EXIT-SUCCESS
  786. * returns STATUS_SUCCESS
  787. * EXIT-FAILURE
  788. * returns AMLIERR_ code
  789. */
  790. NTSTATUS LOCAL MapUnmapPhysMem(PCTXT pctxt, ULONG_PTR uipAddr, ULONG dwLen,
  791. PULONG_PTR puipMappedAddr)
  792. {
  793. TRACENAME("MAPUNMAPPHYSMEM")
  794. NTSTATUS rc = STATUS_SUCCESS;
  795. ENTER(3, ("MapUnmapPhysMem(pctxt=%x,Addr=%x,Len=%d,pMappedAddr=%x)\n",
  796. pctxt, uipAddr, dwLen, puipMappedAddr));
  797. if (KeGetCurrentIrql() == PASSIVE_LEVEL)
  798. {
  799. if (puipMappedAddr != NULL)
  800. {
  801. *puipMappedAddr = MapPhysMem(uipAddr, dwLen);
  802. }
  803. else
  804. {
  805. MmUnmapIoSpace((PVOID)uipAddr, dwLen);
  806. }
  807. }
  808. else if (pctxt != NULL)
  809. {
  810. PPASSIVEHOOK pph;
  811. if ((pph = NEWPHOBJ(sizeof(PASSIVEHOOK))) == NULL)
  812. {
  813. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  814. ("MapUnmapPhysMem: failed to allocate passive hook"));
  815. }
  816. else
  817. {
  818. pph->pctxt = pctxt;
  819. pph->uipAddr = uipAddr;
  820. pph->dwLen = dwLen;
  821. pph->puipMappedAddr = puipMappedAddr;
  822. ExInitializeWorkItem(&pph->WorkItem, MapUnmapCallBack, pph);
  823. OSQueueWorkItem(&pph->WorkItem);
  824. rc = AMLISTA_PENDING;
  825. }
  826. }
  827. else
  828. {
  829. rc = AMLI_LOGERR(AMLIERR_FATAL,
  830. ("MapUnmapPhysMem: IRQL is not at PASSIVE (IRQL=%x)",
  831. KeGetCurrentIrql()));
  832. }
  833. EXIT(3, ("MapUnmapPhysMem=%x (MappedAddr=%x)\n",
  834. rc, puipMappedAddr? *puipMappedAddr: 0));
  835. return rc;
  836. } //MapUnmapPhysMem
  837. /***LP MapPhysMem - Map physical memory
  838. *
  839. * ENTRY
  840. * uipAddr - physical memory address
  841. * dwLen - length of memory block
  842. *
  843. * EXIT
  844. * returns mapped address
  845. */
  846. ULONG_PTR LOCAL MapPhysMem(ULONG_PTR uipAddr, ULONG dwLen)
  847. {
  848. TRACENAME("MAPPHYSMEM")
  849. ULONG_PTR uipMappedAddr = 0;
  850. PHYSICAL_ADDRESS phyaddr = {0, 0}, XlatedAddr;
  851. ULONG dwAddrSpace;
  852. ENTER(3, ("MapPhysMem(Addr=%x,Len=%d)\n", uipAddr, dwLen));
  853. phyaddr.HighPart = 0;
  854. phyaddr.QuadPart = uipAddr;
  855. dwAddrSpace = 0;
  856. if (HalTranslateBusAddress(Internal, 0, phyaddr, &dwAddrSpace, &XlatedAddr))
  857. {
  858. uipMappedAddr = (ULONG_PTR)MmMapIoSpace(XlatedAddr, dwLen, FALSE);
  859. }
  860. EXIT(3, ("MapPhysMem=%x", uipMappedAddr));
  861. return uipMappedAddr;
  862. } //MapPhysMem
  863. /***LP MapUnmapCallBack - Map/Unmap physical memory callback
  864. *
  865. * ENTRY
  866. * pph -> PASSIVEHOOK
  867. *
  868. * EXIT
  869. * None
  870. */
  871. VOID MapUnmapCallBack(PPASSIVEHOOK pph)
  872. {
  873. TRACENAME("MAPUNMAPCALLBACK")
  874. ENTER(3, ("MapUnmapCallBack(pph=%x,pctxt=%x,Addr=%x,Len=%d,pdwMappedAddr=%x)\n",
  875. pph, pph->pctxt, pph->uipAddr, pph->dwLen, pph->puipMappedAddr));
  876. ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
  877. if (pph->puipMappedAddr != NULL)
  878. {
  879. *pph->puipMappedAddr = MapPhysMem(pph->uipAddr, pph->dwLen);
  880. }
  881. else
  882. {
  883. MmUnmapIoSpace((PVOID)pph->uipAddr, pph->dwLen);
  884. }
  885. RestartContext(pph->pctxt,
  886. (BOOLEAN)((pph->pctxt->dwfCtxt & CTXTF_ASYNC_EVAL) == 0));
  887. FREEPHOBJ(pph);
  888. EXIT(3, ("MapUnmapCallBack!\n"));
  889. } //MapUnmapCallBack
  890. /***LP MatchObjType - match object type
  891. *
  892. * ENTRY
  893. * dwObjType - object type
  894. * dwExpected - expected type
  895. *
  896. * EXIT-SUCCESS
  897. * returns TRUE - type matched
  898. * EXIT-FAILURE
  899. * returns FALSE - type mismatch
  900. */
  901. BOOLEAN LOCAL MatchObjType(ULONG dwObjType, ULONG dwExpectedType)
  902. {
  903. TRACENAME("MATCHOBJTYPE")
  904. BOOLEAN rc = FALSE;
  905. ENTER(3, ("MatchObjType(ObjType=%s,Expected=%s)\n",
  906. GetObjectTypeName(dwObjType), GetObjectTypeName(dwExpectedType)));
  907. //
  908. // OBJTYPE_BUFFFIELD is essentially OBJTYPE_INTDATA, so we'll let
  909. // it pass the check.
  910. //
  911. if ((dwObjType == OBJTYPE_BUFFFIELD) &&
  912. (dwExpectedType == OBJTYPE_INTDATA))
  913. {
  914. rc = TRUE;
  915. }
  916. else if ((dwExpectedType == OBJTYPE_UNKNOWN) ||
  917. (dwObjType == OBJTYPE_UNKNOWN) ||
  918. (dwObjType == dwExpectedType))
  919. {
  920. rc = TRUE;
  921. }
  922. else
  923. {
  924. if ((dwObjType == OBJTYPE_INTDATA) ||
  925. (dwObjType == OBJTYPE_STRDATA) ||
  926. (dwObjType == OBJTYPE_BUFFDATA) ||
  927. (dwObjType == OBJTYPE_PKGDATA))
  928. {
  929. dwObjType = OBJTYPE_DATA;
  930. }
  931. else if ((dwObjType == OBJTYPE_FIELDUNIT) ||
  932. (dwObjType == OBJTYPE_BUFFFIELD))
  933. {
  934. dwObjType = OBJTYPE_DATAFIELD;
  935. }
  936. if ((dwObjType == dwExpectedType) ||
  937. (dwExpectedType == OBJTYPE_DATAOBJ) &&
  938. ((dwObjType == OBJTYPE_DATA) || (dwObjType == OBJTYPE_DATAFIELD)))
  939. {
  940. rc = TRUE;
  941. }
  942. }
  943. EXIT(3, ("MatchObjType=%x\n", rc));
  944. return rc;
  945. } //MatchObjType
  946. /***LP ValidateTarget - Validate target object type
  947. *
  948. * ENTRY
  949. * pdataTarget -> target object data
  950. * dwExpectedType - expected target object type
  951. * ppdata -> to hold base target object data pointer
  952. *
  953. * EXIT-SUCCESS
  954. * returns STATUS_SUCCESS
  955. * EXIT-FAILURE
  956. * returns AMLIERR_ code
  957. */
  958. NTSTATUS LOCAL ValidateTarget(POBJDATA pdataTarget, ULONG dwExpectedType,
  959. POBJDATA *ppdata)
  960. {
  961. TRACENAME("VALIDATETARGET")
  962. NTSTATUS rc = STATUS_SUCCESS;
  963. ENTER(3, ("ValidateTarget(pdataTarget=%x,ExpectedType=%s,ppdata=%x)\n",
  964. pdataTarget, GetObjectTypeName(dwExpectedType), ppdata));
  965. ASSERT(pdataTarget != NULL);
  966. if (pdataTarget->dwDataType == OBJTYPE_OBJALIAS)
  967. {
  968. *ppdata = &pdataTarget->pnsAlias->ObjData;
  969. }
  970. else if (pdataTarget->dwDataType == OBJTYPE_DATAALIAS)
  971. {
  972. *ppdata = pdataTarget->pdataAlias;
  973. }
  974. else if ((pdataTarget->dwDataType == OBJTYPE_UNKNOWN) ||
  975. (pdataTarget->dwDataType == OBJTYPE_BUFFFIELD) ||
  976. (pdataTarget->dwDataType == OBJTYPE_DEBUG))
  977. {
  978. *ppdata = pdataTarget;
  979. }
  980. else
  981. {
  982. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_TARGETTYPE,
  983. ("ValidateTarget: target is not a supername (Type=%s)",
  984. GetObjectTypeName(pdataTarget->dwDataType)));
  985. }
  986. if ((rc == STATUS_SUCCESS) &&
  987. (pdataTarget->dwDataType == OBJTYPE_OBJALIAS) &&
  988. !MatchObjType((*ppdata)->dwDataType, dwExpectedType))
  989. {
  990. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_TARGETTYPE,
  991. ("ValidateTarget: unexpected target type (Type=%s,Expected=%s)",
  992. GetObjectTypeName((*ppdata)->dwDataType),
  993. GetObjectTypeName(dwExpectedType)));
  994. }
  995. if ((rc == STATUS_SUCCESS) &&
  996. (pdataTarget->dwDataType != OBJTYPE_OBJALIAS) &&
  997. MatchObjType((*ppdata)->dwDataType, OBJTYPE_DATA))
  998. {
  999. FreeDataBuffs(*ppdata, 1);
  1000. }
  1001. EXIT(3, ("ValidateTarget=%x (pdataTarget=%x)\n", rc, *ppdata));
  1002. return rc;
  1003. } //ValidateTarget
  1004. /***LP ValidateArgTypes - Validate argument types
  1005. *
  1006. * ENTRY
  1007. * pArgs -> argument array
  1008. * pszExpectedTypes -> expected argument types string
  1009. *
  1010. * EXIT-SUCCESS
  1011. * returns STATUS_SUCCESS
  1012. * EXIT-FAILURE
  1013. * returns AMLIERR_ code
  1014. */
  1015. NTSTATUS LOCAL ValidateArgTypes(POBJDATA pArgs, PSZ pszExpectedTypes)
  1016. {
  1017. TRACENAME("VALIDATEARGTYPES")
  1018. NTSTATUS rc = STATUS_SUCCESS;
  1019. int icArgs, i;
  1020. ENTER(3, ("ValidateArgTypes(pArgs=%x,ExpectedTypes=%s)\n",
  1021. pArgs, pszExpectedTypes));
  1022. ASSERT(pszExpectedTypes != NULL);
  1023. icArgs = STRLEN(pszExpectedTypes);
  1024. for (i = 0; (rc == STATUS_SUCCESS) && (i < icArgs); ++i)
  1025. {
  1026. switch (pszExpectedTypes[i])
  1027. {
  1028. case ARGOBJ_UNKNOWN:
  1029. break;
  1030. case ARGOBJ_INTDATA:
  1031. if (pArgs[i].dwDataType != OBJTYPE_INTDATA)
  1032. {
  1033. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
  1034. ("ValidateArgTypes: expected Arg%d to be type Integer (Type=%s)",
  1035. i,
  1036. GetObjectTypeName(pArgs[i].dwDataType)));
  1037. }
  1038. break;
  1039. case ARGOBJ_STRDATA:
  1040. if (pArgs[i].dwDataType != OBJTYPE_STRDATA)
  1041. {
  1042. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
  1043. ("ValidateArgTypes: expected Arg%d to be type String (Type-%s)",
  1044. i,
  1045. GetObjectTypeName(pArgs[i].dwDataType)));
  1046. }
  1047. break;
  1048. case ARGOBJ_BUFFDATA:
  1049. if (pArgs[i].dwDataType != OBJTYPE_BUFFDATA)
  1050. {
  1051. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
  1052. ("ValidateArgTypes: expected Arg%d to be type Buffer (Type=%s)",
  1053. i,
  1054. GetObjectTypeName(pArgs[i].dwDataType)));
  1055. }
  1056. break;
  1057. case ARGOBJ_PKGDATA:
  1058. if (pArgs[i].dwDataType != OBJTYPE_PKGDATA)
  1059. {
  1060. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
  1061. ("ValidateArgTypes: expected Arg%d to be type Package (Type=%s)",
  1062. i,
  1063. GetObjectTypeName(pArgs[i].dwDataType)));
  1064. }
  1065. break;
  1066. case ARGOBJ_FIELDUNIT:
  1067. if (pArgs[i].dwDataType != OBJTYPE_FIELDUNIT)
  1068. {
  1069. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
  1070. ("ValidateArgTypes: expected Arg%d to be type FieldUnit (Type=%s)",
  1071. i,
  1072. GetObjectTypeName(pArgs[i].dwDataType)));
  1073. }
  1074. break;
  1075. case ARGOBJ_OBJALIAS:
  1076. if (pArgs[i].dwDataType != OBJTYPE_OBJALIAS)
  1077. {
  1078. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  1079. ("ValidateArgTypes: expected Arg%d to be type ObjAlias (Type=%s)",
  1080. i,
  1081. GetObjectTypeName(pArgs[i].dwDataType)));
  1082. }
  1083. break;
  1084. case ARGOBJ_DATAALIAS:
  1085. if (pArgs[i].dwDataType != OBJTYPE_DATAALIAS)
  1086. {
  1087. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  1088. ("ValidateArgTypes: expected Arg%d to be type DataAlias (Type=%s)",
  1089. i,
  1090. GetObjectTypeName(pArgs[i].dwDataType)));
  1091. }
  1092. break;
  1093. case ARGOBJ_BASICDATA:
  1094. if ((pArgs[i].dwDataType != OBJTYPE_INTDATA) &&
  1095. (pArgs[i].dwDataType != OBJTYPE_STRDATA) &&
  1096. (pArgs[i].dwDataType != OBJTYPE_BUFFDATA))
  1097. {
  1098. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  1099. ("ValidateArgTypes: expected Arg%d to be type int/str/buff (Type=%s)",
  1100. i,
  1101. GetObjectTypeName(pArgs[i].dwDataType)));
  1102. }
  1103. break;
  1104. case ARGOBJ_COMPLEXDATA:
  1105. if ((pArgs[i].dwDataType != OBJTYPE_BUFFDATA) &&
  1106. (pArgs[i].dwDataType != OBJTYPE_PKGDATA))
  1107. {
  1108. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_OBJTYPE,
  1109. ("ValidateArgTypes: expected Arg%d to be type buff/pkg (Type=%s)",
  1110. i,
  1111. GetObjectTypeName(pArgs[i].dwDataType)));
  1112. }
  1113. break;
  1114. case ARGOBJ_REFERENCE:
  1115. if ((pArgs[i].dwDataType != OBJTYPE_OBJALIAS) &&
  1116. (pArgs[i].dwDataType != OBJTYPE_DATAALIAS) &&
  1117. (pArgs[i].dwDataType != OBJTYPE_BUFFFIELD))
  1118. {
  1119. rc = AMLI_LOGERR(AMLIERR_UNEXPECTED_ARGTYPE,
  1120. ("ValidateArgTypes: expected Arg%d to be type reference (Type=%s)",
  1121. i,
  1122. GetObjectTypeName(pArgs[i].dwDataType)));
  1123. }
  1124. break;
  1125. default:
  1126. rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
  1127. ("ValidateArgTypes: internal error (invalid type - %c)",
  1128. pszExpectedTypes[i]));
  1129. }
  1130. }
  1131. EXIT(3, ("ValidateArgTypes=%x\n", rc));
  1132. return rc;
  1133. } //ValidateArgTypes
  1134. /***LP RegEventHandler - register event handler
  1135. *
  1136. * ENTRY
  1137. * peh -> EVHANDLE
  1138. * pfnHandler -> handler entry point
  1139. * uipParam - parameter pass to handler
  1140. *
  1141. * EXIT-SUCCESS
  1142. * returns STATUS_SUCCESS
  1143. * EXIT-FAILURE
  1144. * returns AMLIERR_ code
  1145. */
  1146. NTSTATUS LOCAL RegEventHandler(PEVHANDLE peh, PFNHND pfnHandler,
  1147. ULONG_PTR uipParam)
  1148. {
  1149. TRACENAME("REGEVENTHANDLER")
  1150. NTSTATUS rc = STATUS_SUCCESS;
  1151. ENTER(3, ("RegEventHandler(peh=%x,pfnHandler=%x,Param=%x)\n",
  1152. peh, pfnHandler, uipParam));
  1153. if ((peh->pfnHandler != NULL) && (pfnHandler != NULL))
  1154. {
  1155. rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
  1156. ("RegEventHandler: event handler already exist"));
  1157. }
  1158. else
  1159. {
  1160. peh->pfnHandler = pfnHandler;
  1161. peh->uipParam = uipParam;
  1162. }
  1163. EXIT(3, ("RegEventHandler=%x\n", rc));
  1164. return rc;
  1165. } //RegEventHandler
  1166. /***LP RegOpcodeHandler - register an opcode callback handler
  1167. *
  1168. * The callback handler will be called after the opcode finishes its
  1169. * execution. If an opcode has a variable list, the opcode handler
  1170. * will be called at the point of processing the closing brace.
  1171. *
  1172. * ENTRY
  1173. * dwOpcode - opcode event to hook
  1174. * pfnHandler -> handler entry point
  1175. * uipParam - parameter pass to handler
  1176. * dwfOpcode - opcode flags
  1177. *
  1178. * EXIT-SUCCESS
  1179. * returns STATUS_SUCCESS
  1180. * EXIT-FAILURE
  1181. * returns AMLIERR_ code
  1182. */
  1183. NTSTATUS LOCAL RegOpcodeHandler(ULONG dwOpcode, PFNOH pfnHandler,
  1184. ULONG_PTR uipParam, ULONG dwfOpcode)
  1185. {
  1186. TRACENAME("REGOPCODEHANDLER")
  1187. NTSTATUS rc = STATUS_SUCCESS;
  1188. PAMLTERM pamlterm;
  1189. ENTER(3, ("RegOpcodeHandler(Opcode=%x,pfnHandler=%x,Param=%x,dwfOpcode=%x)\n",
  1190. dwOpcode, pfnHandler, uipParam, dwfOpcode));
  1191. if ((dwOpcode & 0xff) == OP_EXT_PREFIX)
  1192. pamlterm = FindOpcodeTerm(dwOpcode >> 8, ExOpcodeTable);
  1193. else
  1194. pamlterm = OpcodeTable[dwOpcode];
  1195. if (pamlterm == NULL)
  1196. {
  1197. rc = AMLI_LOGERR(AMLIERR_REGHANDLER_FAILED,
  1198. ("RegOpcodeHandler: either invalid opcode or "
  1199. "opcode does not allow callback"));
  1200. }
  1201. else if ((pamlterm->pfnCallBack != NULL) && (pfnHandler != NULL))
  1202. {
  1203. rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
  1204. ("RegOpcodeHandler: opcode or opcode class already "
  1205. "has a handler"));
  1206. }
  1207. else
  1208. {
  1209. pamlterm->pfnCallBack = pfnHandler;
  1210. pamlterm->dwCBData = (ULONG)uipParam;
  1211. pamlterm->dwfOpcode |= dwfOpcode;
  1212. }
  1213. EXIT(3, ("RegOpcodeHandler=%x\n", rc));
  1214. return rc;
  1215. } //RegOpcodeHandler
  1216. /***LP RegRSAccess - register region space cook/raw access handler
  1217. *
  1218. * ENTRY
  1219. * dwRegionSpace - specifying the region space to handle
  1220. * pfnHandler -> handler entry point
  1221. * uipParam - parameter pass to handler
  1222. * fRaw - TRUE if registering raw access handler
  1223. *
  1224. * EXIT-SUCCESS
  1225. * returns STATUS_SUCCESS
  1226. * EXIT-FAILURE
  1227. * returns AMLIERR_ code
  1228. */
  1229. NTSTATUS LOCAL RegRSAccess(ULONG dwRegionSpace, PFNHND pfnHandler,
  1230. ULONG_PTR uipParam, BOOLEAN fRaw)
  1231. {
  1232. TRACENAME("REGRSACCESS")
  1233. NTSTATUS rc = STATUS_SUCCESS;
  1234. ENTER(3, ("RegRSAccess(RegionSpace=%x,pfnHandler=%x,Param=%x,fRaw=%x)\n",
  1235. dwRegionSpace, pfnHandler, uipParam, fRaw));
  1236. if ((dwRegionSpace != REGSPACE_MEM) && (dwRegionSpace != REGSPACE_IO))
  1237. {
  1238. PRSACCESS prsa;
  1239. if ((prsa = FindRSAccess(dwRegionSpace)) == NULL)
  1240. {
  1241. if ((prsa = NEWRSOBJ(sizeof(RSACCESS))) == NULL)
  1242. {
  1243. rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
  1244. ("RegRSAccess: failed to allocate handler structure"));
  1245. }
  1246. else
  1247. {
  1248. MEMZERO(prsa, sizeof(RSACCESS));
  1249. prsa->dwRegionSpace = dwRegionSpace;
  1250. prsa->prsaNext = gpRSAccessHead;
  1251. gpRSAccessHead = prsa;
  1252. }
  1253. }
  1254. if (rc == STATUS_SUCCESS)
  1255. {
  1256. if (fRaw)
  1257. {
  1258. if ((prsa->pfnRawAccess != NULL) && (pfnHandler != NULL))
  1259. {
  1260. rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
  1261. ("RegRSAccess: RawAccess for RegionSpace %x "
  1262. "already have a handler", dwRegionSpace));
  1263. }
  1264. else
  1265. {
  1266. prsa->pfnRawAccess = (PFNRA)pfnHandler;
  1267. prsa->uipRawParam = uipParam;
  1268. }
  1269. }
  1270. else
  1271. {
  1272. if ((prsa->pfnCookAccess != NULL) && (pfnHandler != NULL))
  1273. {
  1274. rc = AMLI_LOGERR(AMLIERR_HANDLER_EXIST,
  1275. ("RegRSAccess: CookAccess for RegionSpace %x "
  1276. "already have a handler", dwRegionSpace));
  1277. }
  1278. else
  1279. {
  1280. prsa->pfnCookAccess = (PFNCA)pfnHandler;
  1281. prsa->uipCookParam = uipParam;
  1282. }
  1283. }
  1284. }
  1285. }
  1286. else
  1287. {
  1288. rc = AMLI_LOGERR(AMLIERR_INVALID_REGIONSPACE,
  1289. ("RegRSAccess: illegal region space - %x",
  1290. dwRegionSpace));
  1291. }
  1292. EXIT(3, ("RegRSAccess=%x\n", rc));
  1293. return rc;
  1294. } //RegRSAccess
  1295. /***LP FindRSAccess - Find RSACCESS structure with a given RegionSpace
  1296. *
  1297. * ENTRY
  1298. * dwRegionSpace - region space
  1299. *
  1300. * EXIT-SUCCESS
  1301. * returns the pointer to the structure found
  1302. * EXIT-FAILURE
  1303. * returns NULL
  1304. */
  1305. PRSACCESS LOCAL FindRSAccess(ULONG dwRegionSpace)
  1306. {
  1307. TRACENAME("FINDRSACCESS")
  1308. PRSACCESS prsa;
  1309. ENTER(3, ("FindRSAccess(RegionSpace=%x)\n", dwRegionSpace));
  1310. for (prsa = gpRSAccessHead; prsa != NULL; prsa = prsa->prsaNext)
  1311. {
  1312. if (prsa->dwRegionSpace == dwRegionSpace)
  1313. break;
  1314. }
  1315. EXIT(3, ("FindRSAccess=%x\n", prsa));
  1316. return prsa;
  1317. } //FindRSAccess
  1318. /***LP FreeRSAccessList - free the RSACCESS structure list
  1319. *
  1320. * ENTRY
  1321. * prsa -> RSACCESS list
  1322. *
  1323. * EXIT
  1324. * None
  1325. */
  1326. VOID LOCAL FreeRSAccessList(PRSACCESS prsa)
  1327. {
  1328. TRACENAME("FREERSACCESSLIST")
  1329. PRSACCESS prsaNext;
  1330. ENTER(3, ("FreeRSAccessList(prsa=%x)\n", prsa));
  1331. while (prsa != NULL)
  1332. {
  1333. prsaNext = prsa->prsaNext;
  1334. FREERSOBJ(prsa);
  1335. prsa = prsaNext;
  1336. }
  1337. EXIT(3, ("FreeRSAccessList!\n"));
  1338. } //FreeRSAccessList
  1339. /***LP GetObjectPath - get object namespace path
  1340. *
  1341. * ENTRY
  1342. * pns -> object
  1343. *
  1344. * EXIT
  1345. * returns name space path
  1346. */
  1347. PSZ LOCAL GetObjectPath(PNSOBJ pns)
  1348. {
  1349. TRACENAME("GETOBJECTPATH")
  1350. static char szPath[MAX_NAME_LEN + 1] = {0};
  1351. int i;
  1352. ENTER(4, ("GetObjectPath(pns=%x)\n", pns));
  1353. if (pns != NULL)
  1354. {
  1355. if (pns->pnsParent == NULL)
  1356. STRCPY(szPath, "\\");
  1357. else
  1358. {
  1359. GetObjectPath(pns->pnsParent);
  1360. if (pns->pnsParent->pnsParent != NULL)
  1361. STRCAT(szPath, ".");
  1362. STRCATN(szPath, (PSZ)&pns->dwNameSeg, sizeof(NAMESEG));
  1363. }
  1364. for (i = STRLEN(szPath) - 1; i >= 0; --i)
  1365. {
  1366. if (szPath[i] == '_')
  1367. szPath[i] = '\0';
  1368. else
  1369. break;
  1370. }
  1371. }
  1372. else
  1373. {
  1374. szPath[0] = '\0';
  1375. }
  1376. EXIT(4, ("GetObjectPath=%s\n", szPath));
  1377. return szPath;
  1378. } //GetObjectPath
  1379. #ifdef DEBUGGER
  1380. /***LP NameSegString - convert a NameSeg to an ASCIIZ string
  1381. *
  1382. * ENTRY
  1383. * dwNameSeg - NameSeg
  1384. *
  1385. * EXIT
  1386. * returns string
  1387. */
  1388. PSZ LOCAL NameSegString(ULONG dwNameSeg)
  1389. {
  1390. TRACENAME("NAMESEGSTRING")
  1391. static char szNameSeg[sizeof(NAMESEG) + 1] = {0};
  1392. ENTER(5, ("NameSegString(dwNameSeg=%x)\n", dwNameSeg));
  1393. STRCPYN(szNameSeg, (PSZ)&dwNameSeg, sizeof(NAMESEG));
  1394. EXIT(5, ("NameSegString=%s\n", szNameSeg));
  1395. return szNameSeg;
  1396. } //NameSegString
  1397. /***LP GetObjectTypeName - get object type name
  1398. *
  1399. * ENTRY
  1400. * dwObjType - object type
  1401. *
  1402. * EXIT
  1403. * return object type name
  1404. */
  1405. PSZ LOCAL GetObjectTypeName(ULONG dwObjType)
  1406. {
  1407. TRACENAME("GETOBJECTTYPENAME")
  1408. PSZ psz = NULL;
  1409. int i;
  1410. static struct
  1411. {
  1412. ULONG dwObjType;
  1413. PSZ pszObjTypeName;
  1414. } ObjTypeTable[] =
  1415. {
  1416. OBJTYPE_UNKNOWN, "Unknown",
  1417. OBJTYPE_INTDATA, "Integer",
  1418. OBJTYPE_STRDATA, "String",
  1419. OBJTYPE_BUFFDATA, "Buffer",
  1420. OBJTYPE_PKGDATA, "Package",
  1421. OBJTYPE_FIELDUNIT, "FieldUnit",
  1422. OBJTYPE_DEVICE, "Device",
  1423. OBJTYPE_EVENT, "Event",
  1424. OBJTYPE_METHOD, "Method",
  1425. OBJTYPE_MUTEX, "Mutex",
  1426. OBJTYPE_OPREGION, "OpRegion",
  1427. OBJTYPE_POWERRES, "PowerResource",
  1428. OBJTYPE_PROCESSOR, "Processor",
  1429. OBJTYPE_THERMALZONE,"ThermalZone",
  1430. OBJTYPE_BUFFFIELD, "BuffField",
  1431. OBJTYPE_DDBHANDLE, "DDBHandle",
  1432. OBJTYPE_DEBUG, "Debug",
  1433. OBJTYPE_OBJALIAS, "ObjAlias",
  1434. OBJTYPE_DATAALIAS, "DataAlias",
  1435. OBJTYPE_BANKFIELD, "BankField",
  1436. OBJTYPE_FIELD, "Field",
  1437. OBJTYPE_INDEXFIELD, "IndexField",
  1438. OBJTYPE_DATA, "Data",
  1439. OBJTYPE_DATAFIELD, "DataField",
  1440. OBJTYPE_DATAOBJ, "DataObject",
  1441. 0, NULL
  1442. };
  1443. ENTER(4, ("GetObjectTypeName(Type=%x)\n", dwObjType));
  1444. for (i = 0; ObjTypeTable[i].pszObjTypeName != NULL; ++i)
  1445. {
  1446. if (dwObjType == ObjTypeTable[i].dwObjType)
  1447. {
  1448. psz = ObjTypeTable[i].pszObjTypeName;
  1449. break;
  1450. }
  1451. }
  1452. EXIT(4, ("GetObjectTypeName=%s\n", psz? psz: "NULL"));
  1453. return psz;
  1454. } //GetObjectTypeName
  1455. /***LP GetRegionSpaceName - get region space name
  1456. *
  1457. * ENTRY
  1458. * bRegionSpace - region space
  1459. *
  1460. * EXIT
  1461. * return object type name
  1462. */
  1463. PSZ LOCAL GetRegionSpaceName(UCHAR bRegionSpace)
  1464. {
  1465. TRACENAME("GETREGIONSPACENAME")
  1466. PSZ psz = NULL;
  1467. int i;
  1468. static PSZ pszVendorDefined = "VendorDefined";
  1469. static struct
  1470. {
  1471. UCHAR bRegionSpace;
  1472. PSZ pszRegionSpaceName;
  1473. } RegionNameTable[] =
  1474. {
  1475. REGSPACE_MEM, "SystemMemory",
  1476. REGSPACE_IO, "SystemIO",
  1477. REGSPACE_PCICFG, "PCIConfigSpace",
  1478. REGSPACE_EC, "EmbeddedController",
  1479. REGSPACE_SMB, "SMBus",
  1480. 0, NULL
  1481. };
  1482. ENTER(4, ("GetRegionSpaceName(RegionSpace=%x)\n", bRegionSpace));
  1483. for (i = 0; RegionNameTable[i].pszRegionSpaceName != NULL; ++i)
  1484. {
  1485. if (bRegionSpace == RegionNameTable[i].bRegionSpace)
  1486. {
  1487. psz = RegionNameTable[i].pszRegionSpaceName;
  1488. break;
  1489. }
  1490. }
  1491. if (psz == NULL)
  1492. {
  1493. psz = pszVendorDefined;
  1494. }
  1495. EXIT(4, ("GetRegionSpaceName=%s\n", psz? psz: "NULL"));
  1496. return psz;
  1497. } //GetRegionSpaceName
  1498. #endif //ifdef DEBUGGER
  1499. /***LP ValidateTable - Validate the table creator and revision
  1500. *
  1501. * ENTRY
  1502. * pdsdt -> DSDT
  1503. *
  1504. * EXIT-SUCCESS
  1505. * returns TRUE
  1506. * EXIT-FAILURE
  1507. * returns FALSE
  1508. */
  1509. BOOLEAN LOCAL ValidateTable(PDSDT pdsdt)
  1510. {
  1511. TRACENAME("VALIDATETABLE")
  1512. BOOLEAN rc = TRUE;
  1513. ENTER(3, ("ValidateTable(pdsdt=%x)\n", pdsdt));
  1514. if (!(gdwfAMLIInit & AMLIIF_NOCHK_TABLEVER) &&
  1515. (STRCMPN((PSZ)pdsdt->Header.CreatorID, CREATORID_MSFT,
  1516. sizeof(pdsdt->Header.CreatorID)) == 0))
  1517. {
  1518. if (pdsdt->Header.CreatorRev < MIN_CREATOR_REV)
  1519. {
  1520. rc = FALSE;
  1521. }
  1522. }
  1523. EXIT(3, ("ValidateTable=%x\n", rc));
  1524. return rc;
  1525. } //ValidateTable
  1526. /***LP NewObjData - allocate new object data identical to a given old object
  1527. *
  1528. * ENTRY
  1529. * pheap -> HEAP
  1530. * pdata -> old object
  1531. *
  1532. * EXIT-SUCCESS
  1533. * returns pointer to the new data
  1534. * EXIT-FAILURE
  1535. * returns NULL
  1536. */
  1537. PVOID LOCAL NewObjData(PHEAP pheap, POBJDATA pdata)
  1538. {
  1539. PVOID pv = NULL;
  1540. switch (pdata->dwDataType)
  1541. {
  1542. case OBJTYPE_STRDATA:
  1543. pv = NEWSDOBJ(gpheapGlobal, pdata->dwDataLen);
  1544. break;
  1545. case OBJTYPE_BUFFDATA:
  1546. pv = NEWBDOBJ(gpheapGlobal, pdata->dwDataLen);
  1547. break;
  1548. case OBJTYPE_PKGDATA:
  1549. pv = NEWPKOBJ(gpheapGlobal, pdata->dwDataLen);
  1550. break;
  1551. case OBJTYPE_FIELDUNIT:
  1552. pv = NEWFUOBJ(pheap, pdata->dwDataLen);
  1553. break;
  1554. case OBJTYPE_EVENT:
  1555. pv = NEWEVOBJ(pheap, pdata->dwDataLen);
  1556. break;
  1557. case OBJTYPE_METHOD:
  1558. pv = NEWMEOBJ(pheap, pdata->dwDataLen);
  1559. break;
  1560. case OBJTYPE_MUTEX:
  1561. pv = NEWMTOBJ(pheap, pdata->dwDataLen);
  1562. break;
  1563. case OBJTYPE_OPREGION:
  1564. pv = NEWOROBJ(pheap, pdata->dwDataLen);
  1565. break;
  1566. case OBJTYPE_POWERRES:
  1567. pv = NEWPROBJ(pheap, pdata->dwDataLen);
  1568. break;
  1569. case OBJTYPE_PROCESSOR:
  1570. pv = NEWPCOBJ(pheap, pdata->dwDataLen);
  1571. break;
  1572. case OBJTYPE_BUFFFIELD:
  1573. pv = NEWBFOBJ(pheap, pdata->dwDataLen);
  1574. break;
  1575. case OBJTYPE_BANKFIELD:
  1576. pv = NEWKFOBJ(pheap, pdata->dwDataLen);
  1577. break;
  1578. case OBJTYPE_FIELD:
  1579. pv = NEWFOBJ(pheap, pdata->dwDataLen);
  1580. break;
  1581. case OBJTYPE_INDEXFIELD:
  1582. pv = NEWIFOBJ(pheap, pdata->dwDataLen);
  1583. break;
  1584. default:
  1585. AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
  1586. ("NewObjData: invalid object type %s",
  1587. GetObjectTypeName(pdata->dwDataType)));
  1588. }
  1589. return pv;
  1590. } //NewObjData
  1591. /***LP FreeObjData - Free object data
  1592. *
  1593. * ENTRY
  1594. * pdata -> object which its data is to be freed
  1595. *
  1596. * EXIT
  1597. * None
  1598. */
  1599. VOID LOCAL FreeObjData(POBJDATA pdata)
  1600. {
  1601. switch (pdata->dwDataType)
  1602. {
  1603. case OBJTYPE_STRDATA:
  1604. FREESDOBJ(pdata->pbDataBuff);
  1605. break;
  1606. case OBJTYPE_BUFFDATA:
  1607. FREEBDOBJ(pdata->pbDataBuff);
  1608. break;
  1609. case OBJTYPE_PKGDATA:
  1610. FREEPKOBJ(pdata->pbDataBuff);
  1611. break;
  1612. case OBJTYPE_FIELDUNIT:
  1613. FREEFUOBJ(pdata->pbDataBuff);
  1614. break;
  1615. case OBJTYPE_EVENT:
  1616. FREEEVOBJ(pdata->pbDataBuff);
  1617. break;
  1618. case OBJTYPE_METHOD:
  1619. FREEMEOBJ(pdata->pbDataBuff);
  1620. break;
  1621. case OBJTYPE_MUTEX:
  1622. FREEMTOBJ(pdata->pbDataBuff);
  1623. break;
  1624. case OBJTYPE_OPREGION:
  1625. FREEOROBJ(pdata->pbDataBuff);
  1626. break;
  1627. case OBJTYPE_POWERRES:
  1628. FREEPROBJ(pdata->pbDataBuff);
  1629. break;
  1630. case OBJTYPE_PROCESSOR:
  1631. FREEPCOBJ(pdata->pbDataBuff);
  1632. break;
  1633. case OBJTYPE_BUFFFIELD:
  1634. FREEBFOBJ(pdata->pbDataBuff);
  1635. break;
  1636. case OBJTYPE_BANKFIELD:
  1637. FREEKFOBJ(pdata->pbDataBuff);
  1638. break;
  1639. case OBJTYPE_FIELD:
  1640. FREEFOBJ(pdata->pbDataBuff);
  1641. break;
  1642. case OBJTYPE_INDEXFIELD:
  1643. FREEIFOBJ(pdata->pbDataBuff);
  1644. break;
  1645. default:
  1646. AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
  1647. ("FreeObjData: invalid object type %s",
  1648. GetObjectTypeName(pdata->dwDataType)));
  1649. }
  1650. } //FreeObjData
  1651. /*** LP InitializeRegOverrideFlags - Get override flags from
  1652. * the registry.
  1653. *
  1654. * ENTRY
  1655. * None
  1656. *
  1657. * EXIT
  1658. * None
  1659. */
  1660. VOID LOCAL InitializeRegOverrideFlags(VOID)
  1661. {
  1662. TRACENAME("InitializeRegOverrideFlags")
  1663. HANDLE hRegKey=NULL;
  1664. NTSTATUS status;
  1665. ULONG argSize;
  1666. ENTER(3, ("InitializeRegOverrideFlags\n"));
  1667. status = OSOpenHandle(ACPI_PARAMETERS_REGISTRY_KEY, NULL, &hRegKey);
  1668. if (NT_SUCCESS(status))
  1669. {
  1670. argSize = sizeof(gOverrideFlags);
  1671. OSReadRegValue(AMLI_ATTRIBUTES, hRegKey, &gOverrideFlags, &argSize);
  1672. }
  1673. else
  1674. {
  1675. gOverrideFlags = 0;
  1676. }
  1677. EXIT(3, ("InitializeRegOverrideFlags\n"));
  1678. return;
  1679. }
  1680. /*** LP ValidateMemoryOpregionRange - Validate the memory range that is
  1681. * required for the memory opregion.
  1682. *
  1683. * ENTRY
  1684. * uipAddr - physical memory address
  1685. * dwLen - length of memory block
  1686. *
  1687. * EXIT
  1688. * returns TRUE iff the memory is in the legal range.
  1689. */
  1690. BOOLEAN LOCAL ValidateMemoryOpregionRange(ULONG_PTR uipAddr, ULONG dwLen)
  1691. {
  1692. BOOLEAN Ret = FALSE;
  1693. NTSTATUS status;
  1694. PACPI_BIOS_MULTI_NODE e820Info;
  1695. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartialDesc;
  1696. PCM_PARTIAL_RESOURCE_LIST cmPartialList;
  1697. PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 keyInfo;
  1698. ULONGLONG i;
  1699. ULONGLONG absMin;
  1700. ULONGLONG absMax;
  1701. //
  1702. // Read the key for the AcpiConfigurationData
  1703. //
  1704. status = OSReadAcpiConfigurationData( &keyInfo );
  1705. if (!NT_SUCCESS(status))
  1706. {
  1707. PRINTF("ValidateMemoryOpregionRange: Cannot get E820 Information %08lx\n",
  1708. status
  1709. );
  1710. Ret = TRUE;
  1711. }
  1712. else
  1713. {
  1714. //
  1715. // Crack the structure to get the E820Table entry
  1716. //
  1717. cmPartialList = (PCM_PARTIAL_RESOURCE_LIST) (keyInfo->Data);
  1718. cmPartialDesc = &(cmPartialList->PartialDescriptors[0]);
  1719. e820Info = (PACPI_BIOS_MULTI_NODE) ( (PUCHAR) cmPartialDesc + sizeof(CM_PARTIAL_RESOURCE_LIST) );
  1720. //
  1721. // Calculate absmin and absmax for the incoming address
  1722. //
  1723. absMin = (ULONGLONG)uipAddr;
  1724. absMax = absMin + dwLen;
  1725. //
  1726. // walk the E820 list
  1727. //
  1728. for(i = 0; i < e820Info->Count; i++)
  1729. {
  1730. if (e820Info->E820Entry[i].Type == AcpiAddressRangeMemory)
  1731. {
  1732. if(absMax < (ULONGLONG)PAGE_SIZE)
  1733. {
  1734. Ret = TRUE;
  1735. PRINTF("ValidateMemoryOpregionRange: Memory OpRegion (Base = 0x%I64x, Length = 0x%x) is in first physical page, skipping check.\n",
  1736. absMin,
  1737. dwLen
  1738. );
  1739. }
  1740. else
  1741. {
  1742. if((absMax < (ULONGLONG) e820Info->E820Entry[i].Base.QuadPart)
  1743. ||(absMin >= (ULONGLONG) (e820Info->E820Entry[i].Base.QuadPart + e820Info->E820Entry[i].Length.QuadPart)))
  1744. {
  1745. Ret = TRUE;
  1746. PRINTF("ValidateMemoryOpregionRange: Memory OpRegion (Base = 0x%I64x, Length = 0x%x) is not in AcpiAddressRangeMemory (Base = 0x%I64x, Length = 0x%I64x)\n",
  1747. absMin,
  1748. dwLen,
  1749. e820Info->E820Entry[i].Base.QuadPart,
  1750. e820Info->E820Entry[i].Length.QuadPart
  1751. );
  1752. }
  1753. else
  1754. {
  1755. //
  1756. // This opregion is mapping memory that belongs to the OS.
  1757. // Log a error in the event log.
  1758. //
  1759. PWCHAR illegalMemoryAddress[5];
  1760. WCHAR AMLIName[6];
  1761. WCHAR addressBuffer[64];
  1762. WCHAR addressLengthBuffer[64];
  1763. WCHAR OSaddressBufferRangeMin[64];
  1764. WCHAR OSaddressBufferRangeMax[64];
  1765. //
  1766. // Turn the address into a string
  1767. //
  1768. swprintf( AMLIName, L"AMLI");
  1769. swprintf( addressBuffer, L"0x%I64x", absMin );
  1770. swprintf( addressLengthBuffer, L"0x%lx", dwLen );
  1771. swprintf( OSaddressBufferRangeMin, L"0x%I64x", e820Info->E820Entry[i].Base.QuadPart );
  1772. swprintf( OSaddressBufferRangeMax, L"0x%I64x", e820Info->E820Entry[i].Base.QuadPart + e820Info->E820Entry[i].Length.QuadPart);
  1773. //
  1774. // Build the list of arguments to pass to the function that will write the
  1775. // error log to the registry
  1776. //
  1777. illegalMemoryAddress[0] = AMLIName;
  1778. illegalMemoryAddress[1] = addressBuffer;
  1779. illegalMemoryAddress[2] = addressLengthBuffer;
  1780. illegalMemoryAddress[3] = OSaddressBufferRangeMin;
  1781. illegalMemoryAddress[4] = OSaddressBufferRangeMax;
  1782. //
  1783. // Log error to event log
  1784. //
  1785. ACPIWriteEventLogEntry(ACPI_ERR_AMLI_ILLEGAL_MEMORY_OPREGION_FATAL,
  1786. &illegalMemoryAddress,
  1787. 5,
  1788. NULL,
  1789. 0);
  1790. PRINTF("ValidateMemoryOpregionRange: Memory OpRegion (Base = 0x%I64x, Length = 0x%x) is in AcpiAddressRangeMemory (Base = 0x%I64x, Length = 0x%I64x)\n",
  1791. absMin,
  1792. dwLen,
  1793. e820Info->E820Entry[i].Base.QuadPart,
  1794. e820Info->E820Entry[i].Length.QuadPart
  1795. );
  1796. Ret = FALSE;
  1797. break;
  1798. }
  1799. }
  1800. }
  1801. }
  1802. }
  1803. //
  1804. // Free the E820 info
  1805. //
  1806. ExFreePool( keyInfo );
  1807. return Ret;
  1808. }
  1809. #ifdef DEBUG
  1810. /*** LP FreeMem - Free memory object
  1811. *
  1812. * ENTRY
  1813. * pv -> memory object to be freed
  1814. * pdwcObjs -> object counter to be decremented
  1815. *
  1816. * EXIT
  1817. * None
  1818. */
  1819. VOID LOCAL FreeMem(PVOID pv, PULONG pdwcObjs)
  1820. {
  1821. if (*pdwcObjs != 0)
  1822. {
  1823. ExFreePool(pv);
  1824. (*pdwcObjs)--;
  1825. }
  1826. else
  1827. {
  1828. AMLI_ERROR(("FreeMem: Unbalanced MemFree"));
  1829. }
  1830. } //FreeMem
  1831. /*** LP CheckGlobalHeap - Make sure that the global heap has not become
  1832. * corrupted
  1833. *
  1834. * ENTRY
  1835. * None
  1836. *
  1837. * Exit
  1838. * None
  1839. */
  1840. VOID LOCAL CheckGlobalHeap()
  1841. {
  1842. KIRQL oldIrql;
  1843. //
  1844. // We don't care about this is we are loading a DDB
  1845. //
  1846. if (gdwfAMLI & AMLIF_LOADING_DDB) {
  1847. return;
  1848. }
  1849. //
  1850. // Must have spinlock protection...
  1851. //
  1852. KeAcquireSpinLock( &gdwGHeapSpinLock, &oldIrql );
  1853. //
  1854. // We only care if they don't match...
  1855. //
  1856. if (gdwGlobalHeapSize == gdwGHeapSnapshot) {
  1857. goto CheckGlobalHeapExit;
  1858. }
  1859. //
  1860. // If the new heap size is smaller than the current size, then
  1861. // we shrunk the heap and that is good...
  1862. //
  1863. if (gdwGlobalHeapSize < gdwGHeapSnapshot) {
  1864. //
  1865. // Remember the new "snapshot size"
  1866. //
  1867. gdwGHeapSnapshot = gdwGlobalHeapSize;
  1868. goto CheckGlobalHeapExit;
  1869. }
  1870. if (gDebugger.dwfDebugger & DBGF_VERBOSE_ON) {
  1871. AMLI_WARN(("CheckGlobalHeap: "
  1872. "potential memory leak "
  1873. "detected (CurrentHeapSize=%d,"
  1874. "ReferenceSize=%d)",
  1875. gdwGlobalHeapSize,
  1876. gdwGHeapSnapshot));
  1877. }
  1878. if (gdwGlobalHeapSize - gdwGHeapSnapshot > 8192) {
  1879. AMLI_WARN(("CheckGlobalHeap: detected memory leak"));
  1880. KdBreakPoint();
  1881. }
  1882. CheckGlobalHeapExit:
  1883. //
  1884. // Release the lock and we are done
  1885. //
  1886. KeReleaseSpinLock( &gdwGHeapSpinLock, oldIrql );
  1887. }
  1888. #endif //ifdef DEBUG