summaryrefslogtreecommitdiff
path: root/Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c')
-rw-r--r--Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c552
1 files changed, 552 insertions, 0 deletions
diff --git a/Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c b/Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c
new file mode 100644
index 0000000000..b69bd8ace8
--- /dev/null
+++ b/Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c
@@ -0,0 +1,552 @@
+/** @file
+
+Copyright (c) 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 "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));
+ PcdSet64 (PcdAcpiGnvsAddress, (UINT64)(UINTN)mAcpiParameter);
+
+ 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;
+}