+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
- \r\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
- \r\r
-\r
-Module Name:\r
-\r
-\r
- MemoryPeim.c\r
-\r
-Abstract:\r
-\r
- Tiano PEIM to provide the platform support functionality.\r
- This file implements the Platform Memory Range PPI\r
-\r
---*/\r
-\r
-#include "PlatformEarlyInit.h"\r
-\r
-//\r
-// Need min. of 48MB PEI phase\r
-//\r
-#define PEI_MIN_MEMORY_SIZE (6 * 0x800000)\r
-#define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000)\r
-\r
-//\r
-// This is the memory needed for PEI to start up DXE.\r
-//\r
-// Over-estimating this size will lead to higher fragmentation\r
-// of main memory. Under-estimation of this will cause catastrophic\r
-// failure of PEI to load DXE. Generally, the failure may only be\r
-// realized during capsule updates.\r
-//\r
-#define PRERESERVED_PEI_MEMORY ( \\r
- EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \\r
- )\r
-\r
-EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {\r
- { EfiACPIReclaimMemory, 0x40 }, // 0x40 pages = 256k for ASL\r
- { EfiACPIMemoryNVS, 0x100 }, // 0x100 pages = 1 MB for S3, SMM, HII, etc\r
- { EfiReservedMemoryType, 0x600 }, // 48k for BIOS Reserved\r
- { EfiMemoryMappedIO, 0 },\r
- { EfiMemoryMappedIOPortSpace, 0 },\r
- { EfiPalCode, 0 },\r
- { EfiRuntimeServicesCode, 0x200 },\r
- { EfiRuntimeServicesData, 0x100 },\r
- { EfiLoaderCode, 0x100 },\r
- { EfiLoaderData, 0x100 },\r
- { EfiBootServicesCode, 0x800 },\r
- { EfiBootServicesData, 0x2500},\r
- { EfiConventionalMemory, 0 },\r
- { EfiUnusableMemory, 0 },\r
- { EfiMaxMemoryType, 0 }\r
-};\r
-\r
-STATIC\r
-EFI_STATUS\r
-GetMemorySize (\r
- IN CONST EFI_PEI_SERVICES **PeiServices,\r
- OUT UINT64 *LowMemoryLength,\r
- OUT UINT64 *HighMemoryLength\r
- );\r
-\r
-\r
-/**\r
- Initializes the valid address mask for MTRRs.\r
-\r
- This function initializes the valid bits mask and valid address mask for MTRRs.\r
-\r
-**/\r
-UINT64\r
-InitializeAddressMtrrMask (\r
- VOID\r
- )\r
-{\r
- UINT32 RegEax;\r
- UINT8 PhysicalAddressBits; \r
- UINT64 ValidMtrrBitsMask;\r
-\r
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
-\r
- if (RegEax >= 0x80000008) {\r
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
-\r
- PhysicalAddressBits = (UINT8) RegEax;\r
- } else {\r
- PhysicalAddressBits = 36;\r
- }\r
-\r
- ValidMtrrBitsMask = LShiftU64 (1, PhysicalAddressBits) - 1;\r
- return (ValidMtrrBitsMask & 0xfffffffffffff000ULL);\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-SetPeiCacheMode (\r
- IN CONST EFI_PEI_SERVICES **PeiServices\r
- )\r
-{\r
- EFI_STATUS Status;\r
- PEI_CACHE_PPI *CachePpi;\r
-\r
- EFI_BOOT_MODE BootMode;\r
- UINT64 MemoryLength;\r
- UINT64 MemOverflow;\r
- UINT64 MemoryLengthUc;\r
- UINT64 MaxMemoryLength;\r
- UINT64 LowMemoryLength;\r
- UINT64 HighMemoryLength;\r
- UINT8 Index;\r
- MTRR_SETTINGS MtrrSetting;\r
- UINT64 ValidMtrrAddressMask;\r
-\r
- //\r
- // Load Cache PPI\r
- //\r
- Status = (**PeiServices).LocatePpi (\r
- PeiServices,\r
- &gPeiCachePpiGuid, // GUID\r
- 0, // Instance\r
- NULL, // EFI_PEI_PPI_DESCRIPTOR\r
- (void **)&CachePpi // PPI\r
- );\r
- if (!EFI_ERROR(Status)) {\r
- //\r
- // Clear the CAR Settings (Default Cache Type => UC)\r
- //\r
- DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n"));\r
- CachePpi->ResetCache(\r
- (EFI_PEI_SERVICES**)PeiServices,\r
- CachePpi\r
- );\r
- }\r
-\r
-\r
- //\r
- // Variable initialization\r
- //\r
- LowMemoryLength = 0;\r
- HighMemoryLength = 0;\r
- MemoryLengthUc = 0;\r
-\r
- Status = (*PeiServices)->GetBootMode (\r
- PeiServices,\r
- &BootMode\r
- );\r
-\r
- ValidMtrrAddressMask = InitializeAddressMtrrMask ();\r
-\r
- //\r
- // Determine memory usage\r
- //\r
- GetMemorySize (\r
- PeiServices,\r
- &LowMemoryLength,\r
- &HighMemoryLength\r
- );\r
-\r
- LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70);\r
- LowMemoryLength &= 0xFFF00000ULL;\r
-\r
- MaxMemoryLength = LowMemoryLength;\r
-\r
- //\r
- // Round up to nearest 256MB with high memory and 64MB w/o high memory\r
- //\r
- if (HighMemoryLength != 0 ) {\r
- MemOverflow = (LowMemoryLength & 0x0fffffff);\r
- if (MemOverflow != 0) {\r
- MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow);\r
- }\r
- } else {\r
- MemOverflow = (LowMemoryLength & 0x03ffffff);\r
- if (MemOverflow != 0) {\r
- MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow);\r
- }\r
- }\r
-\r
- ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS));\r
- for (Index = 0; Index < 2; Index++) {\r
- MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606;\r
- }\r
- for (Index = 2; Index < 11; Index++) {\r
- MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505;\r
- }\r
-\r
- //\r
- // Cache the flash area to improve the boot performance in PEI phase\r
- //\r
- Index = 0;\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Uint64 = FixedPcdGet32 (PcdFlashAreaBaseAddress);\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Base)->Bits.Type = CacheWriteProtected;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Uint64 = (~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[0].Mask)->Bits.V = 1;\r
-\r
- Index ++;\r
-\r
- MemOverflow =0;\r
- while (MaxMemoryLength > MemOverflow){\r
- MemoryLength = MaxMemoryLength - MemOverflow;\r
- MemoryLength = GetPowerOfTwo64 (MemoryLength);\r
-\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;\r
-\r
- MemOverflow += MemoryLength;\r
- Index++;\r
- }\r
-\r
- MemoryLength = LowMemoryLength;\r
-\r
- while (MaxMemoryLength != MemoryLength) {\r
- MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength);\r
-\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = (MaxMemoryLength - MemoryLengthUc) & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheUncacheable;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLengthUc - 1)) & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;\r
-\r
- MaxMemoryLength -= MemoryLengthUc;\r
- Index++;\r
- }\r
-\r
- MemOverflow =0x100000000;\r
- while (HighMemoryLength > 0) {\r
-\r
- MemoryLength = HighMemoryLength;\r
- MemoryLength = GetPowerOfTwo64 (MemoryLength);\r
- if (MemoryLength > MemOverflow){\r
- MemoryLength = MemOverflow;\r
- }\r
-\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Uint64 = MemOverflow & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Base)->Bits.Type = CacheWriteBack;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Uint64 = (~(MemoryLength - 1)) & ValidMtrrAddressMask;\r
- ((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &MtrrSetting.Variables.Mtrr[Index].Mask)->Bits.V = 1;\r
-\r
- MemOverflow += MemoryLength;\r
- HighMemoryLength -= MemoryLength;\r
- Index++;\r
- }\r
-\r
-\r
- for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) {\r
- if (MtrrSetting.Variables.Mtrr[Index].Base == 0){\r
- break;\r
- }\r
- DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask));\r
- }\r
-\r
- //\r
- // set FE/E bits for IA32_MTRR_DEF_TYPE\r
- //\r
- MtrrSetting.MtrrDefType |= 3 <<10;\r
-\r
- MtrrSetAllMtrrs(&MtrrSetting);\r
- //\r
- // Dump MTRR Setting\r
- //\r
- MtrrDebugPrintAllMtrrs ();\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-SetDxeCacheMode (\r
- IN CONST EFI_PEI_SERVICES **PeiServices\r
- )\r
-{\r
- //\r
- // This is not needed for now.\r
- //\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC\r
-EFI_STATUS\r
-GetMemorySize (\r
- IN CONST EFI_PEI_SERVICES **PeiServices,\r
- OUT UINT64 *LowMemoryLength,\r
- OUT UINT64 *HighMemoryLength\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PEI_HOB_POINTERS Hob;\r
-\r
- *HighMemoryLength = 0;\r
- *LowMemoryLength = 0x100000;\r
-\r
- //\r
- // Get the HOB list for processing\r
- //\r
- Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
-\r
- //\r
- // Collect memory ranges\r
- //\r
- while (!END_OF_HOB_LIST (Hob)) {\r
- if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
- if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
- //\r
- // Need memory above 1MB to be collected here\r
- //\r
- if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 &&\r
- Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) {\r
- *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);\r
- } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) {\r
- *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength);\r
- }\r
- }\r
- }\r
- Hob.Raw = GET_NEXT_HOB (Hob);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Publish Memory Type Information.\r
-\r
- @param NULL\r
-\r
- @retval EFI_SUCCESS Success.\r
- @retval Others Errors have occurred.\r
-**/\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-PublishMemoryTypeInfo (\r
- void\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;\r
- UINTN DataSize;\r
- EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];\r
-\r
- Status = PeiServicesLocatePpi (\r
- &gEfiPeiReadOnlyVariable2PpiGuid,\r
- 0,\r
- NULL,\r
- (void **)&Variable\r
- );\r
- if (EFI_ERROR(Status)) {\r
- DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status));\r
- DEBUG((EFI_D_ERROR, "Build Hob from default\n"));\r
- //\r
- // Build the default GUID'd HOB for DXE\r
- //\r
- BuildGuidDataHob (\r
- &gEfiMemoryTypeInformationGuid,\r
- mDefaultMemoryTypeInformation,\r
- sizeof (mDefaultMemoryTypeInformation)\r
- );\r
-\r
- return Status;\r
- }\r
-\r
-\r
- DataSize = sizeof (MemoryData);\r
-\r
- //\r
- // This variable is saved in BDS stage. Now read it back\r
- //\r
- Status = Variable->GetVariable (\r
- Variable,\r
- EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
- &gEfiMemoryTypeInformationGuid,\r
- NULL,\r
- &DataSize,\r
- &MemoryData\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- //build default\r
- //\r
- DEBUG((EFI_D_ERROR, "Build Hob from default\n"));\r
- BuildGuidDataHob (\r
- &gEfiMemoryTypeInformationGuid,\r
- mDefaultMemoryTypeInformation,\r
- sizeof (mDefaultMemoryTypeInformation)\r
- );\r
-\r
- } else {\r
- //\r
- // Build the GUID'd HOB for DXE from variable\r
- //\r
- DEBUG((EFI_D_ERROR, "Build Hob from variable \n"));\r
- BuildGuidDataHob (\r
- &gEfiMemoryTypeInformationGuid,\r
- MemoryData,\r
- DataSize\r
- );\r
- }\r
-\r
- return Status;\r
-}\r
-\r