Xen.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /** @file
  2. OVMF ACPI Xen support
  3. Copyright (C) 2021, Red Hat, Inc.
  4. Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
  5. Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include <Library/BaseLib.h> // CpuDeadLoop()
  9. #include <Library/DebugLib.h> // DEBUG()
  10. #include <Library/XenPlatformLib.h> // XenGetInfoHOB()
  11. #include "AcpiPlatform.h"
  12. #define XEN_ACPI_PHYSICAL_ADDRESS 0x000EA020
  13. #define XEN_BIOS_PHYSICAL_END 0x000FFFFF
  14. EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr = NULL;
  15. /**
  16. Get the address of Xen ACPI Root System Description Pointer (RSDP)
  17. structure.
  18. @param RsdpStructurePtr Return pointer to RSDP structure
  19. @return EFI_SUCCESS Find Xen RSDP structure successfully.
  20. @return EFI_NOT_FOUND Don't find Xen RSDP structure.
  21. @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
  22. **/
  23. EFI_STATUS
  24. EFIAPI
  25. GetXenAcpiRsdp (
  26. OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
  27. )
  28. {
  29. EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
  30. UINT8 *XenAcpiPtr;
  31. UINT8 Sum;
  32. EFI_XEN_INFO *XenInfo;
  33. //
  34. // Detect the RSDP structure
  35. //
  36. //
  37. // First look for PVH one
  38. //
  39. XenInfo = XenGetInfoHOB ();
  40. ASSERT (XenInfo != NULL);
  41. if (XenInfo->RsdpPvh != NULL) {
  42. DEBUG ((
  43. DEBUG_INFO,
  44. "%a: Use ACPI RSDP table at 0x%p\n",
  45. gEfiCallerBaseName,
  46. XenInfo->RsdpPvh
  47. ));
  48. *RsdpPtr = XenInfo->RsdpPvh;
  49. return EFI_SUCCESS;
  50. }
  51. //
  52. // Otherwise, look for the HVM one
  53. //
  54. for (XenAcpiPtr = (UINT8 *)(UINTN)XEN_ACPI_PHYSICAL_ADDRESS;
  55. XenAcpiPtr < (UINT8 *)(UINTN)XEN_BIOS_PHYSICAL_END;
  56. XenAcpiPtr += 0x10)
  57. {
  58. RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
  59. (UINTN)XenAcpiPtr;
  60. if (!AsciiStrnCmp ((CHAR8 *)&RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
  61. //
  62. // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
  63. // This is only the first 20 bytes of the structure
  64. //
  65. Sum = CalculateSum8 (
  66. (CONST UINT8 *)RsdpStructurePtr,
  67. sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
  68. );
  69. if (Sum != 0) {
  70. return EFI_ABORTED;
  71. }
  72. if (RsdpStructurePtr->Revision >= 2) {
  73. //
  74. // RSDP ACPI 2.0/3.0 checksum, this is the entire table
  75. //
  76. Sum = CalculateSum8 (
  77. (CONST UINT8 *)RsdpStructurePtr,
  78. sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
  79. );
  80. if (Sum != 0) {
  81. return EFI_ABORTED;
  82. }
  83. }
  84. *RsdpPtr = RsdpStructurePtr;
  85. return EFI_SUCCESS;
  86. }
  87. }
  88. return EFI_NOT_FOUND;
  89. }
  90. /**
  91. Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
  92. into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
  93. ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
  94. @param AcpiProtocol Protocol instance pointer.
  95. @return EFI_SUCCESS The table was successfully inserted.
  96. @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
  97. NULL, or AcpiTableBufferSize and the size
  98. field embedded in the ACPI table pointed to
  99. by AcpiTableBuffer are not in sync.
  100. @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
  101. **/
  102. EFI_STATUS
  103. EFIAPI
  104. InstallXenTables (
  105. IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
  106. )
  107. {
  108. EFI_STATUS Status;
  109. UINTN TableHandle;
  110. EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
  111. EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
  112. VOID *CurrentTableEntry;
  113. UINTN CurrentTablePointer;
  114. EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
  115. UINTN Index;
  116. UINTN NumberOfTableEntries;
  117. EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt2Table;
  118. EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt1Table;
  119. EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs2Table;
  120. EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs1Table;
  121. EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
  122. Fadt2Table = NULL;
  123. Fadt1Table = NULL;
  124. Facs2Table = NULL;
  125. Facs1Table = NULL;
  126. DsdtTable = NULL;
  127. TableHandle = 0;
  128. NumberOfTableEntries = 0;
  129. //
  130. // Try to find Xen ACPI tables
  131. //
  132. Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);
  133. if (EFI_ERROR (Status)) {
  134. return Status;
  135. }
  136. //
  137. // If XSDT table is find, just install its tables.
  138. // Otherwise, try to find and install the RSDT tables.
  139. //
  140. if (XenAcpiRsdpStructurePtr->XsdtAddress) {
  141. //
  142. // Retrieve the addresses of XSDT and
  143. // calculate the number of its table entries.
  144. //
  145. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
  146. XenAcpiRsdpStructurePtr->XsdtAddress;
  147. NumberOfTableEntries = (Xsdt->Length -
  148. sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
  149. sizeof (UINT64);
  150. //
  151. // Install ACPI tables found in XSDT.
  152. //
  153. for (Index = 0; Index < NumberOfTableEntries; Index++) {
  154. //
  155. // Get the table entry from XSDT
  156. //
  157. CurrentTableEntry = (VOID *)((UINT8 *)Xsdt +
  158. sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
  159. Index * sizeof (UINT64));
  160. CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;
  161. CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
  162. //
  163. // Install the XSDT tables
  164. //
  165. Status = AcpiProtocol->InstallAcpiTable (
  166. AcpiProtocol,
  167. CurrentTable,
  168. CurrentTable->Length,
  169. &TableHandle
  170. );
  171. if (EFI_ERROR (Status)) {
  172. return Status;
  173. }
  174. //
  175. // Get the FACS and DSDT table address from the table FADT
  176. //
  177. if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
  178. Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
  179. (UINTN)CurrentTablePointer;
  180. Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
  181. (UINTN)Fadt2Table->FirmwareCtrl;
  182. DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt2Table->Dsdt;
  183. }
  184. }
  185. } else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
  186. //
  187. // Retrieve the addresses of RSDT and
  188. // calculate the number of its table entries.
  189. //
  190. Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
  191. XenAcpiRsdpStructurePtr->RsdtAddress;
  192. NumberOfTableEntries = (Rsdt->Length -
  193. sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
  194. sizeof (UINT32);
  195. //
  196. // Install ACPI tables found in XSDT.
  197. //
  198. for (Index = 0; Index < NumberOfTableEntries; Index++) {
  199. //
  200. // Get the table entry from RSDT
  201. //
  202. CurrentTableEntry = (UINT32 *)((UINT8 *)Rsdt +
  203. sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
  204. Index * sizeof (UINT32));
  205. CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
  206. CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
  207. //
  208. // Install the RSDT tables
  209. //
  210. Status = AcpiProtocol->InstallAcpiTable (
  211. AcpiProtocol,
  212. CurrentTable,
  213. CurrentTable->Length,
  214. &TableHandle
  215. );
  216. if (EFI_ERROR (Status)) {
  217. return Status;
  218. }
  219. //
  220. // Get the FACS and DSDT table address from the table FADT
  221. //
  222. if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
  223. Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)
  224. (UINTN)CurrentTablePointer;
  225. Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
  226. (UINTN)Fadt1Table->FirmwareCtrl;
  227. DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Fadt1Table->Dsdt;
  228. }
  229. }
  230. }
  231. //
  232. // Install the FACS table.
  233. //
  234. if (Fadt2Table) {
  235. //
  236. // FACS 2.0
  237. //
  238. Status = AcpiProtocol->InstallAcpiTable (
  239. AcpiProtocol,
  240. Facs2Table,
  241. Facs2Table->Length,
  242. &TableHandle
  243. );
  244. if (EFI_ERROR (Status)) {
  245. return Status;
  246. }
  247. } else if (Fadt1Table) {
  248. //
  249. // FACS 1.0
  250. //
  251. Status = AcpiProtocol->InstallAcpiTable (
  252. AcpiProtocol,
  253. Facs1Table,
  254. Facs1Table->Length,
  255. &TableHandle
  256. );
  257. if (EFI_ERROR (Status)) {
  258. return Status;
  259. }
  260. }
  261. //
  262. // Install DSDT table. If we reached this point without finding the DSDT,
  263. // then we're out of sync with the hypervisor, and cannot continue.
  264. //
  265. if (DsdtTable == NULL) {
  266. DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));
  267. ASSERT (FALSE);
  268. CpuDeadLoop ();
  269. }
  270. Status = AcpiProtocol->InstallAcpiTable (
  271. AcpiProtocol,
  272. DsdtTable,
  273. DsdtTable->Length,
  274. &TableHandle
  275. );
  276. if (EFI_ERROR (Status)) {
  277. return Status;
  278. }
  279. return EFI_SUCCESS;
  280. }