XenAcpiPlatformDxe.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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 (&gFdtClientProtocolGuid, NULL,
  42. (VOID **)&FdtClient);
  43. ASSERT_EFI_ERROR (Status);
  44. Status = FdtClient->FindCompatibleNodeReg (FdtClient, "xen,guest-acpi",
  45. (CONST VOID **)&Reg, &AddressCells, &SizeCells,
  46. &RegSize);
  47. if (EFI_ERROR (Status)) {
  48. DEBUG ((EFI_D_WARN, "%a: No 'xen,guest-acpi' compatible DT node found\n",
  49. __FUNCTION__));
  50. return EFI_NOT_FOUND;
  51. }
  52. ASSERT (AddressCells == 2);
  53. ASSERT (SizeCells == 2);
  54. ASSERT (RegSize == 2 * sizeof (UINT64));
  55. RegBase = SwapBytes64(Reg[0]);
  56. RsdpStructurePtr =
  57. (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)RegBase;
  58. if (RsdpStructurePtr && RsdpStructurePtr->Revision >= 2) {
  59. Sum = CalculateSum8 ((CONST UINT8 *)RsdpStructurePtr,
  60. sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER));
  61. if (Sum != 0) {
  62. return EFI_ABORTED;
  63. }
  64. }
  65. *RsdpPtr = RsdpStructurePtr;
  66. return EFI_SUCCESS;
  67. }
  68. /**
  69. Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
  70. into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
  71. ACPI tables are: FACP, APIC, GTDT, DSDT.
  72. @param AcpiProtocol Protocol instance pointer.
  73. @return EFI_SUCCESS The table was successfully inserted.
  74. @return EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, TableHandle is
  75. NULL, or AcpiTableBufferSize and the size
  76. field embedded in the ACPI table pointed to
  77. by AcpiTableBuffer are not in sync.
  78. @return EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the request.
  79. **/
  80. STATIC
  81. EFI_STATUS
  82. EFIAPI
  83. InstallXenArmTables (
  84. IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
  85. )
  86. {
  87. EFI_STATUS Status;
  88. UINTN TableHandle;
  89. VOID *CurrentTableEntry;
  90. UINTN CurrentTablePointer;
  91. EFI_ACPI_DESCRIPTION_HEADER *CurrentTable;
  92. UINTN Index;
  93. UINTN NumberOfTableEntries;
  94. EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *XenAcpiRsdpStructurePtr;
  95. EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
  96. EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtTable;
  97. EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
  98. XenAcpiRsdpStructurePtr = NULL;
  99. FadtTable = NULL;
  100. DsdtTable = NULL;
  101. TableHandle = 0;
  102. NumberOfTableEntries = 0;
  103. //
  104. // Try to find Xen ARM ACPI tables
  105. //
  106. Status = GetXenArmAcpiRsdp (&XenAcpiRsdpStructurePtr);
  107. if (EFI_ERROR (Status)) {
  108. DEBUG ((EFI_D_INFO, "%a: No RSDP table found\n", __FUNCTION__));
  109. return Status;
  110. }
  111. //
  112. // If XSDT table is find, just install its tables.
  113. //
  114. if (XenAcpiRsdpStructurePtr->XsdtAddress) {
  115. //
  116. // Retrieve the addresses of XSDT and
  117. // calculate the number of its table entries.
  118. //
  119. Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
  120. XenAcpiRsdpStructurePtr->XsdtAddress;
  121. NumberOfTableEntries = (Xsdt->Length -
  122. sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
  123. sizeof (UINT64);
  124. //
  125. // Install ACPI tables found in XSDT.
  126. //
  127. for (Index = 0; Index < NumberOfTableEntries; Index++) {
  128. //
  129. // Get the table entry from XSDT
  130. //
  131. CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +
  132. sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
  133. Index * sizeof (UINT64));
  134. CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry;
  135. CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
  136. //
  137. // Install the XSDT tables
  138. //
  139. Status = AcpiProtocol->InstallAcpiTable (
  140. AcpiProtocol,
  141. CurrentTable,
  142. CurrentTable->Length,
  143. &TableHandle
  144. );
  145. if (EFI_ERROR (Status)) {
  146. return Status;
  147. }
  148. //
  149. // Get the FACS and DSDT table address from the table FADT
  150. //
  151. if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
  152. FadtTable = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
  153. (UINTN) CurrentTablePointer;
  154. DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) FadtTable->Dsdt;
  155. }
  156. }
  157. }
  158. //
  159. // Install DSDT table.
  160. //
  161. Status = AcpiProtocol->InstallAcpiTable (
  162. AcpiProtocol,
  163. DsdtTable,
  164. DsdtTable->Length,
  165. &TableHandle
  166. );
  167. if (EFI_ERROR (Status)) {
  168. return Status;
  169. }
  170. return EFI_SUCCESS;
  171. }
  172. STATIC
  173. EFI_ACPI_TABLE_PROTOCOL *
  174. FindAcpiTableProtocol (
  175. VOID
  176. )
  177. {
  178. EFI_STATUS Status;
  179. EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
  180. AcpiTable = NULL;
  181. Status = gBS->LocateProtocol (
  182. &gEfiAcpiTableProtocolGuid,
  183. NULL,
  184. (VOID**)&AcpiTable
  185. );
  186. ASSERT_EFI_ERROR (Status);
  187. return AcpiTable;
  188. }
  189. /**
  190. Entrypoint of Xen ARM Acpi Platform driver.
  191. @param ImageHandle
  192. @param SystemTable
  193. @return EFI_SUCCESS
  194. @return EFI_LOAD_ERROR
  195. @return EFI_OUT_OF_RESOURCES
  196. **/
  197. EFI_STATUS
  198. EFIAPI
  199. XenAcpiPlatformEntryPoint (
  200. IN EFI_HANDLE ImageHandle,
  201. IN EFI_SYSTEM_TABLE *SystemTable
  202. )
  203. {
  204. EFI_STATUS Status;
  205. Status = InstallXenArmTables (FindAcpiTableProtocol ());
  206. return Status;
  207. }