Leaked source code of windows server 2003
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.

1223 lines
34 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. loaddsdt.c
  5. Abstract:
  6. This handles loading the DSDT table and all steps leading up to it
  7. Author:
  8. Stephane Plante (splante)
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. 02-Jun-97 Initial Revision
  13. --*/
  14. #include "pch.h"
  15. #include "amlreg.h"
  16. #include <stdio.h>
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGE,ACPILoadFindRSDT)
  19. #pragma alloc_text(PAGE,ACPILoadProcessDSDT)
  20. #pragma alloc_text(PAGE,ACPILoadProcessFADT)
  21. #pragma alloc_text(PAGE,ACPILoadProcessFACS)
  22. #pragma alloc_text(PAGE,ACPILoadProcessRSDT)
  23. #pragma alloc_text(PAGE,ACPILoadTableCheckSum)
  24. #endif
  25. #if DBG
  26. BOOLEAN AcpiLoadSimulatorTable = TRUE;
  27. #else
  28. BOOLEAN AcpiLoadSimulatorTable = FALSE;
  29. #endif
  30. PRSDT
  31. ACPILoadFindRSDT(
  32. VOID
  33. )
  34. /*++
  35. Routine Description:
  36. This routine looks at the registry to find the value stored there by
  37. ntdetect.com
  38. Arguments:
  39. None
  40. Return Value:
  41. Pointer to the RSDT
  42. --*/
  43. {
  44. NTSTATUS status;
  45. PACPI_BIOS_MULTI_NODE rsdpMulti;
  46. PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartialDesc;
  47. PCM_PARTIAL_RESOURCE_LIST cmPartialList;
  48. PHYSICAL_ADDRESS PhysAddress = {0};
  49. PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 keyInfo;
  50. PRSDT rsdtBuffer = NULL;
  51. PRSDT rsdtPointer;
  52. ULONG MemSpace = 0;
  53. PAGED_CODE();
  54. //
  55. // Read the key for that AcpiConfigurationData
  56. //
  57. status = OSReadAcpiConfigurationData( &keyInfo );
  58. if (!NT_SUCCESS(status)) {
  59. ACPIPrint( (
  60. ACPI_PRINT_CRITICAL,
  61. "ACPILoadFindRSDT: Cannot open Configuration Data - 0x%08lx\n",
  62. status
  63. ) );
  64. ACPIBreakPoint();
  65. return NULL;
  66. }
  67. //
  68. // Crack the structure
  69. //
  70. cmPartialList = (PCM_PARTIAL_RESOURCE_LIST) (keyInfo->Data);
  71. cmPartialDesc = &(cmPartialList->PartialDescriptors[0]);
  72. rsdpMulti = (PACPI_BIOS_MULTI_NODE) ( (PUCHAR) cmPartialDesc +
  73. sizeof(CM_PARTIAL_RESOURCE_LIST) );
  74. //
  75. // Read the Header part of the table
  76. //
  77. PhysAddress.QuadPart = rsdpMulti->RsdtAddress.QuadPart;
  78. rsdtPointer = MmMapIoSpace(
  79. PhysAddress,
  80. sizeof(DESCRIPTION_HEADER),
  81. MmNonCached
  82. );
  83. if (rsdtPointer == NULL) {
  84. ACPIPrint( (
  85. ACPI_PRINT_CRITICAL,
  86. "ACPILoadFindRsdt: Cannot Map RSDT Pointer 0x%08lx\n",
  87. rsdpMulti->RsdtAddress.LowPart
  88. ) );
  89. ACPIBreakPoint();
  90. goto RsdtDone;
  91. } else if ((rsdtPointer->Header.Signature != RSDT_SIGNATURE) &&
  92. (rsdtPointer->Header.Signature != XSDT_SIGNATURE)) {
  93. ACPIPrint( (
  94. ACPI_PRINT_CRITICAL,
  95. "ACPILoadFindRsdt: RSDT 0x%08lx has invalid signature\n",
  96. rsdtPointer
  97. ) );
  98. ACPIBreakPoint();
  99. goto RsdtDone;
  100. }
  101. //
  102. // Read the entire RSDT
  103. //
  104. rsdtBuffer = MmMapIoSpace(
  105. PhysAddress,
  106. rsdtPointer->Header.Length,
  107. MmNonCached
  108. );
  109. //
  110. // Give back a PTE now that we're done with the rsdtPointer.
  111. //
  112. MmUnmapIoSpace(rsdtPointer, sizeof(DESCRIPTION_HEADER));
  113. //
  114. // did we find the right rsdt buffer?
  115. //
  116. if (rsdtBuffer == NULL) {
  117. ACPIPrint( (
  118. ACPI_PRINT_CRITICAL,
  119. "ACPILoadFindRsdt: Cannot Map RSDT Pointer 0x%08lx\n",
  120. rsdpMulti->RsdtAddress.LowPart
  121. ) );
  122. ACPIBreakPoint();
  123. goto RsdtDone;
  124. }
  125. RsdtDone:
  126. //
  127. // Done with these buffers
  128. //
  129. ExFreePool( keyInfo );
  130. //
  131. // return the RSDT
  132. //
  133. return rsdtBuffer;
  134. }
  135. NTSTATUS
  136. ACPILoadProcessDSDT(
  137. ULONG_PTR Address
  138. )
  139. /*++
  140. Routine Description:
  141. This routine loads the DSDT (a pointer is stored in the FADT) and forces
  142. the interpreter to process it
  143. Arguments:
  144. Address - Where the DSDT is located in memory
  145. Return Value:
  146. NTSTATUS
  147. --*/
  148. {
  149. BOOLEAN foundOverride;
  150. PDSDT linAddress;
  151. ULONG index;
  152. ULONG length;
  153. ULONG MemSpace = 0;
  154. PHYSICAL_ADDRESS PhysAddress = {0};
  155. //
  156. // Map the header in virtual address space to get the length
  157. //
  158. PhysAddress.QuadPart = (ULONGLONG) Address;
  159. linAddress = MmMapIoSpace(
  160. PhysAddress,
  161. sizeof(DESCRIPTION_HEADER),
  162. MmNonCached
  163. );
  164. if (linAddress == NULL) {
  165. ASSERT (linAddress != NULL);
  166. return STATUS_INSUFFICIENT_RESOURCES;
  167. }
  168. if ( linAddress->Header.Signature != DSDT_SIGNATURE) {
  169. //
  170. // Signature should have matched DSDT but didn't !
  171. //
  172. ACPIPrint( (
  173. ACPI_PRINT_CRITICAL,
  174. "ACPILoadProcessDSDT: 0x%08lx does not have DSDT signature\n",
  175. linAddress
  176. ) );
  177. return STATUS_ACPI_INVALID_TABLE;
  178. }
  179. //
  180. // Determine the size of the DSDT
  181. //
  182. length = linAddress->Header.Length;
  183. //
  184. // Now map the whole thing.
  185. //
  186. MmUnmapIoSpace(linAddress, sizeof(DESCRIPTION_HEADER));
  187. linAddress = MmMapIoSpace(
  188. PhysAddress,
  189. length,
  190. MmNonCached
  191. );
  192. if (linAddress == NULL) {
  193. ASSERT (linAddress != NULL);
  194. return STATUS_INSUFFICIENT_RESOURCES;
  195. }
  196. //
  197. // Look at the RsdtInformation to determine the index of the last
  198. // element in the table. We know that we can use that space to store
  199. // the information about this table
  200. //
  201. index = RsdtInformation->NumElements;
  202. if (index == 0) {
  203. return STATUS_ACPI_NOT_INITIALIZED;
  204. }
  205. index--;
  206. //
  207. // Try to read the DSDT from the registry
  208. //
  209. foundOverride = ACPIRegReadAMLRegistryEntry( &linAddress, TRUE );
  210. if (foundOverride) {
  211. ACPIPrint( (
  212. ACPI_PRINT_WARNING,
  213. "ACPILoadProcessDSDT: DSDT Overloaded from registry (0x%08lx)\n",
  214. linAddress
  215. ) );
  216. RsdtInformation->Tables[index].Flags |= RSDTELEMENT_OVERRIDEN;
  217. }
  218. //
  219. // Store a pointer to the DSDT
  220. //
  221. AcpiInformation->DiffSystemDescTable = linAddress;
  222. //
  223. // Remember this address and that we need to unmap it
  224. //
  225. RsdtInformation->Tables[index].Flags |=
  226. (RSDTELEMENT_MAPPED | RSDTELEMENT_LOADABLE);
  227. RsdtInformation->Tables[index].Address = linAddress;
  228. //
  229. // Done
  230. //
  231. return STATUS_SUCCESS;
  232. }
  233. NTSTATUS
  234. ACPILoadProcessFACS(
  235. ULONG_PTR Address
  236. )
  237. /*++
  238. Routine Description:
  239. This routine handles the FACS
  240. Arguments:
  241. Address - Where the FACS is located
  242. Return Value:
  243. None
  244. --*/
  245. {
  246. PFACS linAddress;
  247. ULONG MemSpace = 0;
  248. PHYSICAL_ADDRESS PhysAddress = {0};
  249. // Note: On Alpha, the FACS is optional.
  250. //
  251. // Return if FACS address is not valid.
  252. //
  253. if (!Address) {
  254. return STATUS_SUCCESS;
  255. }
  256. //
  257. // Map the FACS into virtual address space.
  258. //
  259. PhysAddress.QuadPart = (ULONGLONG) Address;
  260. linAddress = MmMapIoSpace(
  261. PhysAddress,
  262. sizeof(FACS),
  263. MmNonCached
  264. );
  265. if (linAddress == NULL) {
  266. ASSERT (linAddress != NULL);
  267. return STATUS_INSUFFICIENT_RESOURCES;
  268. }
  269. if (linAddress->Signature != FACS_SIGNATURE) {
  270. ACPIPrint( (
  271. ACPI_PRINT_CRITICAL,
  272. "ACPILoadProcessFACS: 0x%08lx does not have FACS signature\n",
  273. linAddress
  274. ) );
  275. return STATUS_ACPI_INVALID_TABLE;
  276. }
  277. if (linAddress->Length != sizeof(FACS)) {
  278. ACPIPrint( (
  279. ACPI_PRINT_CRITICAL,
  280. "ACPILoadProcessFACS: 0x%08lx does not have correct FACS length\n",
  281. linAddress
  282. ) );
  283. return STATUS_ACPI_INVALID_TABLE;
  284. }
  285. ACPIPrint( (
  286. ACPI_PRINT_LOADING,
  287. "ACPILoadProcessFACS: FACS located at 0x%8lx\n",
  288. linAddress
  289. ) );
  290. AcpiInformation->FirmwareACPIControlStructure = linAddress;
  291. //
  292. // And store the address of the GlobalLock structure that lives within
  293. // the FACS
  294. //
  295. AcpiInformation->GlobalLock = &(ULONG)(linAddress->GlobalLock);
  296. ACPIPrint( (
  297. ACPI_PRINT_LOADING,
  298. "ACPILoadProcessFACS: Initial GlobalLock state: 0x%8lx\n",
  299. *(AcpiInformation->GlobalLock)
  300. ) );
  301. //
  302. // At this point, we are successfull
  303. //
  304. return STATUS_SUCCESS;
  305. }
  306. ULONG_PTR
  307. GetFadtTablePointerEntry(
  308. PFADT Fadt,
  309. PULONG LegacyAddress,
  310. PGEN_ADDR NonLegacyAddress,
  311. SIZE_T Size
  312. )
  313. /*++
  314. Routine Description:
  315. This routine reads an address field from the FADT. If the Fadt revision
  316. is too old, we use the legacy address. If it's new enough, the generic
  317. register address data is used. If necessary, the address is mapped into
  318. memory.
  319. KB. Do not access NonLegacyAddress if the table revision does not support
  320. the NonLegacyAddress, as this will be pointing to a bogus memory location
  321. and could cause an illegal memory access.
  322. Arguments:
  323. Fadt - Pointer to the Fadt
  324. LegacyAddress - Pointer to legacy address.
  325. NonLegacyAddress - Pointer to non-legacy address.
  326. Size - size of entry that address points to.
  327. Return Value:
  328. a valid pointer to the table entry, or NULL if it's invalid.
  329. --*/
  330. {
  331. ULONG_PTR ReturnValue;
  332. //
  333. // revision 3 and greater of FADT define a generic register address
  334. // structure. Before that version we just have to use the legacy address.
  335. //
  336. if (Fadt->Header.Revision < 3) {
  337. ReturnValue = *LegacyAddress;
  338. } else {
  339. switch(NonLegacyAddress->AddressSpaceID) {
  340. case AcpiGenericSpaceIO:
  341. ReturnValue = (ULONG_PTR)NonLegacyAddress->Address.QuadPart;
  342. break;
  343. case AcpiGenericSpaceMemory:
  344. //
  345. // MmMapIoSpace hates it if you pass in zero, so guard against
  346. // this.
  347. //
  348. if (NonLegacyAddress->Address.QuadPart == 0) {
  349. ReturnValue = (ULONG_PTR)0;
  350. } else {
  351. ReturnValue = (ULONG_PTR)MmMapIoSpace(
  352. NonLegacyAddress->Address,
  353. Size,
  354. MmNonCached );
  355. //
  356. // right now, assume all or nothing -- if any of the
  357. // items in the FADT are marked as MMIO space, they
  358. // all are, and we must use register-based access to
  359. // access the backing hardware.
  360. //
  361. if ( ReturnValue &&
  362. (AcpiReadRegisterRoutine == DefPortReadAcpiRegister) &&
  363. (AcpiWriteRegisterRoutine == DefPortWriteAcpiRegister) ) {
  364. AcpiReadRegisterRoutine = DefRegisterReadAcpiRegister;
  365. AcpiWriteRegisterRoutine = DefRegisterWriteAcpiRegister;
  366. }
  367. }
  368. break;
  369. default:
  370. ASSERT(FALSE);
  371. ReturnValue = 0;
  372. }
  373. }
  374. #ifndef IA64
  375. //
  376. // We don't want to support this part of acpi 2.0 for anything other
  377. // than ia64 for the windows server release. we don't want to risk
  378. // breaking bios's that get this table information incorrect. we will turn
  379. // this on when we have a full testing cycle available.
  380. //
  381. ReturnValue = *LegacyAddress;
  382. if ( (AcpiReadRegisterRoutine == DefRegisterReadAcpiRegister) &&
  383. (AcpiWriteRegisterRoutine == DefRegisterWriteAcpiRegister)) {
  384. AcpiReadRegisterRoutine = DefPortReadAcpiRegister;
  385. AcpiWriteRegisterRoutine = DefPortWriteAcpiRegister;
  386. }
  387. #endif
  388. return(ReturnValue);
  389. }
  390. #define GET_FADT_TABLE_ENTRY(_fadt,_legacyaddr,_nonlegacyaddr,_size) \
  391. ( GetFadtTablePointerEntry( _fadt, &_fadt->_legacyaddr, &_fadt->_nonlegacyaddr, _size ) )
  392. NTSTATUS
  393. ACPILoadProcessFADT(
  394. PFADT Fadt
  395. )
  396. /*++
  397. Routine Description:
  398. This reads the FADT and stores some useful information in the
  399. information structure
  400. Arguments:
  401. Fadt - Pointer to the Fadt
  402. Return Value:
  403. None
  404. --*/
  405. {
  406. KAFFINITY processors;
  407. NTSTATUS status;
  408. PUCHAR gpeTable;
  409. PDSDT linAddress;
  410. ULONG length;
  411. ULONG totalSize;
  412. ULONG MemSpace = 0;
  413. PHYSICAL_ADDRESS PhysAddress = {0};
  414. PAGED_CODE();
  415. //
  416. // This is a 2.0-level FADT.
  417. //
  418. //
  419. // Handle the FACS part of the FADT. We must do this before the DSDT
  420. // so that we have the global lock mapped and initialized.
  421. //
  422. #ifdef IA64
  423. status = ACPILoadProcessFACS( (Fadt->Header.Revision < 3)
  424. ? Fadt->facs
  425. : (ULONG_PTR)Fadt->x_firmware_ctrl.QuadPart );
  426. #else
  427. //
  428. // get rid of this ifdef once we have a full testing cycle available for
  429. // catching any broken firmware
  430. //
  431. status = ACPILoadProcessFACS(Fadt->facs);
  432. #endif
  433. if (!NT_SUCCESS(status)) {
  434. return status;
  435. }
  436. //
  437. // Store the I/O addresses of PM1a_BLK, PM1b_BLK, PM1a_CNT, PM1b_CNT,
  438. // PM2_CNT, PM_TMR
  439. //
  440. AcpiInformation->PM1a_BLK = GET_FADT_TABLE_ENTRY(Fadt,
  441. pm1a_evt_blk_io_port,
  442. x_pm1a_evt_blk,
  443. sizeof(ULONG_PTR));
  444. AcpiInformation->PM1b_BLK = GET_FADT_TABLE_ENTRY(Fadt,
  445. pm1b_evt_blk_io_port,
  446. x_pm1b_evt_blk,
  447. sizeof(ULONG_PTR));
  448. AcpiInformation->PM1a_CTRL_BLK = GET_FADT_TABLE_ENTRY(Fadt,
  449. pm1a_ctrl_blk_io_port,
  450. x_pm1a_ctrl_blk,
  451. sizeof(ULONG_PTR));
  452. AcpiInformation->PM1b_CTRL_BLK = GET_FADT_TABLE_ENTRY(Fadt,
  453. pm1b_ctrl_blk_io_port,
  454. x_pm1b_ctrl_blk,
  455. sizeof(ULONG_PTR));
  456. AcpiInformation->PM2_CTRL_BLK = GET_FADT_TABLE_ENTRY(Fadt,
  457. pm2_ctrl_blk_io_port,
  458. x_pm2_ctrl_blk,
  459. sizeof(ULONG_PTR));
  460. AcpiInformation->PM_TMR = GET_FADT_TABLE_ENTRY(Fadt,
  461. pm_tmr_blk_io_port,
  462. x_pm_tmr_blk,
  463. sizeof(ULONG_PTR));
  464. AcpiInformation->SMI_CMD = (ULONG_PTR) Fadt->smi_cmd_io_port;
  465. ACPIPrint( (
  466. ACPI_PRINT_LOADING,
  467. "ACPILoadProcessFADT: PM1a_BLK located at port %p\n"
  468. "ACPILoadProcessFADT: PM1b_BLK located at port %p\n",
  469. AcpiInformation->PM1a_BLK,
  470. AcpiInformation->PM1b_BLK
  471. ) );
  472. ACPIPrint( (
  473. ACPI_PRINT_LOADING,
  474. "ACPILoadProcessFADT: PM1a_CTRL_BLK located at port %p\n"
  475. "ACPILoadProcessFADT: PM1b_CTRL_BLK located at port %p\n",
  476. AcpiInformation->PM1a_CTRL_BLK,
  477. AcpiInformation->PM1b_CTRL_BLK
  478. ) );
  479. ACPIPrint( (
  480. ACPI_PRINT_LOADING,
  481. "ACPILoadProcessFADT: PM2_CTRL_BLK located at port %p\n"
  482. "ACPILoadProcessFADT: PM_TMR located at port %p\n",
  483. AcpiInformation->PM2_CTRL_BLK,
  484. AcpiInformation->PM_TMR
  485. ) );
  486. //
  487. // Initialize the global GPE tables.
  488. //
  489. // If any of the GPn_BLK addresses are 0 leave GPn_LEN at it's initialized
  490. // value (0). That way later on we only have to check GPn_LEN to determine
  491. // the existence of a GP register.
  492. //
  493. //
  494. // Assume this is true until we find out otherwise
  495. //
  496. AcpiInformation->GP1_Base_Index = GP1_NOT_SUPPORTED;
  497. //
  498. // Crack the GP0 block
  499. //
  500. AcpiInformation->GP0_BLK = GET_FADT_TABLE_ENTRY(
  501. Fadt,
  502. gp0_blk_io_port,
  503. x_gp0_blk,
  504. Fadt->gp0_blk_len);
  505. if (AcpiInformation->GP0_BLK != 0) {
  506. AcpiInformation->GP0_LEN = Fadt->gp0_blk_len;
  507. ACPISimpleFatalHardwareAssert(
  508. (Fadt->gp0_blk_len != 0),
  509. ACPI_I_GP_BLK_LEN_0
  510. );
  511. }
  512. //
  513. // Crack the GP1 Block
  514. //
  515. AcpiInformation->GP1_BLK = GET_FADT_TABLE_ENTRY(
  516. Fadt,
  517. gp1_blk_io_port,
  518. x_gp1_blk,
  519. Fadt->gp1_blk_len);
  520. if (AcpiInformation->GP1_BLK != 0) {
  521. AcpiInformation->GP1_LEN = Fadt->gp1_blk_len;
  522. AcpiInformation->GP1_Base_Index = Fadt->gp1_base;
  523. ACPISimpleFatalHardwareAssert (
  524. (Fadt->gp1_blk_len != 0),
  525. ACPI_I_GP_BLK_LEN_1
  526. );
  527. }
  528. //
  529. // Compute sizes of the register blocks. The first half of each block
  530. // contains status registers, the second half contains the enable registers.
  531. //
  532. AcpiInformation->Gpe0Size = AcpiInformation->GP0_LEN / 2;
  533. AcpiInformation->Gpe1Size = AcpiInformation->GP1_LEN / 2;
  534. AcpiInformation->GpeSize = AcpiInformation->Gpe0Size +
  535. AcpiInformation->Gpe1Size;
  536. //
  537. // Addresses of the GPE Enable register blocks
  538. //
  539. AcpiInformation->GP0_ENABLE = AcpiInformation->GP0_BLK +
  540. AcpiInformation->Gpe0Size;
  541. AcpiInformation->GP1_ENABLE = AcpiInformation->GP1_BLK +
  542. AcpiInformation->Gpe1Size;
  543. //
  544. // Create all GPE bookeeping tables with a single allocate
  545. //
  546. if (AcpiInformation->GpeSize) {
  547. totalSize = (AcpiInformation->GpeSize * 12) + // Twelve Bitmaps
  548. (AcpiInformation->GpeSize * 8); // One bytewide table
  549. gpeTable = (PUCHAR)ExAllocatePoolWithTag(
  550. NonPagedPool,
  551. totalSize,
  552. ACPI_SHARED_GPE_POOLTAG
  553. );
  554. if (gpeTable == NULL) {
  555. ACPIPrint( (
  556. ACPI_PRINT_CRITICAL,
  557. "ACPILoadProcessFADT: Could not allocate GPE tables, "
  558. "size = 0x%8lx\n",
  559. totalSize
  560. ) );
  561. return STATUS_INSUFFICIENT_RESOURCES;
  562. }
  563. RtlZeroMemory (gpeTable, totalSize);
  564. //
  565. // Setup the table pointers
  566. //
  567. GpeEnable = gpeTable;
  568. GpeCurEnable = GpeEnable + AcpiInformation->GpeSize;
  569. GpeIsLevel = GpeCurEnable + AcpiInformation->GpeSize;
  570. GpeHandlerType = GpeIsLevel + AcpiInformation->GpeSize;
  571. GpeWakeEnable = GpeHandlerType + AcpiInformation->GpeSize;
  572. GpeWakeHandler = GpeWakeEnable + AcpiInformation->GpeSize;
  573. GpeSpecialHandler = GpeWakeHandler + AcpiInformation->GpeSize;
  574. GpePending = GpeSpecialHandler + AcpiInformation->GpeSize;
  575. GpeRunMethod = GpePending + AcpiInformation->GpeSize;
  576. GpeComplete = GpeRunMethod + AcpiInformation->GpeSize;
  577. GpeSavedWakeMask = GpeComplete + AcpiInformation->GpeSize;
  578. GpeSavedWakeStatus = GpeSavedWakeMask + AcpiInformation->GpeSize;
  579. GpeMap = GpeSavedWakeStatus+ AcpiInformation->GpeSize;
  580. }
  581. ACPIPrint( (
  582. ACPI_PRINT_LOADING,
  583. "ACPILoadProcessFADT: GP0_BLK located at port %p length 0x%08lx\n"
  584. "ACPILoadProcessFADT: GP1_BLK located at port %p length 0x%08lx\n"
  585. "ACPILoadProcessFADT: GP1_Base_Index = 0x%x\n",
  586. AcpiInformation->GP0_BLK,
  587. AcpiInformation->GP0_LEN,
  588. AcpiInformation->GP1_BLK,
  589. AcpiInformation->GP1_LEN,
  590. AcpiInformation->GP1_Base_Index
  591. ) );
  592. //
  593. // At this point, we should know enough to be able to turn off and
  594. // clear all the GPE registers
  595. //
  596. ACPIGpeClearRegisters();
  597. ACPIGpeEnableDisableEvents( FALSE );
  598. AcpiInformation->ACPI_Flags = 0;
  599. AcpiInformation->ACPI_Capabilities = 0;
  600. //
  601. // Can we dock this machine?
  602. //
  603. AcpiInformation->Dockable = (Fadt->flags & DCK_CAP) ? TRUE : FALSE;
  604. //
  605. // This code used to be executed from within InitializeAndEnableACPI,
  606. // however we need to know *while* processing the DSDT what the Enable
  607. // bits are. To start with, we always want the ACPI timer and GL events
  608. //
  609. AcpiInformation->pm1_en_bits = PM1_TMR_EN | PM1_GBL_EN;
  610. //
  611. // Is there a control method Power Button? If not, then there a fixed
  612. // power button
  613. //
  614. if ( !(Fadt->flags & PWR_BUTTON_GENERIC) ) {
  615. AcpiInformation->pm1_en_bits |= PM1_PWRBTN_EN;
  616. ACPIPrint( (
  617. ACPI_PRINT_LOADING,
  618. "ACPILoadProcessFADT: Power Button in Fixed Feature Space\n"
  619. ) );
  620. } else {
  621. ACPIPrint( (
  622. ACPI_PRINT_LOADING,
  623. "ACPILoadProcessFADT: Power Button not fixed event or "
  624. "not present\n"
  625. ) );
  626. }
  627. //
  628. // Is there a control method Sleep Button? If not, then the fixed button
  629. // always doubles as a wake button
  630. //
  631. if ( !(Fadt->flags & SLEEP_BUTTON_GENERIC) ){
  632. AcpiInformation->pm1_en_bits |= PM1_SLEEPBTN_EN;
  633. ACPIPrint( (
  634. ACPI_PRINT_LOADING,
  635. "ACPILoadProcessFADT: Sleep Button in Fixed Feature Space\n"
  636. ) );
  637. } else {
  638. ACPIPrint( (
  639. ACPI_PRINT_LOADING,
  640. "ACPILoadProcessFADT: Sleep Button not fixed event or "
  641. "not present\n"
  642. ) );
  643. }
  644. //
  645. // Handle the DSDT part of the FADT. We handle this last because we
  646. // need to have the FADT fully parsed before we can load the name space
  647. // tree. A particular example is the Dockable bit you see directly above.
  648. //
  649. #ifdef IA64
  650. return ACPILoadProcessDSDT( (Fadt->Header.Revision < 3)
  651. ? Fadt->dsdt
  652. : (ULONG_PTR)Fadt->x_dsdt.QuadPart
  653. );
  654. #else
  655. return ACPILoadProcessDSDT(Fadt->dsdt);
  656. #endif
  657. }
  658. NTSTATUS
  659. ACPILoadProcessRSDT(
  660. VOID
  661. )
  662. /*++
  663. Routine Description:
  664. Called by ACPIInitialize once ACPI has been detected on the machine.
  665. This walks the tables in the RSDT and fills in the information for the
  666. global data structure.
  667. This routine does *NOT* cause the xDSTs to start loading in the
  668. interpreter
  669. Arguments:
  670. None
  671. Return Value:
  672. NTSTATUS
  673. --*/
  674. {
  675. //
  676. // Upon entry acpiinformation->RootSystemDescTable contains the linear
  677. // address of the RSDT walk through the array of the tables pointed to
  678. // by the RSDT and for each table (whose type we are familiar with)
  679. // store the linear base address of the table in the acpiinformation
  680. // structure
  681. //
  682. BOOLEAN foundOverride = FALSE;
  683. BOOLEAN foundFADT = FALSE;
  684. BOOLEAN usingXSDT = FALSE;
  685. PDESCRIPTION_HEADER header;
  686. PVOID linAddress;
  687. ULONG index;
  688. ULONG length;
  689. ULONG numTables;
  690. ULONG MemSpace = 0;
  691. PHYSICAL_ADDRESS PhysAddress = {0};
  692. PAGED_CODE();
  693. //
  694. // Get the number of tables
  695. //
  696. if (AcpiInformation->RootSystemDescTable->Header.Signature ==
  697. XSDT_SIGNATURE) {
  698. numTables = NumTableEntriesFromXSDTPointer(
  699. AcpiInformation->RootSystemDescTable
  700. );
  701. usingXSDT = TRUE;
  702. } else {
  703. numTables = NumTableEntriesFromRSDTPointer(
  704. AcpiInformation->RootSystemDescTable
  705. );
  706. }
  707. ACPIPrint( (
  708. ACPI_PRINT_LOADING,
  709. "ACPILoadProcessRSDT: RSDT contains %u tables\n",
  710. numTables
  711. ) );
  712. if (numTables == 0) {
  713. return STATUS_ACPI_INVALID_TABLE;
  714. }
  715. //
  716. // Allocate the RSDTINFORMATION to hold an entry for each element
  717. // in the table.
  718. //
  719. // NOTENOTE: We are actually allocating space for numTables + 2
  720. // in the RSDT information. The reason for this is that the DSDT
  721. // is actually stored in the FADT, and so it does not have an entry
  722. // in the RSDT. We always, always store the DSDT as the last entry
  723. // in the RsdtInformation structure. In the 2nd to last entry we store
  724. // the dummy header that we use for the ACPI simulator
  725. //
  726. length = sizeof(RSDTINFORMATION) + ( (numTables + 1) * sizeof(RSDTELEMENT) );
  727. RsdtInformation = ExAllocatePoolWithTag(
  728. NonPagedPool,
  729. length,
  730. ACPI_SHARED_TABLE_POOLTAG
  731. );
  732. if (RsdtInformation == NULL) {
  733. return STATUS_INSUFFICIENT_RESOURCES;
  734. }
  735. RtlZeroMemory( RsdtInformation, length );
  736. RsdtInformation->NumElements = (numTables + 2);
  737. //
  738. // Examine each table entry in the RSDT
  739. //
  740. for (index = 0;index < numTables; index++) {
  741. //
  742. // RSDT contains an array of physical pointers.
  743. //
  744. //
  745. // Get the linear address of the table
  746. //
  747. PhysAddress.QuadPart = usingXSDT ?
  748. (ULONGLONG) ((PXSDT)AcpiInformation->RootSystemDescTable)->Tables[index].QuadPart :
  749. (ULONGLONG) AcpiInformation->RootSystemDescTable->Tables[index];
  750. linAddress = MmMapIoSpace(
  751. PhysAddress,
  752. sizeof (DESCRIPTION_HEADER),
  753. MmNonCached
  754. );
  755. if (linAddress == NULL) {
  756. ASSERT (linAddress != NULL);
  757. return STATUS_ACPI_INVALID_TABLE;
  758. }
  759. //
  760. // Is this a known, but unused table?
  761. //
  762. header = (PDESCRIPTION_HEADER) linAddress;
  763. if (header->Signature == SBST_SIGNATURE) {
  764. ACPIPrint( (
  765. ACPI_PRINT_LOADING,
  766. "ACPILoadProcessRSDT: SBST Found at 0x%08lx\n",
  767. linAddress
  768. ) );
  769. MmUnmapIoSpace(linAddress, sizeof(DESCRIPTION_HEADER));
  770. continue;
  771. }
  772. //
  773. // Is this an unrecognized table?
  774. //
  775. if (header->Signature != FADT_SIGNATURE &&
  776. header->Signature != SSDT_SIGNATURE &&
  777. header->Signature != PSDT_SIGNATURE &&
  778. header->Signature != APIC_SIGNATURE) {
  779. ACPIPrint( (
  780. ACPI_PRINT_WARNING,
  781. "ACPILoadProcessRSDT: Unrecognized table signature 0x%08lx\n",
  782. header->Signature
  783. ) );
  784. MmUnmapIoSpace(linAddress, sizeof(DESCRIPTION_HEADER));
  785. continue;
  786. }
  787. //
  788. // At this point, we know that we need to bring the entire table
  789. // in. To do that, we need to remember the length
  790. //
  791. length = header->Length;
  792. //
  793. // map the entire table using the now known length
  794. //
  795. MmUnmapIoSpace(linAddress, sizeof(DESCRIPTION_HEADER));
  796. linAddress = MmMapIoSpace(
  797. PhysAddress,
  798. length,
  799. MmNonCached
  800. );
  801. if (linAddress == NULL) {
  802. ACPIPrint( (
  803. ACPI_PRINT_CRITICAL,
  804. "ACPILoadProcesRSDT: Could not load table at 0x%08lx\n",
  805. AcpiInformation->RootSystemDescTable->Tables[index]
  806. ) );
  807. return STATUS_ACPI_INVALID_TABLE;
  808. }
  809. //
  810. // Should we override the table?
  811. //
  812. foundOverride = ACPIRegReadAMLRegistryEntry( &linAddress, TRUE);
  813. if (foundOverride) {
  814. ACPIPrint( (
  815. ACPI_PRINT_WARNING,
  816. "ACPILoadProcessRSDT: Table Overloaded from "
  817. "registry (0x%08lx)\n",
  818. linAddress
  819. ) );
  820. RsdtInformation->Tables[index].Flags |= RSDTELEMENT_OVERRIDEN;
  821. }
  822. //
  823. // Remember this address and that we need to unmap it
  824. //
  825. RsdtInformation->Tables[index].Flags |= RSDTELEMENT_MAPPED;
  826. RsdtInformation->Tables[index].Address = linAddress;
  827. //
  828. // Remember the new header
  829. //
  830. header = (PDESCRIPTION_HEADER) linAddress;
  831. //
  832. // At this point, we only need to do any kind of special processing
  833. // if the table is the FADT or if it is the MAPIC
  834. //
  835. if (header->Signature == FADT_SIGNATURE) {
  836. //
  837. // fill in the appropriate field in acpiinformation
  838. //
  839. AcpiInformation->FixedACPIDescTable = (PFADT) linAddress;
  840. //
  841. // Process the table. This does not cause the interpreter
  842. // to load anything
  843. //
  844. foundFADT = TRUE;
  845. ACPILoadProcessFADT( AcpiInformation->FixedACPIDescTable );
  846. } else if (header->Signature == APIC_SIGNATURE) {
  847. //
  848. // fill in the appropriate field in acpiinformation
  849. //
  850. AcpiInformation->MultipleApicTable = (PMAPIC)linAddress;
  851. } else {
  852. //
  853. // We can only reach this case if the table is one of the
  854. // xSDT variety. We need to remember that we will eventually
  855. // need to load it into the interpreter. If we start supporting
  856. // any more tables, we need to make sure that they don't fall
  857. // down here unless they really, really are supported
  858. //
  859. RsdtInformation->Tables[index].Flags |= RSDTELEMENT_LOADABLE;
  860. }
  861. }
  862. //
  863. // At this point, we need to make sure that the ACPI simulator table
  864. // gets loaded
  865. //
  866. header = ExAllocatePoolWithTag(
  867. NonPagedPool,
  868. sizeof(DESCRIPTION_HEADER),
  869. ACPI_SHARED_TABLE_POOLTAG
  870. );
  871. if (header) {
  872. //
  873. // Initialize the header so that it can be passed into the overload
  874. // engine
  875. //
  876. RtlZeroMemory( header, sizeof(DESCRIPTION_HEADER) );
  877. header->Signature = SSDT_SIGNATURE;
  878. header->Length = sizeof(DESCRIPTION_HEADER),
  879. header->Revision = 1;
  880. header->Checksum = 0;
  881. header->OEMRevision = 1;
  882. header->CreatorRev = 1;
  883. RtlCopyMemory( header->OEMID, "MSFT", 4 );
  884. RtlCopyMemory( header->OEMTableID, "simulatr", 8);
  885. RtlCopyMemory( header->CreatorID, "MSFT", 4);
  886. //
  887. // Should we override the table?
  888. //
  889. if (AcpiLoadSimulatorTable) {
  890. foundOverride = ACPIRegReadAMLRegistryEntry( &header, FALSE);
  891. }
  892. if (foundOverride) {
  893. ACPIPrint( (
  894. ACPI_PRINT_LOADING,
  895. "ACPILoadProcessRSDT: Simulator Table Overloaded from "
  896. "registry (0x%08lx)\n",
  897. linAddress
  898. ) );
  899. //
  900. // Remember this address and that we need to unmap it
  901. //
  902. RsdtInformation->Tables[numTables].Flags |= RSDTELEMENT_MAPPED;
  903. RsdtInformation->Tables[numTables].Flags |= RSDTELEMENT_OVERRIDEN;
  904. RsdtInformation->Tables[numTables].Flags |= RSDTELEMENT_LOADABLE;
  905. RsdtInformation->Tables[numTables].Address = header;
  906. } else {
  907. //
  908. // If we have found an override, we don't need the dummy table
  909. //
  910. ExFreePool( header );
  911. }
  912. }
  913. //
  914. // Save whatever tables we found in the registry
  915. //
  916. ACPIRegDumpAcpiTables ();
  917. //
  918. // Did we find an FADT?
  919. //
  920. if (!foundFADT) {
  921. ACPIPrint( (
  922. ACPI_PRINT_CRITICAL,
  923. "ACPILoadProcessRSDT: Did not find an FADT\n"
  924. ) );
  925. return STATUS_ACPI_INVALID_TABLE;
  926. }
  927. return STATUS_SUCCESS;
  928. }
  929. BOOLEAN
  930. ACPILoadTableCheckSum(
  931. PVOID StartAddress,
  932. ULONG Length
  933. )
  934. {
  935. PUCHAR currentAddress;
  936. UCHAR sum = 0;
  937. ULONG i;
  938. PAGED_CODE();
  939. ASSERT (Length > 0);
  940. currentAddress = (PUCHAR)StartAddress;
  941. ACPIPrint( (
  942. ACPI_PRINT_LOADING,
  943. "ACPILoadTableCheckSum: Checking table 0x%p to 0x%p\n",
  944. StartAddress, (ULONG_PTR)StartAddress + Length - 1
  945. ) );
  946. for (i = 0; i < Length; i++, currentAddress++ ) {
  947. sum += *currentAddress;
  948. }
  949. ACPISimpleSoftwareAssert ( (sum == 0), ACPI_ERROR_INT_BAD_TABLE_CHECKSUM );
  950. if (sum) {
  951. ACPIPrint( (
  952. ACPI_PRINT_CRITICAL,
  953. "ACPILoadTableCheckSum: Checksum Failed!, table %p to %p\n",
  954. StartAddress, (ULONG_PTR) StartAddress + Length - 1
  955. ) );
  956. return FALSE;
  957. }
  958. return TRUE;
  959. }