/** @file
|
|
Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
#include "BoardAcpiDxe.h"
|
|
EFI_STATUS
|
PatchDsdtTable (
|
IN OUT EFI_ACPI_COMMON_HEADER *Table
|
);
|
|
#pragma optimize("",off)
|
|
BIOS_ACPI_PARAM *mAcpiParameter;
|
|
EFI_IIO_UDS_PROTOCOL *mIioUds;
|
|
UINT32 mNumOfBitShift;
|
BOOLEAN mForceX2ApicId;
|
BOOLEAN mX2ApicEnabled;
|
|
struct SystemMemoryMapHob *mSystemMemoryMap;
|
|
SOCKET_MP_LINK_CONFIGURATION mSocketMpLinkConfiguration;
|
SOCKET_IIO_CONFIGURATION mSocketIioConfiguration;
|
SOCKET_POWERMANAGEMENT_CONFIGURATION mSocketPowermanagementConfiguration;
|
|
BOOLEAN mFirstNotify;
|
PCH_RC_CONFIGURATION mPchRcConfiguration;
|
|
UINT8 mKBPresent = 0;
|
UINT8 mMousePresent = 0;
|
|
/**
|
|
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 Protocol - The protocol to find.
|
Instance - Return pointer to the first instance of the protocol.
|
Type - The type of protocol to locate.
|
|
@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 UINT32 Type
|
)
|
{
|
EFI_STATUS Status;
|
EFI_HANDLE *HandleBuffer;
|
UINTN NumberOfHandles;
|
EFI_FV_FILETYPE FileType;
|
UINT32 FvStatus;
|
EFI_FV_FILE_ATTRIBUTES Attributes;
|
UINTN Size;
|
UINTN Index;
|
|
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 (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
|
//
|
Status = ((EFI_FIRMWARE_VOLUME2_PROTOCOL *) (*Instance))->ReadFile (
|
*Instance,
|
gEfiAcpiMultiTableStorageGuid,
|
NULL,
|
&Size,
|
&FileType,
|
&Attributes,
|
&FvStatus
|
);
|
|
//
|
// If we found it, then we are done
|
//
|
if (!EFI_ERROR (Status)) {
|
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;
|
}
|
|
/**
|
|
GC_TODO: add routine description
|
|
@param None
|
|
@retval EFI_SUCCESS - GC_TODO: add retval description
|
|
**/
|
EFI_STATUS
|
PlatformHookInit (
|
VOID
|
)
|
{
|
EFI_STATUS Status;
|
EFI_PHYSICAL_ADDRESS AcpiParameterAddr;
|
UINT32 RegEax;
|
UINT32 RegEbx;
|
UINT32 RegEcx;
|
UINT32 RegEdx;
|
|
CopyMem (&mSocketMpLinkConfiguration, PcdGetPtr(PcdSocketMpLinkConfigData), sizeof(SOCKET_MP_LINK_CONFIGURATION));
|
CopyMem (&mSocketPowermanagementConfiguration, PcdGetPtr(PcdSocketPowerManagementConfigData), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION));
|
CopyMem (&mSocketIioConfiguration, PcdGetPtr(PcdSocketIioConfigData), sizeof(SOCKET_IIO_CONFIGURATION));
|
CopyMem (&mPchRcConfiguration, PcdGetPtr(PcdPchRcConfigurationData), sizeof(PCH_RC_CONFIGURATION));
|
|
DEBUG ((DEBUG_INFO, "mX2ApicEnabled - 0x%x\n", mX2ApicEnabled));
|
DEBUG ((DEBUG_INFO, "mForceX2ApicId - 0x%x\n", mForceX2ApicId));
|
|
{
|
UINT32 Index;
|
|
for (Index = 0; Index < 4; Index++) {
|
AsmCpuidEx(CPUID_EXTENDED_TOPOLOGY, Index, &RegEax, &RegEbx, &RegEcx, &RegEdx);
|
DEBUG ((DEBUG_INFO, "CPUID(0xB - %d) - 0x%08x.0x%08x.0x%08x.0x%08x\n", Index, RegEax, RegEbx, RegEcx, RegEdx));
|
}
|
}
|
|
//
|
// Allocate 256 runtime memory to pass ACPI parameter
|
// This Address must be < 4G because we only have 32bit in the dsdt
|
//
|
AcpiParameterAddr = 0xffffffff;
|
Status = gBS->AllocatePages (
|
AllocateMaxAddress,
|
EfiACPIMemoryNVS,
|
EFI_SIZE_TO_PAGES (sizeof(BIOS_ACPI_PARAM)),
|
&AcpiParameterAddr
|
);
|
ASSERT_EFI_ERROR (Status);
|
mAcpiParameter = (BIOS_ACPI_PARAM *)AcpiParameterAddr;
|
|
DEBUG ((EFI_D_ERROR, "ACPI Parameter Block Address: 0x%X\n", mAcpiParameter));
|
Status = PcdSet64S (PcdAcpiGnvsAddress, (UINT64)(UINTN)mAcpiParameter);
|
ASSERT_EFI_ERROR (Status);
|
|
ZeroMem (mAcpiParameter, sizeof (BIOS_ACPI_PARAM));
|
mAcpiParameter->PlatformId = 0;
|
#if MAX_SOCKET > 4
|
mAcpiParameter->IoApicEnable = PcdGet32 (PcdPcIoApicEnable);
|
#else
|
mAcpiParameter->IoApicEnable = (PcdGet32 (PcdPcIoApicEnable) << 1) | 1;
|
#endif
|
DEBUG((EFI_D_ERROR, "io apic settings:%d\n", mAcpiParameter->IoApicEnable));
|
|
AsmCpuid (CPUID_VERSION_INFO, &RegEax, &RegEbx, &RegEcx, &RegEdx);
|
mAcpiParameter->ProcessorId = (RegEax & 0xFFFF0);
|
|
// support up to 64 threads/socket
|
AsmCpuidEx(CPUID_EXTENDED_TOPOLOGY, 1, &mNumOfBitShift, NULL, NULL, NULL);
|
mNumOfBitShift &= 0x1F;
|
|
// Set the bit shift value for CPU SKU
|
mAcpiParameter->CpuSkuNumOfBitShift = (UINT8) mNumOfBitShift;
|
|
mAcpiParameter->ProcessorApicIdBase[0] = (UINT32) (0 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[1] = (UINT32) (1 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[2] = (UINT32) (2 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[3] = (UINT32) (3 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[4] = (UINT32) (4 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[5] = (UINT32) (5 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[6] = (UINT32) (6 << mNumOfBitShift);
|
mAcpiParameter->ProcessorApicIdBase[7] = (UINT32) (7 << mNumOfBitShift);
|
|
if(mForceX2ApicId) {
|
mAcpiParameter->ProcessorApicIdBase[0] = 0x7F00;
|
mAcpiParameter->ProcessorApicIdBase[1] = 0x7F20;
|
mAcpiParameter->ProcessorApicIdBase[2] = 0x7F40;
|
mAcpiParameter->ProcessorApicIdBase[3] = 0x7F60;
|
mAcpiParameter->ProcessorApicIdBase[4] = 0x7F80;
|
mAcpiParameter->ProcessorApicIdBase[5] = 0x7Fa0;
|
mAcpiParameter->ProcessorApicIdBase[6] = 0x7Fc0;
|
mAcpiParameter->ProcessorApicIdBase[7] = 0x7Fe0;
|
|
if (mNumOfBitShift == 4) {
|
mAcpiParameter->ProcessorApicIdBase[0] = 0x7F00;
|
mAcpiParameter->ProcessorApicIdBase[1] = 0x7F10;
|
mAcpiParameter->ProcessorApicIdBase[2] = 0x7F20;
|
mAcpiParameter->ProcessorApicIdBase[3] = 0x7F30;
|
mAcpiParameter->ProcessorApicIdBase[4] = 0x7F40;
|
mAcpiParameter->ProcessorApicIdBase[5] = 0x7F50;
|
mAcpiParameter->ProcessorApicIdBase[6] = 0x7F60;
|
mAcpiParameter->ProcessorApicIdBase[7] = 0x7F70;
|
} else if(mNumOfBitShift == 6) {
|
mAcpiParameter->ProcessorApicIdBase[0] = 0x7E00;
|
mAcpiParameter->ProcessorApicIdBase[1] = 0x7E20;
|
mAcpiParameter->ProcessorApicIdBase[2] = 0x7E40;
|
mAcpiParameter->ProcessorApicIdBase[3] = 0x7E60;
|
mAcpiParameter->ProcessorApicIdBase[4] = 0x7E80;
|
mAcpiParameter->ProcessorApicIdBase[5] = 0x7Ea0;
|
mAcpiParameter->ProcessorApicIdBase[6] = 0x7Ec0;
|
mAcpiParameter->ProcessorApicIdBase[7] = 0x7Ee0;
|
}
|
}
|
|
//
|
// If SNC is enabled, and NumOfCluster is 2, set the ACPI variable for PXM value
|
//
|
if(mIioUds->IioUdsPtr->SystemStatus.OutSncEn && (mIioUds->IioUdsPtr->SystemStatus.OutNumOfCluster == 2)){
|
mAcpiParameter->SncAnd2Cluster = 1;
|
} else {
|
mAcpiParameter->SncAnd2Cluster = 0;
|
}
|
|
mAcpiParameter->MmCfg = (UINT32)mIioUds->IioUdsPtr->PlatformData.PciExpressBase;
|
mAcpiParameter->TsegSize = (UINT32)(mIioUds->IioUdsPtr->PlatformData.MemTsegSize >> 20);
|
|
return EFI_SUCCESS;
|
}
|
|
/**
|
|
This function will update any runtime platform specific information.
|
This currently includes:
|
Setting OEM table values, ID, table ID, creator ID and creator revision.
|
Enabling the proper processor entries in the APIC tables.
|
|
@param Table - The table to update
|
|
@retval EFI_SUCCESS - The function completed successfully.
|
|
**/
|
EFI_STATUS
|
PlatformUpdateTables (
|
IN OUT EFI_ACPI_COMMON_HEADER *Table,
|
IN OUT EFI_ACPI_TABLE_VERSION *Version
|
)
|
{
|
EFI_STATUS Status;
|
|
Status = EFI_SUCCESS;
|
|
//
|
// By default, a table belongs in all ACPI table versions published.
|
// Some tables will override this because they have different versions of the table.
|
//
|
*Version = EFI_ACPI_TABLE_VERSION_2_0;
|
//
|
// Update the processors in the APIC table
|
//
|
switch (Table->Signature) {
|
|
case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
|
//
|
// Patch the memory resource
|
//
|
Status = PatchDsdtTable(Table);
|
break;
|
|
default:
|
ASSERT(FALSE);
|
break;
|
}
|
//
|
//
|
// Update the hardware signature in the FACS structure
|
//
|
//
|
//
|
return Status;
|
}
|
|
|
|
/**
|
|
GC_TODO: Add function description
|
|
@param Event - GC_TODO: add argument description
|
@param Context - GC_TODO: add argument description
|
|
@retval GC_TODO: add return values
|
|
**/
|
STATIC
|
VOID
|
EFIAPI
|
OnReadyToBoot (
|
IN EFI_EVENT Event,
|
IN VOID *Context
|
)
|
{
|
UINT32 RegEax;
|
UINT32 RegEbx;
|
UINT32 RegEcx;
|
UINT32 RegEdx;
|
|
if (mFirstNotify) {
|
return ;
|
}
|
|
mFirstNotify = TRUE;
|
|
CopyMem (&mSocketIioConfiguration, PcdGetPtr(PcdSocketIioConfigData), sizeof(SOCKET_IIO_CONFIGURATION));
|
CopyMem (&mSocketPowermanagementConfiguration,PcdGetPtr(PcdSocketPowerManagementConfigData), sizeof(SOCKET_POWERMANAGEMENT_CONFIGURATION));
|
CopyMem (&mPchRcConfiguration, PcdGetPtr(PcdPchRcConfigurationData), sizeof(PCH_RC_CONFIGURATION));
|
|
// CpuPm.Asl: External (CSEN, FieldUnitObj)
|
mAcpiParameter->CStateEnable = !mSocketPowermanagementConfiguration.ProcessorAutonomousCstateEnable;
|
// CpuPm.Asl: External (C3EN, FieldUnitObj)
|
mAcpiParameter->C3Enable = mSocketPowermanagementConfiguration.C3Enable;
|
// CpuPm.Asl: External (C6EN, FieldUnitObj)
|
if (mSocketPowermanagementConfiguration.C6Enable == PPM_AUTO) {
|
mAcpiParameter->C6Enable = 1; //POR Default = Enabled
|
} else {
|
mAcpiParameter->C6Enable = mSocketPowermanagementConfiguration.C6Enable;
|
}
|
if(mAcpiParameter->C6Enable && mAcpiParameter->C3Enable) { //C3 and C6 enable are exclusive
|
mAcpiParameter->C6Enable = 1;
|
mAcpiParameter->C3Enable = 0;
|
}
|
// CpuPm.Asl: External (C7EN, FieldUnitObj)
|
mAcpiParameter->C7Enable = 0;
|
// CpuPm.Asl: External (OSCX, FieldUnitObj)
|
mAcpiParameter->OSCX = mSocketPowermanagementConfiguration.OSCx;
|
// CpuPm.Asl: External (MWOS, FieldUnitObj)
|
mAcpiParameter->MonitorMwaitEnable = 1;
|
// CpuPm.Asl: External (PSEN, FieldUnitObj)
|
mAcpiParameter->PStateEnable = mSocketPowermanagementConfiguration.ProcessorEistEnable;
|
// CpuPm.Asl: External (HWAL, FieldUnitObj)
|
mAcpiParameter->HWAllEnable = 0; //Update in PatchGv3SsdtTable
|
|
mAcpiParameter->KBPresent = mKBPresent;
|
mAcpiParameter->MousePresent = mMousePresent;
|
mAcpiParameter->TStateEnable = mSocketPowermanagementConfiguration.TStateEnable;
|
//Fine grained T state
|
AsmCpuid (CPUID_THERMAL_POWER_MANAGEMENT, &RegEax, &RegEbx, &RegEcx, &RegEdx);
|
if ((RegEax & EFI_FINE_GRAINED_CLOCK_MODULATION) && (mSocketPowermanagementConfiguration.OnDieThermalThrottling > 0)){
|
mAcpiParameter->TStateFineGrained = 1;
|
}
|
if(RegEax & B_CPUID_POWER_MANAGEMENT_EAX_HWP_LVT_INTERRUPT_SUPPORT) {
|
mAcpiParameter->HwpInterrupt = 1;
|
}
|
// CpuPm.Asl: External (HWEN, FieldUnitObj)
|
mAcpiParameter->HWPMEnable = mSocketPowermanagementConfiguration.ProcessorHWPMEnable;
|
// CpuPm.Asl: External (ACEN, FieldUnitObj)
|
mAcpiParameter->AutoCstate = mSocketPowermanagementConfiguration.ProcessorAutonomousCstateEnable;
|
|
mAcpiParameter->EmcaEn = 0;
|
|
mAcpiParameter->PcieAcpiHotPlugEnable = (UINT8) (BOOLEAN) (mSocketIioConfiguration.PcieAcpiHotPlugEnable != 0);
|
//
|
// Initialize USB3 mode from setup data
|
//
|
// If mode != manual control
|
// just copy mode from setup
|
if (mPchRcConfiguration.PchUsbManualMode != 1) {
|
mAcpiParameter->XhciMode = mPchRcConfiguration.PchUsbManualMode;
|
}
|
|
}
|
|
/**
|
|
Entry point for Acpi platform driver.
|
|
@param ImageHandle - A handle for the image that is initializing this driver.
|
@param SystemTable - A pointer to the EFI system table.
|
|
@retval EFI_SUCCESS - Driver initialized successfully.
|
@retval EFI_LOAD_ERROR - Failed to Initialize or has been loaded.
|
@retval EFI_OUT_OF_RESOURCES - Could not allocate needed resources.
|
|
**/
|
EFI_STATUS
|
EFIAPI
|
InstallAcpiBoard (
|
IN EFI_HANDLE ImageHandle,
|
IN EFI_SYSTEM_TABLE *SystemTable
|
)
|
{
|
EFI_STATUS Status;
|
EFI_STATUS AcpiStatus;
|
EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
|
EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
|
INTN Instance;
|
EFI_ACPI_COMMON_HEADER *CurrentTable;
|
UINTN TableHandle;
|
UINT32 FvStatus;
|
UINT32 Size;
|
EFI_EVENT Event;
|
EFI_ACPI_TABLE_VERSION TableVersion;
|
EFI_HOB_GUID_TYPE *GuidHob;
|
|
mFirstNotify = FALSE;
|
|
TableVersion = EFI_ACPI_TABLE_VERSION_NONE;
|
Instance = 0;
|
CurrentTable = NULL;
|
TableHandle = 0;
|
|
//
|
// Locate the IIO Protocol Interface
|
//
|
Status = gBS->LocateProtocol (&gEfiIioUdsProtocolGuid,NULL,&mIioUds);
|
ASSERT_EFI_ERROR (Status);
|
|
GuidHob = GetFirstGuidHob (&gEfiMemoryMapGuid);
|
ASSERT (GuidHob != NULL);
|
if (GuidHob == NULL) {
|
return EFI_NOT_FOUND;
|
}
|
mSystemMemoryMap = GET_GUID_HOB_DATA(GuidHob);
|
|
PlatformHookInit ();
|
|
//
|
// Find the AcpiTable protocol
|
//
|
Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, &AcpiTable);
|
ASSERT_EFI_ERROR (Status);
|
|
//
|
// Locate the firmware volume protocol
|
//
|
Status = LocateSupportProtocol (
|
&gEfiFirmwareVolume2ProtocolGuid,
|
&gEfiCallerIdGuid,
|
&FwVol,
|
TRUE
|
);
|
ASSERT_EFI_ERROR (Status);
|
|
Status = EFI_SUCCESS;
|
Instance = 0;
|
|
//
|
// Read tables from the storage file.
|
//
|
while (!EFI_ERROR (Status)) {
|
CurrentTable = NULL;
|
|
Status = FwVol->ReadSection (
|
FwVol,
|
&gEfiCallerIdGuid,
|
EFI_SECTION_RAW,
|
Instance,
|
&CurrentTable,
|
(UINTN *) &Size,
|
&FvStatus
|
);
|
|
if (!EFI_ERROR (Status)) {
|
//
|
// Allow platform specific code to reject the table or update it
|
//
|
{
|
//
|
// Perform any table specific updates.
|
//
|
AcpiStatus = PlatformUpdateTables (CurrentTable, &TableVersion);
|
if (!EFI_ERROR (AcpiStatus)) {
|
//
|
// Add the table
|
//
|
TableHandle = 0;
|
if (TableVersion != EFI_ACPI_TABLE_VERSION_NONE) {
|
AcpiStatus = AcpiTable->InstallAcpiTable (
|
AcpiTable,
|
CurrentTable,
|
CurrentTable->Length,
|
&TableHandle
|
);
|
}
|
ASSERT_EFI_ERROR (AcpiStatus);
|
}
|
}
|
//
|
// Increment the instance
|
//
|
Instance++;
|
}
|
}
|
|
Status = EfiCreateEventReadyToBootEx(
|
TPL_NOTIFY,
|
OnReadyToBoot,
|
NULL,
|
&Event
|
);
|
|
//
|
// Finished
|
//
|
return EFI_SUCCESS;
|
}
|