/** @file Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.
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; }