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.

357 lines
8.6 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 = 0;
  61. ULONG romEnd = 0;
  62. PACPI_BIOS_INSTALLATION_CHECK header;
  63. UCHAR sum;
  64. USHORT i;
  65. ULONG EbdaSegmentPtr;
  66. ULONG EbdaPhysicalAdd = 0;
  67. PUCHAR EbdaVirtualAdd = 0;
  68. PHYSICAL_ADDRESS paddr;
  69. enum PASS { PASS1 = 0, PASS2, MAX_PASSES } pass;
  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 = 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. //
  152. // Make the FADT table global.
  153. // It will be used when resetting legacy free machines.
  154. //
  155. PFADT fadt = NULL;
  156. BOOLEAN
  157. BlDetectLegacyFreeBios(
  158. VOID
  159. )
  160. {
  161. if (BlLegacyFree) {
  162. return TRUE;
  163. }
  164. BlFindRsdp();
  165. if (BlRsdt) {
  166. fadt = (PFADT)BlFindACPITable("FACP", sizeof(FADT));
  167. if (fadt == NULL) {
  168. return FALSE;
  169. }
  170. if ((fadt->Header.Revision < 2) ||
  171. (fadt->Header.Length <= 116)) {
  172. //
  173. // The BIOS is earlier than the legacy-free
  174. // additions.
  175. //
  176. return FALSE;
  177. }
  178. if (!(fadt->boot_arch & I8042)) {
  179. BlLegacyFree = TRUE;
  180. return TRUE;
  181. }
  182. }
  183. return FALSE;
  184. }
  185. PDESCRIPTION_HEADER
  186. BlFindACPITable(
  187. IN PCHAR TableName,
  188. IN ULONG TableLength
  189. )
  190. /*++
  191. Routine Description:
  192. Given a table name, finds that table in the ACPI BIOS
  193. Arguments:
  194. TableName - Supplies the table name
  195. TableLength - Supplies the length of the table to map
  196. Return Value:
  197. Pointer to the table if found
  198. NULL if the table is not found
  199. --*/
  200. {
  201. ULONG Signature;
  202. PFADT Fadt;
  203. PDESCRIPTION_HEADER Header;
  204. ULONG TableCount;
  205. ULONG i;
  206. PHYSICAL_ADDRESS paddr = {0};
  207. Signature = *((ULONG UNALIGNED *)TableName);
  208. if (Signature == RSDT_SIGNATURE) {
  209. return(&BlRsdt->Header);
  210. } else if (Signature == XSDT_SIGNATURE) {
  211. return(&BlXsdt->Header);
  212. } else if (Signature == DSDT_SIGNATURE) {
  213. Fadt = (PFADT)BlFindACPITable("FACP", sizeof(PFADT));
  214. if (Fadt == NULL) {
  215. return(NULL);
  216. }
  217. if (BlXsdt) {
  218. paddr = Fadt->x_dsdt;
  219. } else {
  220. #if defined(_X86_)
  221. paddr.LowPart = Fadt->dsdt;
  222. #else
  223. paddr.QuadPart = Fadt->dsdt;
  224. #endif
  225. }
  226. Header = MmMapIoSpace(paddr, TableLength, TRUE);
  227. return(Header);
  228. } else {
  229. //
  230. // Make sure...
  231. //
  232. if( !BlRsdt ) {
  233. BlFindRsdp();
  234. }
  235. if( BlRsdt ) {
  236. TableCount = BlXsdt ?
  237. NumTableEntriesFromXSDTPointer(BlXsdt) :
  238. NumTableEntriesFromRSDTPointer(BlRsdt);
  239. //
  240. // Sanity check.
  241. //
  242. if( TableCount > 0x100 ) {
  243. return(NULL);
  244. }
  245. for (i=0;i<TableCount;i++) {
  246. if (BlXsdt) {
  247. paddr = BlXsdt->Tables[i];
  248. } else {
  249. #if defined(_X86_)
  250. paddr.HighPart = 0;
  251. paddr.LowPart = BlRsdt->Tables[i];
  252. #else
  253. paddr.QuadPart = BlRsdt->Tables[i];
  254. #endif
  255. }
  256. Header = MmMapIoSpace(paddr, sizeof(DESCRIPTION_HEADER), TRUE);
  257. if (Header == NULL) {
  258. return(NULL);
  259. }
  260. if (Header->Signature == Signature) {
  261. //
  262. // if we need to map more than just the DESCRIPTION_HEADER, do that before
  263. // returning. Check to see if the end of the table lies past the page
  264. // boundary the header lies on. If so, we will have to map it.
  265. //
  266. if ( ((paddr.LowPart + TableLength) & ~(PAGE_SIZE - 1)) >
  267. ((paddr.LowPart + sizeof(DESCRIPTION_HEADER)) & ~(PAGE_SIZE - 1)) ) {
  268. Header = MmMapIoSpace(paddr, TableLength, TRUE);
  269. }
  270. return(Header);
  271. }
  272. }
  273. }
  274. }
  275. return(NULL);
  276. }