/** @file This driver handle msdm OA data between variable and SPI ROM ;****************************************************************************** ;* Copyright (c) 2021, Insyde Software Corporation. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ /** @file Cpu driver, which initializes CPU and implements CPU Architecture Protocol as defined in Framework specification. @copyright INTEL CONFIDENTIAL Copyright 1999 - 2021 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. This file contains an 'Intel Peripheral Driver' and is uniquely identified as "Intel Reference Module" and is licensed for Intel CPUs and chipsets under the terms of your license agreement with Intel or your vendor. This file may be modified by the user, subject to additional terms of the license agreement. @par Specification **/ #include #include #include #include #include #include #include #include #include "CpuInitDxe.h" #include "BiosGuard.h" #include #include #include #include #include #include #include #include //[-start-210318-IB11790410-add]// #include //[-end-210318-IB11790410-add]// // // Private GUIDs for BIOS Guard initializes // extern EFI_GUID gBiosGuardHobGuid; EFI_MP_SERVICES_PROTOCOL *mMpService; UINT32 mCoreTypeBitMap = 0; UINT8 mNumBigCore = 0; UINT8 mNumSmallCore = 0; UINT8 mBigCoreThreads = 0; UINT8 mSmallCoreThreads = 0; UINT8 *mCoreModuleInfo = NULL; UINTN mNumberOfProcessors = 0; UINTN mNumberOfEnabledProcessors = 0; UINT8 mSmallCoreNominalPerformance = 0; static BOOLEAN mSmallCoreNominalPerformanceUpdated = FALSE; /// /// The Cpu Init Data Hob /// GLOBAL_REMOVE_IF_UNREFERENCED CPU_INIT_DATA_HOB *mCpuInitDataHob = NULL; GLOBAL_REMOVE_IF_UNREFERENCED FVID_TABLE *mFvidTable = NULL; GLOBAL_REMOVE_IF_UNREFERENCED CPU_INFO_PROTOCOL *mCpuInfo; GLOBAL_REMOVE_IF_UNREFERENCED UINTN mCommonFeatures; GLOBAL_REMOVE_IF_UNREFERENCED UINTN mSiliconFeatures; /** Set all APs to deepest C-State before ready to boot for better power saving **/ VOID EFIAPI RequestDeepestCStateForAps ( IN EFI_EVENT Event, IN VOID *Context ) { CPUID_MONITOR_MWAIT_ECX MonitorMwaitEcx; CPUID_MONITOR_MWAIT_EDX MonitorMwaitEdx; UINT8 MaxCstate; MSR_BROADWELL_PKG_CST_CONFIG_CONTROL_REGISTER Msr; UINT32 SubStates; /// /// APs should be at deepest C-State before ready to boot for better power saving, /// if boot to DOS/EFI_SHARE or any operating system that running only single thread. /// /// BIOS should use CPUID.(EAX=5) Monitor/Mwait Leaf and also check MSR E2h[3:0] Package C-state limit to determine /// if the processor supports MONITOR/MWAIT extensions for various C-states and sub C-states. /// Msr.Uint64 = AsmReadMsr64 (MSR_BROADWELL_PKG_CST_CONFIG_CONTROL); GetSubCStateSupported ((UINT32 *)&MonitorMwaitEcx, (UINT32 *)&MonitorMwaitEdx); MaxCstate = 0; SubStates = 0; if (MonitorMwaitEcx.Bits.ExtensionsSupported) { switch (Msr.Bits.Limit) { case V_CSTATE_LIMIT_C10: SubStates = MonitorMwaitEdx.Bits.C7States; MaxCstate = 0x60; break; case V_CSTATE_LIMIT_C9: SubStates = MonitorMwaitEdx.Bits.C6States; MaxCstate = 0x50; break; case V_CSTATE_LIMIT_C8: SubStates = MonitorMwaitEdx.Bits.C5States; MaxCstate = 0x40; break; case V_CSTATE_LIMIT_C7S: SubStates = MonitorMwaitEdx.Bits.C4States; MaxCstate = 0x30; break; case V_CSTATE_LIMIT_C7: SubStates = MonitorMwaitEdx.Bits.C4States; MaxCstate = 0x30; break; case V_CSTATE_LIMIT_C6: SubStates = MonitorMwaitEdx.Bits.C3States; MaxCstate = 0x20; break; case V_CSTATE_LIMIT_C3: SubStates = MonitorMwaitEdx.Bits.C2States; MaxCstate = 0x10; break; case V_CSTATE_LIMIT_C1: SubStates = MonitorMwaitEdx.Bits.C1States; MaxCstate = 0x00; break; default: break; } } /// /// If Substates opcode is greater than 1 than add that info to the MaxCstate Opcode. /// if (SubStates > 1) { MaxCstate |= (UINT8) SubStates - 1; } /// /// Update Target C State EAX[7:4] value alone in PcdCpuApTargetCstate /// PcdSet8S (PcdCpuApTargetCstate, MaxCstate >> 4); } /** CpuInitOnReadyToLockCallback - Callback will be triggered when OnReadyToLock event is signaled - Create SMBIOS Table type - FviSmbiosType - Drop into SMM to register IOTRAP for BIOS Guard tools interface @param[in] Event - A pointer to the Event that triggered the callback. @param[in] Context - A pointer to private data registered with the callback function. **/ VOID EFIAPI CpuInitOnReadyToLockCallback ( IN EFI_EVENT Event, IN VOID *Context ) { BIOSGUARD_HOB *BiosGuardHobPtr; MSR_BIOS_INFO_FLAGS_REGISTER MsrBiosInfoFlags; EFI_STATUS Status; VOID *DxeSmmReadyToLock; //[-start-210318-IB11790410-add]// UINT64 BiosInfoFlagsData; //[-end-210318-IB11790410-add]// /// /// Account for the initial call from EfiCreateProtocolNotifyEvent /// Status = gBS->LocateProtocol ( &gEfiDxeSmmReadyToLockProtocolGuid, NULL, &DxeSmmReadyToLock ); if (EFI_ERROR (Status)) { return; } /// /// Close the event /// gBS->CloseEvent (Event); /// /// Enable BIOS Guard Flash Wear-Out Protection mitigation. /// BiosGuardHobPtr = GetFirstGuidHob (&gBiosGuardHobGuid); if (BiosGuardHobPtr != NULL) { if (BiosGuardHobPtr->Bgpdt.BiosGuardAttr & EnumFlashwearoutProtection) { MsrBiosInfoFlags.Uint64 = AsmReadMsr64 (MSR_BIOS_INFO_FLAGS); MsrBiosInfoFlags.Bits.BiosInfoFlagsData = 1; AsmWriteMsr64 (MSR_BIOS_INFO_FLAGS, MsrBiosInfoFlags.Uint64); //[-start-210318-IB11790410-add]// BiosInfoFlagsData = 1; Status = CommonSetVariable ( L"BiosInfoFlagData", &gBiosInfoFlagGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (UINT64), &BiosInfoFlagsData ); if (EFI_ERROR (Status)) { return; } } else { SetVariableToSensitiveVariable ( L"BiosInfoFlagData", &gBiosInfoFlagGuid, 0, 0, NULL ); //[-end-210318-IB11790410-add]// } } return; } /** Collect Cpu Cache Infomation @param[in] CPU_INFO_PROTOCOL *CpuInfo - Pointer to the CPU_INFO_PROTOCOL Structure @retval EFI_SUCCESS - Collect information Successfully. @retval EFI_NOT_FOUND - Specified HOB can not be found. @retval EFI_INVALID_PARAMETER - Input buffer is invalid. **/ EFI_STATUS CollectCpuCacheInfo ( IN CPU_INFO_PROTOCOL *CpuInfo ) { EFI_HOB_GUID_TYPE *CacheInfoHob; CPU_CACHE_INFO *CacheInfoData; UINTN CacheInfoDataSize; UINT8 CoreType; UINT8 CacheCount; UINT8 SmallCoreCacheCount; UINT8 BigCoreCacheCount; UINT8 Index; CacheInfoHob = GetFirstGuidHob (&gCpuCacheInfoHobGuid); if (CacheInfoHob == NULL) { DEBUG ((DEBUG_ERROR, "CPU Cache info HOB not available\n")); return EFI_NOT_FOUND; } CacheInfoData = GET_GUID_HOB_DATA (CacheInfoHob); CacheInfoDataSize = GET_GUID_HOB_DATA_SIZE (CacheInfoHob); CoreType = 0; CacheCount = 0; SmallCoreCacheCount = 0; BigCoreCacheCount = 0; for (Index = 0; Index < CacheInfoDataSize / sizeof (*CacheInfoData); Index++) { switch (CacheInfoData[Index].CoreType) { case CORE_TYPE_NON_HYBRID: if (mNumBigCore != 0 && mNumSmallCore == 0) { CoreType = BIG_CORE; CacheCount = BigCoreCacheCount; BigCoreCacheCount++; } else if (mNumBigCore == 0 && mNumSmallCore != 0) { CoreType = SMALL_CORE; CacheCount = SmallCoreCacheCount; SmallCoreCacheCount ++; } else { ASSERT (FALSE); } break; case CPUID_CORE_TYPE_INTEL_ATOM: CoreType = SMALL_CORE; CacheCount = SmallCoreCacheCount; SmallCoreCacheCount++; break; case CPUID_CORE_TYPE_INTEL_CORE: CoreType = BIG_CORE; CacheCount = BigCoreCacheCount; BigCoreCacheCount++; break; default: DEBUG ((DEBUG_ERROR, "CPU Core type not available\n")); ASSERT (FALSE); break; } CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Type = (UINT8) CacheInfoData[Index].CacheType; CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Level = (UINT8) CacheInfoData[Index].CacheLevel; CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Associativity = CacheInfoData[Index].CacheWays + 1; CpuInfo->CpuInfo[CoreType].CacheInfo[CacheCount].Size = CacheInfoData[Index].CacheSizeinKB; } // // Subtract 1 because there are 2 counts for L1 (Data and Code). // if (SmallCoreCacheCount > 0) { CpuInfo->CpuInfo[SMALL_CORE].MaxCacheSupported = SmallCoreCacheCount - 1; } if (BigCoreCacheCount > 0) { CpuInfo->CpuInfo[BIG_CORE].MaxCacheSupported = BigCoreCacheCount - 1; } return EFI_SUCCESS; } /** Collect Core Type Cpu Infomation @param[in] VOID *Buffer - Pointer to the CORE_INFORMATION Structure @retval EFI_SUCCESS - Successfully prepared. @retval EFI_INVALID_PARAMETER - Input Buffer is invalid. **/ EFI_STATUS CollectCoreTypeCpuInfo ( IN VOID *Buffer ) { CPU_INFO *CoreInfo; CHAR8 *BrandString; UINT32 CpuSignature; UINT8 VfPointIndex; CPUID_BRAND_STRING_DATA BrandStringEax; CPUID_BRAND_STRING_DATA BrandStringEbx; CPUID_BRAND_STRING_DATA BrandStringEcx; CPUID_BRAND_STRING_DATA BrandStringEdx; CPUID_EXTENDED_TOPOLOGY_EBX ExtendedTopologyEbx; CPUID_VERSION_INFO_ECX VersionInfoEcx; CPUID_VERSION_INFO_EDX VersionInfoEdx; CoreInfo = (CPU_INFO *) Buffer; BrandString = CoreInfo->BrandString; if (BrandString == NULL) { return EFI_INVALID_PARAMETER; } /// /// Get Brand string /// AsmCpuid (CPUID_BRAND_STRING1, &BrandStringEax.Uint32, &BrandStringEbx.Uint32, &BrandStringEcx.Uint32, &BrandStringEdx.Uint32); *(UINT32*) BrandString = BrandStringEax.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEbx.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEcx.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEdx.Uint32; BrandString += 4; AsmCpuid (CPUID_BRAND_STRING2, &BrandStringEax.Uint32, &BrandStringEbx.Uint32, &BrandStringEcx.Uint32, &BrandStringEdx.Uint32); *(UINT32*) BrandString = BrandStringEax.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEbx.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEcx.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEdx.Uint32; BrandString += 4; AsmCpuid (CPUID_BRAND_STRING3, &BrandStringEax.Uint32, &BrandStringEbx.Uint32, &BrandStringEcx.Uint32, &BrandStringEdx.Uint32); *(UINT32*) BrandString = BrandStringEax.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEbx.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEcx.Uint32; BrandString += 4; *(UINT32*) BrandString = BrandStringEdx.Uint32; BrandString += 4; *BrandString = '\0'; /// /// Remove leading spaces. After removing leading spaces, the Brand String can not be freed. However, it should never be freed. /// while (*CoreInfo->BrandString == ' ') { ++CoreInfo->BrandString; } /// /// Get information on enabled threads, cores, dies and package for the CPU(s) on this platform /// AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, NULL, &ExtendedTopologyEbx.Uint32, NULL, NULL); CoreInfo->NumSupportedThreadsPerCore = (UINT8) ExtendedTopologyEbx.Uint32; CoreInfo->Voltage = 0; CoreInfo->NumberOfPStates = mFvidTable[0].FvidHeader.EistStates; CoreInfo->CoreVfPointCount = mCpuInitDataHob->CoreVfPointCount; for (VfPointIndex = 0; VfPointIndex < mCpuInitDataHob->CoreVfPointCount; VfPointIndex++) { CoreInfo->CoreVfPointRatio[VfPointIndex] = mCpuInitDataHob->CoreVfPointRatio[VfPointIndex]; } CoreInfo->RingVfPointCount = mCpuInitDataHob->RingVfPointCount; for (VfPointIndex = 0; VfPointIndex < mCpuInitDataHob->RingVfPointCount; VfPointIndex++) { CoreInfo->RingVfPointRatio[VfPointIndex] = mCpuInitDataHob->RingVfPointRatio[VfPointIndex]; } /// /// Gather CPU info /// AsmCpuid (CPUID_VERSION_INFO, &CpuSignature, NULL, &VersionInfoEcx.Uint32, &VersionInfoEdx.Uint32); CoreInfo->CpuSignature = CpuSignature; CoreInfo->Features = LShiftU64 (VersionInfoEcx.Uint32, 32) + VersionInfoEdx.Uint32; if (mCpuInitDataHob->CtdpLevelsSupported > 1 && mCpuInitDataHob->ConfigTdpLevel != 0xFF && mCpuInitDataHob->ApplyConfigTdp == 1) { CoreInfo->IntendedFreq = MsrGetSelectCtdpRatio (mCpuInitDataHob->ConfigTdpLevel) * 100; } else { CoreInfo->IntendedFreq = MsrGetMaxNonTurboRatio () * 100; } return EFI_SUCCESS; } /** Update the Core Infomation for Small Core and Big Core This is executed across all threads **/ VOID UpdateCoreInformation ( VOID ) { EFI_STATUS Status; UINT8 CoreType; UINT8 ModuleId; UINTN ApNumber; MSR_IA32_HWP_CAPABILITIES_REGISTER MsrHwpCapabilities; Status = mMpService->WhoAmI (mMpService, &ApNumber); ASSERT_EFI_ERROR (Status); CoreType = 0; DetectCoreType (&CoreType); ModuleId = (UINT8) (GetCpuApicId () >> 3); // // CoreModule Information has the module ID of the running core and Num of processors in the Module // BITS 7:4 has the Num of processors in that module. // BITS 3:0 denotes the ModuleID of that core // mCoreModuleInfo [ApNumber] = ModuleId; if (CoreType == CPUID_CORE_TYPE_INTEL_ATOM) { if (mNumSmallCore == 0) { CollectCoreTypeCpuInfo (&mCpuInfo->CpuInfo[SMALL_CORE]); } mSmallCoreThreads ++; if (!IsSecondaryThread ()) { mNumSmallCore ++; } if (IsHwpSupported () && (mSmallCoreNominalPerformanceUpdated == FALSE)) { MsrHwpCapabilities.Uint64 = AsmReadMsr64 (MSR_IA32_HWP_CAPABILITIES); mSmallCoreNominalPerformance = (UINT8) MsrHwpCapabilities.Bits.Guaranteed_Performance; mSmallCoreNominalPerformanceUpdated = TRUE; } } else if (CoreType == CPUID_CORE_TYPE_INTEL_CORE) { if (mNumBigCore == 0) { CollectCoreTypeCpuInfo (&mCpuInfo->CpuInfo[BIG_CORE]); } mBigCoreThreads ++; if (!IsSecondaryThread ()) { mNumBigCore ++; } // // If detected Core is BIG, then respective BIT position will be SET. // mCoreTypeBitMap |= (1 << ApNumber); } } /** Initialize CPU info. @retval EFI_SUCCESS - Successfully prepared. @retval EFI_OUT_OF_RESOURCES - Not enough memory to complete the function. **/ EFI_STATUS InitCpuInfo ( VOID ) { EFI_STATUS Status; EFI_HANDLE Handle; UINT8 Index; UINT8 Index2; UINT8 ModuleIdNum; MSR_IA32_PM_ENABLE_REGISTER MsrPmEnable; Handle = NULL; mCpuInfo = AllocateZeroPool (sizeof (CPU_INFO_PROTOCOL)); if (mCpuInfo == NULL) { return EFI_OUT_OF_RESOURCES; } mCpuInfo->CpuInfo = (CPU_INFO*) AllocateZeroPool (CORE_TYPE_NUM * sizeof (CPU_INFO)); if (mCpuInfo->CpuInfo == NULL) { return EFI_OUT_OF_RESOURCES; } for (Index = 0; Index < CORE_TYPE_NUM; Index ++) { mCpuInfo->CpuInfo[Index].BrandString = AllocateZeroPool (MAX_BRANDSTRING_SIZE); if (mCpuInfo->CpuInfo[Index].BrandString == NULL) { return EFI_OUT_OF_RESOURCES; } mCpuInfo->CpuInfo[Index].CacheInfo = (CACHE_DESCRIPTOR_INFO *) AllocateZeroPool (MAX_CACHE_LEVEL_COUNT * sizeof (CACHE_DESCRIPTOR_INFO)); if (mCpuInfo->CpuInfo[Index].CacheInfo == NULL) { return EFI_OUT_OF_RESOURCES; } } if (IsHwpSupported ()) { MsrPmEnable.Uint64 = AsmReadMsr64 (MSR_IA32_PM_ENABLE); MsrPmEnable.Bits.HWP_ENABLE = 1; AsmWriteMsr64 (MSR_IA32_PM_ENABLE, MsrPmEnable.Uint64); } Status = gBS->LocateProtocol ( &gEfiMpServiceProtocolGuid, NULL, (VOID **) &mMpService ); ASSERT_EFI_ERROR (Status); Status = mMpService->GetNumberOfProcessors (mMpService, &mNumberOfProcessors, &mNumberOfEnabledProcessors); DEBUG ((DEBUG_INFO, "Total num of Processors - 0x%x. Enabled Processors - 0x%x\n", mNumberOfProcessors, mNumberOfEnabledProcessors)); mCoreModuleInfo = AllocateZeroPool (mNumberOfProcessors); if (mCoreModuleInfo == NULL) { return EFI_OUT_OF_RESOURCES; } UpdateCoreInformation (); mMpService->StartupAllAPs ( mMpService, // This (EFI_AP_PROCEDURE) UpdateCoreInformation, // Procedure TRUE, // SingleThread NULL, // WaitEvent 0, // TimeoutInMicrosecsond NULL, // ProcedureArgument NULL // FailedCpuList ); DEBUG ((DEBUG_INFO, "Total Enabled Big Core - 0x%x, Total Enabled Small Core - 0x%x\n", mNumBigCore, mNumSmallCore)); DEBUG ((DEBUG_INFO, "Total Enabled Big Core Threads - 0x%x, Total Enabled Small Core Threads- 0x%x\n",mBigCoreThreads, mSmallCoreThreads)); ModuleIdNum = 0; for (Index = 0; Index < mNumberOfEnabledProcessors; Index ++) { for (Index2 = 0; Index2 < mNumberOfEnabledProcessors; Index2 ++) { if ((mCoreModuleInfo[Index] & 0xF) == (mCoreModuleInfo[Index2] & 0xF)) { ModuleIdNum ++; } } mCoreModuleInfo[Index] |= ModuleIdNum << 4; ModuleIdNum = 0; } if (IsHwpSupported ()) { MsrPmEnable.Uint64 = AsmReadMsr64 (MSR_IA32_PM_ENABLE); MsrPmEnable.Bits.HWP_ENABLE = 0; AsmWriteMsr64 (MSR_IA32_PM_ENABLE, MsrPmEnable.Uint64); } CollectCpuCacheInfo (mCpuInfo); if (mNumSmallCore != 0) { mCpuInfo->CpuInfo[SMALL_CORE].NumHts = mSmallCoreThreads / mNumSmallCore; mCpuInfo->CpuInfo[SMALL_CORE].NumCores = mNumSmallCore; } else { mCpuInfo->CpuInfo[SMALL_CORE].NumHts = 0; mCpuInfo->CpuInfo[SMALL_CORE].NumCores = 0; } if (mNumBigCore != 0) { mCpuInfo->CpuInfo[BIG_CORE].NumHts = mBigCoreThreads / mNumBigCore; mCpuInfo->CpuInfo[BIG_CORE].NumCores = mNumBigCore; } else { mCpuInfo->CpuInfo[BIG_CORE].NumHts = 0; mCpuInfo->CpuInfo[BIG_CORE].NumCores = 0; } mCpuInfo->Revision = CPU_INFO_PROTOCOL_REVISION; mCpuInfo->CpuCommonFeatures = mCommonFeatures | (mSiliconFeatures << 10); /// Update per core OC ratio information if (mCpuInitDataHob->PerCoreRatioOverride) { mCpuInfo->CpuInfo[SMALL_CORE].PerCoreRatioOverride = (UINT8) mCpuInitDataHob->PerCoreRatioOverride; mCpuInfo->CpuInfo[BIG_CORE].PerCoreRatioOverride = (UINT8) mCpuInitDataHob->PerCoreRatioOverride; for (Index = 0; Index < CPU_MAX_BIG_CORES; Index++) { mCpuInfo->CpuInfo[BIG_CORE].PerCoreRatio[Index] = mCpuInitDataHob->PerCoreRatio[Index]; } for (Index = 0; Index < CPU_MAX_ATOM_CLUSTERS; Index++) { mCpuInfo->CpuInfo[SMALL_CORE].PerCoreRatio[Index] = mCpuInitDataHob->PerAtomClusterRatio[Index]; } } /// /// Install CPU info protocol /// gBS->InstallMultipleProtocolInterfaces ( &Handle, &gCpuInfoProtocolGuid, mCpuInfo, NULL ); return EFI_SUCCESS; } /** Initialize the state information for the CPU Architectural Protocol @param[in] ImageHandle - Image handle of the loaded driver @param[in] SystemTable - Pointer to the System Table @retval EFI_SUCCESS - Thread was successfully created @retval EFI_OUT_OF_RESOURCES - Can not allocate protocol data structure @retval EFI_DEVICE_ERROR - Can not create the thread @retval EFI_NOT_FOUND - Can not locate CPU Data HOB **/ EFI_STATUS EFIAPI InitializeCpu ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; VOID *Hob; EFI_EVENT LegacyBootEvent; EFI_EVENT ExitBootServicesEvent; VOID *Registration; MSR_MISC_PWR_MGMT_REGISTER MiscPowerManagement; BOOLEAN HdcSupported; #if FixedPcdGetBool(PcdBiosGuardEnable) == 1 BIOSGUARD_HOB *BiosGuardHobPtr; #endif /// /// Get CPU Init Data Hob /// Hob = GetFirstGuidHob (&gCpuInitDataHobGuid); if (Hob == NULL) { DEBUG ((DEBUG_ERROR, "CPU Data HOB not available\n")); return EFI_NOT_FOUND; } MiscPowerManagement.Uint64 = AsmReadMsr64 (MSR_MISC_PWR_MGMT); HdcSupported = (MiscPowerManagement.Bits.EnableSdc != 0); mCpuInitDataHob = (CPU_INIT_DATA_HOB *) ((UINTN) Hob + sizeof (EFI_HOB_GUID_TYPE)); mSiliconFeatures = ((HdcSupported) << N_HDC_SUPPORT) & B_HDC_SUPPORT; mFvidTable = (FVID_TABLE *) &(mCpuInitDataHob->FvidTable); /// /// Initialize DxeCpuInfo protocol instance and gather CPU information /// Status = InitCpuInfo (); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Failed to initialize DxeCpuInfo\n")); } /// /// Create an OnReadyToLock protocol callback event for BIOS Guard. /// This function causes CpuInitOnReadyToLockCallback() to be executed, /// Ensure CpuInitOnReadyToLockCallback() accounts for this initial call. /// EfiCreateProtocolNotifyEvent ( &gEfiDxeSmmReadyToLockProtocolGuid, TPL_CALLBACK, CpuInitOnReadyToLockCallback, NULL, &Registration ); CpuAcpiInit (ImageHandle); #if FixedPcdGetBool(PcdBiosGuardEnable) == 1 /// /// Get Bios Guard Config Hob /// BiosGuardHobPtr = GetFirstGuidHob (&gBiosGuardHobGuid); if (BiosGuardHobPtr != NULL) { /// /// Determine if BGUP is to be placed in TSEG /// If the size allocated to Bios Guard in DPR is 0, BGUP will be stored in TSEG /// Otherwise, BGUP will use the memory allocated within DPR and /// will initialize the Bios Guard NVS related variables /// DEBUG ((DEBUG_INFO, "\n BiosGuardMemSize :%x \n",BiosGuardHobPtr->BiosGuardMemSize)); if (BiosGuardHobPtr->BiosGuardMemSize != 0) { BiosGuardAcpiInit (ImageHandle); } } else { DEBUG ((DEBUG_ERROR, "Bios Guard Config HOB not available, Bios Guard NVS variables not initialized\n")); } #endif TxtNvsUpdate (); // // Set PCD to request deepest C-states in monitor/mwait right before boot. // Use TPL_NOTIFY signal to trigger callback before TPL_CALLBACK signal used by // UefiCpuPkg to put APs in deep sleep before giving control to OS. // Status = gBS->CreateEvent ( EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, RequestDeepestCStateForAps, NULL, &ExitBootServicesEvent ); ASSERT_EFI_ERROR (Status); Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, RequestDeepestCStateForAps, NULL, &gEfiEventLegacyBootGuid, &LegacyBootEvent ); ASSERT_EFI_ERROR (Status); return EFI_SUCCESS; }