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.

350 lines
8.2 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. #include "bootx86.h"
  17. #include "stdlib.h"
  18. #include "string.h"
  19. VOID
  20. BlPrint(
  21. PCHAR cp,
  22. ...
  23. );
  24. #ifdef DEBUG
  25. #undef DEBUG_PRINT
  26. #define DEBUG_PRINT BlPrint
  27. #else
  28. #define DEBUG_PRINT
  29. #endif
  30. typedef struct _ACPI_BIOS_INSTALLATION_CHECK {
  31. UCHAR Signature[8]; // "RSD PTR" (ascii)
  32. UCHAR Checksum;
  33. UCHAR OemId[6]; // An OEM-supplied string
  34. UCHAR reserved; // must be 0
  35. ULONG RsdtAddress; // 32-bit physical address of RSDT
  36. } ACPI_BIOS_INSTALLATION_CHECK, *PACPI_BIOS_INSTALLATION_CHECK;
  37. #include "acpitabl.h"
  38. PRSDP BlRsdp;
  39. PRSDT BlRsdt;
  40. PXSDT BlXsdt;
  41. BOOLEAN BlLegacyFree = FALSE;
  42. PDESCRIPTION_HEADER
  43. BlFindACPITable(
  44. IN PCHAR TableName,
  45. IN ULONG TableLength
  46. );
  47. // from boot\detect\i386\acpibios.h
  48. //
  49. // Acpi BIOS Installation check
  50. //
  51. #define ACPI_BIOS_START 0xE0000
  52. #define ACPI_BIOS_END 0xFFFFF
  53. #define ACPI_BIOS_HEADER_INCREMENT 16
  54. VOID
  55. BlFindRsdp (
  56. VOID
  57. )
  58. #define EBDA_SEGMENT_PTR 0x40e
  59. {
  60. ULONG romAddr, romEnd;
  61. PACPI_BIOS_INSTALLATION_CHECK header;
  62. UCHAR sum, node = 0;
  63. USHORT i, nodeSize;
  64. ULONG EbdaSegmentPtr;
  65. ULONG EbdaPhysicalAdd = 0;
  66. PUCHAR EbdaVirtualAdd = 0;
  67. PHYSICAL_ADDRESS paddr;
  68. enum PASS { PASS1 = 0, PASS2, MAX_PASSES } pass;
  69. USHORT count = 0;
  70. //
  71. // Search on 16 byte boundaries for the signature of the
  72. // Root System Description Table structure.
  73. //
  74. for (pass = PASS1; pass < MAX_PASSES; pass++) {
  75. if (pass == PASS1) {
  76. //
  77. // On the first pass, we search the first 1K of the
  78. // Extended BIOS data area. The EBDA segment address
  79. // is available at physical address 40:0E.
  80. //
  81. paddr.QuadPart = 0;
  82. EbdaSegmentPtr = (ULONG) MmMapIoSpace( paddr,
  83. PAGE_SIZE,
  84. TRUE);
  85. EbdaSegmentPtr += EBDA_SEGMENT_PTR;
  86. EbdaPhysicalAdd = *((PUSHORT)EbdaSegmentPtr);
  87. EbdaPhysicalAdd = EbdaPhysicalAdd << 4;
  88. if (EbdaPhysicalAdd) {
  89. paddr.HighPart = 0;
  90. paddr.LowPart = EbdaPhysicalAdd;
  91. EbdaVirtualAdd = MmMapIoSpace( paddr,
  92. 2 * PAGE_SIZE,
  93. TRUE);
  94. }
  95. if (!EbdaVirtualAdd) {
  96. continue;
  97. }
  98. romAddr = (ULONG)EbdaVirtualAdd;
  99. romEnd = romAddr + 1024;
  100. } else {
  101. //
  102. // On the second pass, we search (physical) memory 0xE0000
  103. // to 0xF0000.
  104. paddr.LowPart = ACPI_BIOS_START;
  105. romAddr = (ULONG)MmMapIoSpace(paddr,
  106. ACPI_BIOS_END - ACPI_BIOS_START,
  107. TRUE);
  108. romEnd = romAddr + (ACPI_BIOS_END - ACPI_BIOS_START);
  109. }
  110. while (romAddr < romEnd) {
  111. header = (PACPI_BIOS_INSTALLATION_CHECK)romAddr;
  112. //
  113. // Signature to match is the string "RSD PTR ".
  114. //
  115. if (header->Signature[0] == 'R' && header->Signature[1] == 'S' &&
  116. header->Signature[2] == 'D' && header->Signature[3] == ' ' &&
  117. header->Signature[4] == 'P' && header->Signature[5] == 'T' &&
  118. header->Signature[6] == 'R' && header->Signature[7] == ' ' ) {
  119. sum = 0;
  120. for (i = 0; i < sizeof(ACPI_BIOS_INSTALLATION_CHECK); i++) {
  121. sum += ((PUCHAR)romAddr)[i];
  122. }
  123. if (sum == 0) {
  124. pass = MAX_PASSES; // leave 'for' loop
  125. break; // leave 'while' loop
  126. }
  127. }
  128. romAddr += ACPI_BIOS_HEADER_INCREMENT;
  129. }
  130. }
  131. if (romAddr >= romEnd) {
  132. BlRsdp = NULL;
  133. BlRsdt = NULL;
  134. return;
  135. }
  136. BlRsdp = (PRSDP)romAddr;
  137. paddr.LowPart = BlRsdp->RsdtAddress;
  138. BlRsdt = MmMapIoSpace(paddr, sizeof(RSDT), TRUE);
  139. BlRsdt = MmMapIoSpace(paddr, BlRsdt->Header.Length, TRUE);
  140. #ifdef ACPI_20_COMPLIANT
  141. if (BlRsdp->Revision > 1) {
  142. //
  143. // ACPI 2.0 BIOS
  144. //
  145. BlXsdt = MmMapIoSpace(paddr, sizeof(XSDT), TRUE);
  146. BlXsdt = MmMapIoSpace(paddr, BlXsdt->Header.Length, TRUE);
  147. }
  148. #endif
  149. return;
  150. }
  151. BOOLEAN
  152. BlDetectLegacyFreeBios(
  153. VOID
  154. )
  155. {
  156. PFADT fadt;
  157. if (BlLegacyFree) {
  158. return TRUE;
  159. }
  160. BlFindRsdp();
  161. if (BlRsdt) {
  162. fadt = (PFADT)BlFindACPITable("FACP", sizeof(FADT));
  163. if (fadt == NULL) {
  164. return FALSE;
  165. }
  166. if ((fadt->Header.Revision < 2) ||
  167. (fadt->Header.Length <= 116)) {
  168. //
  169. // The BIOS is earlier than the legacy-free
  170. // additions.
  171. //
  172. return FALSE;
  173. }
  174. if (!(fadt->boot_arch & I8042)) {
  175. BlLegacyFree = TRUE;
  176. return TRUE;
  177. }
  178. }
  179. return FALSE;
  180. }
  181. PDESCRIPTION_HEADER
  182. BlFindACPITable(
  183. IN PCHAR TableName,
  184. IN ULONG TableLength
  185. )
  186. /*++
  187. Routine Description:
  188. Given a table name, finds that table in the ACPI BIOS
  189. Arguments:
  190. TableName - Supplies the table name
  191. TableLength - Supplies the length of the table to map
  192. Return Value:
  193. Pointer to the table if found
  194. NULL if the table is not found
  195. --*/
  196. {
  197. ULONG Signature;
  198. PFADT Fadt;
  199. PDESCRIPTION_HEADER Header;
  200. ULONG TableCount;
  201. ULONG i;
  202. PHYSICAL_ADDRESS paddr = {0};
  203. Signature = *((ULONG UNALIGNED *)TableName);
  204. if (Signature == RSDT_SIGNATURE) {
  205. return(&BlRsdt->Header);
  206. } else if (Signature == XSDT_SIGNATURE) {
  207. return(&BlXsdt->Header);
  208. } else if (Signature == DSDT_SIGNATURE) {
  209. Fadt = (PFADT)BlFindACPITable("FACP", sizeof(PFADT));
  210. if (Fadt == NULL) {
  211. return(NULL);
  212. }
  213. if (BlXsdt) {
  214. paddr = Fadt->x_dsdt;
  215. } else {
  216. #if defined(_X86_)
  217. paddr.LowPart = Fadt->dsdt;
  218. #else
  219. paddr.QuadPart = Fadt->dsdt;
  220. #endif
  221. }
  222. Header = MmMapIoSpace(paddr, TableLength, TRUE);
  223. return(Header);
  224. } else {
  225. //
  226. // Make sure...
  227. //
  228. if( !BlRsdt ) {
  229. BlFindRsdp();
  230. }
  231. if( BlRsdt ) {
  232. TableCount = BlXsdt ?
  233. NumTableEntriesFromXSDTPointer(BlXsdt) :
  234. NumTableEntriesFromRSDTPointer(BlRsdt);
  235. //
  236. // Sanity check.
  237. //
  238. if( TableCount > 0x100 ) {
  239. return(NULL);
  240. }
  241. for (i=0;i<TableCount;i++) {
  242. if (BlXsdt) {
  243. paddr = BlXsdt->Tables[i];
  244. } else {
  245. #if defined(_X86_)
  246. paddr.HighPart = 0;
  247. paddr.LowPart = BlRsdt->Tables[i];
  248. #else
  249. paddr.QuadPart = BlRsdt->Tables[i];
  250. #endif
  251. }
  252. Header = MmMapIoSpace(paddr, sizeof(DESCRIPTION_HEADER), TRUE);
  253. if (Header == NULL) {
  254. return(NULL);
  255. }
  256. if (Header->Signature == Signature) {
  257. //
  258. // if we need to map more than just the DESCRIPTION_HEADER, do that before
  259. // returning. Check to see if the end of the table lies past the page
  260. // boundary the header lies on. If so, we will have to map it.
  261. //
  262. if ( ((paddr.LowPart + TableLength) & ~(PAGE_SIZE - 1)) >
  263. ((paddr.LowPart + sizeof(DESCRIPTION_HEADER)) & ~(PAGE_SIZE - 1)) ) {
  264. Header = MmMapIoSpace(paddr, TableLength, TRUE);
  265. }
  266. return(Header);
  267. }
  268. }
  269. }
  270. }
  271. return(NULL);
  272. }