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.

504 lines
13 KiB

  1. /*** acpitab.c - ACPI VXD to provide table access IOCTLs
  2. *
  3. * Author: Michael Tsang (MikeTs)
  4. * Created 10/08/97
  5. *
  6. * MODIFICATION HISTORY
  7. */
  8. #include "acpitabp.h"
  9. /*** Function prototypes
  10. */
  11. CM_VXD_RESULT CM_SYSCTRL ACPITabIOCtrl(PDIOCPARAMETERS pdioc);
  12. PRSDT LOCAL FindRSDT(PDWORD pdwRSDPAddr, PDWORD pdwRSDTAddr);
  13. DWORD LOCAL FindTable(DWORD dwSig, PDWORD pdwLen);
  14. BOOL LOCAL ValidateTable(DWORD dwTableAddr, DWORD dwLen);
  15. BOOL LOCAL IsALikelySig(DWORD dwTableSig);
  16. VOID LOCAL CopyROM(DWORD dwPhyAddr, PBYTE pbBuff, DWORD dwLen);
  17. BYTE LOCAL CheckSum(PBYTE pb, DWORD dwLen);
  18. #ifdef TRACING
  19. PSZ LOCAL SigStr(DWORD dwSig);
  20. #endif
  21. #pragma VXD_PAGEABLE_DATA
  22. #pragma VXD_PAGEABLE_CODE
  23. /***EP ACPITabIOCtrl - Win32 Device IO Control entry point
  24. *
  25. * ENTRY
  26. * pioc -> DIOC structure
  27. *
  28. * EXIT-SUCCESS
  29. * returns ERROR_SUCCESS
  30. * EXIT-FAILURE
  31. * returns ERROR_*
  32. */
  33. CM_VXD_RESULT CM_SYSCTRL ACPITabIOCtrl(PDIOCPARAMETERS pdioc)
  34. {
  35. TRACENAME("ACPITabIOCTRL")
  36. CM_VXD_RESULT rc = ERROR_SUCCESS;
  37. ENTER(1, ("ACPITabIOCtrl(hVM=%lx,hDev=%lx,Code=%lx)\n",
  38. pdioc->VMHandle, pdioc->hDevice, pdioc->dwIoControlCode));
  39. switch (pdioc->dwIoControlCode)
  40. {
  41. case ACPITAB_DIOC_GETVERSION:
  42. if ((pdioc->cbOutBuffer < sizeof(DWORD)) ||
  43. (pdioc->lpvOutBuffer == NULL))
  44. {
  45. DBG_ERR(("ACPITabIOCtrl: invalid parameter on GetVersion"));
  46. rc = ERROR_INVALID_PARAMETER;
  47. }
  48. else
  49. {
  50. PVMMDDB pddb = (PVMMDDB)pdioc->Internal2;
  51. *((PDWORD)pdioc->lpvOutBuffer) =
  52. (pddb->DDB_Dev_Major_Version << 8) |
  53. pddb->DDB_Dev_Minor_Version;
  54. if (pdioc->lpcbBytesReturned != NULL)
  55. *((PDWORD)pdioc->lpcbBytesReturned) = sizeof(DWORD);
  56. }
  57. break;
  58. case ACPITAB_DIOC_GETTABINFO:
  59. if ((pdioc->lpvOutBuffer == NULL) ||
  60. (pdioc->cbOutBuffer != sizeof(TABINFO)))
  61. {
  62. DBG_ERR(("ACPITabIOCtrl: invalid parameter on GetTabInfo"));
  63. rc = ERROR_INVALID_PARAMETER;
  64. }
  65. else
  66. {
  67. PTABINFO pTabInfo = (PTABINFO)pdioc->lpvOutBuffer;
  68. DWORD dwLen;
  69. if ((pTabInfo->dwPhyAddr = FindTable(pTabInfo->dwTabSig, NULL))
  70. != 0)
  71. {
  72. if (pTabInfo->dwTabSig == SIG_RSDP)
  73. {
  74. dwLen = sizeof(RSDP);
  75. }
  76. else if (pTabInfo->dwTabSig == FACS_SIGNATURE)
  77. {
  78. dwLen = sizeof(FACS);
  79. }
  80. else
  81. {
  82. dwLen = sizeof(DESCRIPTION_HEADER);
  83. }
  84. CopyROM(pTabInfo->dwPhyAddr, (PBYTE)&pTabInfo->dh, dwLen);
  85. }
  86. else
  87. {
  88. DBG_ERR(("ACPITabIOCtrl: failed to get table info"));
  89. rc = ERROR_GEN_FAILURE;
  90. }
  91. }
  92. break;
  93. case ACPITAB_DIOC_GETTABLE:
  94. if ((pdioc->lpvInBuffer == NULL) || (pdioc->lpvOutBuffer == NULL) ||
  95. (pdioc->cbOutBuffer == 0) ||
  96. !ValidateTable((DWORD)pdioc->lpvInBuffer, pdioc->cbOutBuffer))
  97. {
  98. DBG_ERR(("ACPITabIOCtrl: invalid parameter on GetTable"));
  99. rc = ERROR_INVALID_PARAMETER;
  100. }
  101. else
  102. {
  103. CopyROM((DWORD)pdioc->lpvInBuffer, (PBYTE)pdioc->lpvOutBuffer,
  104. pdioc->cbOutBuffer);
  105. }
  106. break;
  107. }
  108. EXIT(1, ("ACPITabIOCtrl=%x\n", rc));
  109. return rc;
  110. } //ACPITabIOCtrl
  111. /***LP FindRSDT - Find the RSDT
  112. *
  113. * ENTRY
  114. * pdwRSDPAddr -> to hold the physical address of RSDP
  115. * pdwRSDTAddr -> to hold the physical address of RSDT
  116. *
  117. * EXIT-SUCCESS
  118. * returns the RSDT pointer
  119. * EXIT-FAILURE
  120. * returns NULL
  121. */
  122. PRSDT LOCAL FindRSDT(PDWORD pdwRSDPAddr, PDWORD pdwRSDTAddr)
  123. {
  124. TRACENAME("FINDRSDT")
  125. PRSDT pRSDT = NULL;
  126. PBYTE pbROM;
  127. ENTER(2, ("FindRSDT(pdwRSDPAddr=%p,pdwRSDTAddr=%p)\n",
  128. pdwRSDPAddr, pdwRSDTAddr));
  129. if ((pbROM = (PBYTE)_MapPhysToLinear(RSDP_SEARCH_RANGE_BEGIN,
  130. RSDP_SEARCH_RANGE_LENGTH, 0)) !=
  131. (PBYTE)0xffffffff)
  132. {
  133. PBYTE pbROMEnd;
  134. pbROMEnd = pbROM + RSDP_SEARCH_RANGE_LENGTH - RSDP_SEARCH_INTERVAL;
  135. while (pbROM != NULL)
  136. {
  137. if ((((PRSDP)pbROM)->Signature == RSDP_SIGNATURE) &&
  138. (CheckSum(pbROM, sizeof(RSDP)) == 0))
  139. {
  140. *pdwRSDPAddr = (RSDP_SEARCH_RANGE_BEGIN +
  141. RSDP_SEARCH_RANGE_LENGTH) -
  142. (pbROMEnd + RSDP_SEARCH_INTERVAL - pbROM);
  143. *pdwRSDTAddr = ((PRSDP)pbROM)->RsdtAddress;
  144. if (((pbROM = (PBYTE)_MapPhysToLinear(*pdwRSDTAddr,
  145. sizeof(DESCRIPTION_HEADER),
  146. 0)) ==
  147. (PBYTE)0xffffffff) ||
  148. (((PDESCRIPTION_HEADER)pbROM)->Signature != RSDT_SIGNATURE))
  149. {
  150. pbROM = NULL;
  151. *pdwRSDTAddr = 0;
  152. }
  153. break;
  154. }
  155. else
  156. {
  157. pbROM += RSDP_SEARCH_INTERVAL;
  158. if (pbROM > pbROMEnd)
  159. {
  160. pbROM = NULL;
  161. }
  162. }
  163. }
  164. if (pbROM != NULL)
  165. {
  166. DWORD dwLen = ((PDESCRIPTION_HEADER)pbROM)->Length;
  167. pRSDT = (PRSDT)_MapPhysToLinear(*pdwRSDTAddr, dwLen, 0);
  168. if ((pRSDT == (PRSDT)0xffffffff) ||
  169. (CheckSum((PBYTE)pRSDT, dwLen) != 0))
  170. {
  171. pRSDT = NULL;
  172. *pdwRSDTAddr = 0;
  173. }
  174. }
  175. }
  176. EXIT(2, ("FindRSDT=%x (RSDPAddr=%x,RSDTAddr=%x)\n",
  177. pRSDT, *pdwRSDPAddr, *pdwRSDTAddr));
  178. return pRSDT;
  179. } //FindRSDT
  180. /***LP FindTable - Find an ACPI Table
  181. *
  182. * ENTRY
  183. * dwSig - signature of the table
  184. * pdwLen -> to hold length of table (can be NULL)
  185. *
  186. * EXIT-SUCCESS
  187. * returns physical address of table
  188. * EXIT-FAILURE
  189. * returns 0
  190. */
  191. DWORD LOCAL FindTable(DWORD dwSig, PDWORD pdwLen)
  192. {
  193. TRACENAME("FINDTABLE")
  194. DWORD dwPhyAddr = 0, dwTableLen = 0;
  195. static PRSDT pRSDT = (PRSDT)0xffffffff;
  196. static DWORD dwRSDPAddr = 0, dwRSDTAddr = 0;
  197. ENTER(2, ("FindTable(Sig=%s,pdwLen=%x)\n", SigStr(dwSig), pdwLen));
  198. if (pRSDT == (PRSDT)0xffffffff)
  199. {
  200. pRSDT = FindRSDT(&dwRSDPAddr, &dwRSDTAddr);
  201. }
  202. if (pRSDT != NULL)
  203. {
  204. PVOID pv;
  205. if (dwSig == SIG_RSDP)
  206. {
  207. //
  208. // We are looking for "RSD PTR"
  209. //
  210. dwPhyAddr = dwRSDPAddr;
  211. dwTableLen = sizeof(RSDP);
  212. }
  213. else if (dwSig == RSDT_SIGNATURE)
  214. {
  215. dwPhyAddr = dwRSDTAddr;
  216. dwTableLen = pRSDT->Header.Length;
  217. }
  218. else if ((dwSig == DSDT_SIGNATURE) || (dwSig == FACS_SIGNATURE))
  219. {
  220. PFADT pFADT;
  221. if (((dwPhyAddr = FindTable(FADT_SIGNATURE, &dwTableLen)) != 0) &&
  222. ((pFADT = (PFADT)_MapPhysToLinear(dwPhyAddr, dwTableLen, 0)) !=
  223. (PFADT)0xffffffff))
  224. {
  225. if (dwSig == DSDT_SIGNATURE)
  226. {
  227. dwPhyAddr = pFADT->dsdt;
  228. if ((pv = _MapPhysToLinear(dwPhyAddr,
  229. sizeof(DESCRIPTION_HEADER), 0))
  230. != (PVOID)0xffffffff)
  231. {
  232. dwTableLen = ((PDESCRIPTION_HEADER)pv)->Length;
  233. }
  234. else
  235. {
  236. dwPhyAddr = 0;
  237. }
  238. }
  239. else
  240. {
  241. dwPhyAddr = pFADT->facs;
  242. if ((pv = _MapPhysToLinear(dwPhyAddr, sizeof(FACS), 0)) !=
  243. (PVOID)0xffffffff)
  244. {
  245. dwTableLen = ((PFACS)pv)->Length;
  246. }
  247. else
  248. {
  249. dwPhyAddr = 0;
  250. }
  251. }
  252. }
  253. else
  254. {
  255. dwPhyAddr = 0;
  256. }
  257. }
  258. else
  259. {
  260. int i, iNumTables = NumTableEntriesFromRSDTPointer(pRSDT);
  261. for (i = 0; i < iNumTables; ++i)
  262. {
  263. if (((pv = _MapPhysToLinear(pRSDT->Tables[i],
  264. sizeof(DESCRIPTION_HEADER), 0)) !=
  265. (PVOID)0xffffffff) &&
  266. (((PDESCRIPTION_HEADER)pv)->Signature == dwSig))
  267. {
  268. dwPhyAddr = pRSDT->Tables[i];
  269. dwTableLen = ((PDESCRIPTION_HEADER)pv)->Length;
  270. break;
  271. }
  272. }
  273. }
  274. if ((dwPhyAddr != 0) && (pdwLen != NULL))
  275. {
  276. *pdwLen = dwTableLen;
  277. }
  278. }
  279. EXIT(2, ("FindTable=%x (Len=%x)\n", dwPhyAddr, pdwLen? *pdwLen: 0));
  280. return dwPhyAddr;
  281. } //FindTable
  282. /***LP ValidateTable - Validate the table
  283. *
  284. * ENTRY
  285. * dwTableAddr - physical address of table
  286. * dwLen - table length
  287. *
  288. * EXIT-SUCCESS
  289. * returns TRUE
  290. * EXIT-FAILURE
  291. * returns FALSE
  292. */
  293. BOOL LOCAL ValidateTable(DWORD dwTableAddr, DWORD dwLen)
  294. {
  295. TRACENAME("VALIDATETABLE")
  296. BOOL rc = TRUE;
  297. PBYTE pbTable;
  298. ENTER(2, ("ValidateTable(TableAddr=%x,Len=%d)\n", dwTableAddr, dwLen));
  299. if ((pbTable = (PBYTE)_MapPhysToLinear(dwTableAddr, dwLen, 0)) !=
  300. (PBYTE)0xffffffff)
  301. {
  302. DWORD dwTableSig, dwTableLen = 0;
  303. BOOL fNeedChkSum = FALSE;
  304. dwTableSig = ((PDESCRIPTION_HEADER)pbTable)->Signature;
  305. switch (dwTableSig)
  306. {
  307. case SIG_LOW_RSDP:
  308. dwTableLen = sizeof(RSDP);
  309. fNeedChkSum = TRUE;
  310. break;
  311. case RSDT_SIGNATURE:
  312. case FADT_SIGNATURE:
  313. case DSDT_SIGNATURE:
  314. case SSDT_SIGNATURE:
  315. case PSDT_SIGNATURE:
  316. case APIC_SIGNATURE:
  317. case SBST_SIGNATURE:
  318. case SIG_BOOT:
  319. dwTableLen = ((PDESCRIPTION_HEADER)pbTable)->Length;
  320. fNeedChkSum = TRUE;
  321. break;
  322. case FACS_SIGNATURE:
  323. dwTableLen = ((PFACS)pbTable)->Length;
  324. break;
  325. default:
  326. if (IsALikelySig(dwTableSig) &&
  327. (((PDESCRIPTION_HEADER)pbTable)->Length < 256))
  328. {
  329. dwTableLen = ((PDESCRIPTION_HEADER)pbTable)->Length;
  330. fNeedChkSum = TRUE;
  331. }
  332. else
  333. {
  334. rc = FALSE;
  335. }
  336. }
  337. if ((rc == TRUE) && fNeedChkSum)
  338. {
  339. if (((pbTable = (PBYTE)_MapPhysToLinear(dwTableAddr, dwTableLen, 0))
  340. == (PBYTE)0xffffffff) ||
  341. (CheckSum(pbTable, dwTableLen) != 0))
  342. {
  343. rc = FALSE;
  344. }
  345. }
  346. }
  347. else
  348. {
  349. rc = FALSE;
  350. }
  351. EXIT(2, ("ValidateTable=%x\n", rc));
  352. return rc;
  353. } //ValidateTable
  354. /***LP IsALikelySig - Check if it looks like a table signature
  355. *
  356. * ENTRY
  357. * dwTableSig - table signature
  358. *
  359. * EXIT-SUCCESS
  360. * returns TRUE
  361. * EXIT-FAILURE
  362. * returns FALSE
  363. */
  364. BOOL LOCAL IsALikelySig(DWORD dwTableSig)
  365. {
  366. TRACENAME("ISALIKELYSIG")
  367. BOOL rc = TRUE;
  368. int i, ch;
  369. ENTER(2, ("IsALikelySig(TableSig=%x)\n", dwTableSig));
  370. for (i = 0; i < sizeof(DWORD); ++i)
  371. {
  372. ch = BYTEOF(dwTableSig, i);
  373. if ((ch < 'A') || (ch > 'Z'))
  374. {
  375. rc = FALSE;
  376. break;
  377. }
  378. }
  379. EXIT(2, ("IsALikelySig=%x\n", rc));
  380. return rc;
  381. } //IsALikelySig
  382. /***LP CopyROM - Copy ROM memory to buffer
  383. *
  384. * ENTRY
  385. * dwPhyAddr - physical address of ROM location
  386. * pbBuff -> buffer
  387. * dwLen - buffer length
  388. *
  389. * EXIT
  390. * None
  391. */
  392. VOID LOCAL CopyROM(DWORD dwPhyAddr, PBYTE pbBuff, DWORD dwLen)
  393. {
  394. TRACENAME("COPYROM")
  395. PBYTE pbROM;
  396. ENTER(2, ("CopyROM(PhyAddr=%x,pbBuff=%x,Len=%x)\n",
  397. dwPhyAddr, pbBuff, dwLen));
  398. if ((pbROM = (PBYTE)_MapPhysToLinear(dwPhyAddr, dwLen, 0)) !=
  399. (PBYTE)0xffffffff)
  400. {
  401. memcpy(pbBuff, pbROM, dwLen);
  402. }
  403. EXIT(2, ("CopyROM!\n"));
  404. } //CopyROM
  405. /***LP CheckSum - Calculate checksum of a buffer
  406. *
  407. * ENTRY
  408. * pb -> buffer
  409. * dwLen - length of buffer
  410. *
  411. * EXIT
  412. * returns checksum
  413. */
  414. BYTE LOCAL CheckSum(PBYTE pb, DWORD dwLen)
  415. {
  416. TRACENAME("CHECKSUM")
  417. BYTE bChkSum = 0;
  418. ENTER(2, ("CheckSum(pb=%x,Len=%x)\n", pb, dwLen));
  419. while (dwLen > 0)
  420. {
  421. bChkSum = (BYTE)(bChkSum + *pb);
  422. pb++;
  423. dwLen--;
  424. }
  425. EXIT(2, ("CheckSum=%x\n", bChkSum));
  426. return bChkSum;
  427. } //CheckSum
  428. #ifdef TRACING
  429. /***LP SigStr - return string of DWORD signature
  430. *
  431. * ENTRY
  432. * dwSig - signature
  433. *
  434. * EXIT
  435. * returns signature string
  436. */
  437. PSZ LOCAL SigStr(DWORD dwSig)
  438. {
  439. static char szSig[sizeof(DWORD) + 1] = {0};
  440. memcpy(szSig, &dwSig, sizeof(DWORD));
  441. return (PSZ)szSig;
  442. } //SigStr
  443. #endif