Home | History | Annotate | Download | only in AcpiPlatformDxe
      1 /** @file
      2   OVMF ACPI Platform Driver
      3 
      4   Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "AcpiPlatform.h"
     16 
     17 EFI_STATUS
     18 EFIAPI
     19 InstallAcpiTable (
     20   IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
     21   IN   VOID                          *AcpiTableBuffer,
     22   IN   UINTN                         AcpiTableBufferSize,
     23   OUT  UINTN                         *TableKey
     24   )
     25 {
     26   return AcpiProtocol->InstallAcpiTable (
     27                          AcpiProtocol,
     28                          AcpiTableBuffer,
     29                          AcpiTableBufferSize,
     30                          TableKey
     31                          );
     32 }
     33 
     34 
     35 /**
     36   Locate the first instance of a protocol.  If the protocol requested is an
     37   FV protocol, then it will return the first FV that contains the ACPI table
     38   storage file.
     39 
     40   @param  Instance      Return pointer to the first instance of the protocol
     41 
     42   @return EFI_SUCCESS           The function completed successfully.
     43   @return EFI_NOT_FOUND         The protocol could not be located.
     44   @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
     45 
     46 **/
     47 EFI_STATUS
     48 LocateFvInstanceWithTables (
     49   OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
     50   )
     51 {
     52   EFI_STATUS                    Status;
     53   EFI_HANDLE                    *HandleBuffer;
     54   UINTN                         NumberOfHandles;
     55   EFI_FV_FILETYPE               FileType;
     56   UINT32                        FvStatus;
     57   EFI_FV_FILE_ATTRIBUTES        Attributes;
     58   UINTN                         Size;
     59   UINTN                         Index;
     60   EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
     61 
     62   FvStatus = 0;
     63 
     64   //
     65   // Locate protocol.
     66   //
     67   Status = gBS->LocateHandleBuffer (
     68                    ByProtocol,
     69                    &gEfiFirmwareVolume2ProtocolGuid,
     70                    NULL,
     71                    &NumberOfHandles,
     72                    &HandleBuffer
     73                    );
     74   if (EFI_ERROR (Status)) {
     75     //
     76     // Defined errors at this time are not found and out of resources.
     77     //
     78     return Status;
     79   }
     80 
     81   //
     82   // Looking for FV with ACPI storage file
     83   //
     84   for (Index = 0; Index < NumberOfHandles; Index++) {
     85     //
     86     // Get the protocol on this handle
     87     // This should not fail because of LocateHandleBuffer
     88     //
     89     Status = gBS->HandleProtocol (
     90                      HandleBuffer[Index],
     91                      &gEfiFirmwareVolume2ProtocolGuid,
     92                      (VOID**) &FvInstance
     93                      );
     94     ASSERT_EFI_ERROR (Status);
     95 
     96     //
     97     // See if it has the ACPI storage file
     98     //
     99     Status = FvInstance->ReadFile (
    100                            FvInstance,
    101                            (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
    102                            NULL,
    103                            &Size,
    104                            &FileType,
    105                            &Attributes,
    106                            &FvStatus
    107                            );
    108 
    109     //
    110     // If we found it, then we are done
    111     //
    112     if (Status == EFI_SUCCESS) {
    113       *Instance = FvInstance;
    114       break;
    115     }
    116   }
    117 
    118   //
    119   // Our exit status is determined by the success of the previous operations
    120   // If the protocol was found, Instance already points to it.
    121   //
    122 
    123   //
    124   // Free any allocated buffers
    125   //
    126   gBS->FreePool (HandleBuffer);
    127 
    128   return Status;
    129 }
    130 
    131 
    132 /**
    133   Find ACPI tables in an FV and install them.
    134 
    135   This is now a fall-back path. Normally, we will search for tables provided
    136   by the VMM first.
    137 
    138   If that fails, we use this function to load the ACPI tables from an FV. The
    139   sources for the FV based tables is located under OvmfPkg/AcpiTables.
    140 
    141   @param  AcpiTable     Protocol instance pointer
    142 
    143 **/
    144 EFI_STATUS
    145 EFIAPI
    146 InstallOvmfFvTables (
    147   IN  EFI_ACPI_TABLE_PROTOCOL     *AcpiTable
    148   )
    149 {
    150   EFI_STATUS                           Status;
    151   EFI_FIRMWARE_VOLUME2_PROTOCOL        *FwVol;
    152   INTN                                 Instance;
    153   EFI_ACPI_COMMON_HEADER               *CurrentTable;
    154   UINTN                                TableHandle;
    155   UINT32                               FvStatus;
    156   UINTN                                TableSize;
    157   UINTN                                Size;
    158   EFI_ACPI_TABLE_INSTALL_ACPI_TABLE    TableInstallFunction;
    159 
    160   Instance     = 0;
    161   CurrentTable = NULL;
    162   TableHandle  = 0;
    163 
    164   if (QemuDetected ()) {
    165     TableInstallFunction = QemuInstallAcpiTable;
    166   } else {
    167     TableInstallFunction = InstallAcpiTable;
    168   }
    169 
    170   //
    171   // Locate the firmware volume protocol
    172   //
    173   Status = LocateFvInstanceWithTables (&FwVol);
    174   if (EFI_ERROR (Status)) {
    175     return EFI_ABORTED;
    176   }
    177   //
    178   // Read tables from the storage file.
    179   //
    180   while (Status == EFI_SUCCESS) {
    181 
    182     Status = FwVol->ReadSection (
    183                       FwVol,
    184                       (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
    185                       EFI_SECTION_RAW,
    186                       Instance,
    187                       (VOID**) &CurrentTable,
    188                       &Size,
    189                       &FvStatus
    190                       );
    191     if (!EFI_ERROR (Status)) {
    192       //
    193       // Add the table
    194       //
    195       TableHandle = 0;
    196 
    197       TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
    198       ASSERT (Size >= TableSize);
    199 
    200       //
    201       // Install ACPI table
    202       //
    203       Status = TableInstallFunction (
    204                  AcpiTable,
    205                  CurrentTable,
    206                  TableSize,
    207                  &TableHandle
    208                  );
    209 
    210       //
    211       // Free memory allocated by ReadSection
    212       //
    213       gBS->FreePool (CurrentTable);
    214 
    215       if (EFI_ERROR (Status)) {
    216         return EFI_ABORTED;
    217       }
    218 
    219       //
    220       // Increment the instance
    221       //
    222       Instance++;
    223       CurrentTable = NULL;
    224     }
    225   }
    226 
    227   return EFI_SUCCESS;
    228 }
    229 
    230 /**
    231   Effective entrypoint of Acpi Platform driver.
    232 
    233   @param  ImageHandle
    234   @param  SystemTable
    235 
    236   @return EFI_SUCCESS
    237   @return EFI_LOAD_ERROR
    238   @return EFI_OUT_OF_RESOURCES
    239 
    240 **/
    241 EFI_STATUS
    242 EFIAPI
    243 InstallAcpiTables (
    244   IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiTable
    245   )
    246 {
    247   EFI_STATUS                         Status;
    248 
    249   if (XenDetected ()) {
    250     Status = InstallXenTables (AcpiTable);
    251   } else {
    252     Status = InstallQemuFwCfgTables (AcpiTable);
    253   }
    254 
    255   if (EFI_ERROR (Status)) {
    256     Status = InstallOvmfFvTables (AcpiTable);
    257   }
    258 
    259   return Status;
    260 }
    261 
    262