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.

1555 lines
39 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. All rights reserved
  4. Module Name:
  5. acpisetd.c
  6. Abstract:
  7. This module detects an ACPI system. It
  8. is included into setup so that setup
  9. can figure out which HAL to load
  10. Author:
  11. Jake Oshins (jakeo) - Feb. 7, 1997.
  12. Environment:
  13. Textmode setup.
  14. Revision History:
  15. --*/
  16. VOID
  17. BlPrint(
  18. PCHAR cp,
  19. ...
  20. );
  21. ULONG
  22. SlGetChar(
  23. VOID
  24. );
  25. VOID
  26. SlPrint(
  27. IN PCHAR FormatString,
  28. ...
  29. );
  30. #define HalpBiosDbgPrint(_x_) if (HalpGoodBiosDebug) {SlPrint _x_; }
  31. #define HalpGoodBiosPause() if (HalpGoodBiosDebug) {SlGetChar();}
  32. #ifdef DEBUG
  33. #undef DEBUG_PRINT
  34. #define DEBUG_PRINT BlPrint
  35. #else
  36. #define DEBUG_PRINT
  37. #endif
  38. typedef struct _ACPI_BIOS_INSTALLATION_CHECK {
  39. UCHAR Signature[8]; // "RSD PTR" (ascii)
  40. UCHAR Checksum;
  41. UCHAR OemId[6]; // An OEM-supplied string
  42. UCHAR reserved; // must be 0
  43. ULONG RsdtAddress; // 32-bit physical address of RSDT
  44. } ACPI_BIOS_INSTALLATION_CHECK, *PACPI_BIOS_INSTALLATION_CHECK;
  45. #include "acpitabl.h"
  46. #include "halp.h"
  47. typedef
  48. BOOLEAN
  49. (* PFN_RULE)(
  50. PCHAR Section,
  51. ULONG KeyIndex
  52. );
  53. extern BOOLEAN DisableACPI;
  54. BOOLEAN MatchAcpiOemIdRule(PCHAR Section, ULONG KeyIndex);
  55. BOOLEAN MatchAcpiOemTableIdRule(PCHAR Section, ULONG KeyIndex);
  56. BOOLEAN MatchAcpiOemRevisionRule(PCHAR Section, ULONG KeyIndex);
  57. BOOLEAN MatchAcpiRevisionRule(PCHAR Section, ULONG KeyIndex);
  58. BOOLEAN MatchAcpiCreatorRevisionRule(PCHAR Section, ULONG KeyIndex);
  59. BOOLEAN MatchAcpiCreatorIdRule(PCHAR Section, ULONG KeyIndex);
  60. typedef struct _INF_RULE {
  61. PCHAR szRule;
  62. PFN_RULE pRule;
  63. } INF_RULE, *PINF_RULE;
  64. INF_RULE InfRule[] =
  65. {
  66. {"AcpiOemId", MatchAcpiOemIdRule},
  67. {"AcpiOemTableId", MatchAcpiOemTableIdRule},
  68. {"AcpiOemRevision", MatchAcpiOemRevisionRule},
  69. {"AcpiRevision", MatchAcpiRevisionRule},
  70. {"AcpiCreatorRevision", MatchAcpiCreatorRevisionRule},
  71. {"AcpiCreatorId", MatchAcpiCreatorIdRule},
  72. {NULL, NULL}
  73. };
  74. ULONG
  75. DetectMPACPI (
  76. OUT PBOOLEAN IsConfiguredMp
  77. );
  78. ULONG
  79. DetectApicACPI (
  80. OUT PBOOLEAN IsConfiguredMp
  81. );
  82. ULONG
  83. DetectPicACPI (
  84. OUT PBOOLEAN IsConfiguredMp
  85. );
  86. VOID
  87. HalpFindRsdp (
  88. VOID
  89. );
  90. BOOLEAN
  91. HalpValidateRsdp(
  92. VOID
  93. );
  94. PVOID
  95. HalpFindApic (
  96. VOID
  97. );
  98. ULONG
  99. HalpAcpiNumProcessors(
  100. VOID
  101. );
  102. BOOLEAN
  103. HalpMatchInfList(
  104. IN PCHAR Section
  105. );
  106. BOOLEAN
  107. HalpMatchDescription(
  108. PCHAR Section
  109. );
  110. PRSDP HalpRsdp = NULL;
  111. PRSDT HalpRsdt = NULL;
  112. PXSDT HalpXsdt = NULL;
  113. BOOLEAN HalpSearchedForRsdp = FALSE;
  114. PVOID HalpApic = NULL;
  115. BOOLEAN HalpSearchedForApic = FALSE;
  116. BOOLEAN HalpGoodBiosDebug = FALSE;
  117. // from boot\detect\i386\acpibios.h
  118. //
  119. // Acpi BIOS Installation check
  120. //
  121. #define ACPI_BIOS_START 0xE0000
  122. #define ACPI_BIOS_END 0xFFFFF
  123. #define ACPI_BIOS_HEADER_INCREMENT 16
  124. #ifndef SETUP
  125. #ifdef ALLOC_PRAGMA
  126. #pragma alloc_text(INIT,DetectMPACPI)
  127. #pragma alloc_text(INIT,DetectApicACPI)
  128. #pragma alloc_text(INIT,DetectPicACPI)
  129. #endif // ALLOC_PRAGMA
  130. #endif // SETUP
  131. ULONG
  132. DetectMPACPI(
  133. OUT PBOOLEAN IsConfiguredMp
  134. )
  135. /*++
  136. Routine Description:
  137. This function looks for an ACPI Root System Description
  138. table in the BIOS. If it exists, this is an ACPI machine.
  139. Arguments:
  140. IsConfiguredMp - TRUE if this machine is a MP instance of the ACPI spec, else FALSE.
  141. Return Value:
  142. 0 - if not a ACPI
  143. 1 - if ACPI
  144. */
  145. {
  146. *IsConfiguredMp = FALSE;
  147. DEBUG_PRINT("DetectMPACPI\n");
  148. //
  149. // Detect whether this is an ACPI machine.
  150. //
  151. if (HalpSearchedForRsdp == FALSE) {
  152. PCHAR AcpiDebug;
  153. //
  154. // Check whether ACPI detection debugging is enabled
  155. //
  156. if ( InfFile ) {
  157. AcpiDebug = SlGetIniValue(InfFile, "ACPIOptions", "Debug", "0");
  158. if (AcpiDebug[0] == '1') {
  159. HalpGoodBiosDebug = TRUE;
  160. SlPrint("Enabling GOOD BIOS DEBUG\n");
  161. SlGetChar();
  162. }
  163. }
  164. HalpFindRsdp();
  165. HalpSearchedForRsdp = TRUE;
  166. }
  167. if (!HalpValidateRsdp()) {
  168. return(FALSE);
  169. }
  170. DEBUG_PRINT("Found Rsdp: %x\n", HalpRsdp);
  171. if (HalpSearchedForApic == FALSE) {
  172. HalpApic = HalpFindApic();
  173. HalpSearchedForApic = TRUE;
  174. }
  175. if (HalpAcpiNumProcessors() < 2) {
  176. return FALSE;
  177. }
  178. *IsConfiguredMp = TRUE;
  179. return TRUE;
  180. }
  181. ULONG
  182. DetectApicACPI(
  183. OUT PBOOLEAN IsConfiguredMp
  184. )
  185. /*++
  186. Routine Description:
  187. This function is called by setup after DetectACPI has returned
  188. false. During setup time DetectACPI will return false, if the
  189. machine is an ACPI system, but only has one processor. This
  190. function is used to detect such a machine at setup time.
  191. Arguments:
  192. IsConfiguredMp - FALSE
  193. Return Value:
  194. 0 - if not a UP ACPI
  195. 1 - if UP ACPI
  196. --*/
  197. {
  198. DEBUG_PRINT("DetectApicACPI\n");
  199. if (HalpSearchedForRsdp == FALSE) {
  200. PCHAR AcpiDebug;
  201. //
  202. // Check whether ACPI detection debugging is enabled
  203. //
  204. if ( InfFile ) {
  205. AcpiDebug = SlGetIniValue(InfFile, "ACPIOptions", "Debug", "0");
  206. if (AcpiDebug[0] == '1') {
  207. HalpGoodBiosDebug = TRUE;
  208. } else {
  209. HalpGoodBiosDebug = FALSE;
  210. }
  211. }
  212. HalpFindRsdp();
  213. HalpSearchedForRsdp = TRUE;
  214. }
  215. if (!HalpValidateRsdp()) {
  216. return FALSE;
  217. }
  218. if (HalpSearchedForApic == FALSE) {
  219. HalpApic = HalpFindApic();
  220. HalpSearchedForApic = TRUE;
  221. }
  222. if (!HalpApic) {
  223. return FALSE;
  224. }
  225. *IsConfiguredMp = FALSE;
  226. return TRUE;
  227. }
  228. ULONG
  229. DetectPicACPI(
  230. OUT PBOOLEAN IsConfiguredMp
  231. )
  232. /*++
  233. Routine Description:
  234. This function is called by setup after DetectACPI has returned
  235. false. During setup time DetectACPI will return false, if the
  236. machine is an ACPI system, but only has one processor. This
  237. function is used to detect such a machine at setup time.
  238. Arguments:
  239. IsConfiguredMp - FALSE
  240. Return Value:
  241. 0 - if not a PIC ACPI
  242. 1 - if PIC ACPI
  243. --*/
  244. {
  245. *IsConfiguredMp = FALSE;
  246. if (HalpSearchedForRsdp == FALSE) {
  247. PCHAR AcpiDebug;
  248. //
  249. // Check whether ACPI detection debugging is enabled
  250. //
  251. if ( InfFile ) {
  252. AcpiDebug = SlGetIniValue(InfFile, "ACPIOptions", "Debug", "0");
  253. if (AcpiDebug[0] == '1') {
  254. HalpGoodBiosDebug = TRUE;
  255. } else {
  256. HalpGoodBiosDebug = FALSE;
  257. }
  258. }
  259. HalpFindRsdp();
  260. HalpSearchedForRsdp = TRUE;
  261. }
  262. if (HalpValidateRsdp()) {
  263. return TRUE;
  264. }
  265. return FALSE;
  266. }
  267. #define EBDA_SEGMENT_PTR 0x40e
  268. VOID
  269. HalpFindRsdp (
  270. VOID
  271. )
  272. {
  273. ULONG romAddr = 0;
  274. ULONG romEnd = 0;
  275. PACPI_BIOS_INSTALLATION_CHECK header;
  276. UCHAR sum;
  277. USHORT i;
  278. ULONG EbdaSegmentPtr;
  279. ULONG EbdaPhysicalAdd = 0;
  280. PUCHAR EbdaVirtualAdd = 0;
  281. enum PASS { PASS1 = 0, PASS2, MAX_PASSES } pass;
  282. //
  283. // Search on 16 byte boundaries for the signature of the
  284. // Root System Description Table structure.
  285. //
  286. for (pass = PASS1; pass < MAX_PASSES; pass++) {
  287. if (pass == PASS1) {
  288. //
  289. // On the first pass, we search the first 1K of the
  290. // Extended BIOS data area. The EBDA segment address
  291. // is available at physical address 40:0E.
  292. //
  293. EbdaSegmentPtr = (ULONG) HalpMapPhysicalMemoryWriteThrough( (PVOID) 0, 1);
  294. EbdaSegmentPtr += EBDA_SEGMENT_PTR;
  295. EbdaPhysicalAdd = (ULONG)*((PUSHORT)EbdaSegmentPtr) << 4;
  296. if (EbdaPhysicalAdd) {
  297. EbdaVirtualAdd = HalpMapPhysicalMemoryWriteThrough( (PVOID)EbdaPhysicalAdd, 2);
  298. }
  299. if (!EbdaVirtualAdd) {
  300. continue;
  301. }
  302. romAddr = (ULONG)EbdaVirtualAdd;
  303. romEnd = romAddr + 1024;
  304. } else {
  305. //
  306. // On the second pass, we search (physical) memory 0xE0000
  307. // to 0xF0000.
  308. romAddr = (ULONG)HalpMapPhysicalMemoryWriteThrough((PVOID)ACPI_BIOS_START,
  309. ROUND_TO_PAGES(ACPI_BIOS_END - ACPI_BIOS_START) / PAGE_SIZE);
  310. romEnd = romAddr + (ACPI_BIOS_END - ACPI_BIOS_START);
  311. }
  312. while (romAddr < romEnd) {
  313. header = (PACPI_BIOS_INSTALLATION_CHECK)romAddr;
  314. //
  315. // Signature to match is the string "RSD PTR ".
  316. //
  317. if (header->Signature[0] == 'R' && header->Signature[1] == 'S' &&
  318. header->Signature[2] == 'D' && header->Signature[3] == ' ' &&
  319. header->Signature[4] == 'P' && header->Signature[5] == 'T' &&
  320. header->Signature[6] == 'R' && header->Signature[7] == ' ' ) {
  321. sum = 0;
  322. for (i = 0; i < sizeof(ACPI_BIOS_INSTALLATION_CHECK); i++) {
  323. sum = sum + ((PUCHAR)romAddr)[i];
  324. }
  325. if (sum == 0) {
  326. pass = MAX_PASSES; // leave 'for' loop
  327. break; // leave 'while' loop
  328. }
  329. }
  330. romAddr += ACPI_BIOS_HEADER_INCREMENT;
  331. }
  332. }
  333. if (romAddr >= romEnd) {
  334. HalpRsdp = NULL;
  335. HalpRsdt = NULL;
  336. HalpXsdt = NULL;
  337. HalpBiosDbgPrint(("NO ACPI BIOS FOUND!\n"));
  338. HalpGoodBiosPause();
  339. return;
  340. }
  341. HalpRsdp = (PRSDP)romAddr;
  342. HalpRsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->RsdtAddress,
  343. sizeof(RSDT));
  344. HalpRsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->RsdtAddress,
  345. HalpRsdt->Header.Length);
  346. HalpBiosDbgPrint(("Found RSDP at %08lx, RSDT at %08lx\n", HalpRsdp, HalpRsdt));
  347. #ifdef ACPI_20_COMPLIANT
  348. if (HalpRsdp->Revision > 1) {
  349. //
  350. // ACPI 2.0 BIOS
  351. //
  352. HalpXsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->XsdtAddress.LowPart,
  353. sizeof(XSDT));
  354. HalpXsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->XsdtAddress.LowPart,
  355. HalpXsdt->Header.Length);
  356. HalpBiosDbgPrint(("Found XSDT at %08lx\n", HalpXsdt));
  357. }
  358. #endif
  359. return;
  360. }
  361. PVOID
  362. HalpFindApic (
  363. VOID
  364. )
  365. {
  366. ULONG entry, rsdtEntries, rsdtLength;
  367. PVOID physicalAddr;
  368. PDESCRIPTION_HEADER header = NULL;
  369. //
  370. // Calculate the number of entries in the RSDT.
  371. //
  372. if (HalpXsdt) {
  373. //
  374. // ACPI 2.0 BIOS
  375. //
  376. rsdtLength = HalpXsdt->Header.Length;
  377. rsdtEntries = NumTableEntriesFromXSDTPointer(HalpXsdt);
  378. } else {
  379. //
  380. // ACPI 1.0 BIOS
  381. //
  382. rsdtLength = HalpRsdt->Header.Length;
  383. rsdtEntries = NumTableEntriesFromRSDTPointer(HalpRsdt);
  384. }
  385. DEBUG_PRINT("rsdt length: %d\n", HalpRsdt->Header.Length);
  386. DEBUG_PRINT("rsdtEntries: %d\n", rsdtEntries);
  387. //
  388. // Look down the pointer in each entry to see if it points to
  389. // the table we are looking for.
  390. //
  391. for (entry = 0; entry < rsdtEntries; entry++) {
  392. physicalAddr = HalpXsdt ?
  393. (PVOID)HalpXsdt->Tables[entry].LowPart :
  394. (PVOID)HalpRsdt->Tables[entry];
  395. header = HalpMapPhysicalMemoryWriteThrough(physicalAddr, 2);
  396. if (!header) {
  397. return NULL;
  398. }
  399. DEBUG_PRINT("header: %x%x\n", ((ULONG)header) >> 16, (ULONG)header & 0xffff);
  400. DEBUG_PRINT("entry: %d\n", header->Signature);
  401. if (header->Signature == APIC_SIGNATURE) {
  402. break;
  403. }
  404. }
  405. //
  406. // We didn't find an APIC table.
  407. //
  408. if (entry >= rsdtEntries) {
  409. DEBUG_PRINT("Didn't find an APIC table\n");
  410. return NULL;
  411. }
  412. DEBUG_PRINT("returning: %x\n", header);
  413. return (PVOID)header;
  414. }
  415. ULONG
  416. HalpAcpiNumProcessors(
  417. VOID
  418. )
  419. {
  420. PUCHAR TraversePtr;
  421. UCHAR procCount = 0;
  422. if (!HalpApic) {
  423. return 1;
  424. }
  425. TraversePtr = (PUCHAR)((PMAPIC)HalpApic)->APICTables;
  426. DEBUG_PRINT("APIC table header length %d\n", ((PMAPIC)HalpApic)->Header.Length);
  427. DEBUG_PRINT("APIC table: %x%x TraversePtr: %x%x\n",
  428. (ULONG)HalpApic >> 16,
  429. (ULONG)HalpApic & 0xffff,
  430. (ULONG)TraversePtr >> 16,
  431. (ULONG)TraversePtr & 0xffff);
  432. while (TraversePtr <= ((PUCHAR)HalpApic + ((PMAPIC)HalpApic)->Header.Length)) {
  433. if ((((PPROCLOCALAPIC)(TraversePtr))->Type == PROCESSOR_LOCAL_APIC)
  434. && (((PPROCLOCALAPIC)(TraversePtr))->Length == PROCESSOR_LOCAL_APIC_LENGTH)) {
  435. if(((PPROCLOCALAPIC)(TraversePtr))->Flags & PLAF_ENABLED) {
  436. //
  437. // This processor is enabled.
  438. //
  439. procCount++;
  440. }
  441. TraversePtr += ((PPROCLOCALAPIC)(TraversePtr))->Length;
  442. } else if ((((PIOAPIC)(TraversePtr))->Type == IO_APIC) &&
  443. (((PIOAPIC)(TraversePtr))->Length == IO_APIC_LENGTH)) {
  444. //
  445. // Found an I/O APIC entry. Skipping it.
  446. //
  447. TraversePtr += ((PIOAPIC)(TraversePtr))->Length;
  448. } else if ((((PISA_VECTOR)(TraversePtr))->Type == ISA_VECTOR_OVERRIDE) &&
  449. (((PISA_VECTOR)(TraversePtr))->Length == ISA_VECTOR_OVERRIDE_LENGTH)) {
  450. //
  451. // Found an Isa Vector Override entry. Skipping it.
  452. //
  453. TraversePtr += ISA_VECTOR_OVERRIDE_LENGTH;
  454. } else {
  455. //
  456. // Found random bits in the table. Try the next byte and
  457. // see if we can make sense of it.
  458. //
  459. TraversePtr += 1;
  460. }
  461. }
  462. DEBUG_PRINT("returning %d processors\n", procCount);
  463. return procCount;
  464. }
  465. BOOLEAN
  466. HalpValidateRsdp(
  467. VOID
  468. )
  469. /*++
  470. Routine Description:
  471. Given a pointer to the RSDP, this function validates that it
  472. is suitable for running NT. Currently this test includes:
  473. Checking for a known good version of a known BIOS
  474. OR Checking for a date of 1/1/99 or greater
  475. Arguments:
  476. Return Value:
  477. TRUE - The ACPI BIOS on this machine is good and can be used by NT
  478. FALSE - The ACPI BIOS on this machine is broken and will be ignored
  479. by NT.
  480. --*/
  481. {
  482. ULONG AcpiOptionValue = 2;
  483. PCHAR AcpiOption;
  484. PCHAR szMonth = "01", szDay = "01", szYear = "1999";
  485. ULONG Month, Day, Year;
  486. CHAR Temp[3];
  487. ULONG BiosDate, CheckDate;
  488. PUCHAR DateAddress;
  489. if (HalpRsdp == NULL) {
  490. HalpBiosDbgPrint(("Disabling ACPI since there is NO ACPI BIOS\n"));
  491. HalpGoodBiosPause();
  492. return(FALSE);
  493. }
  494. //
  495. // Check if the user has manually disabled ACPI with the F7 key
  496. //
  497. if (DisableACPI) {
  498. HalpBiosDbgPrint(("Disabling ACPI due to user pressing F7\n"));
  499. HalpGoodBiosPause();
  500. return(FALSE);
  501. }
  502. if (WinntSifHandle) {
  503. AcpiOption = SlGetIniValue(WinntSifHandle, "Unattended", "ForceHALDetection", "no");
  504. if (_stricmp(AcpiOption,"yes") == 0) {
  505. HalpBiosDbgPrint(("Unattend Files specifies ForceHALDetection.\n"));
  506. AcpiOptionValue = 2;
  507. } else {
  508. //
  509. // Check the setting for ACPIEnable.
  510. // 0 = Disable ACPI
  511. // 1 = Enable ACPI
  512. // 2 = Do normal good/bad BIOS detection
  513. //
  514. HalpBiosDbgPrint(("Unattend Files does not Contain ForceHALDetection.\n"));
  515. AcpiOption = SlGetIniValue(WinntSifHandle, "Data", "AcpiHAL", "3");
  516. if (AcpiOption[0] == '0' || AcpiOption[0] == '1') {
  517. HalpBiosDbgPrint(("Got AcpiHal value from WINNT.SIF\n"));
  518. AcpiOptionValue = AcpiOption[0] - '0';
  519. } else if (InfFile) {
  520. AcpiOption = SlGetIniValue(InfFile, "ACPIOptions", "ACPIEnable", "2");
  521. if (AcpiOption[0] >= '0' && AcpiOption[0] <= '2') {
  522. HalpBiosDbgPrint(("No AcpiHal value from WINNT.SIF\n"));
  523. HalpBiosDbgPrint(("Got ACPIEnable from TXTSETUP.SIF\n"));
  524. AcpiOptionValue = AcpiOption[0] - '0';
  525. }
  526. }
  527. }
  528. } else if (InfFile) {
  529. AcpiOption = SlGetIniValue(InfFile, "ACPIOptions", "ACPIEnable", "2");
  530. if (AcpiOption[0] >= '0' && AcpiOption[0] <= '2') {
  531. HalpBiosDbgPrint(("No WINNT.SIF\n"));
  532. HalpBiosDbgPrint(("Got ACPIEnable from TXTSETUP.SIF\n"));
  533. AcpiOptionValue = AcpiOption[0] - '0';
  534. }
  535. }
  536. if (AcpiOptionValue == 0) {
  537. HalpBiosDbgPrint(("Force Disabling ACPI due to ACPIEnable == 0\n"));
  538. HalpGoodBiosPause();
  539. return(FALSE);
  540. } else if (AcpiOptionValue == 1) {
  541. HalpBiosDbgPrint(("Force Enabling ACPI due to ACPIEnable == 1\n"));
  542. HalpGoodBiosPause();
  543. return(TRUE);
  544. } else {
  545. HalpBiosDbgPrint(("System will detect ACPI due to ACPIEnable == 2\n"));
  546. HalpGoodBiosPause();
  547. }
  548. if ( InfFile ) {
  549. //
  550. // Check the Good BIOS list. If the BIOS is on this list, it is OK to
  551. // enable ACPI.
  552. //
  553. if (HalpMatchInfList("GoodACPIBios")) {
  554. HalpBiosDbgPrint(("Enabling ACPI since machine is on Good BIOS list\n"));
  555. HalpGoodBiosPause();
  556. return(TRUE);
  557. }
  558. //
  559. // The BIOS is not on our Known Good list. Check the BIOS date and see
  560. // if it is after our date at which we hope all BIOSes work.
  561. //
  562. szMonth = SlGetSectionKeyIndex(InfFile, "ACPIOptions", "ACPIBiosDate", 0);
  563. szDay = SlGetSectionKeyIndex(InfFile, "ACPIOptions", "ACPIBiosDate", 1);
  564. szYear = SlGetSectionKeyIndex(InfFile, "ACPIOptions", "ACPIBiosDate", 2);
  565. }
  566. if ((szMonth == NULL) ||
  567. (szDay == NULL) ||
  568. (szYear == NULL)) {
  569. HalpBiosDbgPrint(("No Good BIOS date present in INF file\n"));
  570. } else {
  571. RtlCharToInteger(szMonth, 16, &Month);
  572. RtlCharToInteger(szDay, 16, &Day);
  573. RtlCharToInteger(szYear, 16, &Year);
  574. CheckDate = (Year << 16) + (Month << 8) + Day;
  575. DateAddress = HalpMapPhysicalRange((PVOID)0xFFFF5, 8);
  576. Temp[2] = '\0';
  577. RtlCopyMemory(Temp, DateAddress+6, 2);
  578. RtlCharToInteger(Temp, 16, &Year);
  579. if (Year < 0x80) {
  580. Year += 0x2000;
  581. } else {
  582. Year += 0x1900;
  583. }
  584. RtlCopyMemory(Temp, DateAddress, 2);
  585. RtlCharToInteger(Temp, 16, &Month);
  586. RtlCopyMemory(Temp, DateAddress+3, 2);
  587. RtlCharToInteger(Temp, 16, &Day);
  588. BiosDate = (Year << 16) + (Month << 8) + Day;
  589. HalpBiosDbgPrint(("\n Checking good date %08lx against BIOS date %08lx - ",CheckDate,BiosDate));
  590. if (BiosDate >= CheckDate) {
  591. HalpBiosDbgPrint(("GOOD!\n"));
  592. //
  593. // The date on the BIOS is new enough, now just make sure the machine
  594. // is not on the BAD BIOS list.
  595. //
  596. if ( InfFile ) {
  597. HalpBiosDbgPrint(("Checking BAD BIOS LIST\n"));
  598. if (HalpMatchInfList("NWACL")) {
  599. HalpBiosDbgPrint(("Disabling ACPI since machine is on BAD BIOS list\n"));
  600. HalpGoodBiosPause();
  601. return(FALSE);
  602. } else {
  603. HalpBiosDbgPrint(("Enabling ACPI since BIOS is new enough to work\n"));
  604. HalpGoodBiosPause();
  605. return(TRUE);
  606. }
  607. } else {
  608. return(TRUE);
  609. }
  610. } else {
  611. HalpBiosDbgPrint(("BAD!\n"));
  612. }
  613. }
  614. HalpBiosDbgPrint(("Disabling ACPI since machine is NOT on Good BIOS list\n"));
  615. HalpGoodBiosPause();
  616. return(FALSE);
  617. }
  618. PDESCRIPTION_HEADER
  619. HalpFindACPITable(
  620. IN PCHAR TableName,
  621. IN ULONG TableLength
  622. )
  623. /*++
  624. Routine Description:
  625. Given a table name, finds that table in the ACPI BIOS
  626. Arguments:
  627. TableName - Supplies the table name
  628. TableLength - Supplies the length of the table to map
  629. Return Value:
  630. Pointer to the table if found
  631. NULL if the table is not found
  632. --*/
  633. {
  634. ULONG Signature;
  635. PFADT Fadt;
  636. PDESCRIPTION_HEADER Header;
  637. ULONG TableCount;
  638. ULONG i;
  639. ULONG TableAddr;
  640. Signature = *((ULONG UNALIGNED *)TableName);
  641. if (Signature == RSDT_SIGNATURE) {
  642. return(&HalpRsdt->Header);
  643. } else if (Signature == XSDT_SIGNATURE) {
  644. return(&HalpXsdt->Header);
  645. } else if (Signature == DSDT_SIGNATURE) {
  646. Fadt = (PFADT)HalpFindACPITable("FACP", sizeof(FADT));
  647. if (Fadt == NULL) {
  648. return(NULL);
  649. }
  650. Header = HalpMapPhysicalRangeWriteThrough((PVOID)Fadt->dsdt, TableLength);
  651. return(Header);
  652. } else {
  653. TableCount = HalpXsdt ?
  654. NumTableEntriesFromXSDTPointer(HalpXsdt) :
  655. NumTableEntriesFromRSDTPointer(HalpRsdt);
  656. for (i=0;i<TableCount;i++) {
  657. TableAddr = HalpXsdt ?
  658. HalpXsdt->Tables[i].LowPart :
  659. HalpRsdt->Tables[i];
  660. Header = HalpMapPhysicalRangeWriteThrough((PVOID)TableAddr, sizeof(DESCRIPTION_HEADER));
  661. if (Header->Signature == Signature) {
  662. if (TableLength/PAGE_SIZE > sizeof(DESCRIPTION_HEADER)/PAGE_SIZE) {
  663. //
  664. // if we need to map more than just the DESCRIPTION_HEADER, do that before
  665. // returning.
  666. //
  667. Header = HalpMapPhysicalRangeWriteThrough((PVOID)TableAddr, TableLength);
  668. }
  669. return(Header);
  670. }
  671. }
  672. }
  673. return(NULL);
  674. }
  675. BOOLEAN
  676. HalpMatchInfList(
  677. IN PCHAR Section
  678. )
  679. /*++
  680. Routine Description:
  681. This function determines if the computer matches any of the computer
  682. descriptions in an INF file list.
  683. Arguments:
  684. Section - Section of INF that contains the list of descriptions
  685. Return Value:
  686. TRUE - The computer matches one of the descriptions
  687. FALSE - The computer does not match any of the descriptions
  688. --*/
  689. {
  690. ULONG i;
  691. PCHAR ComputerName;
  692. for (i=0; ; i++) {
  693. ComputerName = SlGetKeyName(InfFile,
  694. Section,
  695. i);
  696. if (ComputerName == NULL) {
  697. break;
  698. }
  699. if (HalpMatchDescription(ComputerName)) {
  700. return(TRUE);
  701. }
  702. }
  703. return(FALSE);
  704. }
  705. BOOLEAN
  706. HalpMatchDescription(
  707. PCHAR Section
  708. )
  709. /*++
  710. Routine Description:
  711. This function processes an ACPI BIOS description to see if the
  712. BIOS matches all of the rules in the section
  713. Arguments:
  714. Section - Supplies the section name of the INF to process
  715. Return Value:
  716. TRUE - The BIOS matches all the rules
  717. FALSE - The BIOS failed one or more rules
  718. --*/
  719. {
  720. ULONG RuleNumber;
  721. PCHAR Rule;
  722. ULONG i;
  723. BOOLEAN Success;
  724. HalpBiosDbgPrint(("Matching against %s\n", Section));
  725. //
  726. // Check to see if the specified section exists
  727. //
  728. if (!SpSearchINFSection(InfFile, Section)) {
  729. HalpBiosDbgPrint(("\tERROR - no INF section %s\n", Section));
  730. HalpGoodBiosPause();
  731. return(FALSE);
  732. }
  733. for (RuleNumber=0; ;RuleNumber++) {
  734. Rule = SlGetKeyName(InfFile, Section, RuleNumber);
  735. if (Rule == NULL) {
  736. break;
  737. }
  738. for (i=0; InfRule[i].szRule != NULL;i++) {
  739. if (_stricmp(Rule, InfRule[i].szRule) == 0) {
  740. HalpBiosDbgPrint(("\tTesting Rule %s\n",Rule));
  741. Success = (*(InfRule[i].pRule))(Section, RuleNumber);
  742. if (!Success) {
  743. HalpBiosDbgPrint(("\tFAILED!\n"));
  744. HalpGoodBiosPause();
  745. return(FALSE);
  746. }
  747. HalpBiosDbgPrint(("\tSucceeded\n"));
  748. break;
  749. }
  750. }
  751. if (InfRule[i].szRule == NULL) {
  752. //
  753. // rule in the INF was not found
  754. //
  755. HalpBiosDbgPrint(("\tRULE %s not found!\n",Rule));
  756. HalpGoodBiosPause();
  757. return(FALSE);
  758. }
  759. }
  760. HalpBiosDbgPrint(("Machine matches %s\n",Section));
  761. HalpGoodBiosPause();
  762. return(TRUE);
  763. }
  764. BOOLEAN
  765. HalpCheckOperator(
  766. IN PCHAR Operator,
  767. IN ULONG Arg1,
  768. IN ULONG Arg2
  769. )
  770. /*++
  771. Routine Description:
  772. Given an operator and two ULONG arguments, this function
  773. returns the boolean result.
  774. Arguments:
  775. Operator = Supplies the logical operator: =, ==, <=, >=, !=, <, >
  776. Arg1 - Supplies the first argument
  777. Arg2 - Supplies the second argument
  778. Return Value:
  779. TRUE if Arg1 Operator Arg2
  780. FALSE otherwise
  781. --*/
  782. {
  783. BOOLEAN Success = FALSE;
  784. HalpBiosDbgPrint(("\t\tChecking %lx %s %lx - ",Arg1, Operator, Arg2));
  785. if ((strcmp(Operator, "=") == 0) ||
  786. (strcmp(Operator, "==") == 0)) {
  787. Success = (Arg1 == Arg2) ? TRUE : FALSE;
  788. } else if (strcmp(Operator, "!=") == 0) {
  789. Success = (Arg1 != Arg2) ? TRUE : FALSE;
  790. } else if (strcmp(Operator, "<") == 0) {
  791. Success = (Arg1 < Arg2) ? TRUE : FALSE;
  792. } else if (strcmp(Operator, "<=") == 0) {
  793. Success = (Arg1 <= Arg2) ? TRUE : FALSE;
  794. } else if (strcmp(Operator, ">") == 0) {
  795. Success = (Arg1 > Arg2) ? TRUE : FALSE;
  796. } else if (strcmp(Operator, ">=") == 0) {
  797. Success = (Arg1 >= Arg2) ? TRUE : FALSE;
  798. } else {
  799. //
  800. // Invalid operator
  801. //
  802. }
  803. if (Success) {
  804. HalpBiosDbgPrint(("TRUE\n"));
  805. } else {
  806. HalpBiosDbgPrint(("FALSE\n"));
  807. }
  808. return(Success);
  809. }
  810. BOOLEAN
  811. MatchAcpiOemIdRule(
  812. PCHAR Section,
  813. ULONG KeyIndex
  814. )
  815. /*++
  816. Routine Description:
  817. This function processes a ACPI OEM ID rule from an INF file
  818. Examples:
  819. AcpiOemId="RSDT", "123456"
  820. is true if the RSDT has the OEM ID of 123456.
  821. AcpiOemId="DSDT", "768000"
  822. is true if the DSDT has the OEM ID of 768000.
  823. Arguments:
  824. Section - Specifies the section name the rule is in
  825. KeyIndex - Specifies the index of the rule in the section
  826. Return Value:
  827. TRUE - the computer has the specified ACPI OEM ID.
  828. FALSE - the computer does not have the specified ACPI OEM ID.
  829. --*/
  830. {
  831. PCHAR TableName;
  832. PCHAR OemId;
  833. PDESCRIPTION_HEADER Header;
  834. CHAR ACPIOemId[6];
  835. ULONG IdLength;
  836. TableName = SlGetSectionLineIndex(InfFile,
  837. Section,
  838. KeyIndex,
  839. 0);
  840. OemId = SlGetSectionLineIndex(InfFile,
  841. Section,
  842. KeyIndex,
  843. 1);
  844. if ((TableName == NULL) || (OemId == NULL)) {
  845. //
  846. // the INF line is ill-formed
  847. //
  848. HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
  849. return(FALSE);
  850. }
  851. Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
  852. if (Header == NULL) {
  853. //
  854. // The specified table was not found
  855. //
  856. HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
  857. return(FALSE);
  858. }
  859. RtlZeroMemory(ACPIOemId, sizeof(ACPIOemId));
  860. IdLength = strlen(OemId);
  861. if (IdLength > sizeof(ACPIOemId)) {
  862. IdLength = sizeof(ACPIOemId);
  863. }
  864. RtlCopyMemory(ACPIOemId, OemId, IdLength);
  865. HalpBiosDbgPrint(("\t\tComparing OEM ID %s '%6.6s' with '%6.6s' - ",
  866. TableName,
  867. ACPIOemId,
  868. Header->OEMID));
  869. if (RtlEqualMemory(ACPIOemId, Header->OEMID, sizeof(Header->OEMID))) {
  870. HalpBiosDbgPrint(("TRUE\n"));
  871. return(TRUE);
  872. } else {
  873. HalpBiosDbgPrint(("FALSE\n"));
  874. return(FALSE);
  875. }
  876. }
  877. BOOLEAN
  878. MatchAcpiOemTableIdRule(
  879. PCHAR Section,
  880. ULONG KeyIndex
  881. )
  882. /*++
  883. Routine Description:
  884. This function processes a ACPI OEM Table ID rule from an INF file
  885. Examples:
  886. AcpiOemTableId="RSDT", "12345678"
  887. is true if the RSDT has the Oem Table ID of 12345678.
  888. AcpiOemTableId="DSDT", "87654321"
  889. is true if the DSDT has the Oem Table ID of 87654321.
  890. Arguments:
  891. Section - Specifies the section name the rule is in
  892. KeyIndex - Specifies the index of the rule in the section
  893. Return Value:
  894. TRUE - the computer has the specified ACPI OEM ID.
  895. FALSE - the computer does not have the specified ACPI OEM ID.
  896. --*/
  897. {
  898. PCHAR TableName;
  899. PCHAR OemTableId;
  900. PDESCRIPTION_HEADER Header;
  901. CHAR ACPIOemTableId[8];
  902. ULONG IdLength;
  903. TableName = SlGetSectionLineIndex(InfFile,
  904. Section,
  905. KeyIndex,
  906. 0);
  907. OemTableId = SlGetSectionLineIndex(InfFile,
  908. Section,
  909. KeyIndex,
  910. 1);
  911. if ((TableName == NULL) || (OemTableId == NULL)) {
  912. //
  913. // the INF line is ill-formed
  914. //
  915. HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
  916. return(FALSE);
  917. }
  918. Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
  919. if (Header == NULL) {
  920. //
  921. // The specified table was not found
  922. //
  923. HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
  924. return(FALSE);
  925. }
  926. RtlZeroMemory(ACPIOemTableId, sizeof(ACPIOemTableId));
  927. IdLength = strlen(OemTableId);
  928. if (IdLength > sizeof(ACPIOemTableId)) {
  929. IdLength = sizeof(ACPIOemTableId);
  930. }
  931. RtlCopyMemory(ACPIOemTableId, OemTableId, IdLength);
  932. HalpBiosDbgPrint(("\t\tComparing OEM TableID %s '%8.8s' with '%8.8s' - ",
  933. TableName,
  934. ACPIOemTableId,
  935. Header->OEMTableID));
  936. if (RtlEqualMemory(ACPIOemTableId,
  937. Header->OEMTableID,
  938. sizeof(Header->OEMTableID))) {
  939. HalpBiosDbgPrint(("TRUE\n"));
  940. return(TRUE);
  941. } else {
  942. HalpBiosDbgPrint(("FALSE\n"));
  943. return(FALSE);
  944. }
  945. }
  946. BOOLEAN
  947. MatchAcpiOemRevisionRule(
  948. PCHAR Section,
  949. ULONG KeyIndex
  950. )
  951. /*++
  952. Routine Description:
  953. This function processes a ACPI Oem Revision rule from an INF file
  954. Examples:
  955. AcpiOemRevision="=","RSDT", 1234
  956. is true if the RSDT has the Oem Revision EQUAL to 1234.
  957. AcpiOemRevision=">","DSDT", 4321
  958. is true if the DSDT has the Oem Revision GREATER than 4321.
  959. Arguments:
  960. Section - Specifies the section name the rule is in
  961. KeyIndex - Specifies the index of the rule in the section
  962. Return Value:
  963. TRUE - the computer has the specified ACPI OEM ID.
  964. FALSE - the computer does not have the specified ACPI OEM ID.
  965. --*/
  966. {
  967. PCHAR TableName;
  968. PCHAR szOemRevision;
  969. ULONG OemRevision;
  970. PCHAR Operator;
  971. PDESCRIPTION_HEADER Header;
  972. BOOLEAN Success;
  973. Operator = SlGetSectionLineIndex(InfFile,
  974. Section,
  975. KeyIndex,
  976. 0);
  977. TableName = SlGetSectionLineIndex(InfFile,
  978. Section,
  979. KeyIndex,
  980. 1);
  981. szOemRevision = SlGetSectionLineIndex(InfFile,
  982. Section,
  983. KeyIndex,
  984. 2);
  985. if ((Operator == NULL) || (TableName == NULL) || (szOemRevision == NULL)) {
  986. //
  987. // the INF line is ill-formed
  988. //
  989. HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
  990. return(FALSE);
  991. }
  992. RtlCharToInteger(szOemRevision, 16, &OemRevision);
  993. Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
  994. if (Header == NULL) {
  995. //
  996. // The specified table was not found
  997. //
  998. HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
  999. return(FALSE);
  1000. }
  1001. Success = HalpCheckOperator(Operator, Header->OEMRevision, OemRevision);
  1002. return(Success);
  1003. }
  1004. BOOLEAN
  1005. MatchAcpiRevisionRule(
  1006. PCHAR Section,
  1007. ULONG KeyIndex
  1008. )
  1009. /*++
  1010. Routine Description:
  1011. This function processes a ACPI Revision rule from an INF file
  1012. Examples:
  1013. AcpiRevision="=", "RSDT", 1234
  1014. is true if the RSDT ACPI Revision is EQUAL to 1234.
  1015. AcpiRevision=">", "DSDT", 4321
  1016. is true if the DSDT ACPI Revision is GREATER than 4321.
  1017. Arguments:
  1018. Section - Specifies the section name the rule is in
  1019. KeyIndex - Specifies the index of the rule in the section
  1020. Return Value:
  1021. TRUE - the computer has the specified ACPI OEM ID.
  1022. FALSE - the computer does not have the specified ACPI OEM ID.
  1023. --*/
  1024. {
  1025. PCHAR TableName;
  1026. PCHAR szRevision;
  1027. ULONG Revision;
  1028. PCHAR Operator;
  1029. PDESCRIPTION_HEADER Header;
  1030. BOOLEAN Success;
  1031. Operator = SlGetSectionLineIndex(InfFile,
  1032. Section,
  1033. KeyIndex,
  1034. 0);
  1035. TableName = SlGetSectionLineIndex(InfFile,
  1036. Section,
  1037. KeyIndex,
  1038. 1);
  1039. szRevision = SlGetSectionLineIndex(InfFile,
  1040. Section,
  1041. KeyIndex,
  1042. 2);
  1043. if ((Operator == NULL) || (TableName == NULL) || (szRevision == NULL)) {
  1044. //
  1045. // the INF line is ill-formed
  1046. //
  1047. HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
  1048. return(FALSE);
  1049. }
  1050. RtlCharToInteger(szRevision, 16, &Revision);
  1051. Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
  1052. if (Header == NULL) {
  1053. //
  1054. // The specified table was not found
  1055. //
  1056. HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
  1057. return(FALSE);
  1058. }
  1059. Success = HalpCheckOperator(Operator, Header->Revision, Revision);
  1060. return(Success);
  1061. }
  1062. BOOLEAN
  1063. MatchAcpiCreatorRevisionRule(
  1064. PCHAR Section,
  1065. ULONG KeyIndex
  1066. )
  1067. /*++
  1068. Routine Description:
  1069. This function processes a ACPI Creator Revision rule from an INF file
  1070. Examples:
  1071. AcpiCreatorRevision="=", "RSDT", 1234
  1072. is true if the RSDT ACPI Creator Revision is EQUAL to 1234.
  1073. AcpiCreatorRevision=">", "DSDT", 4321
  1074. is true if the DSDT ACPI Creator Revision is GREATER than 4321.
  1075. Arguments:
  1076. Section - Specifies the section name the rule is in
  1077. KeyIndex - Specifies the index of the rule in the section
  1078. Return Value:
  1079. TRUE - the computer has the specified ACPI OEM ID.
  1080. FALSE - the computer does not have the specified ACPI OEM ID.
  1081. --*/
  1082. {
  1083. PCHAR TableName;
  1084. PCHAR szCreatorRevision;
  1085. ULONG CreatorRevision;
  1086. PCHAR Operator;
  1087. PDESCRIPTION_HEADER Header;
  1088. BOOLEAN Success;
  1089. Operator = SlGetSectionLineIndex(InfFile,
  1090. Section,
  1091. KeyIndex,
  1092. 0);
  1093. TableName = SlGetSectionLineIndex(InfFile,
  1094. Section,
  1095. KeyIndex,
  1096. 1);
  1097. szCreatorRevision = SlGetSectionLineIndex(InfFile,
  1098. Section,
  1099. KeyIndex,
  1100. 2);
  1101. if ((Operator == NULL) || (TableName == NULL) || (szCreatorRevision == NULL)) {
  1102. //
  1103. // the INF line is ill-formed
  1104. //
  1105. HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
  1106. return(FALSE);
  1107. }
  1108. RtlCharToInteger(szCreatorRevision, 16, &CreatorRevision);
  1109. Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
  1110. if (Header == NULL) {
  1111. //
  1112. // The specified table was not found
  1113. //
  1114. HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
  1115. return(FALSE);
  1116. }
  1117. Success = HalpCheckOperator(Operator, Header->CreatorRev, CreatorRevision);
  1118. return(Success);
  1119. }
  1120. BOOLEAN
  1121. MatchAcpiCreatorIdRule(
  1122. PCHAR Section,
  1123. ULONG KeyIndex
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. This function processes a ACPI Creator ID rule from an INF file
  1128. Examples:
  1129. AcpiCreatorId="RSDT", "MSFT"
  1130. is true if the RSDT has the Creator ID of MSFT.
  1131. Arguments:
  1132. Section - Specifies the section name the rule is in
  1133. KeyIndex - Specifies the index of the rule in the section
  1134. Return Value:
  1135. TRUE - the computer has the specified ACPI OEM ID.
  1136. FALSE - the computer does not have the specified ACPI OEM ID.
  1137. --*/
  1138. {
  1139. PCHAR TableName;
  1140. PCHAR CreatorId;
  1141. PDESCRIPTION_HEADER Header;
  1142. CHAR ACPICreatorId[6];
  1143. ULONG IdLength;
  1144. TableName = SlGetSectionLineIndex(InfFile,
  1145. Section,
  1146. KeyIndex,
  1147. 0);
  1148. CreatorId = SlGetSectionLineIndex(InfFile,
  1149. Section,
  1150. KeyIndex,
  1151. 1);
  1152. if ((TableName == NULL) || (CreatorId == NULL)) {
  1153. //
  1154. // the INF line is ill-formed
  1155. //
  1156. HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
  1157. return(FALSE);
  1158. }
  1159. Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
  1160. if (Header == NULL) {
  1161. //
  1162. // The specified table was not found
  1163. //
  1164. HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
  1165. return(FALSE);
  1166. }
  1167. RtlZeroMemory(ACPICreatorId, sizeof(ACPICreatorId));
  1168. IdLength = strlen(CreatorId);
  1169. if (IdLength > sizeof(ACPICreatorId)) {
  1170. IdLength = sizeof(ACPICreatorId);
  1171. }
  1172. RtlCopyMemory(ACPICreatorId, CreatorId, IdLength);
  1173. if (RtlEqualMemory(ACPICreatorId, Header->CreatorID, sizeof(Header->CreatorID))) {
  1174. return(TRUE);
  1175. } else {
  1176. return(FALSE);
  1177. }
  1178. }