315 lines
8.5 KiB
C
315 lines
8.5 KiB
C
/** @file
|
|
ACPI Platform Driver
|
|
|
|
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials are licensed and made available under
|
|
the terms and conditions of the BSD License that accompanies this distribution.
|
|
The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <Base.h>
|
|
#include <Uefi.h>
|
|
#include <IndustryStandard/Acpi.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/PciLib.h>
|
|
#include <Library/BoardAcpiTableLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/AslUpdateLib.h>
|
|
|
|
#include <Protocol/PlatformNvsArea.h>
|
|
#include <Protocol/FirmwareVolume2.h>
|
|
#include <Protocol/AcpiTable.h>
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PLATFORM_NVS_AREA_PROTOCOL mPlatformNvsAreaProtocol;
|
|
|
|
/**
|
|
@brief
|
|
Global NVS initialize.
|
|
|
|
@param[in] PlatformNvsAreaPtr - Pointer of global NVS area
|
|
|
|
@retval EFI_SUCCESS - Allocate Global NVS completed.
|
|
@retval EFI_OUT_OF_RESOURCES - Failed to allocate required page for GNVS.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AcpiGnvsInit (
|
|
IN OUT VOID **PlatformNvsAreaPtr
|
|
);
|
|
|
|
VOID
|
|
UpdateDsdt (
|
|
IN VOID *Table
|
|
);
|
|
|
|
//
|
|
// Function implementations
|
|
//
|
|
|
|
/**
|
|
Locate the first instance of a protocol. If the protocol requested is an
|
|
FV protocol, then it will return the first FV that contains the ACPI table
|
|
storage file.
|
|
|
|
@param[in] Protocol The protocol to find.
|
|
@param[in] Instance Return pointer to the first instance of the protocol.
|
|
@param[in] Type TRUE if the desired protocol is a FV protocol.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_NOT_FOUND The protocol could not be located.
|
|
@retval EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
|
|
**/
|
|
EFI_STATUS
|
|
LocateSupportProtocol (
|
|
IN EFI_GUID *Protocol,
|
|
IN EFI_GUID *gEfiAcpiMultiTableStorageGuid,
|
|
OUT VOID **Instance,
|
|
IN BOOLEAN Type
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN NumberOfHandles;
|
|
EFI_FV_FILETYPE FileType;
|
|
UINT32 FvStatus;
|
|
EFI_FV_FILE_ATTRIBUTES Attributes;
|
|
UINTN Size;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Locate protocol.
|
|
//
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
Protocol,
|
|
NULL,
|
|
&NumberOfHandles,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Defined errors at this time are not found and out of resources.
|
|
//
|
|
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],
|
|
Protocol,
|
|
Instance
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (!Type) {
|
|
|
|
//
|
|
// Not looking for the FV protocol, so find the first instance of the
|
|
// protocol. There should not be any errors because our handle buffer
|
|
// should always contain at least one or LocateHandleBuffer would have
|
|
// returned not found.
|
|
//
|
|
break;
|
|
}
|
|
|
|
//
|
|
// See if it has the ACPI storage file
|
|
//
|
|
Size = 0;
|
|
FvStatus = 0;
|
|
Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile (
|
|
*Instance,
|
|
gEfiAcpiMultiTableStorageGuid,
|
|
NULL,
|
|
&Size,
|
|
&FileType,
|
|
&Attributes,
|
|
&FvStatus
|
|
);
|
|
|
|
//
|
|
// If we found it, then we are done
|
|
//
|
|
if (Status == EFI_SUCCESS) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Our exit status is determined by the success of the previous operations
|
|
// If the protocol was found, Instance already points to it.
|
|
//
|
|
//
|
|
// Free any allocated buffers
|
|
//
|
|
FreePool (HandleBuffer);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PublishAcpiTablesFromFv (
|
|
IN EFI_GUID *gEfiAcpiMultiTableStorageGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
|
|
EFI_ACPI_COMMON_HEADER *CurrentTable;
|
|
UINT32 FvStatus;
|
|
UINTN Size;
|
|
EFI_ACPI_TABLE_VERSION Version;
|
|
UINTN TableHandle;
|
|
INTN Instance;
|
|
EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
|
|
|
|
Instance = 0;
|
|
TableHandle = 0;
|
|
CurrentTable = NULL;
|
|
FwVol = NULL;
|
|
|
|
//
|
|
// Find the AcpiSupport protocol
|
|
//
|
|
Status = LocateSupportProtocol (
|
|
&gEfiAcpiTableProtocolGuid,
|
|
gEfiAcpiMultiTableStorageGuid,
|
|
(VOID **) &AcpiTable,
|
|
FALSE
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Locate the firmware volume protocol
|
|
//
|
|
Status = LocateSupportProtocol (
|
|
&gEfiFirmwareVolume2ProtocolGuid,
|
|
gEfiAcpiMultiTableStorageGuid,
|
|
(VOID **) &FwVol,
|
|
TRUE
|
|
);
|
|
|
|
//
|
|
// Read tables from the storage file.
|
|
//
|
|
|
|
while (Status == EFI_SUCCESS) {
|
|
Status = FwVol->ReadSection (
|
|
FwVol,
|
|
gEfiAcpiMultiTableStorageGuid,
|
|
EFI_SECTION_RAW,
|
|
Instance,
|
|
(VOID **) &CurrentTable,
|
|
&Size,
|
|
&FvStatus
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
//
|
|
// Perform any table specific updates.
|
|
//
|
|
if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
|
|
UpdateDsdt (CurrentTable);
|
|
}
|
|
BoardUpdateAcpiTable (CurrentTable, &Version);
|
|
|
|
//
|
|
// Add the table
|
|
//
|
|
TableHandle = 0;
|
|
|
|
if (Version != EFI_ACPI_TABLE_VERSION_NONE) {
|
|
Status = AcpiTable->InstallAcpiTable (
|
|
AcpiTable,
|
|
CurrentTable,
|
|
CurrentTable->Length,
|
|
&TableHandle
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
if (CurrentTable != NULL) {
|
|
gBS->FreePool (CurrentTable);
|
|
}
|
|
//
|
|
// Increment the instance
|
|
//
|
|
Instance++;
|
|
CurrentTable = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Finished
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
ACPI Platform driver installation function.
|
|
|
|
@param[in] ImageHandle Handle for this drivers loaded image protocol.
|
|
@param[in] SystemTable EFI system table.
|
|
|
|
@retval EFI_SUCCESS The driver installed without error.
|
|
@retval EFI_ABORTED The driver encountered an error and could not complete installation of
|
|
the ACPI tables.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InstallAcpiBoard (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
|
|
AcpiGnvsInit((VOID **) &mPlatformNvsAreaProtocol.Area);
|
|
|
|
//
|
|
// This PCD set must be done before PublishAcpiTablesFromFv.
|
|
// The PCD data will be used there.
|
|
//
|
|
PcdSet64S (PcdAcpiGnvsAddress, (UINT64)(UINTN)mPlatformNvsAreaProtocol.Area);
|
|
|
|
//
|
|
// Platform ACPI Tables
|
|
//
|
|
PublishAcpiTablesFromFv (&gEfiCallerIdGuid);
|
|
|
|
//
|
|
// This protocol publish must be done after PublishAcpiTablesFromFv.
|
|
// The NVS data is be updated there.
|
|
//
|
|
Handle = NULL;
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Handle,
|
|
&gPlatformNvsAreaProtocolGuid,
|
|
&mPlatformNvsAreaProtocol,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|