XenAcpiPlatformDxe.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /** @file
  2. Xen ARM ACPI Platform Driver using Xen ARM multiboot protocol
  3. Copyright (C) 2016, Linaro Ltd. All rights reserved.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/BaseLib.h>
  7. #include <Library/DebugLib.h>
  8. #include <Library/UefiBootServicesTableLib.h>
  9. #include <Library/UefiDriverEntryPoint.h>
  10. #include <Protocol/AcpiTable.h>
  11. #include <Protocol/FdtClient.h>
  12. #include <IndustryStandard/Acpi.h>
  13. /**
  14. Get the address of Xen ACPI Root System Description Pointer (RSDP)
  15. structure.
  16. @param RsdpStructurePtr Return pointer to RSDP structure
  17. @return EFI_SUCCESS Find Xen RSDP structure successfully.
  18. @return EFI_NOT_FOUND Don't find Xen RSDP structure.
  19. @return EFI_ABORTED Find Xen RSDP structure, but it's not integrated.
  20. **/
  21. STATIC
  22. EFI_STATUS
  23. EFIAPI
  24. GetXenArmAcpiRsdp (
  25. OUT EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER **RsdpPtr
  26. )
  27. {
  28. EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *RsdpStructurePtr;
  29. EFI_STATUS Status;
  30. FDT_CLIENT_PROTOCOL *FdtClient;
  31. CONST UINT64 *Reg;
  32. UINT32 RegSize;
  33. UINTN AddressCells, SizeCells;
  34. UINT64 RegBase;
  35. UINT8 Sum;
  36. RsdpStructurePtr = NULL;
  37. FdtClient = NULL;
  38. //
  39. // Get the RSDP structure address from DeviceTree
  40. //
  41. Status = gBS->LocateProtocol (
  42. &gFdtClientProtocolGuid,
  43. NULL,
  44. (VOID **)&FdtClient
  45. );
  46. ASSERT_EFI_ERROR (Status);
  47. Status = FdtClient->FindCompatibleNodeReg (
  48. FdtClient,
  49. "xen,guest-acpi",
  50. (CONST VOID **)&Reg,
  51. &AddressCells,
  52. &SizeCells,
  53. &RegSize
  54. );
  55. if (EFI_ERROR (Status)) {
  56. DEBUG ((
  57. DEBUG_WARN,
  58. "%a: No 'xen,guest-acpi' compatible DT node found\n",
  59. __FUNCTION__
  60. ));
  61. return EFI_NOT_FOUND;
  62. }
  63. ASSERT (AddressCells == 2);
  64. ASSERT (SizeCells == 2);
  65. ASSERT (RegSize == 2 * sizeof (UINT64));
  66. RegBase = SwapBytes64 (Reg[0]);
  67. RsdpStructurePtr =
  68. (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)RegBase;
  69. if (RsdpStructurePtr && (RsdpStructurePtr->Revision >= 2)) {
  70. Sum = CalculateSum8 (
  71. (CONST UINT8 *)RsdpStructurePtr,
  72. sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
  73. );
  74. if (Sum != 0) {
  75. return EFI_ABORTED;
  76. }
  77. }
  78. *RsdpPtr = RsdpStructurePtr;
  79. return EFI_SUCCESS;
  80. }
  81. /**
  82. Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
  83. into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
  84. ACPI tables are: FACP, APIC, GTDT, DSDT.
  85. @param AcpiProtocol Protocol instance pointer.
  86. @return EFI_SUCCESS The table was successfully inserted.
  87. @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
  88. NULL, or AcpiTableBufferSize and the size
  89. field embedded in the ACPI table pointed to
  90. by AcpiTableBuffer are not in sync.
  91. @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
  92. **/
  93. STATIC
  94. EFI_STATUS
  95. EFIAPI
  96. InstallXenArmTables (
  97. IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
  98. )
  99. {
  100. EFI_STATUS Status;
  101. UINTN TableHandle;
  102. VOID *CurrentTableEntry;
  103. UINTN CurrentTablePointer;
  104. EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
  105. UINTN Index;
  106. UINTN NumberOfTableEntries;
  107. EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr;
  108. EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
  109. EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtTable;
  110. EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
  111. XenAcpiRsdpStructurePtr = NULL;
  112. FadtTable = NULL;
  113. DsdtTable = NULL;
  114. TableHandle = 0;
  115. NumberOfTableEntries = 0;
  116. //
  117. // Try to find Xen ARM ACPI tables
  118. //
  119. Status = GetXenArmAcpiRsdp (&XenAcpiRsdpStructurePtr);
  120. if (EFI_ERROR (Status)) {
  121. DEBUG ((DEBUG_INFO, "%a: No RSDP table found\n", __FUNCTION__));
  122. return Status;
  123. }
  124. //
  125. // If XSDT table is find, just install its tables.
  126. //
  127. if (XenAcpiRsdpStructurePtr->XsdtAddress) {
  128. //
  129. // Retrieve the addresses of XSDT and
  130. // calculate the number of its table entries.
  131. //
  132. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)
  133. XenAcpiRsdpStructurePtr->XsdtAddress;
  134. NumberOfTableEntries = (Xsdt->Length -
  135. sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
  136. sizeof (UINT64);
  137. //
  138. // Install ACPI tables found in XSDT.
  139. //
  140. for (Index = 0; Index < NumberOfTableEntries; Index++) {
  141. //
  142. // Get the table entry from XSDT
  143. //
  144. CurrentTableEntry = (VOID *)((UINT8 *)Xsdt +
  145. sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
  146. Index * sizeof (UINT64));
  147. CurrentTablePointer = (UINTN)*(UINT64 *)CurrentTableEntry;
  148. CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *)CurrentTablePointer;
  149. //
  150. // Install the XSDT tables
  151. //
  152. Status = AcpiProtocol->InstallAcpiTable (
  153. AcpiProtocol,
  154. CurrentTable,
  155. CurrentTable->Length,
  156. &TableHandle
  157. );
  158. if (EFI_ERROR (Status)) {
  159. return Status;
  160. }
  161. //
  162. // Get the FACS and DSDT table address from the table FADT
  163. //
  164. if (!AsciiStrnCmp ((CHAR8 *)&CurrentTable->Signature, "FACP", 4)) {
  165. FadtTable = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
  166. (UINTN)CurrentTablePointer;
  167. DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)FadtTable->Dsdt;
  168. }
  169. }
  170. }
  171. //
  172. // Install DSDT table.
  173. //
  174. Status = AcpiProtocol->InstallAcpiTable (
  175. AcpiProtocol,
  176. DsdtTable,
  177. DsdtTable->Length,
  178. &TableHandle
  179. );
  180. if (EFI_ERROR (Status)) {
  181. return Status;
  182. }
  183. return EFI_SUCCESS;
  184. }
  185. STATIC
  186. EFI_ACPI_TABLE_PROTOCOL *
  187. FindAcpiTableProtocol (
  188. VOID
  189. )
  190. {
  191. EFI_STATUS Status;
  192. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  193. AcpiTable = NULL;
  194. Status = gBS->LocateProtocol (
  195. &gEfiAcpiTableProtocolGuid,
  196. NULL,
  197. (VOID **)&AcpiTable
  198. );
  199. ASSERT_EFI_ERROR (Status);
  200. return AcpiTable;
  201. }
  202. /**
  203. Entrypoint of Xen ARM Acpi Platform driver.
  204. @param ImageHandle
  205. @param SystemTable
  206. @return EFI_SUCCESS
  207. @return EFI_LOAD_ERROR
  208. @return EFI_OUT_OF_RESOURCES
  209. **/
  210. EFI_STATUS
  211. EFIAPI
  212. XenAcpiPlatformEntryPoint (
  213. IN EFI_HANDLE ImageHandle,
  214. IN EFI_SYSTEM_TABLE *SystemTable
  215. )
  216. {
  217. EFI_STATUS Status;
  218. Status = InstallXenArmTables (FindAcpiTableProtocol ());
  219. return Status;
  220. }