summaryrefslogtreecommitdiff
path: root/Core/CPU/CpuPei.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/CPU/CpuPei.c')
-rw-r--r--Core/CPU/CpuPei.c936
1 files changed, 936 insertions, 0 deletions
diff --git a/Core/CPU/CpuPei.c b/Core/CPU/CpuPei.c
new file mode 100644
index 0000000..901171b
--- /dev/null
+++ b/Core/CPU/CpuPei.c
@@ -0,0 +1,936 @@
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1987-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+
+//**********************************************************************
+// $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.c 9 8/05/14 2:21a Crystallee $
+//
+// $Revision: 9 $
+//
+// $Date: 8/05/14 2:21a $
+//**********************************************************************
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/Haswell/AMI Cpu PKG/CPU Core/CpuPei.c $
+//
+// 9 8/05/14 2:21a Crystallee
+// [TAG] EIPNone
+// [Category] Improvement
+// [Description] For backward compatible, add old MTRR setting method
+// back. Change new MTRR setting method to Policy2.
+//
+// 8 7/16/14 4:12a Crystallee
+// [TAG] EIPNone
+// [Category] Improvement
+// [Description] Add WbMemMap and UcMemMap vectors size to prevent
+// accessing out of bound.
+//
+// 7 7/08/14 3:35a Crystallee
+// [TAG] EIPNone
+// [Category] Improvement
+// [Description] Add all the possible methods to describing memory in
+// MTRRS.
+// [Files] CpuPei.c, CpuPei.h, CpuPeiFuncs.c
+//
+// 6 6/25/14 2:15a Davidhsieh
+// [TAG] None
+// [Category] Improvement
+// [Description] Add APIC version information in CpuInfoHob
+//
+// 5 6/13/14 2:22a Davidhsieh
+// [TAG] EIP173454
+// [Category] Improvement
+// [Description] Add TSEG address and size in CpuInfoHob
+//
+// 4 9/05/12 1:40a Davidhsieh
+// Rename PEI_IFFS_TRANSITION_START_PPI_GUID to
+// PEI_RAPID_START_TRANSITION_START_PPI_GUID
+//
+// 3 3/16/12 3:11a Davidhsieh
+// Setup items create for CPU RC policy
+//
+// 2 3/09/12 2:13a Davidhsieh
+// Create BIST data
+//
+// 1 2/07/12 3:58a Davidhsieh
+//
+//**********************************************************************
+
+//<AMI_FHDR_START>
+//---------------------------------------------------------------------------
+// Name: CpuPei.c
+//
+// Description:
+// This file is the main CPU PEI component file. This component utilizes
+// CPU I/O & PCI CFG PPI to publish early CPU Init PPI which can be used
+// by NB PEI to load itself. Also this file contains a CPU init routine
+// to be executed in permanent memory present environment. This is handled
+// by issuing a notifyPPI on permanent memory PPI.
+//
+//---------------------------------------------------------------------------
+//<AMI_FHDR_END>
+
+#include "cpu.h"
+#include "AmiCspLibInc.h"
+#include <AmiPeiLib.h>
+#include <core\PeiHob.h>
+#include <token.h>
+#include <Ppi\ReadOnlyVariable.h>
+#include "CpuPei.h"
+
+#define EFI_HT_BIST_HOB_GUID \
+ { \
+ 0xbe644001, 0xe7d4, 0x48b1, 0xb0, 0x96, 0x8b, 0xa0, 0x47, 0xbc, 0x7a, 0xe7 \
+ }
+
+typedef struct _CPU_BIST_HOB {
+ EFI_HOB_GENERIC_HEADER Header;
+ EFI_GUID Name;
+ UINT32 ApicId;
+ UINT32 BIST;
+} CPU_BIST_HOB;
+
+// Setup GUID variables for installing, locating and notifying PPIs
+EFI_GUID gPeiCachePpiGuid = PEI_CACHE_PPI_GUID;
+EFI_GUID gEfiPeiEndOfPeiPhasePpiGuid = EFI_PEI_END_OF_PEI_PHASE_PPI_GUID;
+EFI_GUID gAmiCpuinfoHobGuid = AMI_CPUINFO_HOB_GUID;
+EFI_GUID gEfiPeiReadOnlyVariablePpiGuid = EFI_PEI_READ_ONLY_VARIABLE_PPI_GUID;
+EFI_GUID gAmiInternaluCodeHobGuid = AMI_INTERNAL_UCODE_HOB_GUID;
+EFI_GUID gSmmHobGuid = SMM_HOB_GUID;
+EFI_GUID gPeiRapidStartTransitionStartPpiGuid = PEI_RAPID_START_TRANSITION_START_PPI_GUID;
+//EFI_GUID gCacheInstallGuid = EFI_CACHE_INSTALL_PPI_GUID;
+EFI_GUID gAmiStatusCodeCpuBistDataGuid = AMI_STATUS_CODE_CPU_BIST_DATA_GUID;
+EFI_GUID gEfiHtBistHobGuid = EFI_HT_BIST_HOB_GUID;
+
+EFI_STATUS NotifyAtPeiEnd (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+);
+
+EFI_PEI_NOTIFY_DESCRIPTOR CpuNotifyDescs = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiEndOfPeiPhasePpiGuid,
+ NotifyAtPeiEnd
+};
+
+/*EFI_PEI_PPI_DESCRIPTOR CacheInstallPpi[] = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gCacheInstallGuid,
+ NULL
+};*/
+
+EFI_PEI_PPI_DESCRIPTOR IffsTransitionStartPpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), \
+ &gPeiRapidStartTransitionStartPpiGuid,
+ NULL
+};
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+//
+// Procedure: ReportBistStatusCodes
+//
+// Description: Report the BIST Status Code.
+//
+// Input: VOID
+//
+// Output: VOID
+//
+//---------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID ReportBistStatusCodes(IN EFI_PEI_SERVICES **PeiServices, IN CPUINFO_HOB *CpuInfoHob, IN UINT32 NumCpus)
+{
+ UINT32 i;
+ AMI_STATUS_CODE_CPU_BIST_DATA BistData;
+
+ BistData.DataHeader.HeaderSize = sizeof(EFI_STATUS_CODE_DATA);
+ BistData.DataHeader.Size = sizeof(UINT32);
+ MemCpy(&BistData.DataHeader.Type, &gAmiStatusCodeCpuBistDataGuid, sizeof(EFI_GUID));
+
+ for (i = 0; i < NumCpus; ++i) {
+ if (CpuInfoHob->Cpuinfo[i].BIST != 0) {
+ PEI_TRACE((-1, PeiServices, "CpuInfo[%x].BIST = %x \n", i, CpuInfoHob->Cpuinfo[i].BIST));
+ BistData.Bist = CpuInfoHob->Cpuinfo[i].BIST;
+
+ (*PeiServices)->ReportStatusCode(
+ PeiServices,
+ EFI_ERROR_CODE| EFI_ERROR_MAJOR,
+ PEI_CPU_SELF_TEST_FAILED,
+ CpuInfoHob->Cpuinfo[i].ApicId,
+ NULL,
+ (EFI_STATUS_CODE_DATA*)&BistData
+ );
+ }
+ }
+}
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: CreateCpuHobWithDefaults
+//
+// Description: Create CPU Hob and fill in default data.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// IN UINT8 NumCpus
+//
+// Output:
+// CPUINFO_HOB *
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+CPUINFO_HOB * CreateCpuHobWithDefaults(EFI_PEI_SERVICES **PeiServices, UINT8 NumCpus)
+{
+ CPUINFO_HOB *CpuinfoHob;
+ EFI_STATUS Status;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ UINT8 i;
+ VOID *FirstHob;
+ CPU_BIST_HOB *SecBistHob;
+
+ //Create hob for storing Cpu Data
+ Status = (**PeiServices).CreateHob(PeiServices,
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ //NOTE: sizeof(CPUINFO_HOB) already includes size of one CPUINFO structure
+ sizeof(CPUINFO_HOB) + (NumCpus - 1) * sizeof(CPUINFO),
+ &CpuinfoHob
+ );
+ ASSERT_PEI_ERROR(PeiServices, Status);
+
+ CpuinfoHob->EfiHobGuidType.Name = gAmiCpuinfoHobGuid;
+ CpuinfoHob->CpuCount = NumCpus;
+ CpuinfoHob->NodeCount = NUMBER_CPU_SOCKETS;
+ CpuinfoHob->CacheLineSize = 64;
+
+ CpuinfoHob->TsegAddress = NBGetTsegBase();
+ CpuinfoHob->TsegSize = TSEG_SIZE;
+
+
+ for(i = 0; i < NumCpus; ++i) {
+ CpuinfoHob->Cpuinfo[i].Valid = FALSE;
+ CpuinfoHob->Cpuinfo[i].Disabled = FALSE;
+ CpuinfoHob->Cpuinfo[i].BIST = 0;
+ CpuinfoHob->Cpuinfo[i].ApicVer = (UINT8)MemRead32((UINT32*)(UINTN)(LOCAL_APIC_BASE + APIC_VERSION_REGISTER));
+ }
+//Save BSP features to CpuinfoHob
+ CPULib_CpuID(0x01, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ CpuinfoHob->CpuFeatures.FeatureEcx = RegEcx;
+ CpuinfoHob->CpuFeatures.FeatureEdx = RegEdx;
+
+ CPULib_CpuID(0x80000001, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ CpuinfoHob->CpuFeatures.ExtFeatureEax = RegEax;
+ CpuinfoHob->CpuFeatures.ExtFeatureEbx = RegEbx;
+ CpuinfoHob->CpuFeatures.ExtFeatureEcx = RegEcx;
+ CpuinfoHob->CpuFeatures.ExtFeatureEdx = RegEdx;
+
+ (*PeiServices)->GetHobList(PeiServices, &FirstHob);
+ if (!FirstHob) ASSERT_PEI_ERROR(PeiServices, EFI_NOT_FOUND);
+
+ (VOID*)SecBistHob = FirstHob;
+ while (!EFI_ERROR(Status = FindNextHobByType(EFI_HOB_TYPE_GUID_EXTENSION, &SecBistHob))) {
+ if (guidcmp(&((EFI_HOB_GUID_TYPE*)SecBistHob)->Name, &gEfiHtBistHobGuid) == 0) {
+ break;
+ }
+ }
+
+ if (!EFI_ERROR(Status)) {
+ CpuinfoHob->Cpuinfo[SecBistHob->ApicId].BIST = SecBistHob->BIST;
+ }
+
+ return CpuinfoHob;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: UpdateOrCreateCpuHob
+//
+// Description: Finds or Create Cpu Hob and initialize it.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+//
+// Output:
+// VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+
+VOID UpdateOrCreateCpuHob(EFI_PEI_SERVICES **PeiServices)
+{
+ VOID *FirstHob;
+ EFI_HOB_CPU *CpuHob;
+ UINT32 RegEax;
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+ EFI_STATUS Status;
+
+ (*PeiServices)->GetHobList(PeiServices, &FirstHob);
+ if (!FirstHob) ASSERT_PEI_ERROR(PeiServices, EFI_NOT_FOUND);
+
+ CpuHob = (EFI_HOB_CPU*) FirstHob;
+ Status = FindNextHobByType(EFI_HOB_TYPE_CPU, &CpuHob);
+ if (EFI_ERROR(Status)) {
+ Status = (**PeiServices).CreateHob(PeiServices,
+ EFI_HOB_TYPE_CPU,
+ sizeof(CpuHob),
+ &CpuHob
+ );
+ ASSERT_PEI_ERROR(PeiServices, Status);
+
+ CpuHob->SizeOfMemorySpace = 0xff;
+ MemSet(CpuHob->Reserved, 6, 0);
+ }
+
+ CPULib_CpuID(0x80000008, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+ RegEax &= 0xff;
+ if (RegEax < CpuHob->SizeOfMemorySpace) CpuHob->SizeOfMemorySpace = RegEax;
+ CpuHob->SizeOfIoSpace = 16;
+}
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: NotifyAtPeiEnd
+//
+// Description: According to resource descriptor HOBs to config system cache.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor
+// IN VOID *Ppi
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS NotifyAtPeiEnd (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+)
+{
+ EFI_STATUS Status;
+ PEI_CACHE_PPI *CachePpi;
+ UINT64 MaxMemoryLength;
+ EFI_BOOT_MODE BootMode;
+
+#if MTRR_POLICY == 1
+ EFI_PEI_HOB_POINTERS Hob;
+ UINT64 Above4GMemoryLength = 0;
+ MEMORY_MAP WbMemMap[12]; //Memory map of wb regions.
+ MEMORY_MAP UcMemMap[12]; //Memory map of uc regions.
+ UINTN i;
+#endif
+ //
+ //Get bootmode
+ //
+ Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode);
+ PEI_TRACE((-1, PeiServices, "CPUPEI Get boot mode in end of PEI\n"));
+
+ if (BootMode == BOOT_ON_S3_RESUME){
+ PEI_TRACE((-1, PeiServices, "CPUPEI boot mode is S3 in end of PEI\n"));
+ //Trigger SWSMI to save CPU fixed & varible MTRRs
+ IoWrite8(SW_SMI_IO_ADDRESS, SW_SMI_RESTORE_MSR);
+ IoWrite8(SW_SMI_IO_ADDRESS, SW_SMI_S3_RESTORE_MSR_FROM_SDL);
+ }else{
+ //
+ // Load Cache PPI
+ //
+ Status = (*PeiServices)->LocatePpi(
+ PeiServices,
+ &gPeiCachePpiGuid,
+ 0,
+ NULL,
+ &CachePpi
+ ) ;
+ ASSERT_PEI_ERROR (PeiServices, Status);
+#if MTRR_POLICY == 1
+ //if MTRR_POLICY = 1, init MTRR above4G here
+ Above4GMemoryLength = 0;
+ (*PeiServices)->GetHobList(PeiServices, &Hob.Raw);
+ //Get above 4G memory length
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
+ ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED))
+ ) {
+ if (Hob.ResourceDescriptor->PhysicalStart >= SIZE_4G
+ && Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ Above4GMemoryLength += (Hob.ResourceDescriptor->ResourceLength);
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ //
+ // Program the MTRR for above 4G memory range if it exist
+ // or just disable cache flash range
+ //
+ if (Above4GMemoryLength > 0) {
+ Status = InitMtrrPolicy1(PeiServices, WbMemMap, UcMemMap, Above4GMemoryLength);
+ if(EFI_ERROR(Status))
+ Status = InitMtrrPolicy2(PeiServices, WbMemMap, UcMemMap, Above4GMemoryLength);
+
+ //If cache map init successful, start program MTRR
+ if(!EFI_ERROR(Status)){
+ CachePpi->ResetCache(
+ PeiServices,
+ CachePpi);
+ //WB region start first
+ for(i = 0; i < 10 ;i++){
+ CachePpi->SetCache(
+ PeiServices,
+ CachePpi,
+ WbMemMap[i].Base,
+ WbMemMap[i].Len,
+ EfiCacheTypeWriteBack);
+ if(WbMemMap[i + 1].Len == 0) break;
+ }
+ //UC region start
+ if(UcMemMap[0].Len != 0){
+ for(i = 0; i < 10 ;i++){
+ CachePpi->SetCache(
+ PeiServices,
+ CachePpi,
+ UcMemMap[i].Base,
+ UcMemMap[i].Len,
+ EfiCacheTypeUncacheable);
+ if(UcMemMap[i + 1].Len == 0) break;
+ }
+ }
+ //
+ // Programm fix MTRRs WB from 0 to A0000
+ //
+ CachePpi->SetCache(
+ PeiServices,
+ CachePpi,
+ 0,
+ 640*1024,
+ EfiCacheTypeWriteBack );
+ } else{ //Get MTRR setting fail, still need disable cache flash range
+ MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE);
+ if (MaxMemoryLength < FLASH_SIZE) {
+ MaxMemoryLength = Shl64 (MaxMemoryLength, 1);
+ }
+ PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength)));
+ Status = CachePpi->SetCache (
+ PeiServices,
+ CachePpi,
+ (SIZE_4G - MaxMemoryLength),
+ MaxMemoryLength,
+ EfiCacheTypeUncacheable
+ );
+
+ if (Status) PEI_TRACE((-1, PeiServices, "Disabling Flash Area Cache Error!!\n"));
+ }
+ } else{ // if (Above4GMemoryLength > 0)
+ MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE);
+ if (MaxMemoryLength < FLASH_SIZE) {
+ MaxMemoryLength = Shl64 (MaxMemoryLength, 1);
+ }
+ PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength)));
+ Status = CachePpi->SetCache (
+ PeiServices,
+ CachePpi,
+ (SIZE_4G - MaxMemoryLength),
+ MaxMemoryLength,
+ EfiCacheTypeUncacheable
+ );
+
+ if (Status) PEI_TRACE((-1, PeiServices, "Disabling Flash Area Cache Error!!\n"));
+ }
+ //
+ //Disable NEM, Update MTRR setting from MTRR buffer
+ //
+ CachePpi->ActivateCache (PeiServices, CachePpi);
+#else
+ //
+ // MTRR for above 4G memory range is already done at this point,
+ // only disable cache flash range is required
+ //
+
+ MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE);
+ if (MaxMemoryLength < FLASH_SIZE) {
+ MaxMemoryLength = Shl64 (MaxMemoryLength, 1);
+ }
+
+ PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength)));
+ Status = CachePpi->SetCache (
+ PeiServices,
+ CachePpi,
+ (SIZE_4G - MaxMemoryLength),
+ MaxMemoryLength,
+ EfiCacheTypeUncacheable );
+
+ if (Status) PEI_TRACE((-1, PeiServices, "Disabling Flash Area Cache Error!!\n"));
+
+ //
+ //Disable NEM, Update MTRR setting from MTRR buffer
+ //
+ CachePpi->ActivateCache (PeiServices, CachePpi);
+#endif
+ }
+
+ return Status;
+}
+
+
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: SetupCache
+//
+// Description: According to resource descriptor HOBs to config system cache.
+//
+// Input:
+// IN EFI_PEI_SERVICES **PeiServices
+// IN EFI_BOOT_MODE BootMode
+//
+// Output:
+// VOID
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID SetupCache ( IN EFI_PEI_SERVICES **PeiServices, IN EFI_BOOT_MODE BootMode)
+{
+ EFI_STATUS Status;
+ PEI_CACHE_PPI *CachePpi;
+ UINT64 MemoryLength;
+ UINT64 MemoryLengthUc;
+ UINT64 MaxMemoryLength;
+ UINT64 CurrentBaseAddress;
+ UINT64 Above4GMemoryLength;
+ UINT64 PowerTwo;
+ UINT64 PowerTwoEnd;
+ UINT8 MtrrCount = 0;
+#if MTRR_POLICY == 0
+ EFI_PEI_HOB_POINTERS Hob;
+#endif
+ //
+ // Load Cache PPI
+ //
+ Status = (*PeiServices)->LocatePpi(
+ PeiServices,
+ &gPeiCachePpiGuid,
+ 0,
+ NULL,
+ &CachePpi
+ ) ;
+ ASSERT_PEI_ERROR (PeiServices, Status);
+
+ //
+ // Clear the CAR Settings
+ //
+ CachePpi->ResetCache(
+ PeiServices,
+ CachePpi
+ );
+
+
+ //
+ // Parse the HOB list and determine the amount of memory installed
+ // The first 1MB will be set until overridden by the CSM.
+ // The above 4G memory length will be calculated separately.
+ //
+
+ MemoryLength = SIZE_1M;
+ Above4GMemoryLength = 0;
+
+ MemoryLength = (UINT64)NBGetTsegBase() + TSEG_SIZE;
+ PEI_TRACE((-1, PeiServices, "Memory Length below 4G= %lx.\n", MemoryLength));
+
+ //
+ // Record the current address
+ //
+ CurrentBaseAddress = 0;
+ //
+ // Set WB loop first
+ //
+
+ for (PowerTwo = SIZE_2G, PowerTwoEnd = SIZE_64M; PowerTwo >= PowerTwoEnd; PowerTwo = Shr64 (PowerTwo, 1)) {
+ if (MemoryLength >= PowerTwo && MtrrCount < 8) {
+ PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", PowerTwo, CurrentBaseAddress));
+ CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, PowerTwo, EfiCacheTypeWriteBack);
+ MtrrCount++;
+ CurrentBaseAddress += PowerTwo;
+ MemoryLength -= PowerTwo;
+ }
+ }
+ //
+ // Get Max Address for WB/UC
+ //
+ if (MemoryLength == GetPowerOfTwo64 (MemoryLength)) {
+ MaxMemoryLength = MemoryLength;
+ } else {
+ MaxMemoryLength = GetPowerOfTwo64 (Shl64 (MemoryLength, 1));
+ }
+ //
+ // Set the MAX memory range as WB
+ //
+ if (MaxMemoryLength != 0 && MtrrCount < 8) {
+ PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", MaxMemoryLength, CurrentBaseAddress));
+ CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, MaxMemoryLength, EfiCacheTypeWriteBack);
+ MtrrCount++;
+ }
+ //
+ // Start Setting UC here
+ //
+ while (MaxMemoryLength != MemoryLength) {
+ if (MtrrCount == 8) break;
+ MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);
+ PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx.\n", MemoryLengthUc, CurrentBaseAddress + MaxMemoryLength - MemoryLengthUc));
+ CachePpi->SetCache (
+ PeiServices,
+ CachePpi,
+ CurrentBaseAddress + MaxMemoryLength - MemoryLengthUc,
+ MemoryLengthUc,
+ EfiCacheTypeUncacheable
+ );
+ MtrrCount++;
+ MaxMemoryLength -= MemoryLengthUc;
+ }
+
+#if MTRR_POLICY == 0
+ //
+ // Program the MTRR for above 4G memory range
+ // if MTRR_POLICY = 1, program the MTRR for above 4G memory range at end of PEI
+ //
+ if (BootMode != BOOT_ON_S3_RESUME){
+ (*PeiServices)->GetHobList(PeiServices, &Hob.Raw);
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
+ if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
+ ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED))
+ ) {
+ //
+ // Calculate the memory above 4G
+ //
+ if (Hob.ResourceDescriptor->PhysicalStart >= SIZE_4G
+ && Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
+ Above4GMemoryLength += (Hob.ResourceDescriptor->ResourceLength);
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ }
+ PEI_TRACE((-1, PeiServices, "Memory Length Above 4G= %lx.\n", Above4GMemoryLength));
+ if (Above4GMemoryLength > 0) {
+ CurrentBaseAddress = SIZE_4G;
+ while (Above4GMemoryLength >= SIZE_4G) {
+ if (MtrrCount == 10) break;
+ PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", SIZE_4G, CurrentBaseAddress));
+ CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, SIZE_4G, EfiCacheTypeWriteBack);
+ MtrrCount++;
+ Above4GMemoryLength -= SIZE_4G;
+ CurrentBaseAddress += SIZE_4G;
+ }
+ //
+ // Set WB loop first
+ //
+ for (PowerTwo = SIZE_2G, PowerTwoEnd = SIZE_256M; PowerTwo >= PowerTwoEnd; PowerTwo = Shr64 (PowerTwo, 1)) {
+ if (MtrrCount == 10) break;
+ if (Above4GMemoryLength >= PowerTwo) {
+ PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", PowerTwo, CurrentBaseAddress));
+ CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, PowerTwo, EfiCacheTypeWriteBack);
+ MtrrCount++;
+ CurrentBaseAddress += PowerTwo;
+ Above4GMemoryLength -= PowerTwo;
+ }
+ }
+ //
+ // Get Max Address for WB/UC
+ //
+ if (Above4GMemoryLength == GetPowerOfTwo64 (Above4GMemoryLength)) {
+ MaxMemoryLength = Above4GMemoryLength;
+ } else {
+ MaxMemoryLength = GetPowerOfTwo64 (Shl64(Above4GMemoryLength, 1));
+ }
+ //
+ // Set the MAX memory range as WB
+ //
+ if (MaxMemoryLength != 0 && MtrrCount < 10) {
+ //PEI_TRACE((-1, PeiServices, "WB Memory Length = %08lx at %09lx.\n", MaxMemoryLength, CurrentBaseAddress));
+ CachePpi->SetCache (PeiServices, CachePpi, CurrentBaseAddress, MaxMemoryLength, EfiCacheTypeWriteBack);
+ MtrrCount++;
+ }
+ //
+ // Start Setting UC here
+ //
+ while (MaxMemoryLength != Above4GMemoryLength) {
+ if (MtrrCount == 10) break;
+ MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - Above4GMemoryLength);
+ if (MtrrCount == 9 && (MaxMemoryLength - Above4GMemoryLength) != MemoryLengthUc) {
+ MemoryLengthUc = Shl64 (MemoryLengthUc, 1);
+ }
+ PEI_TRACE((-1, PeiServices, "UC Memory Length = %08lx at %09lx.\n", MemoryLengthUc, CurrentBaseAddress + MaxMemoryLength - MemoryLengthUc));
+ CachePpi->SetCache (
+ PeiServices,
+ CachePpi,
+ (CurrentBaseAddress+ MaxMemoryLength - MemoryLengthUc),
+ MemoryLengthUc,
+ EfiCacheTypeUncacheable
+ );
+ MtrrCount++;
+ MaxMemoryLength -= MemoryLengthUc;
+ }
+ }
+#endif
+ //
+ // Programm fix MTRRs WB from 0 to A0000
+ //
+ PEI_TRACE((-1, PeiServices, "WB Memory Length = %08x at %09x.\n", 640*1024, 0));
+ CachePpi->SetCache(
+ PeiServices,
+ CachePpi,
+ 0,
+ 640*1024,
+ EfiCacheTypeWriteBack
+ );
+
+#if PEI_CACHE_FLASH_ENABLED
+ //
+ // Cache Flash Area
+ //
+ MaxMemoryLength = GetPowerOfTwo64 (FLASH_SIZE);
+ if (MaxMemoryLength < FLASH_SIZE) {
+ MaxMemoryLength = Shl64 (MaxMemoryLength, 1);
+ }
+
+ PEI_TRACE((-1, PeiServices, "WP Memory Length = %08lx at %09lx.\n", MaxMemoryLength, (SIZE_4G - MaxMemoryLength)));
+ Status = CachePpi->SetCache (
+ PeiServices,
+ CachePpi,
+ (SIZE_4G - MaxMemoryLength),
+ MaxMemoryLength,
+ EfiCacheTypeWriteProtected
+ );
+
+ if (Status) PEI_TRACE((-1, PeiServices, "Flash Area Caching Error!!\n"));
+#endif
+ //
+ //Disable NEM, Update MTRR setting from MTRR buffer
+ //
+ CachePpi->ActivateCache (PeiServices, CachePpi);
+
+ //Call back to disable caching flash at end of PEI.
+ (*PeiServices)->NotifyPpi(
+ PeiServices,
+ &CpuNotifyDescs
+ );
+ //
+ // Install EFI_CACHE_INSTALL_PPI_GUID to indicate memory and CPU cache are initialzed.
+ //
+ /*Status = (*PeiServices)->InstallPpi (
+ PeiServices,
+ CacheInstallPpi);
+ ASSERT_PEI_ERROR(PeiServices, Status);*/
+}
+//<AMI_PHDR_START>
+//---------------------------------------------------------------------------
+// Procedure: CpuPeiEntry
+//
+// Description: AMI CPU PEI driver entry
+//
+// Input:
+// IN EFI_FFS_FILE_HEADER *FfsHeader
+// IN EFI_PEI_SERVICES **PeiServices
+//
+// Output:
+// EFI_STATUS
+//
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS CpuPeiEntry(
+ IN EFI_FFS_FILE_HEADER *FfsHeader,
+ IN EFI_PEI_SERVICES **PeiServices
+)
+{
+ EFI_PEI_READ_ONLY_VARIABLE_PPI *ReadOnlyVariable;
+ EFI_BOOT_MODE BootMode;
+ EFI_STATUS Status;
+ CPUINFO_HOB *CpuinfoHob;
+ UINT32 NumCpus;
+ BOOLEAN X2ApicEnabled = FALSE;
+ BOOLEAN Serialize = FALSE;
+ UINT32 CpuSignature = GetCpuSignature();
+ UINT32 CpuSigNoVer = CpuSignature & 0xfffffff0;
+ VOID *MicrocodeAddr = NULL;
+ UINT32 MicrocodeSize = 0;
+ EFI_PHYSICAL_ADDRESS MicrocodeBuffer;
+ AMI_INTERNAL_UCODE_HOB *uCodeHob;
+ UINT32 Tseg = (UINT32)NBGetTsegBase();
+ SMM_HOB *SmmHob;
+ UINT32 SmmBspBase;
+ UINT32 SmmCpuBase;
+ UINT32 SmmBase;
+ UINT32 LargestSmmBase;
+ UINT32 MaxCpusBeforeOverlap;
+ UINT32 BeforeOverlapCount;
+ UINT32 NextUnoverlapSmmBase;
+ UINT32 i;
+
+ PEI_PROGRESS_CODE(PeiServices, PEI_CPU_INIT);
+
+ Status = (*PeiServices)->LocatePpi(
+ PeiServices, &gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, &ReadOnlyVariable
+ );
+ ASSERT_PEI_ERROR(PeiServices, Status);
+
+ Status = (*PeiServices)->GetBootMode(PeiServices, &BootMode);
+ ASSERT_PEI_ERROR(PeiServices, Status);
+
+ SetupCache(PeiServices, BootMode);
+ UpdateOrCreateCpuHob(PeiServices);
+
+ Status = (*PeiServices)->InstallPpi( PeiServices, \
+ &IffsTransitionStartPpiDescriptor);
+
+ //After initialized, APs are in holding loop until halted.
+ NumCpus = (UINT32)((UINT8)ReadMsr(MSR_CORE_THREAD_COUNT));
+
+ PEI_TRACE((-1, PeiServices, "Cpu Pei - number of Cpus %x\n",NumCpus ));
+ CpuinfoHob = CreateCpuHobWithDefaults(PeiServices, NumCpus);
+
+ CpuinfoHob->BspNo = 0;
+
+ ReportBistStatusCodes(PeiServices, CpuinfoHob, NumCpus);
+ //Create Smm Hob
+ Status = (*PeiServices)->CreateHob(
+ PeiServices,
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof(SMM_HOB)+ (NumCpus - 1) * sizeof(VOID*),
+ &SmmHob
+ );
+ ASSERT_PEI_ERROR(PeiServices, Status);
+ MemCpy(&SmmHob->EfiHobGuidType.Name, &gSmmHobGuid, sizeof(EFI_GUID));
+
+ SmmHob->Tseg = Tseg;
+ SmmHob->TsegLength = TSEG_SIZE;
+ PEI_ASSERT(PeiServices, (SmmHob->Tseg & 0x7fffff)==0); //Must be 8MB boundary.
+ PEI_ASSERT(PeiServices, TSEG_SIZE >= 0x800000); //Must be >= 8MB.
+
+ SmmHob->IedStart = Tseg + TSEG_SIZE - IED_SIZE;
+ SmmHob->IedSize = IED_SIZE;
+
+ SmmHob->NumCpus = NumCpus;
+ SmmHob->Bsp = 0;
+
+ SmmBspBase = (UINTN)Tseg - 0x8000; //Get bottom of TSEG - 0x8000
+ SmmBase = SmmBspBase + MAX_SMM_SAVE_STATE_SIZE;
+
+ MaxCpusBeforeOverlap = 0x8000 / MAX_SMM_SAVE_STATE_SIZE - 1;
+ BeforeOverlapCount = 0;
+ NextUnoverlapSmmBase = (UINTN)Tseg - 0x8000 + 0x10000 - 2 * MAX_SMM_SAVE_STATE_SIZE;
+ LargestSmmBase = 0;
+
+ for (i = 0; i < NumCpus; ++i)
+ {
+ if (i == SmmHob->Bsp)
+ {
+ SmmCpuBase = SmmBspBase;
+ if (SmmCpuBase >= ((UINTN)Tseg - 0x8000)) ++BeforeOverlapCount; //Only increment count if BSP in TSEG.
+ }
+ else
+ {
+ SmmCpuBase = SmmBase;
+ ++BeforeOverlapCount;
+ if (BeforeOverlapCount < MaxCpusBeforeOverlap)
+ {
+ SmmBase += MAX_SMM_SAVE_STATE_SIZE;
+ }
+ else
+ {
+ SmmBase = NextUnoverlapSmmBase;
+ NextUnoverlapSmmBase += 0x10000 - 2 * MAX_SMM_SAVE_STATE_SIZE;
+ BeforeOverlapCount = 0;
+ }
+ }
+
+ SmmHob->SmmBase[i] = SmmCpuBase;
+
+ if (SmmCpuBase > LargestSmmBase) LargestSmmBase = SmmCpuBase;
+ }
+
+ if (LargestSmmBase < 0xC0000)
+ SmmHob->ManagedMemStart = Tseg;
+ else
+ SmmHob->ManagedMemStart = LargestSmmBase + 0x10000; //+ 0x10000 = end of save state.
+
+ SmmHob->ManagedMemSize = Tseg + TSEG_SIZE - SmmHob->ManagedMemStart;
+ SmmHob->ManagedMemSize -= SmmHob->IedSize;
+
+ PEI_TRACE((-1, PeiServices, "TSEG Base %x\n", SmmHob->Tseg));
+ PEI_TRACE((-1, PeiServices, "TSEG Size %x\n", SmmHob->TsegLength));
+ PEI_TRACE((-1, PeiServices, "ManagedMemStart %x\n", SmmHob->ManagedMemStart));
+
+ if (BootMode != BOOT_ON_S3_RESUME){
+ //Copy CPU microcode from ROM to RAM, when flash ragne is still cached
+ //and create hob to record the microcode address
+ //Create CPU microcode HOB
+ MicrocodeAddr = CPULib_FindMicrocode();
+
+ if(MicrocodeAddr != NULL){
+ PEI_TRACE((-1, PeiServices, "Cpu uCode ID - %x\n",((MICROCODE_HEADER*)MicrocodeAddr)->CpuSignature ));
+ MicrocodeSize = ((MICROCODE_HEADER*)MicrocodeAddr)->TotalSize;
+
+ Status = (*PeiServices)->AllocatePages (
+ PeiServices,
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (MicrocodeSize),
+ &MicrocodeBuffer );
+ if(!EFI_ERROR(Status)){
+ // Copy Microcode from ROM to RAM
+ (*PeiServices)->CopyMem (
+ (VOID*)MicrocodeBuffer,
+ (VOID*)MicrocodeAddr,
+ (UINTN)MicrocodeSize );
+
+ Status = (*PeiServices)->CreateHob(
+ PeiServices,
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof(AMI_INTERNAL_UCODE_HOB),
+ &uCodeHob );
+ if (!EFI_ERROR(Status)){
+ MemCpy(&uCodeHob->EfiHobGuidType.Name, &gAmiInternaluCodeHobGuid, sizeof(EFI_GUID));
+ uCodeHob->uCodeAddr = (UINT32)MicrocodeBuffer;
+ }
+ }
+ }
+ }
+
+ CpuPeiMiscFuncs(PeiServices, ReadOnlyVariable, BootMode);
+
+ return EFI_SUCCESS;
+
+}
+
+//*************************************************************************
+//*************************************************************************
+//** **
+//** (C)Copyright 1987-2013, American Megatrends, Inc. **
+//** **
+//** All Rights Reserved. **
+//** **
+//** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 **
+//** **
+//** Phone: (770)-246-8600 **
+//** **
+//*************************************************************************
+//*************************************************************************
+