Home | History | Annotate | Download | only in AcpiPlatformDxe
      1 /** @file
      2   OVMF ACPI Xen support
      3 
      4   Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
      5   Copyright (c) 2012, Bei Guan <gbtju85 (at) gmail.com>
      6 
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "AcpiPlatform.h"
     18 #include <Library/HobLib.h>
     19 #include <Guid/XenInfo.h>
     20 #include <Library/BaseLib.h>
     21 
     22 #define XEN_ACPI_PHYSICAL_ADDRESS         0x000EA020
     23 #define XEN_BIOS_PHYSICAL_END             0x000FFFFF
     24 
     25 EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *XenAcpiRsdpStructurePtr = NULL;
     26 
     27 /**
     28   This function detects if OVMF is running on Xen.
     29 
     30 **/
     31 BOOLEAN
     32 XenDetected (
     33   VOID
     34   )
     35 {
     36   EFI_HOB_GUID_TYPE         *GuidHob;
     37 
     38   //
     39   // See if a XenInfo HOB is available
     40   //
     41   GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
     42   if (GuidHob == NULL) {
     43     return FALSE;
     44   }
     45 
     46   return TRUE;
     47 }
     48 
     49 /**
     50   Get the address of Xen ACPI Root System Description Pointer (RSDP)
     51   structure.
     52 
     53   @param  RsdpStructurePtr   Return pointer to RSDP structure
     54 
     55   @return EFI_SUCCESS        Find Xen RSDP structure successfully.
     56   @return EFI_NOT_FOUND      Don't find Xen RSDP structure.
     57   @return EFI_ABORTED        Find Xen RSDP structure, but it's not integrated.
     58 
     59 **/
     60 EFI_STATUS
     61 EFIAPI
     62 GetXenAcpiRsdp (
     63   OUT   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   **RsdpPtr
     64   )
     65 {
     66   EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER   *RsdpStructurePtr;
     67   UINT8                                          *XenAcpiPtr;
     68   UINT8                                          Sum;
     69 
     70   //
     71   // Detect the RSDP structure
     72   //
     73   for (XenAcpiPtr = (UINT8*)(UINTN) XEN_ACPI_PHYSICAL_ADDRESS;
     74        XenAcpiPtr < (UINT8*)(UINTN) XEN_BIOS_PHYSICAL_END;
     75        XenAcpiPtr += 0x10) {
     76 
     77     RsdpStructurePtr = (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)
     78                          (UINTN) XenAcpiPtr;
     79 
     80     if (!AsciiStrnCmp ((CHAR8 *) &RsdpStructurePtr->Signature, "RSD PTR ", 8)) {
     81       //
     82       // RSDP ACPI 1.0 checksum for 1.0/2.0/3.0 table.
     83       // This is only the first 20 bytes of the structure
     84       //
     85       Sum = CalculateSum8 (
     86               (CONST UINT8 *)RsdpStructurePtr,
     87               sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
     88               );
     89       if (Sum != 0) {
     90         return EFI_ABORTED;
     91       }
     92 
     93       if (RsdpStructurePtr->Revision >= 2) {
     94         //
     95         // RSDP ACPI 2.0/3.0 checksum, this is the entire table
     96         //
     97         Sum = CalculateSum8 (
     98                 (CONST UINT8 *)RsdpStructurePtr,
     99                 sizeof (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER)
    100                 );
    101         if (Sum != 0) {
    102           return EFI_ABORTED;
    103         }
    104       }
    105       *RsdpPtr = RsdpStructurePtr;
    106       return EFI_SUCCESS;
    107     }
    108   }
    109 
    110   return EFI_NOT_FOUND;
    111 }
    112 
    113 /**
    114   Get Xen Acpi tables from the RSDP structure. And installs Xen ACPI tables
    115   into the RSDT/XSDT using InstallAcpiTable. Some signature of the installed
    116   ACPI tables are: FACP, APIC, HPET, WAET, SSDT, FACS, DSDT.
    117 
    118   @param  AcpiProtocol           Protocol instance pointer.
    119 
    120   @return EFI_SUCCESS            The table was successfully inserted.
    121   @return EFI_INVALID_PARAMETER  Either AcpiTableBuffer is NULL, TableHandle is
    122                                  NULL, or AcpiTableBufferSize and the size
    123                                  field embedded in the ACPI table pointed to
    124                                  by AcpiTableBuffer are not in sync.
    125   @return EFI_OUT_OF_RESOURCES   Insufficient resources exist to complete the request.
    126 
    127 **/
    128 EFI_STATUS
    129 EFIAPI
    130 InstallXenTables (
    131   IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol
    132   )
    133 {
    134   EFI_STATUS                                       Status;
    135   UINTN                                            TableHandle;
    136 
    137   EFI_ACPI_DESCRIPTION_HEADER                      *Rsdt;
    138   EFI_ACPI_DESCRIPTION_HEADER                      *Xsdt;
    139   VOID                                             *CurrentTableEntry;
    140   UINTN                                            CurrentTablePointer;
    141   EFI_ACPI_DESCRIPTION_HEADER                      *CurrentTable;
    142   UINTN                                            Index;
    143   UINTN                                            NumberOfTableEntries;
    144   EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE        *Fadt2Table;
    145   EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE        *Fadt1Table;
    146   EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE     *Facs2Table;
    147   EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE     *Facs1Table;
    148   EFI_ACPI_DESCRIPTION_HEADER                      *DsdtTable;
    149 
    150   Fadt2Table  = NULL;
    151   Fadt1Table  = NULL;
    152   Facs2Table  = NULL;
    153   Facs1Table  = NULL;
    154   DsdtTable   = NULL;
    155   TableHandle = 0;
    156   NumberOfTableEntries = 0;
    157 
    158   //
    159   // Try to find Xen ACPI tables
    160   //
    161   Status = GetXenAcpiRsdp (&XenAcpiRsdpStructurePtr);
    162   if (EFI_ERROR (Status)) {
    163     return Status;
    164   }
    165 
    166   //
    167   // If XSDT table is find, just install its tables.
    168   // Otherwise, try to find and install the RSDT tables.
    169   //
    170   if (XenAcpiRsdpStructurePtr->XsdtAddress) {
    171     //
    172     // Retrieve the addresses of XSDT and
    173     // calculate the number of its table entries.
    174     //
    175     Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
    176              XenAcpiRsdpStructurePtr->XsdtAddress;
    177     NumberOfTableEntries = (Xsdt->Length -
    178                              sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
    179                              sizeof (UINT64);
    180 
    181     //
    182     // Install ACPI tables found in XSDT.
    183     //
    184     for (Index = 0; Index < NumberOfTableEntries; Index++) {
    185       //
    186       // Get the table entry from XSDT
    187       //
    188       CurrentTableEntry = (VOID *) ((UINT8 *) Xsdt +
    189                             sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
    190                             Index * sizeof (UINT64));
    191       CurrentTablePointer = (UINTN) *(UINT64 *)CurrentTableEntry;
    192       CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
    193 
    194       //
    195       // Install the XSDT tables
    196       //
    197       Status = InstallAcpiTable (
    198                  AcpiProtocol,
    199                  CurrentTable,
    200                  CurrentTable->Length,
    201                  &TableHandle
    202                  );
    203 
    204       if (EFI_ERROR (Status)) {
    205         return Status;
    206       }
    207 
    208       //
    209       // Get the FACS and DSDT table address from the table FADT
    210       //
    211       if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
    212         Fadt2Table = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *)
    213                        (UINTN) CurrentTablePointer;
    214         Facs2Table = (EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
    215                        (UINTN) Fadt2Table->FirmwareCtrl;
    216         DsdtTable  = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt2Table->Dsdt;
    217       }
    218     }
    219   }
    220   else if (XenAcpiRsdpStructurePtr->RsdtAddress) {
    221     //
    222     // Retrieve the addresses of RSDT and
    223     // calculate the number of its table entries.
    224     //
    225     Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)
    226              XenAcpiRsdpStructurePtr->RsdtAddress;
    227     NumberOfTableEntries = (Rsdt->Length -
    228                              sizeof (EFI_ACPI_DESCRIPTION_HEADER)) /
    229                              sizeof (UINT32);
    230 
    231     //
    232     // Install ACPI tables found in XSDT.
    233     //
    234     for (Index = 0; Index < NumberOfTableEntries; Index++) {
    235       //
    236       // Get the table entry from RSDT
    237       //
    238       CurrentTableEntry = (UINT32 *) ((UINT8 *) Rsdt +
    239                             sizeof (EFI_ACPI_DESCRIPTION_HEADER) +
    240                             Index * sizeof (UINT32));
    241       CurrentTablePointer = *(UINT32 *)CurrentTableEntry;
    242       CurrentTable = (EFI_ACPI_DESCRIPTION_HEADER *) CurrentTablePointer;
    243 
    244       //
    245       // Install the RSDT tables
    246       //
    247       Status = InstallAcpiTable (
    248                  AcpiProtocol,
    249                  CurrentTable,
    250                  CurrentTable->Length,
    251                  &TableHandle
    252                  );
    253 
    254       if (EFI_ERROR (Status)) {
    255         return Status;
    256       }
    257 
    258       //
    259       // Get the FACS and DSDT table address from the table FADT
    260       //
    261       if (!AsciiStrnCmp ((CHAR8 *) &CurrentTable->Signature, "FACP", 4)) {
    262         Fadt1Table = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *)
    263                        (UINTN) CurrentTablePointer;
    264         Facs1Table = (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)
    265                        (UINTN) Fadt1Table->FirmwareCtrl;
    266         DsdtTable  = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Fadt1Table->Dsdt;
    267       }
    268     }
    269   }
    270 
    271   //
    272   // Install the FACS table.
    273   //
    274   if (Fadt2Table) {
    275     //
    276     // FACS 2.0
    277     //
    278     Status = InstallAcpiTable (
    279                AcpiProtocol,
    280                Facs2Table,
    281                Facs2Table->Length,
    282                &TableHandle
    283                );
    284     if (EFI_ERROR (Status)) {
    285       return Status;
    286     }
    287   }
    288   else if (Fadt1Table) {
    289     //
    290     // FACS 1.0
    291     //
    292     Status = InstallAcpiTable (
    293                AcpiProtocol,
    294                Facs1Table,
    295                Facs1Table->Length,
    296                &TableHandle
    297                );
    298     if (EFI_ERROR (Status)) {
    299       return Status;
    300     }
    301   }
    302 
    303   //
    304   // Install DSDT table.
    305   //
    306   Status = InstallAcpiTable (
    307              AcpiProtocol,
    308              DsdtTable,
    309              DsdtTable->Length,
    310              &TableHandle
    311              );
    312   if (EFI_ERROR (Status)) {
    313     return Status;
    314   }
    315 
    316   return EFI_SUCCESS;
    317 }
    318 
    319