Home | History | Annotate | Download | only in AcpiLib
      1 /** @file
      2 *
      3 *  Copyright (c) 2014-2015, ARM Limited. All rights reserved.
      4 *
      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 <Uefi.h>
     16 
     17 #include <Library/AcpiLib.h>
     18 #include <Library/DebugLib.h>
     19 #include <Library/UefiBootServicesTableLib.h>
     20 
     21 #include <Protocol/AcpiTable.h>
     22 #include <Protocol/FirmwareVolume2.h>
     23 
     24 #include <IndustryStandard/Acpi.h>
     25 
     26 /**
     27   Locate and Install the ACPI tables from the Firmware Volume if it verifies
     28   the function condition.
     29 
     30   @param  AcpiFile                Guid of the ACPI file into the Firmware Volume
     31   @param  CheckAcpiTableFunction  Function that checks if the ACPI table should be installed
     32 
     33   @return EFI_SUCCESS             The function completed successfully.
     34   @return EFI_NOT_FOUND           The protocol could not be located.
     35   @return EFI_OUT_OF_RESOURCES    There are not enough resources to find the protocol.
     36 
     37 **/
     38 EFI_STATUS
     39 LocateAndInstallAcpiFromFvConditional (
     40   IN CONST EFI_GUID*        AcpiFile,
     41   IN EFI_LOCATE_ACPI_CHECK  CheckAcpiTableFunction
     42   )
     43 {
     44   EFI_STATUS                    Status;
     45   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol;
     46   EFI_HANDLE                    *HandleBuffer;
     47   UINTN                         NumberOfHandles;
     48   UINT32                        FvStatus;
     49   UINTN                         Index;
     50   EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
     51   INTN                          SectionInstance;
     52   UINTN                         SectionSize;
     53   EFI_ACPI_COMMON_HEADER       *AcpiTable;
     54   UINTN                         AcpiTableSize;
     55   UINTN                         AcpiTableKey;
     56   BOOLEAN                       Valid;
     57 
     58   // Ensure the ACPI Table is present
     59   Status = gBS->LocateProtocol (
     60                   &gEfiAcpiTableProtocolGuid,
     61                   NULL,
     62                   (VOID**)&AcpiProtocol
     63                   );
     64   if (EFI_ERROR (Status)) {
     65     return Status;
     66   }
     67 
     68   FvStatus        = 0;
     69   SectionInstance = 0;
     70 
     71   // Locate all the Firmware Volume protocols.
     72   Status = gBS->LocateHandleBuffer (
     73                    ByProtocol,
     74                    &gEfiFirmwareVolume2ProtocolGuid,
     75                    NULL,
     76                    &NumberOfHandles,
     77                    &HandleBuffer
     78                    );
     79   if (EFI_ERROR (Status)) {
     80     return Status;
     81   }
     82 
     83   // Looking for FV with ACPI storage file
     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     if (EFI_ERROR (Status)) {
     95       goto FREE_HANDLE_BUFFER;
     96     }
     97 
     98     while (Status == EFI_SUCCESS) {
     99       // AcpiTable must be allocated by ReadSection (ie: AcpiTable == NULL)
    100       AcpiTable = NULL;
    101 
    102       // See if it has the ACPI storage file
    103       Status = FvInstance->ReadSection (
    104                         FvInstance,
    105                         AcpiFile,
    106                         EFI_SECTION_RAW,
    107                         SectionInstance,
    108                         (VOID**) &AcpiTable,
    109                         &SectionSize,
    110                         &FvStatus
    111                         );
    112       if (!EFI_ERROR (Status)) {
    113         AcpiTableKey = 0;
    114         AcpiTableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Length;
    115         ASSERT (SectionSize >= AcpiTableSize);
    116 
    117         DEBUG ((EFI_D_ERROR, "- Found '%c%c%c%c' ACPI Table\n",
    118             (((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature & 0xFF),
    119             ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 8) & 0xFF),
    120             ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 16) & 0xFF),
    121             ((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 24) & 0xFF)));
    122 
    123         // Is the ACPI table valid?
    124         if (CheckAcpiTableFunction) {
    125           Valid = CheckAcpiTableFunction ((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable);
    126         } else {
    127           Valid = TRUE;
    128         }
    129 
    130         // Install the ACPI Table
    131         if (Valid) {
    132           Status = AcpiProtocol->InstallAcpiTable (
    133                                  AcpiProtocol,
    134                                  AcpiTable,
    135                                  AcpiTableSize,
    136                                  &AcpiTableKey
    137                                  );
    138         }
    139 
    140         // Free memory allocated by ReadSection
    141         gBS->FreePool (AcpiTable);
    142 
    143         if (EFI_ERROR (Status)) {
    144           break;
    145         }
    146 
    147         // Increment the section instance
    148         SectionInstance++;
    149       }
    150     }
    151   }
    152 
    153 FREE_HANDLE_BUFFER:
    154   //
    155   // Free any allocated buffers
    156   //
    157   gBS->FreePool (HandleBuffer);
    158 
    159   return EFI_SUCCESS;
    160 }
    161 
    162 /**
    163   Locate and Install the ACPI tables from the Firmware Volume
    164 
    165   @param  AcpiFile              Guid of the ACPI file into the Firmware Volume
    166 
    167   @return EFI_SUCCESS           The function completed successfully.
    168   @return EFI_NOT_FOUND         The protocol could not be located.
    169   @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
    170 
    171 **/
    172 EFI_STATUS
    173 LocateAndInstallAcpiFromFv (
    174   IN CONST EFI_GUID* AcpiFile
    175   )
    176 {
    177   return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL);
    178 }
    179