blob: 36300efd3146fb8c0a5276bcd030b09de1fca6c3 [file] [log] [blame]
/** @file
ACPI Platform Driver
Copyright (c) 2013-2016 Intel Corporation.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which 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 <Protocol/AcpiTable.h>
#include <IndustryStandard/Pci22.h>
#include "AcpiPlatform.h"
//
// Global Variable
//
EFI_GLOBAL_NVS_AREA_PROTOCOL mGlobalNvsArea;
EFI_ACPI_SDT_PROTOCOL *mAcpiSdt;
EFI_ACPI_HANDLE mDsdtHandle = NULL;
EFI_STATUS
LocateSupportProtocol (
IN EFI_GUID *Protocol,
OUT VOID **Instance,
IN UINT32 Type
)
/*++
Routine Description:
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.
Arguments:
Protocol The protocol to find.
Instance Return pointer to the first instance of the protocol
Returns:
EFI_SUCCESS The function completed successfully.
EFI_NOT_FOUND The protocol could not be located.
EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
--*/
{
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer;
UINTN NumberOfHandles;
EFI_FV_FILETYPE FileType;
UINT32 FvStatus;
EFI_FV_FILE_ATTRIBUTES Attributes;
UINTN Size;
UINTN i;
FvStatus = 0;
//
// 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 (i = 0; i < NumberOfHandles; i++) {
//
// Get the protocol on this handle
// This should not fail because of LocateHandleBuffer
//
Status = gBS->HandleProtocol (
HandleBuffer[i],
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
//
Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL*) (*Instance))->ReadFile (*Instance,
(EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
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
//
gBS->FreePool (HandleBuffer);
return Status;
}
VOID
DsdtTableUpdate (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
IN OUT EFI_ACPI_TABLE_VERSION *Version
)
/*++
Routine Description:
Update the DSDT table
Arguments:
Table - The table to be set
Version - Version to publish
Returns:
None
--*/
{
UINT8 *CurrPtr;
UINT8 *DsdtPointer;
UINT32 *Signature;
UINT8 *Operation;
UINT32 *Address;
UINT16 *Size;
//
// Loop through the ASL looking for values that we must fix up.
//
CurrPtr = (UINT8 *) TableHeader;
for (DsdtPointer = CurrPtr;
DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length);
DsdtPointer++
)
{
Signature = (UINT32 *) DsdtPointer;
switch (*Signature) {
//
// MNVS operation region
//
case (SIGNATURE_32 ('M', 'N', 'V', 'S')):
//
// Conditional match. For Region Objects, the Operator will always be the
// byte immediately before the specific name. Therefore, subtract 1 to check
// the Operator.
//
Operation = DsdtPointer - 1;
if (*Operation == AML_OPREGION_OP) {
Address = (UINT32 *) (DsdtPointer + 6);
*Address = (UINT32) (UINTN) mGlobalNvsArea.Area;
Size = (UINT16 *) (DsdtPointer + 11);
*Size = sizeof (EFI_GLOBAL_NVS_AREA);
}
break;
//
// Update processor PBLK register I/O base address
//
case (SIGNATURE_32 ('P', 'R', 'I', 'O')):
//
// Conditional match. Update the following ASL code:
// Processor (CPU0, 0x01, 0x4F495250, 0x06) {}
// The 3rd parameter will be updated to the actual PBLK I/O base address.
// the Operator.
//
Operation = DsdtPointer - 8;
if ((*Operation == AML_EXT_OP) && (*(Operation + 1) == AML_EXT_PROCESSOR_OP)) {
*(UINT32 *)DsdtPointer = PcdGet16(PcdPmbaIoBaseAddress);
}
break;
default:
break;
}
}
}
VOID
ApicTableUpdate (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
IN OUT EFI_ACPI_TABLE_VERSION *Version
)
/*++
Routine Description:
Update the processors information in the APIC table
Arguments:
Table - The table to be set
Version - Version to publish
Returns:
None
--*/
{
EFI_STATUS Status;
EFI_MP_SERVICES_PROTOCOL *MpService;
UINT8 *CurrPtr;
UINT8 *EndPtr;
UINT8 CurrIoApic;
UINT8 CurrProcessor;
UINTN NumberOfCPUs;
UINTN NumberOfEnabledCPUs;
EFI_PROCESSOR_INFORMATION MpContext;
ACPI_APIC_STRUCTURE_PTR *ApicPtr;
CurrIoApic = 0;
CurrProcessor = 0;
//
// Find the MP Protocol. This is an MP platform, so MP protocol must be
// there.
//
Status = gBS->LocateProtocol (
&gEfiMpServiceProtocolGuid,
NULL,
(VOID**)&MpService
);
if (EFI_ERROR (Status)) {
//
// Failed to get MP information, doesn't publish the invalid table
//
*Version = EFI_ACPI_TABLE_VERSION_NONE;
return;
}
//
// Determine the number of processors
//
MpService->GetNumberOfProcessors (
MpService,
&NumberOfCPUs,
&NumberOfEnabledCPUs
);
CurrPtr = (UINT8*) &(TableHeader[1]);
CurrPtr = CurrPtr + 8; // Size of Local APIC Address & Flag
EndPtr = (UINT8*) TableHeader;
EndPtr = EndPtr + TableHeader->Length;
while (CurrPtr < EndPtr) {
ApicPtr = (ACPI_APIC_STRUCTURE_PTR*) CurrPtr;
switch (ApicPtr->AcpiApicCommon.Type) {
case EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC:
ApicPtr->AcpiLocalApic.Flags = 0;
ApicPtr->AcpiLocalApic.ApicId = 0;
Status = MpService->GetProcessorInfo (
MpService,
CurrProcessor,
&MpContext
);
if (!EFI_ERROR (Status)) {
if (MpContext.StatusFlag & PROCESSOR_ENABLED_BIT) {
ApicPtr->AcpiLocalApic.Flags = EFI_ACPI_3_0_LOCAL_APIC_ENABLED;
}
ApicPtr->AcpiLocalApic.ApicId = (UINT8)MpContext.ProcessorId;
}
CurrProcessor++;
break;
case EFI_ACPI_1_0_IO_APIC:
//
// IO APIC entries can be patched here
//
if (CurrIoApic == 0) {
//
// Update SOC internel IOAPIC base
//
ApicPtr->AcpiIoApic.IoApicId = PcdGet8 (PcdIoApicSettingIoApicId);
ApicPtr->AcpiIoApic.IoApicAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress);
ApicPtr->AcpiIoApic.GlobalSystemInterruptBase = 0;
} else {
//
// Porting is required to update other IOAPIC entries if available
//
ASSERT (0);
}
CurrIoApic++;
break;
default:
break;
};
CurrPtr = CurrPtr + ApicPtr->AcpiApicCommon.Length;
}
}
VOID
AcpiUpdateTable (
IN OUT EFI_ACPI_DESCRIPTION_HEADER *TableHeader,
IN OUT EFI_ACPI_TABLE_VERSION *Version
)
/*++
Routine Description:
Set the correct table revision upon the setup value
Arguments:
Table - The table to be set
Version - Version to publish
Returns:
None
--*/
{
EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader1;
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader2;
EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtHeader3;
EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *AllocationStructurePtr;
if (TableHeader != NULL && Version != NULL) {
*Version = EFI_ACPI_TABLE_VERSION_1_0B | EFI_ACPI_TABLE_VERSION_2_0 | EFI_ACPI_TABLE_VERSION_3_0;
//
// Here we use all 3.0 signature because all version use same signature if they supported
//
switch (TableHeader->Signature) {
//
// "APIC" Multiple APIC Description Table
//
case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
ApicTableUpdate (TableHeader, Version);
break;
//
// "DSDT" Differentiated System Description Table
//
case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
DsdtTableUpdate (TableHeader, Version);
break;
//
// "FACP" Fixed ACPI Description Table (FADT)
//
case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
*Version = EFI_ACPI_TABLE_VERSION_NONE;
if (TableHeader->Revision == EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
*Version = EFI_ACPI_TABLE_VERSION_1_0B;
FadtHeader1 = (EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
FadtHeader1->SmiCmd = PcdGet16(PcdSmmActivationPort);
FadtHeader1->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
FadtHeader1->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
FadtHeader1->PmTmrBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
FadtHeader1->Gpe0Blk = PcdGet16(PcdGpe0blkIoBaseAddress);
} else if (TableHeader->Revision == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
*Version = EFI_ACPI_TABLE_VERSION_2_0;
FadtHeader2 = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
FadtHeader2->SmiCmd = PcdGet16(PcdSmmActivationPort);
FadtHeader2->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
FadtHeader2->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
FadtHeader2->PmTmrBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
FadtHeader2->Gpe0Blk = PcdGet16(PcdGpe0blkIoBaseAddress);
FadtHeader2->XPm1aEvtBlk.Address = FadtHeader2->Pm1aEvtBlk;
FadtHeader2->XPm1aCntBlk.Address = FadtHeader2->Pm1aCntBlk;
FadtHeader2->XPmTmrBlk.Address = FadtHeader2->PmTmrBlk;
FadtHeader2->XGpe0Blk.Address = FadtHeader2->Gpe0Blk;
} else if (TableHeader->Revision == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
*Version = EFI_ACPI_TABLE_VERSION_3_0;
FadtHeader3 = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) TableHeader;
FadtHeader3->SmiCmd = PcdGet16(PcdSmmActivationPort);
FadtHeader3->Pm1aEvtBlk = PcdGet16(PcdPm1blkIoBaseAddress);
FadtHeader3->Pm1aCntBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C;
FadtHeader3->PmTmrBlk = PcdGet16(PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1T;
FadtHeader3->Gpe0Blk = PcdGet16(PcdGpe0blkIoBaseAddress);
FadtHeader3->XPm1aEvtBlk.Address = FadtHeader3->Pm1aEvtBlk;
FadtHeader3->XPm1aCntBlk.Address = FadtHeader3->Pm1aCntBlk;
FadtHeader3->XPmTmrBlk.Address = FadtHeader3->PmTmrBlk;
FadtHeader3->XGpe0Blk.Address = FadtHeader3->Gpe0Blk;
}
break;
//
// "FACS" Firmware ACPI Control Structure
//
case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
break;
//
// "SSDT" Secondary System Description Table
//
case EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
break;
//
// "HPET" IA-PC High Precision Event Timer Table
//
case EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE:
//
// If HPET is disabled in setup, don't publish the table.
//
if (mGlobalNvsArea.Area->HpetEnable == 0) {
*Version = EFI_ACPI_TABLE_VERSION_NONE;
}
((EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER *) TableHeader)->BaseAddressLower32Bit.Address
= PcdGet64 (PcdHpetBaseAddress);
break;
//
// "SPCR" Serial Port Concole Redirection Table
//
case EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE:
break;
//
// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
//
case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
AllocationStructurePtr = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)
((UINT8 *)TableHeader + sizeof(EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER));
AllocationStructurePtr->BaseAddress = PcdGet64(PcdPciExpressBaseAddress);
break;
// Lakeport platform doesn't support the following table
/*
//
// "ECDT" Embedded Controller Boot Resources Table
//
case EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE:
break;
//
// "PSDT" Persistent System Description Table
//
case EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
break;
//
// "SBST" Smart Battery Specification Table
//
case EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE:
break;
//
// "SLIT" System Locality Information Table
//
case EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE:
break;
//
// "SRAT" Static Resource Affinity Table
//
case EFI_ACPI_3_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE:
break;
//
// "XSDT" Extended System Description Table
//
case EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
break;
//
// "BOOT" MS Simple Boot Spec
//
case EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE:
break;
//
// "CPEP" Corrected Platform Error Polling Table
//
case EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE:
break;
//
// "DBGP" MS Debug Port Spec
//
case EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE:
break;
//
// "ETDT" Event Timer Description Table
//
case EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE:
break;
//
// "SPMI" Server Platform Management Interface Table
//
case EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE:
break;
//
// "TCPA" Trusted Computing Platform Alliance Capabilities Table
//
case EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE:
break;
*/
default:
break;
}
}
}
//
// Description:
// Entrypoint of Acpi Platform driver
// In:
// ImageHandle
// SystemTable
// Out:
// EFI_SUCCESS
// EFI_LOAD_ERROR
// EFI_OUT_OF_RESOURCES
//
EFI_STATUS
AcpiPlatformEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
INTN Instance;
EFI_ACPI_COMMON_HEADER *CurrentTable;
UINTN TableHandle;
UINT32 FvStatus;
UINTN Size;
EFI_ACPI_TABLE_VERSION Version;
EFI_HANDLE Handle;
UINTN Index;
PCI_DEVICE_INFO *PciDeviceInfo;
EFI_ACPI_HANDLE PciRootHandle;
BOOLEAN UpdatePRT;
BOOLEAN UpdatePRW;
PCI_DEVICE_SETTING *mConfigData;
DEBUG((DEBUG_INFO, "ACPI Platform start...\n"));
Instance = 0;
TableHandle = 0;
CurrentTable = NULL;
mConfigData = NULL;
//
// Initialize the EFI Driver Library
//
ASSERT (sizeof (EFI_GLOBAL_NVS_AREA) == 512);
Status = gBS->AllocatePool (
EfiACPIMemoryNVS,
sizeof (EFI_GLOBAL_NVS_AREA),
(VOID**)&mGlobalNvsArea.Area
);
Handle = NULL;
Status = gBS->InstallProtocolInterface (
&Handle,
&gEfiGlobalNvsAreaProtocolGuid,
EFI_NATIVE_INTERFACE,
&mGlobalNvsArea
);
ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR (Status)) {
SetMem (
mGlobalNvsArea.Area,
sizeof (EFI_GLOBAL_NVS_AREA),
0
);
}
//
// Initialize the data. Eventually, this will be controlled by setup options.
//
mGlobalNvsArea.Area->HpetEnable = PcdGetBool (PcdHpetEnable);
mGlobalNvsArea.Area->Pm1blkIoBaseAddress = PcdGet16(PcdPm1blkIoBaseAddress);
mGlobalNvsArea.Area->PmbaIoBaseAddress = PcdGet16(PcdPmbaIoBaseAddress);
mGlobalNvsArea.Area->Gpe0blkIoBaseAddress = PcdGet16(PcdGpe0blkIoBaseAddress);
mGlobalNvsArea.Area->GbaIoBaseAddress = PcdGet16(PcdGbaIoBaseAddress);
mGlobalNvsArea.Area->SmbaIoBaseAddress = PcdGet16(PcdSmbaIoBaseAddress);
mGlobalNvsArea.Area->WdtbaIoBaseAddress = PcdGet16(PcdWdtbaIoBaseAddress);
mGlobalNvsArea.Area->HpetBaseAddress = (UINT32)PcdGet64(PcdHpetBaseAddress);
mGlobalNvsArea.Area->HpetSize = (UINT32)PcdGet64(PcdHpetSize);
mGlobalNvsArea.Area->PciExpressBaseAddress= (UINT32)PcdGet64(PcdPciExpressBaseAddress);
mGlobalNvsArea.Area->PciExpressSize = (UINT32)PcdGet64(PcdPciExpressSize);
mGlobalNvsArea.Area->RcbaMmioBaseAddress = (UINT32)PcdGet64(PcdRcbaMmioBaseAddress);
mGlobalNvsArea.Area->RcbaMmioSize = (UINT32)PcdGet64(PcdRcbaMmioSize);
mGlobalNvsArea.Area->IoApicBaseAddress = (UINT32)PcdGet64(PcdIoApicBaseAddress);
mGlobalNvsArea.Area->IoApicSize = (UINT32)PcdGet64(PcdIoApicSize);
mGlobalNvsArea.Area->TpmPresent = (UINT32)(FALSE);
mGlobalNvsArea.Area->DBG2Present = (UINT32)(FALSE);
mGlobalNvsArea.Area->PlatformType = (UINT32)PcdGet16 (PcdPlatformType);
//
// Configure platform IO expander I2C Slave Address.
//
if (mGlobalNvsArea.Area->PlatformType == Galileo) {
if (PlatformLegacyGpioGetLevel (R_QNC_GPIO_RGLVL_RESUME_WELL, GALILEO_DETERMINE_IOEXP_SLA_RESUMEWELL_GPIO)) {
mGlobalNvsArea.Area->AlternateSla = FALSE;
} else {
mGlobalNvsArea.Area->AlternateSla = TRUE;
}
}
//
// Find the AcpiTable protocol
//
Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID**)&AcpiTable);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
//
// Initialize MADT table
//
Status = MadtTableInitialize (&CurrentTable, &Size);
ASSERT_EFI_ERROR (Status);
//
// Perform any table specific updates.
//
AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
//
// Update the check sum
// It needs to be zeroed before the checksum calculation
//
((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
//
// Add the table
//
TableHandle = 0;
Status = AcpiTable->InstallAcpiTable (
AcpiTable,
CurrentTable,
CurrentTable->Length,
&TableHandle
);
ASSERT_EFI_ERROR (Status);
CurrentTable = NULL;
//
// Init Pci Device PRT PRW information structure from PCD
//
mConfigData = (PCI_DEVICE_SETTING *)AllocateZeroPool (sizeof (PCI_DEVICE_SETTING));
ASSERT (mConfigData != NULL);
InitPciDeviceInfoStructure (mConfigData);
//
// Get the Acpi SDT protocol for manipulation on acpi table
//
Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **)&mAcpiSdt);
ASSERT_EFI_ERROR (Status);
//
// Locate the firmware volume protocol
//
Status = LocateSupportProtocol (&gEfiFirmwareVolume2ProtocolGuid, (VOID**)&FwVol, 1);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
//
// Read tables from the storage file.
//
while (Status == EFI_SUCCESS) {
Status = FwVol->ReadSection (
FwVol,
(EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
EFI_SECTION_RAW,
Instance,
(VOID**)&CurrentTable,
&Size,
&FvStatus
);
if (!EFI_ERROR(Status)) {
//
// Perform any table specific updates.
//
AcpiUpdateTable ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable, &Version);
//
// Update the check sum
// It needs to be zeroed before the checksum calculation
//
((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum = 0;
((EFI_ACPI_SDT_HEADER *)CurrentTable)->Checksum =
CalculateCheckSum8 ((VOID *)CurrentTable, CurrentTable->Length);
//
// Add the table
//
TableHandle = 0;
Status = AcpiTable->InstallAcpiTable (
AcpiTable,
CurrentTable,
((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length,
&TableHandle
);
if (EFI_ERROR(Status)) {
return EFI_ABORTED;
}
//
// If this table is the DSDT table, then update the _PRT and _PRW based on
// the settings from pcds
//
if (CurrentTable->Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
//
// Create the root handle for DSDT table
//
Status = mAcpiSdt->OpenSdt (TableHandle, &mDsdtHandle);
ASSERT_EFI_ERROR (Status);
PciRootHandle = NULL;
PciRootHandle = SdtGetRootBridgeHandle (mAcpiSdt, mDsdtHandle);
ASSERT (PciRootHandle != NULL);
PciDeviceInfo = NULL;
for (Index = 0; Index < mConfigData->PciDeviceInfoNumber; Index++) {
PciDeviceInfo = &(mConfigData->PciDeviceInfo[Index]);
//
// Check whether this is a valid item
//
if ((PciDeviceInfo->BridgeAddress != 0xFFFFFFFF) && (PciDeviceInfo->DeviceAddress != 0xFFFFFFFF)) {
//DEBUG ((EFI_D_ERROR, "Valid pci info structure: bridge address:0x%x, device address:0x%x\n", PciDeviceInfo->BridgeAddress, PciDeviceInfo->DeviceAddress));
UpdatePRT = FALSE;
UpdatePRW = FALSE;
SdtCheckPciDeviceInfoChanged (PciDeviceInfo, &UpdatePRT, &UpdatePRW);
//
// Check whether there is any valid pci routing item
//
if (UpdatePRT) {
//
// Update the pci routing information
//
//DEBUG ((EFI_D_ERROR, "Update _PRT\n"));
SdtUpdatePciRouting (mAcpiSdt, PciRootHandle, PciDeviceInfo);
}
//
// Check whether there is any valid pci routing item
//
if (UpdatePRW) {
//
// Update the pci wakeup information
//
//DEBUG ((EFI_D_ERROR, "Update _PRW\n"));
SdtUpdatePowerWake (mAcpiSdt, PciRootHandle, PciDeviceInfo);
}
}
}
Status = mAcpiSdt->Close (PciRootHandle);
ASSERT_EFI_ERROR (Status);
//
// Mark the root handle as modified , let SDT protocol recaculate the checksum
//
((EFI_AML_HANDLE *)mDsdtHandle)->Modified = TRUE;
Status = mAcpiSdt->Close (mDsdtHandle);
ASSERT_EFI_ERROR (Status);
}
//
// Increment the instance
//
Instance++;
CurrentTable = NULL;
}
}
gBS->FreePool (mConfigData);
return EFI_SUCCESS;
}