blob: ff7d678433d5c8dfdd7ac346faf7535da33cb959 [file] [log] [blame]
/** @file
*
* Copyright (c) 2014-2015, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/
#include <Uefi.h>
#include <Library/AcpiLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/AcpiTable.h>
#include <Protocol/FirmwareVolume2.h>
#include <IndustryStandard/Acpi.h>
/**
Locate and Install the ACPI tables from the Firmware Volume if it verifies
the function condition.
@param AcpiFile Guid of the ACPI file into the Firmware Volume
@param CheckAcpiTableFunction Function that checks if the ACPI table should be installed
@return EFI_SUCCESS The function completed successfully.
@return EFI_NOT_FOUND The protocol could not be located.
@return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
**/
EFI_STATUS
LocateAndInstallAcpiFromFvConditional (
IN CONST EFI_GUID* AcpiFile,
IN EFI_LOCATE_ACPI_CHECK CheckAcpiTableFunction
)
{
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol;
EFI_HANDLE *HandleBuffer;
UINTN NumberOfHandles;
UINT32 FvStatus;
UINTN Index;
EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
INTN SectionInstance;
UINTN SectionSize;
EFI_ACPI_COMMON_HEADER *AcpiTable;
UINTN AcpiTableSize;
UINTN AcpiTableKey;
BOOLEAN Valid;
// Ensure the ACPI Table is present
Status = gBS->LocateProtocol (
&gEfiAcpiTableProtocolGuid,
NULL,
(VOID**)&AcpiProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
FvStatus = 0;
SectionInstance = 0;
// Locate all the Firmware Volume protocols.
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareVolume2ProtocolGuid,
NULL,
&NumberOfHandles,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return Status;
}
// Looking for FV with ACPI storage file
for (Index = 0; Index < NumberOfHandles; Index++) {
//
// Get the protocol on this handle
// This should not fail because of LocateHandleBuffer
//
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiFirmwareVolume2ProtocolGuid,
(VOID**) &FvInstance
);
if (EFI_ERROR (Status)) {
goto FREE_HANDLE_BUFFER;
}
while (Status == EFI_SUCCESS) {
// AcpiTable must be allocated by ReadSection (ie: AcpiTable == NULL)
AcpiTable = NULL;
// See if it has the ACPI storage file
Status = FvInstance->ReadSection (
FvInstance,
AcpiFile,
EFI_SECTION_RAW,
SectionInstance,
(VOID**) &AcpiTable,
&SectionSize,
&FvStatus
);
if (!EFI_ERROR (Status)) {
AcpiTableKey = 0;
AcpiTableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Length;
ASSERT (SectionSize >= AcpiTableSize);
DEBUG ((EFI_D_ERROR, "- Found '%c%c%c%c' ACPI Table\n",
(((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature & 0xFF),
((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 8) & 0xFF),
((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 16) & 0xFF),
((((EFI_ACPI_DESCRIPTION_HEADER *) AcpiTable)->Signature >> 24) & 0xFF)));
// Is the ACPI table valid?
if (CheckAcpiTableFunction) {
Valid = CheckAcpiTableFunction ((EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable);
} else {
Valid = TRUE;
}
// Install the ACPI Table
if (Valid) {
Status = AcpiProtocol->InstallAcpiTable (
AcpiProtocol,
AcpiTable,
AcpiTableSize,
&AcpiTableKey
);
}
// Free memory allocated by ReadSection
gBS->FreePool (AcpiTable);
if (EFI_ERROR (Status)) {
break;
}
// Increment the section instance
SectionInstance++;
}
}
}
FREE_HANDLE_BUFFER:
//
// Free any allocated buffers
//
gBS->FreePool (HandleBuffer);
return EFI_SUCCESS;
}
/**
Locate and Install the ACPI tables from the Firmware Volume
@param AcpiFile Guid of the ACPI file into the Firmware Volume
@return EFI_SUCCESS The function completed successfully.
@return EFI_NOT_FOUND The protocol could not be located.
@return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
**/
EFI_STATUS
LocateAndInstallAcpiFromFv (
IN CONST EFI_GUID* AcpiFile
)
{
return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL);
}