/** @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; | |
} |