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.

338 lines
8.6 KiB

  1. /*++
  2. Copyright (c) 1990, 1991 Microsoft Corporation
  3. Module Name:
  4. hwpmbiosc.c
  5. Abstract:
  6. This modules contains ACPI BIOS C supporting routines
  7. Author:
  8. Jake Oshins (jakeo) 6-Feb-1997
  9. Environment:
  10. Real mode.
  11. Revision History:
  12. --*/
  13. #include "hwdetect.h"
  14. #include <string.h>
  15. #include "acpibios.h"
  16. typedef struct {
  17. ULONG ErrorFlag;
  18. ULONG Key;
  19. ULONG Size;
  20. struct {
  21. ULONG BaseAddrLow;
  22. ULONG BaseAddrHigh;
  23. ULONG SizeLow;
  24. ULONG SizeHigh;
  25. ULONG MemoryType;
  26. } Descriptor;
  27. } E820Frame;
  28. BOOLEAN
  29. Int15E820 (
  30. E820Frame *Frame
  31. );
  32. BOOLEAN
  33. Int15E980 (
  34. PLEGACY_GEYSERVILLE_INT15 Info
  35. );
  36. BOOLEAN
  37. HwGetAcpiBiosData(
  38. IN FPUCHAR *Configuration,
  39. OUT PUSHORT Length
  40. )
  41. /*++
  42. Routine Description:
  43. This routine checks to see if an ACPI BIOS is present. If it is,
  44. then it returns the ACPI Root System Description Pointer.
  45. Arguments:
  46. Configuration - structure that holds ACPI pointer
  47. Length - length of that structure
  48. Return Value:
  49. TRUE if ACPI BIOS is present, FALSE otherwise
  50. --*/
  51. {
  52. ULONG romAddr, romEnd;
  53. FPUCHAR current;
  54. FPULONG EbdaAddr;
  55. FPACPI_BIOS_INSTALLATION_CHECK header;
  56. UCHAR sum, node = 0;
  57. USHORT i, nodeSize;
  58. USHORT numE820Blocks, e820BlockIndex;
  59. BOOLEAN complete;
  60. FPACPI_E820_ENTRY e820Blocks;
  61. E820Frame Frame;
  62. LEGACY_GEYSERVILLE_INT15 geyservilleInfo;
  63. BOOLEAN geyservillePresent;
  64. enum PASS { PASS1 = 0, PASS2, MAX_PASSES } pass;
  65. //
  66. // Search on 16 byte boundaries for the signature of the
  67. // Root System Description Table structure.
  68. //
  69. for (pass = PASS1; pass < MAX_PASSES; pass++) {
  70. if (pass == PASS1) {
  71. //
  72. // On the first pass, we search the first 1K of the
  73. // Extended BIOS data area.
  74. //
  75. //
  76. // Earlier, we stored the address of the EBDA in address
  77. // DOS_BEGIN_SEGMENT << 4 : EBIOS_INFO_OFFSET
  78. //
  79. MAKE_FP(EbdaAddr, ((DOS_BEGIN_SEGMENT << 4) + EBIOS_INFO_OFFSET));
  80. MAKE_FP(current, *EbdaAddr);
  81. if (*EbdaAddr == 0) {
  82. continue;
  83. }
  84. romAddr = *EbdaAddr;
  85. romEnd = romAddr + 1024;
  86. } else {
  87. //
  88. // On the second pass, we search (physical) memory 0xE0000
  89. // to 0xF0000.
  90. MAKE_FP(current, ACPI_BIOS_START);
  91. romAddr = ACPI_BIOS_START;
  92. romEnd = ACPI_BIOS_END;
  93. }
  94. while (romAddr < romEnd) {
  95. header = (FPACPI_BIOS_INSTALLATION_CHECK)current;
  96. //
  97. // Signature to match is the string "RSD PTR".
  98. //
  99. if (header->Signature[0] == 'R' && header->Signature[1] == 'S' &&
  100. header->Signature[2] == 'D' && header->Signature[3] == ' ' &&
  101. header->Signature[4] == 'P' && header->Signature[5] == 'T' &&
  102. header->Signature[6] == 'R' && header->Signature[7] == ' ' ) {
  103. sum = 0;
  104. for (i = 0; i < sizeof(ACPI_BIOS_INSTALLATION_CHECK); i++) {
  105. sum += current[i];
  106. }
  107. if (sum == 0) {
  108. pass = MAX_PASSES; // leave 'for' loop
  109. break; // leave 'while' loop
  110. }
  111. #if DBG
  112. BlPrint("GetAcpiBiosData: Checksum fails\n");
  113. #endif
  114. }
  115. romAddr += ACPI_BIOS_HEADER_INCREMENT;
  116. MAKE_FP(current, romAddr);
  117. }
  118. }
  119. if (romAddr >= romEnd) {
  120. #if DBG
  121. BlPrint("GetAcpiBiosData: RSDT pointer not found\n");
  122. #endif
  123. return FALSE;
  124. }
  125. //
  126. // Now header points at the RSDP. So we can move on to collecting the
  127. // E820 blocks.
  128. //
  129. numE820Blocks = 20;
  130. while (TRUE) {
  131. e820Blocks =
  132. (FPACPI_E820_ENTRY)HwAllocateHeap(
  133. sizeof(ACPI_E820_ENTRY) * numE820Blocks,
  134. FALSE);
  135. if (!e820Blocks) {
  136. #if DBG
  137. BlPrint("GetAcpiBiosData: Out of heap space.\n");
  138. #endif
  139. return FALSE;
  140. }
  141. e820BlockIndex = 0;
  142. Frame.Key = 0;
  143. complete = FALSE;
  144. while (!complete) {
  145. #if DBG
  146. BlPrint("Searching for E820 block # %d.\n", e820BlockIndex);
  147. #endif
  148. if (e820BlockIndex == numE820Blocks) {
  149. HwFreeHeap(sizeof(ACPI_E820_ENTRY) * numE820Blocks);
  150. numE820Blocks += 20;
  151. break;
  152. }
  153. //
  154. // Set up the context.
  155. //
  156. Frame.Size = sizeof (Frame.Descriptor);
  157. Int15E820 (&Frame);
  158. if (Frame.ErrorFlag || Frame.Size < sizeof (Frame.Descriptor)) {
  159. //
  160. // The BIOS just didn't do it.
  161. //
  162. #if DBG
  163. BlPrint("The BIOS failed the E820 call\n");
  164. #endif
  165. complete = TRUE;
  166. break;
  167. }
  168. //
  169. // Copy the data from the Frame into the array.
  170. //
  171. e820Blocks[e820BlockIndex].Base.LowPart = Frame.Descriptor.BaseAddrLow;
  172. e820Blocks[e820BlockIndex].Base.HighPart = Frame.Descriptor.BaseAddrHigh;
  173. e820Blocks[e820BlockIndex].Length.LowPart = Frame.Descriptor.SizeLow;
  174. e820Blocks[e820BlockIndex].Length.HighPart = Frame.Descriptor.SizeHigh;
  175. e820Blocks[e820BlockIndex].Type = Frame.Descriptor.MemoryType;
  176. e820Blocks[e820BlockIndex].Reserved = 0;
  177. #if DBG
  178. BlPrint("Base: %x%x Len: %x%x Type: %x\n",
  179. (USHORT)(Frame.Descriptor.BaseAddrLow >> 16),
  180. (USHORT)(Frame.Descriptor.BaseAddrLow & 0xffff),
  181. (USHORT)(Frame.Descriptor.SizeLow >> 16),
  182. (USHORT)(Frame.Descriptor.SizeLow & 0xffff),
  183. (USHORT)(Frame.Descriptor.MemoryType));
  184. #endif
  185. e820BlockIndex++;
  186. if (Frame.Key == 0) {
  187. //
  188. // This was the last descriptor
  189. //
  190. complete = TRUE;
  191. break;
  192. }
  193. }
  194. if (complete) {
  195. break;
  196. }
  197. }
  198. #if DBG
  199. BlPrint("Finished with %d E820 descriptors\n", e820BlockIndex);
  200. #endif
  201. //
  202. // Check for Geyserville
  203. //
  204. if (geyservillePresent = Int15E980(&geyservilleInfo)) {
  205. geyservilleInfo.Signature = 'GS';
  206. }
  207. #if DBG
  208. BlPrint("GetAcpiBiosData: Geyserville is %s present.\n",
  209. geyservillePresent ? "" : "not");
  210. if (geyservillePresent) {
  211. BlPrint("GetAcpiBiosData: Geyserville command port: %x.\n",
  212. geyservilleInfo.CommandPortAddress);
  213. }
  214. #endif
  215. //
  216. // Now we know how big the lump of data is going to be.
  217. //
  218. nodeSize = sizeof(ACPI_BIOS_MULTI_NODE) + DATA_HEADER_SIZE +
  219. (sizeof(ACPI_E820_ENTRY) * (e820BlockIndex - 1)) +
  220. (geyservillePresent ? sizeof(LEGACY_GEYSERVILLE_INT15) : 0);
  221. current = (FPUCHAR) HwAllocateHeap(nodeSize, FALSE);
  222. if (!current) {
  223. #if DBG
  224. BlPrint("GetAcpiBiosData: Out of heap space.\n");
  225. #endif
  226. return FALSE;
  227. }
  228. //
  229. // Collect ACPI Bios installation check data and device node data.
  230. //
  231. ((FPACPI_BIOS_MULTI_NODE)(current + DATA_HEADER_SIZE))->RsdtAddress.HighPart = 0;
  232. ((FPACPI_BIOS_MULTI_NODE)(current + DATA_HEADER_SIZE))->RsdtAddress.LowPart =
  233. header->RsdtAddress;
  234. ((FPACPI_BIOS_MULTI_NODE)(current + DATA_HEADER_SIZE))->Count = e820BlockIndex;
  235. ((FPACPI_BIOS_MULTI_NODE)(current + DATA_HEADER_SIZE))->Reserved = 0;
  236. _fmemcpy (&(((FPACPI_BIOS_MULTI_NODE)(current + DATA_HEADER_SIZE))->E820Entry[0]),
  237. (FPUCHAR)e820Blocks,
  238. sizeof(ACPI_E820_ENTRY) * e820BlockIndex
  239. );
  240. if (geyservillePresent) {
  241. //
  242. // Append Geyserville information to the end of the block.
  243. //
  244. _fmemcpy(&(((FPACPI_BIOS_MULTI_NODE)(current + DATA_HEADER_SIZE))->E820Entry[e820BlockIndex]),
  245. &geyservilleInfo,
  246. sizeof(geyservilleInfo));
  247. }
  248. *Configuration = current;
  249. *Length = nodeSize;
  250. #if DBG
  251. BlPrint("ACPI BIOS found at 0x%x:%x. RdstAddress is 0x%x:%x\n",
  252. (USHORT)(romAddr >> 16),
  253. (USHORT)(romAddr),
  254. (USHORT)(header->RsdtAddress >> 16),
  255. (USHORT)(header->RsdtAddress)
  256. );
  257. #endif
  258. return TRUE;
  259. }