1 /** @file 2 3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 4 5 This program and the accompanying materials are licensed and made available under 7 the terms and conditions of the BSD License that accompanies this distribution. 9 The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php. 13 15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 21 23 Module Name: 24 25 26 MemoryPeim.c 27 28 Abstract: 29 30 Tiano PEIM to provide the platform support functionality. 31 This file implements the Platform Memory Range PPI 32 33 --*/ 34 35 #include "PlatformEarlyInit.h" 36 37 // 38 // Need min. of 48MB PEI phase 39 // 40 #define PEI_MIN_MEMORY_SIZE (6 * 0x800000) 41 #define PEI_RECOVERY_MIN_MEMORY_SIZE (6 * 0x800000) 42 43 // 44 // This is the memory needed for PEI to start up DXE. 45 // 46 // Over-estimating this size will lead to higher fragmentation 47 // of main memory. Under-estimation of this will cause catastrophic 48 // failure of PEI to load DXE. Generally, the failure may only be 49 // realized during capsule updates. 50 // 51 #define PRERESERVED_PEI_MEMORY ( \ 52 EFI_SIZE_TO_PAGES (3 * 0x800000) /* PEI Core memory based stack */ \ 53 ) 54 55 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { 56 { EfiACPIReclaimMemory, 0x40 }, // 0x40 pages = 256k for ASL 57 { EfiACPIMemoryNVS, 0x100 }, // 0x100 pages = 1 MB for S3, SMM, HII, etc 58 { EfiReservedMemoryType, 0x600 }, // 48k for BIOS Reserved 59 { EfiMemoryMappedIO, 0 }, 60 { EfiMemoryMappedIOPortSpace, 0 }, 61 { EfiPalCode, 0 }, 62 { EfiRuntimeServicesCode, 0x200 }, 63 { EfiRuntimeServicesData, 0x100 }, 64 { EfiLoaderCode, 0x100 }, 65 { EfiLoaderData, 0x100 }, 66 { EfiBootServicesCode, 0x800 }, 67 { EfiBootServicesData, 0x2500}, 68 { EfiConventionalMemory, 0 }, 69 { EfiUnusableMemory, 0 }, 70 { EfiMaxMemoryType, 0 } 71 }; 72 73 STATIC 74 EFI_STATUS 75 GetMemorySize ( 76 IN CONST EFI_PEI_SERVICES **PeiServices, 77 OUT UINT64 *LowMemoryLength, 78 OUT UINT64 *HighMemoryLength 79 ); 80 81 82 83 EFI_STATUS 84 EFIAPI 85 SetPeiCacheMode ( 86 IN CONST EFI_PEI_SERVICES **PeiServices 87 ) 88 { 89 EFI_STATUS Status; 90 PEI_CACHE_PPI *CachePpi; 91 92 EFI_BOOT_MODE BootMode; 93 UINT64 MemoryLength; 94 UINT64 MemOverflow; 95 UINT64 MemoryLengthUc; 96 UINT64 MaxMemoryLength; 97 UINT64 LowMemoryLength; 98 UINT64 HighMemoryLength; 99 UINT8 Index; 100 MTRR_SETTINGS MtrrSetting; 101 102 // 103 // Load Cache PPI 104 // 105 Status = (**PeiServices).LocatePpi ( 106 PeiServices, 107 &gPeiCachePpiGuid, // GUID 108 0, // Instance 109 NULL, // EFI_PEI_PPI_DESCRIPTOR 110 (void **)&CachePpi // PPI 111 ); 112 if (!EFI_ERROR(Status)) { 113 // 114 // Clear the CAR Settings (Default Cache Type => UC) 115 // 116 DEBUG ((EFI_D_INFO, "Reset cache attribute and disable CAR. \n")); 117 CachePpi->ResetCache( 118 (EFI_PEI_SERVICES**)PeiServices, 119 CachePpi 120 ); 121 } 122 123 124 // 125 // Variable initialization 126 // 127 LowMemoryLength = 0; 128 HighMemoryLength = 0; 129 MemoryLengthUc = 0; 130 131 Status = (*PeiServices)->GetBootMode ( 132 PeiServices, 133 &BootMode 134 ); 135 136 // 137 // Determine memory usage 138 // 139 GetMemorySize ( 140 PeiServices, 141 &LowMemoryLength, 142 &HighMemoryLength 143 ); 144 145 LowMemoryLength = (EFI_PHYSICAL_ADDRESS)MmPci32( 0, 0, 2, 0, 0x70); 146 LowMemoryLength &= 0xFFF00000ULL; 147 148 MaxMemoryLength = LowMemoryLength; 149 150 // 151 // Round up to nearest 256MB with high memory and 64MB w/o high memory 152 // 153 if (HighMemoryLength != 0 ) { 154 MemOverflow = (LowMemoryLength & 0x0fffffff); 155 if (MemOverflow != 0) { 156 MaxMemoryLength = LowMemoryLength + (0x10000000 - MemOverflow); 157 } 158 } else { 159 MemOverflow = (LowMemoryLength & 0x03ffffff); 160 if (MemOverflow != 0) { 161 MaxMemoryLength = LowMemoryLength + (0x4000000 - MemOverflow); 162 } 163 } 164 165 ZeroMem (&MtrrSetting, sizeof(MTRR_SETTINGS)); 166 for (Index = 0; Index < 2; Index++) { 167 MtrrSetting.Fixed.Mtrr[Index]=0x0606060606060606; 168 } 169 for (Index = 2; Index < 11; Index++) { 170 MtrrSetting.Fixed.Mtrr[Index]=0x0505050505050505; 171 } 172 173 // 174 // Cache the flash area to improve the boot performance in PEI phase 175 // 176 Index = 0; 177 MtrrSetting.Variables.Mtrr[0].Base = (FixedPcdGet32 (PcdFlashAreaBaseAddress) | CacheWriteProtected); 178 MtrrSetting.Variables.Mtrr[0].Mask = ((~((UINT64)(FixedPcdGet32 (PcdFlashAreaSize) - 1))) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; 179 Index ++; 180 181 MemOverflow =0; 182 while (MaxMemoryLength > MemOverflow){ 183 MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheWriteBack; 184 MemoryLength = MaxMemoryLength - MemOverflow; 185 MemoryLength = GetPowerOfTwo64 (MemoryLength); 186 MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; 187 188 MemOverflow += MemoryLength; 189 Index++; 190 } 191 192 MemoryLength = LowMemoryLength; 193 194 while (MaxMemoryLength != MemoryLength) { 195 MemoryLengthUc = GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); 196 197 MtrrSetting.Variables.Mtrr[Index].Base = ((MaxMemoryLength - MemoryLengthUc) & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheUncacheable; 198 MtrrSetting.Variables.Mtrr[Index].Mask= ((~(MemoryLengthUc - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; 199 MaxMemoryLength -= MemoryLengthUc; 200 Index++; 201 } 202 203 MemOverflow =0x100000000; 204 while (HighMemoryLength > 0) { 205 MtrrSetting.Variables.Mtrr[Index].Base = (MemOverflow & MTRR_LIB_CACHE_VALID_ADDRESS) | CacheWriteBack; 206 MemoryLength = HighMemoryLength; 207 MemoryLength = GetPowerOfTwo64 (MemoryLength); 208 209 if (MemoryLength > MemOverflow){ 210 MemoryLength = MemOverflow; 211 } 212 213 MtrrSetting.Variables.Mtrr[Index].Mask = ((~(MemoryLength - 1)) & MTRR_LIB_CACHE_VALID_ADDRESS) | MTRR_LIB_CACHE_MTRR_ENABLED; 214 215 MemOverflow += MemoryLength; 216 HighMemoryLength -= MemoryLength; 217 Index++; 218 } 219 220 221 for (Index = 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) { 222 if (MtrrSetting.Variables.Mtrr[Index].Base == 0){ 223 break; 224 } 225 DEBUG ((EFI_D_INFO, "Base=%lx, Mask=%lx\n",MtrrSetting.Variables.Mtrr[Index].Base ,MtrrSetting.Variables.Mtrr[Index].Mask)); 226 } 227 228 // 229 // set FE/E bits for IA32_MTRR_DEF_TYPE 230 // 231 MtrrSetting.MtrrDefType |= 3 <<10; 232 233 MtrrSetAllMtrrs(&MtrrSetting); 234 235 236 237 return EFI_SUCCESS; 238 } 239 240 EFI_STATUS 241 EFIAPI 242 SetDxeCacheMode ( 243 IN CONST EFI_PEI_SERVICES **PeiServices 244 ) 245 { 246 // 247 // This is not needed for now. 248 // 249 return EFI_SUCCESS; 250 } 251 252 STATIC 253 EFI_STATUS 254 GetMemorySize ( 255 IN CONST EFI_PEI_SERVICES **PeiServices, 256 OUT UINT64 *LowMemoryLength, 257 OUT UINT64 *HighMemoryLength 258 ) 259 { 260 EFI_STATUS Status; 261 EFI_PEI_HOB_POINTERS Hob; 262 263 *HighMemoryLength = 0; 264 *LowMemoryLength = 0x100000; 265 266 // 267 // Get the HOB list for processing 268 // 269 Status = (*PeiServices)->GetHobList (PeiServices, (void **)&Hob.Raw); 270 if (EFI_ERROR(Status)) { 271 return Status; 272 } 273 274 // 275 // Collect memory ranges 276 // 277 while (!END_OF_HOB_LIST (Hob)) { 278 if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { 279 if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { 280 // 281 // Need memory above 1MB to be collected here 282 // 283 if (Hob.ResourceDescriptor->PhysicalStart >= 0x100000 && 284 Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) 0x100000000) { 285 *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); 286 } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) 0x100000000) { 287 *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); 288 } 289 } 290 } 291 Hob.Raw = GET_NEXT_HOB (Hob); 292 } 293 294 return EFI_SUCCESS; 295 } 296 297 298 /** 299 Publish Memory Type Information. 300 301 @param NULL 302 303 @retval EFI_SUCCESS Success. 304 @retval Others Errors have occurred. 305 **/ 306 307 EFI_STATUS 308 EFIAPI 309 PublishMemoryTypeInfo ( 310 void 311 ) 312 { 313 EFI_STATUS Status; 314 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; 315 UINTN DataSize; 316 EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; 317 318 Status = PeiServicesLocatePpi ( 319 &gEfiPeiReadOnlyVariable2PpiGuid, 320 0, 321 NULL, 322 (void **)&Variable 323 ); 324 if (EFI_ERROR(Status)) { 325 DEBUG((EFI_D_ERROR, "WARNING: Locating Pei variable failed 0x%x \n", Status)); 326 DEBUG((EFI_D_ERROR, "Build Hob from default\n")); 327 // 328 // Build the default GUID'd HOB for DXE 329 // 330 BuildGuidDataHob ( 331 &gEfiMemoryTypeInformationGuid, 332 mDefaultMemoryTypeInformation, 333 sizeof (mDefaultMemoryTypeInformation) 334 ); 335 336 return Status; 337 } 338 339 340 DataSize = sizeof (MemoryData); 341 342 // 343 // This variable is saved in BDS stage. Now read it back 344 // 345 Status = Variable->GetVariable ( 346 Variable, 347 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, 348 &gEfiMemoryTypeInformationGuid, 349 NULL, 350 &DataSize, 351 &MemoryData 352 ); 353 if (EFI_ERROR (Status)) { 354 // 355 //build default 356 // 357 DEBUG((EFI_D_ERROR, "Build Hob from default\n")); 358 BuildGuidDataHob ( 359 &gEfiMemoryTypeInformationGuid, 360 mDefaultMemoryTypeInformation, 361 sizeof (mDefaultMemoryTypeInformation) 362 ); 363 364 } else { 365 // 366 // Build the GUID'd HOB for DXE from variable 367 // 368 DEBUG((EFI_D_ERROR, "Build Hob from variable \n")); 369 BuildGuidDataHob ( 370 &gEfiMemoryTypeInformationGuid, 371 MemoryData, 372 DataSize 373 ); 374 } 375 376 return Status; 377 } 378 379