]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/AcpiPlatformDxe/Xen.c
BaseTools: Library hashing fix and optimization for --hash feature
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / Xen.c
index 4f4faeebbcaf3d282b16acb3e2e64b7a85bdde90..e4e47bf0e8626f9844d39fa8a4b197eb764c237e 100644 (file)
@@ -1,22 +1,27 @@
 /** @file\r
-  OVMF ACPI QEMU support\r
+  OVMF ACPI Xen support\r
 \r
   Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
+  Copyright (c) 2012, Bei Guan <gbtju85@gmail.com>\r
 \r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/ \r
 \r
 #include "AcpiPlatform.h"\r
 #include <Library/HobLib.h>\r
 #include <Guid/XenInfo.h>\r
+#include <Library/BaseLib.h>\r
 \r
+#define XEN_ACPI_PHYSICAL_ADDRESS         0x000EA020\r
+#define XEN_BIOS_PHYSICAL_END             0x000FFFFF\r
 \r
+EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *XenAcpiRsdpStructurePtr = NULL;\r
+\r
+/**\r
+  This function detects if OVMF is running on Xen.\r
+\r
+**/\r
 BOOLEAN\r
 XenDetected (\r
   VOID\r
@@ -35,21 +40,280 @@ XenDetected (
   return TRUE;\r
 }\r
 \r
+/**\r
+  Get the address of Xen ACPI Root System Description Pointer (RSDP)\r
+  structure.\r
+\r
+  @param  RsdpStructurePtr   Return pointer to RSDP structure\r
+\r
+  @return EFI_SUCCESS        Find Xen RSDP structure successfully.\r
+  @return EFI_NOT_FOUND      Don't find Xen RSDP structure.\r
+  @return EFI_ABORTED        Find Xen RSDP structure, but it's not integrated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetXenAcpiRsdp (\r
+  OUT   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   **RsdpPtr\r
+  )\r
+{\r
+  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *RsdpStructurePtr;\r
+  UINT8                                          *XenAcpiPtr;\r
+  UINT8                                          Sum;\r
+\r
+  //\r
+  // Detect the RSDP structure\r
+  //\r
+  for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;\r
+       XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;\r
+       XenAcpiPtr += 0x10) {\r
+\r
+    RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)\r
+                         (UINTN) XenAcpiPtr;\r
+\r
+    if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {\r
+      //\r
+      // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.\r
+      // This is only the first 20 bytes of the structure\r
+      //\r
+      Sum = CalculateSum8 (\r
+              (CONST UINT8 *)RsdpStructurePtr,\r
+              sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)\r
+              );\r
+      if (Sum != 0) {\r
+        return EFI_ABORTED;\r
+      }\r
+\r
+      if (RsdpStructurePtr->Revision >= 2) {\r
+        //\r
+        // RSDP ACPI 2.0/3.0 checksum, this is the entire table\r
+        //\r
+        Sum = CalculateSum8 (\r
+                (CONST UINT8 *)RsdpStructurePtr,\r
+                sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)\r
+                );\r
+        if (Sum != 0) {\r
+          return EFI_ABORTED;\r
+        }\r
+      }\r
+      *RsdpPtr = RsdpStructurePtr;\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables\r
+  into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed\r
+  ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.\r
+\r
+  @param  AcpiProtocol           Protocol instance pointer.\r
 \r
+  @return EFI_SUCCESS            The table was successfully inserted.\r
+  @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableHandle is\r
+                                 NULL, or AcpiTableBufferSize and the size\r
+                                 field embedded in the ACPI table pointed to\r
+                                 by AcpiTableBuffer are not in sync.\r
+  @return EFI_OUT_OF_RESOURCES   Insufficient resources exist to complete the request.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
-XenInstallAcpiTable (\r
-  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,\r
-  IN   VOID                          *AcpiTableBuffer,\r
-  IN   UINTN                         AcpiTableBufferSize,\r
-  OUT  UINTN                         *TableKey\r
+InstallXenTables (\r
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol\r
   )\r
 {\r
-  return InstallAcpiTable(\r
-           AcpiProtocol,\r
-           AcpiTableBuffer,\r
-           AcpiTableBufferSize,\r
-           TableKey\r
-           );\r
+  EFI_STATUS                                       Status;\r
+  UINTN                                            TableHandle;\r
+\r
+  EFI_ACPI_DESCRIPTION_HEADER                      *Rsdt;\r
+  EFI_ACPI_DESCRIPTION_HEADER                      *Xsdt;\r
+  VOID                                             *CurrentTableEntry;\r
+  UINTN                                            CurrentTablePointer;\r
+  EFI_ACPI_DESCRIPTION_HEADER                      *CurrentTable;\r
+  UINTN                                            Index;\r
+  UINTN                                            NumberOfTableEntries;\r
+  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE        *Fadt2Table;\r
+  EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE        *Fadt1Table;\r
+  EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE     *Facs2Table;\r
+  EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE     *Facs1Table;\r
+  EFI_ACPI_DESCRIPTION_HEADER                      *DsdtTable;\r
+\r
+  Fadt2Table  = NULL;\r
+  Fadt1Table  = NULL;\r
+  Facs2Table  = NULL;\r
+  Facs1Table  = NULL;\r
+  DsdtTable   = NULL;\r
+  TableHandle = 0;\r
+  NumberOfTableEntries = 0;\r
+\r
+  //\r
+  // Try to find Xen ACPI tables\r
+  //\r
+  Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // If XSDT table is find, just install its tables. \r
+  // Otherwise, try to find and install the RSDT tables.\r
+  //\r
+  if (XenAcpiRsdpStructurePtr->XsdtAddress) {\r
+    //\r
+    // Retrieve the addresses of XSDT and \r
+    // calculate the number of its table entries.\r
+    //\r
+    Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)\r
+             XenAcpiRsdpStructurePtr->XsdtAddress;\r
+    NumberOfTableEntries = (Xsdt->Length -\r
+                             sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /\r
+                             sizeof (UINT64);\r
+\r
+    //\r
+    // Install ACPI tables found in XSDT.\r
+    //\r
+    for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
+      //\r
+      // Get the table entry from XSDT\r
+      //\r
+      CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +\r
+                            sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+                            Index * sizeof (UINT64));\r
+      CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry;\r
+      CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;\r
+\r
+      //\r
+      // Install the XSDT tables\r
+      //\r
+      Status = InstallAcpiTable (\r
+                 AcpiProtocol,\r
+                 CurrentTable,\r
+                 CurrentTable->Length,\r
+                 &TableHandle\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Get the FACS and DSDT table address from the table FADT\r
+      //\r
+      if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {\r
+        Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)\r
+                       (UINTN) CurrentTablePointer;\r
+        Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)\r
+                       (UINTN) Fadt2Table->FirmwareCtrl;\r
+        DsdtTable  = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt2Table->Dsdt;\r
+      }\r
+    }\r
+  }\r
+  else if (XenAcpiRsdpStructurePtr->RsdtAddress) {\r
+    //\r
+    // Retrieve the addresses of RSDT and\r
+    // calculate the number of its table entries.\r
+    //\r
+    Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)\r
+             XenAcpiRsdpStructurePtr->RsdtAddress;\r
+    NumberOfTableEntries = (Rsdt->Length -\r
+                             sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / \r
+                             sizeof (UINT32);\r
+\r
+    //\r
+    // Install ACPI tables found in XSDT.\r
+    //\r
+    for (Index = 0; Index < NumberOfTableEntries; Index++) {\r
+      //\r
+      // Get the table entry from RSDT\r
+      //\r
+      CurrentTableEntry = (UINT32 *) ((UINT8 *) Rsdt +\r
+                            sizeof (EFI_ACPI_DESCRIPTION_HEADER) +\r
+                            Index * sizeof (UINT32));\r
+      CurrentTablePointer = *(UINT32 *)CurrentTableEntry;\r
+      CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;\r
+\r
+      //\r
+      // Install the RSDT tables\r
+      //\r
+      Status = InstallAcpiTable (\r
+                 AcpiProtocol,\r
+                 CurrentTable,\r
+                 CurrentTable->Length,\r
+                 &TableHandle\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      //\r
+      // Get the FACS and DSDT table address from the table FADT\r
+      //\r
+      if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {\r
+        Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)\r
+                       (UINTN) CurrentTablePointer;\r
+        Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)\r
+                       (UINTN) Fadt1Table->FirmwareCtrl;\r
+        DsdtTable  = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt1Table->Dsdt;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Install the FACS table.\r
+  //\r
+  if (Fadt2Table) {\r
+    //\r
+    // FACS 2.0\r
+    //\r
+    Status = InstallAcpiTable (\r
+               AcpiProtocol,\r
+               Facs2Table,\r
+               Facs2Table->Length,\r
+               &TableHandle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+  else if (Fadt1Table) {\r
+    //\r
+    // FACS 1.0\r
+    //\r
+    Status = InstallAcpiTable (\r
+               AcpiProtocol,\r
+               Facs1Table,\r
+               Facs1Table->Length,\r
+               &TableHandle\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Install DSDT table. If we reached this point without finding the DSDT,\r
+  // then we're out of sync with the hypervisor, and cannot continue.\r
+  //\r
+  if (DsdtTable == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "%a: no DSDT found\n", __FUNCTION__));\r
+    ASSERT (FALSE);\r
+    CpuDeadLoop ();\r
+  }\r
+\r
+  Status = InstallAcpiTable (\r
+             AcpiProtocol,\r
+             DsdtTable,\r
+             DsdtTable->Length,\r
+             &TableHandle\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r