From 8b2982cd59533486c31f6effae45cdf7899209b8 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Sat, 17 Mar 2018 07:41:44 +0800 Subject: PurleyOpenBoardPkg: Initial version. Cc: Isaac W Oram Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao Reviewed-by: Isaac W Oram --- .../Acpi/BoardAcpiDxe/BoardAcpiDxe.c | 552 +++++++++++++++++++++ 1 file changed, 552 insertions(+) create mode 100644 Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c (limited to 'Platform/Intel/PurleyOpenBoardPkg/Acpi/BoardAcpiDxe/BoardAcpiDxe.c') 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.
+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; +} -- cgit v1.2.3