Files
slimbootloader/BootloaderCorePkg/Library/AcpiInitLib/AcpiInitLib.c
T
Raghava Gudla 76ab33cc94 Skip updating FWST table with csme driver info.
CSME driver is not a component rather it is a driver to
update CSME binary, so it is not required to update status
of the driver to FWST ACPI table.

As part of the above change, gCsmeFWUDriverImageFileGuid is
moved from PayloadPkg.dec to bootloadercommonpkg.dec

Signed-off-by: Raghava Gudla <raghava.gudla@intel.com>
2019-12-19 14:51:41 -07:00

746 lines
24 KiB
C

/** @file
Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/SocInitLib.h>
#include <Library/BoardInitLib.h>
#include <Library/AcpiInitLib.h>
#include <Library/DebugDataLib.h>
#include <Library/AcpiInitLib.h>
#include <Service/PlatformService.h>
#include <IndustryStandard/Acpi.h>
#include <IndustryStandard/HighPrecisionEventTimerTable.h>
#include <IndustryStandard/AcpiAml.h>
#include <Mcfg.h>
#include <Library/DebugDataLib.h>
#include <Library/MpInitLib.h>
#include <Library/FirmwareUpdateLib.h>
#include <Guid/BootLoaderVersionGuid.h>
#define ACPI_ALIGN() (Current = (UINT8 *)ALIGN_POINTER (Current, 0x10))
#define ACPI_ALIGN_PAGE() (Current = (UINT8 *)ALIGN_POINTER (Current, 0x1000))
#define EFI_ACPI_OEM_ID {'O','E','M','I','D',' '} // OEMID 6 bytes long
#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('O','E','M','T','A','B','L','E') // OEM table id 8 bytes long
#define EFI_ACPI_OEM_REVISION 0x00000005
#define EFI_ACPI_CREATOR_ID SIGNATURE_32('C','R','E','A')
#define EFI_ACPI_CREATOR_REVISION 0x0100000D
#define ACPI_SKIP 0
#define ACPI_APPEND 1
#define ACPI_REPLACE 2
extern UINT32 WakeUpBuffer;
extern CHAR8 WakeUp;
extern UINT32 WakeUpSize;
typedef struct {
UINT8 Type;
UINT8 Length;
} EFI_ACPI_MADT_ENTRY_COMMON_HEADER;
/**
Update Firmware Performance Data Table (FPDT).
@param[in] Table Pointer of ACPI FPDT Table.
@retval EFI_SUCCESS Update ACPI FPDT table successfully.
@retval Others Failed to update FPDT table.
**/
EFI_STATUS
UpdateFpdt (
IN VOID *Table
);
const EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER RsdpTmp = {
.Signature = EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE,
.Checksum = 0,
.OemId = EFI_ACPI_OEM_ID,
.Revision = EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION,
.Length = sizeof (EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER),
.ExtendedChecksum = 0,
.Reserved = {0, 0, 0}
};
const EFI_ACPI_DESCRIPTION_HEADER XsdtTmp = {
.Signature = EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
.Checksum = 0,
.Length = 0,
.Revision = EFI_ACPI_5_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION,
.OemId = EFI_ACPI_OEM_ID,
.OemTableId = EFI_ACPI_OEM_TABLE_ID,
.OemRevision = EFI_ACPI_OEM_REVISION,
.CreatorId = EFI_ACPI_CREATOR_ID,
.CreatorRevision = EFI_ACPI_CREATOR_REVISION
};
/**
This function calculates and updates an UINT8 checksum.
@param[in] Buffer Pointer to buffer to checksum
@param[in] Size Number of bytes to checksum
**/
VOID
AcpiPlatformChecksum (
IN UINT8 *Buffer,
IN UINTN Size
)
{
UINTN ChecksumOffset;
ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);
//
// Set checksum to 0 first
//
Buffer[ChecksumOffset] = 0;
//
// Update checksum value
//
Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);
}
/**
This function updates GNVS data structure base address dynamically.
@param[in] Dsdt Pointer to DSDT table
@param[in] GnvsBase Physical address of the GNVS data structure
**/
VOID
UpdateAcpiGnvs (
IN EFI_ACPI_DESCRIPTION_HEADER *Dsdt,
IN UINT32 GnvsBase
)
{
UINT8 *Ptr;
UINT8 *End;
Ptr = (UINT8 *)Dsdt;
End = (UINT8 *)Dsdt + Dsdt->Length;
/*
* Loop through the ASL looking for values that we must fix up.
*/
for (; Ptr < End; Ptr++) {
if (* (UINT32 *)Ptr != SIGNATURE_32 ('G', 'N', 'V', 'S')) {
continue;
}
if (* (Ptr - 1) != AML_EXT_REGION_OP) {
continue;
}
* (UINT32 *) (Ptr + 6) = GnvsBase;
* (UINT16 *) (Ptr + 11) = (UINT16)GetAcpiGnvsSize();
break;
}
}
/**
Update ACPI tables using the new table provided.
@param[in] Rsdt ACPI table RSDT pointer.
@param[in] Signature ACPI table signature to find.
@param[in] EntryIndex Address to receive the entry index if found.
@retval ACPI table pointer if found. And EntryIndex is updated.
NULL if not found.
**/
EFI_ACPI_DESCRIPTION_HEADER *
FindAcpiTableBySignature (
IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt,
IN UINT32 Signature,
IN UINT32 *EntryIndex OPTIONAL
)
{
EFI_ACPI_DESCRIPTION_HEADER *CurrHdr;
UINT32 *RsdtEntry;
UINT32 EntryNum;
UINT32 Index;
RsdtEntry = (UINT32 *) ((UINT8 *)Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
EntryNum = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT32);
for (Index = 0; Index < EntryNum; Index++) {
CurrHdr = (EFI_ACPI_DESCRIPTION_HEADER *)RsdtEntry[Index];
if ((CurrHdr != NULL) && (CurrHdr->Signature == Signature)) {
if (EntryIndex != NULL) {
*EntryIndex = Index;
}
return CurrHdr;
}
}
return NULL;
}
/**
Update ACPI tables using the new table provided.
@param[in] AcpiTable ACPI table address to update.
@param[in] Length ACPI table buffer length.
@retval EFI_SUCCESS Read success
@retval EFI_INVALID_PARAMETER Invalid region type given
@retval EFI_UNSUPPORTED Not supported
@retval EFI_ABORTED Error occrued
**/
EFI_STATUS
AcpiTableUpdate (
IN UINT8 *AcpiTable,
IN UINT32 Length
)
{
EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Facp;
EFI_ACPI_DESCRIPTION_HEADER *AcpiHdr;
UINT8 *Current;
UINT8 *Previous;
UINT32 *RsdtEntry;
UINT64 *XsdtEntry;
UINT32 EntryIndex;
UINT32 Policy;
UINT32 Size;
UINT32 EntryNum;
EFI_STATUS Status;
LOADER_GLOBAL_DATA *LdrGlobal;
S3_DATA *S3Data;
UINT32 AcpiMax;
if ((AcpiTable == NULL) || (Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER))) {
return EFI_INVALID_PARAMETER;
}
Rsdp = (EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)PcdGet32 (PcdAcpiTablesRsdp);
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->RsdtAddress;
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)Rsdp->XsdtAddress;
RsdtEntry = (UINT32 *) ((UINT8 *)Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
XsdtEntry = (UINT64 *) ((UINT8 *)Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
EntryNum = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT32);
LdrGlobal = (LOADER_GLOBAL_DATA *)GetLoaderGlobalDataPointer();
S3Data = (S3_DATA *)LdrGlobal->S3DataPtr;
Current = (UINT8 *)S3Data->AcpiTop;
AcpiMax = S3Data->AcpiBase + PcdGet32 (PcdLoaderAcpiReclaimSize);
Status = EFI_SUCCESS;
Size = 0;
while (Size < Length) {
AcpiHdr = (EFI_ACPI_DESCRIPTION_HEADER *)(AcpiTable + Size);
//
// Verify Checksum
//
if (CalculateSum8 ((UINT8 *)AcpiHdr, AcpiHdr->Length) != 0) {
Status = EFI_ABORTED;
break;
}
if (Size + AcpiHdr->Length > Size) {
Size += AcpiHdr->Length;
} else {
Status = EFI_ABORTED;
break;
}
// Determine policy
Previous = Current;
ACPI_ALIGN ();
if (((UINT32)Current + AcpiHdr->Length) > AcpiMax) {
Status = EFI_OUT_OF_RESOURCES;
break;
}
CopyMem (Current, AcpiHdr, AcpiHdr->Length);
// Update the ACPI header to pointer to the new copy
// And then update the table if required
AcpiHdr = (EFI_ACPI_DESCRIPTION_HEADER *)Current;
Status = PlatformUpdateAcpiTable (Current);
if (Status != EFI_SUCCESS) {
Current = Previous;
continue;
}
DEBUG ((DEBUG_INFO, "ACPI Table 0x%08X - ", AcpiHdr->Signature));
if (AcpiHdr->Signature == EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
Facp = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)FindAcpiTableBySignature (
Rsdt, EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, &EntryIndex);
if (Facp != NULL) {
DEBUG ((DEBUG_INFO, "Replaced\n"));
Facp->Dsdt = (UINT32)(UINTN)AcpiHdr;
Facp->XDsdt = (UINT64)(UINTN)AcpiHdr;
AcpiPlatformChecksum ((UINT8 *)Facp, Facp->Header.Length);
UpdateAcpiGnvs (AcpiHdr, PcdGet32 (PcdAcpiGnvsAddress));
} else {
Status = EFI_ABORTED;
break;
}
} else {
Policy = ACPI_APPEND;
if ( (AcpiHdr->Signature == SIGNATURE_32 ('$', 'V', 'B', 'T')) ||
(AcpiHdr->Signature != EFI_ACPI_5_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) ) {
// Try to find the table
if (FindAcpiTableBySignature (Rsdt, AcpiHdr->Signature, &EntryIndex) != NULL) {
Policy = ACPI_REPLACE;
}
}
if (Policy == ACPI_APPEND) {
DEBUG ((DEBUG_INFO, "Appended\n"));
RsdtEntry [EntryNum] = (UINT32)(UINTN)AcpiHdr;
XsdtEntry [EntryNum] = (UINT32)(UINTN)AcpiHdr;
EntryNum++;
if (EntryNum > PcdGet32 (PcdAcpiTablesMaxEntry)) {
Status = EFI_OUT_OF_RESOURCES;
break;
}
} else if (Policy == ACPI_REPLACE) {
DEBUG ((DEBUG_INFO, "Replaced\n"));
RsdtEntry [EntryIndex] = (UINT32)(UINTN)AcpiHdr;
XsdtEntry [EntryIndex] = (UINT32)(UINTN)AcpiHdr;
}
}
AcpiPlatformChecksum ((UINT8 *)AcpiHdr, AcpiHdr->Length);
Current += AcpiHdr->Length;
}
//
// Check ACPI memory range again since a Table length may increase in hook
//
if ((UINT32)Current > AcpiMax) {
Status = EFI_OUT_OF_RESOURCES;
}
Rsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EntryNum * sizeof (UINT32);
AcpiPlatformChecksum ((UINT8 *)Rsdt, Rsdt->Length);
Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + EntryNum * sizeof (UINT64);
AcpiPlatformChecksum ((UINT8 *)Xsdt, Xsdt->Length);
//
// Update AcpiTop for gLoaderSystemTableInfoGuid
//
S3Data->AcpiTop = (UINT32)(UINTN)Current;
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Acpi update failed - %r\n", Status));
}
return Status;
}
/**
This function updates MADT data structure based on Sysinfo APICID
for number of active cores dynamically.
@param[in] Current Pointer to MADT table
@retval EFI_SUCCESS Patched the MADT
EFI_UNSUPPORTED Sysinfo table not found.
EFI_OUT_OF_RESOURCES If less MADT entries
**/
EFI_STATUS
UpdateMadt (
IN UINT8 *Current
)
{
EFI_ACPI_DESCRIPTION_HEADER *Table;
UINT8 *TempMadt;
UINT8 *MadtPtr;
UINT8 *MadtEnd;
EFI_ACPI_MADT_ENTRY_COMMON_HEADER *EntryHeader;
EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
SYS_CPU_INFO *SysCpuInfo;
UINT32 Length;
UINT32 Index;
//
// Get the number of detected CPUs
//
SysCpuInfo = MpGetInfo ();
if ((SysCpuInfo == NULL) || (SysCpuInfo->CpuCount == 0)) {
return EFI_ABORTED;
}
Table = (EFI_ACPI_DESCRIPTION_HEADER *)Current;
//
// Copy original MADT
//
TempMadt = (UINT8 *)AllocateTemporaryMemory (0);
CopyMem ((VOID *)TempMadt, (VOID *)Table, Table->Length);
MadtPtr = TempMadt;
MadtEnd = MadtPtr + Table->Length;
//
// Copy MADT Header
//
Length = sizeof (EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER);
CopyMem ((VOID *)Current, (VOID *)MadtPtr, Length);
MadtPtr += Length;
Current += Length;
//
// Append Processor Local APIC info
//
LocalApic = (EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE *)Current;
for (Index = 0; Index < SysCpuInfo->CpuCount; Index++) {
LocalApic[Index].Type = EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC;
LocalApic[Index].Length = sizeof (EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE);
//
// ProcessorId and ApicId has sizeof (UINT8).
//
LocalApic[Index].AcpiProcessorId = (UINT8)Index + 1;
LocalApic[Index].ApicId = (UINT8)SysCpuInfo->CpuInfo[Index].ApicId;
LocalApic[Index].Flags = 1;
}
Length = sizeof (EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC_STRUCTURE) * SysCpuInfo->CpuCount;
Current += Length;
//
// Copy rest of MADT entries
//
while (MadtPtr < MadtEnd) {
EntryHeader = (EFI_ACPI_MADT_ENTRY_COMMON_HEADER *)MadtPtr;
Length = EntryHeader->Length;
if (EntryHeader->Type != EFI_ACPI_5_0_PROCESSOR_LOCAL_APIC) {
CopyMem ((VOID *)Current, (VOID *)MadtPtr, Length);
Current += Length;
}
MadtPtr += Length;
}
//
// Update Table Length
//
Length = Current - (UINT8 *)Table;
Table->Length = Length;
return EFI_SUCCESS;
}
/**
This function updates FWST ACPI data structure.
@param[in] Current Pointer to FWST table
@retval EFI_SUCCESS Patched the FWST
EFI_NOT_FOUND Reserved region component information not found.
**/
EFI_STATUS
UpdateFwst (
IN UINT8 *Current
)
{
UINT8 Count;
UINT32 RsvdBase;
EFI_STATUS Status;
EFI_FWST_ACPI_DESCRIPTION_TABLE *FwstAcpiTablePtr;
FW_UPDATE_COMP_STATUS *FwUpdCompStatus;
//
// We do not need to populate ACPI table during firmware update
//
if (GetBootMode () == BOOT_ON_FLASH_UPDATE) {
return EFI_SUCCESS;
}
//
// Get bootloader reserved region base
//
Status = GetComponentInfo (FLASH_MAP_SIG_BLRESERVED, &RsvdBase, NULL);
if (EFI_ERROR(Status)) {
DEBUG((DEBUG_ERROR, "Could not get reserved region base\n"));
return Status;
}
//
// Fill in details for FWST ACPI table
//
FwstAcpiTablePtr = (EFI_FWST_ACPI_DESCRIPTION_TABLE *)Current;
FwUpdCompStatus = (FW_UPDATE_COMP_STATUS *)(RsvdBase + sizeof(FW_UPDATE_STATUS));
for (Count = 0; Count < MAX_FW_COMPONENTS; Count ++) {
if (!CompareGuid(&FwUpdCompStatus->FirmwareId, &gCsmeFWUDriverImageFileGuid)) {
CopyMem(&(FwstAcpiTablePtr->EsrtTableEntry[Count].FwClass), &(FwUpdCompStatus->FirmwareId), sizeof(EFI_GUID));
FwstAcpiTablePtr->EsrtTableEntry[Count].FwType = ESRT_FW_TYPE_SYSTEMFIRMWARE;
FwstAcpiTablePtr->EsrtTableEntry[Count].LastAttemptVersion = FwUpdCompStatus->LastAttemptVersion;
FwstAcpiTablePtr->EsrtTableEntry[Count].LastAttemptStatus = FwUpdCompStatus->LastAttemptStatus;
}
FwUpdCompStatus = (FW_UPDATE_COMP_STATUS *)((UINT32)FwUpdCompStatus + sizeof(FW_UPDATE_COMP_STATUS));
}
return EFI_SUCCESS;
}
/**
This function creates necessary ACPI tables and puts the RSDP
table in F segment so that OS can locate it.
@param[in] AcpiMemTop ACPI memory top address.
@retval EFI_SUCCESS ACPI tables are created successfully.
EFI_NOT_FOUND Required ACPI tables could not be found.
EFI_UNSUPPORTED Sysinfo table not found.
**/
EFI_STATUS
EFIAPI
AcpiInit (
IN UINT32 *AcpiMemBase
)
{
UINT8 *TblPtr;
UINT8 *EndPtr;
EFI_ACPI_COMMON_HEADER *Table;
UINT8 *Current;
UINT8 *Previous;
EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Facp;
EFI_ACPI_DESCRIPTION_HEADER *Dsdt;
EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *Mcfg;
PLATFORM_SERVICE *PlatformService;
UINT32 *RsdtEntry;
UINT64 *XsdtEntry;
UINT32 TotalSize;
UINT32 XsdtIndex;
UINT32 SectionLen;
UINT32 UpdateRdstXsdt;
EFI_STATUS Status;
Facs = NULL;
Dsdt = NULL;
Facp = NULL;
UpdateRdstXsdt = 0;
Current = (UINT8 *)(*AcpiMemBase);
//
// Create RSDP
//
Rsdp = (EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) ACPI_ALIGN_PAGE ();
CopyMem (Rsdp, &RsdpTmp, sizeof (RsdpTmp));
TotalSize = sizeof (EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
Current += TotalSize;
//
// Create RSDT structures and allocate buffers.
//
Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) ACPI_ALIGN ();
CopyMem (Rsdt, &XsdtTmp, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
Rsdt->Signature = EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE;
Rsdt->Revision = EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION;
RsdtEntry = (UINT32 *) ((UINT8 *)Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
SetMem (RsdtEntry, PcdGet32 (PcdAcpiTablesMaxEntry) * sizeof (UINT32), 0);
TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + PcdGet32 (PcdAcpiTablesMaxEntry) * sizeof (UINT32);
Current += TotalSize;
//
// Create XSDT structures and allocate buffers.
//
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) ACPI_ALIGN ();
CopyMem (Xsdt, &XsdtTmp, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
XsdtEntry = (UINT64 *) ((UINT8 *)Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
XsdtIndex = 0;
SetMem (XsdtEntry, PcdGet32 (PcdAcpiTablesMaxEntry) * sizeof (UINT64), 0);
TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + PcdGet32 (PcdAcpiTablesMaxEntry) * sizeof (UINT64);
Current += TotalSize;
TblPtr = (UINT8 *)PcdGet32 (PcdAcpiTablesAddress);
EndPtr = TblPtr + ((* ((UINT32 *) (TblPtr - 8)) & 0xFFFFFF) - 28);
while (TblPtr < EndPtr) {
Previous = Current;
Table = (EFI_ACPI_COMMON_HEADER *)TblPtr;
ACPI_ALIGN ();
CopyMem (Current, Table, Table->Length);
Status = PlatformUpdateAcpiTable (Current);
if (Status != EFI_SUCCESS) {
Current = Previous;
DEBUG ((DEBUG_WARN, "Not adding ACPI table \n"));
SectionLen = * (UINT32 *) (TblPtr - 4) & 0x00FFFFFF;
TblPtr = TblPtr + ((SectionLen + 3) & ~3);
continue;
}
UpdateRdstXsdt = 1;
switch (Table->Signature) {
case EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
// FACP
Facp = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *)Current;
break;
case EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
// FACS
Facs = (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)Current;
UpdateRdstXsdt = 0;
break;
case EFI_ACPI_5_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
// DSDT
Dsdt = (EFI_ACPI_DESCRIPTION_HEADER *)Current;
UpdateAcpiGnvs (Dsdt, PcdGet32 (PcdAcpiGnvsAddress));
UpdateRdstXsdt = 0;
break;
case EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
// MCFG
Mcfg = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE *)Current;
Mcfg->Segment.BaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
break;
case EFI_ACPI_5_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
// MADT
Status = UpdateMadt (Current);
if (Status != EFI_SUCCESS) {
return Status;
}
break;
case EFI_ACPI_5_0_FIRMWARE_PERFORMANCE_DATA_TABLE_SIGNATURE:
// FPDT
Status = UpdateFpdt (Current);
if (Status != EFI_SUCCESS) {
return Status;
}
break;
case EFI_FIRMWARE_UPDATE_STATUS_TABLE_SIGNATURE:
// FWST
Status = UpdateFwst (Current);
if (Status != EFI_SUCCESS) {
return Status;
}
break;
default:
// Misc
break;
}
if (UpdateRdstXsdt == 1) {
RsdtEntry[XsdtIndex] = (UINT32) (UINTN)Current;
XsdtEntry[XsdtIndex++] = (UINT64) (UINTN)Current;
}
ASSERT (XsdtIndex < PcdGet32 (PcdAcpiTablesMaxEntry));
if (Current != (UINT8 *)Facp) {
AcpiPlatformChecksum (
Current,
((EFI_ACPI_COMMON_HEADER *)Current)->Length
);
}
SectionLen = * (UINT32 *) (TblPtr - 4) & 0x00FFFFFF;
TblPtr = TblPtr + ((SectionLen + 3) & ~3);
TotalSize = ((EFI_ACPI_COMMON_HEADER *)Current)->Length;
Current += TotalSize;
}
if (Facp == NULL || Facs == NULL || Dsdt == NULL) {
return EFI_NOT_FOUND;
}
Facp->FirmwareCtrl = (UINT32)(UINTN)Facs;
Facp->XFirmwareCtrl = (UINT64)(UINTN)Facs;
Facp->Dsdt = (UINT32)(UINTN)Dsdt;
Facp->XDsdt = (UINT64)(UINTN)Dsdt;
AcpiPlatformChecksum ((UINT8 *)Facp, Facp->Header.Length);
Rsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + XsdtIndex * sizeof (UINT32);
AcpiPlatformChecksum ((UINT8 *)Rsdt, Rsdt->Length);
Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + XsdtIndex * sizeof (UINT64);
AcpiPlatformChecksum ((UINT8 *)Xsdt, Xsdt->Length);
//
// Update RSDP
//
Rsdp->RsdtAddress = (UINT32)Rsdt;
Rsdp->XsdtAddress = (UINT64) (UINTN)Xsdt;
Rsdp->Checksum = CalculateCheckSum8 ((UINT8 *)Rsdp, sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER));
Rsdp->ExtendedChecksum = CalculateCheckSum8 ((UINT8 *)Rsdp, Rsdp->Length);
*AcpiMemBase = (UINT32)Current;
//
// Keep a copy at F segment so that non-UEFI OS will find ACPI tables
//
Status = PcdSet32S (PcdAcpiTablesRsdp, (UINT32)Rsdp);
CopyMem ((VOID *)0xFFF80, Rsdp, sizeof (RsdpTmp));
// Update ACPI update service so that payload can have opportunity to update ACPI tables
PlatformService = (PLATFORM_SERVICE *) GetServiceBySignature (PLATFORM_SERVICE_SIGNATURE);
if (PlatformService != NULL) {
PlatformService->AcpiTableUpdate = AcpiTableUpdate;
}
return EFI_SUCCESS;
}
typedef VOID (*DOWAKEUP) (UINT32 WakeVector);
/**
This function is called on S3 boot flow only.
It will locate the S3 waking vector from the ACPI table and then
jump into it. The control will never return.
@param AcpiTableBase ACPI table base address
**/
VOID
EFIAPI
FindAcpiWakeVectorAndJump (
IN UINT32 AcpiTableBase
)
{
EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
EFI_ACPI_DESCRIPTION_HEADER *Xsdt;
EFI_ACPI_COMMON_HEADER *Hdr;
UINT64 *XsdtEntry;
UINT8 Index;
EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *Facp;
UINT32 WakeVector;
DOWAKEUP DoWake;
Rsdp = (EFI_ACPI_5_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) AcpiTableBase;
Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN)Rsdp->XsdtAddress;
XsdtEntry = (UINT64 *) ((UINT8 *)Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER));
for (Index = 0; Index < PcdGet32 (PcdAcpiTablesMaxEntry); ++Index) {
Hdr = (EFI_ACPI_COMMON_HEADER *) (UINTN)XsdtEntry[Index];
if (Hdr->Signature == EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
Facp = (EFI_ACPI_5_0_FIXED_ACPI_DESCRIPTION_TABLE *) Hdr;
Facs = (EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *) Facp->FirmwareCtrl;
if (Facs->Signature == EFI_ACPI_5_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
WakeVector = Facs->FirmwareWakingVector;
// Calculate CRC32 for 0x00000000 ---> BootLoaderRsvdMemBase and
// compare with the one calculated and saved in Stage1B.
if (PcdGetBool (PcdS3DebugEnabled)) {
if (!S3DebugRestoreAndCompareCRC32 () ) {
return;
}
}
CopyMem ((VOID *)WakeUpBuffer, &WakeUp, WakeUpSize);
DoWake = (DOWAKEUP)WakeUpBuffer;
DEBUG ((DEBUG_INIT, "Jump to Wake vector = 0x%x\n", WakeVector));
DoWake (WakeVector);
//
// Should never reach here!
//
}
}
}
}