1 /** @file 2 Null instance of Platform Sec Lib. 3 4 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php. 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <PiPei.h> 16 17 #include <Library/PeiServicesLib.h> 18 #include <Library/PeiServicesTablePointerLib.h> 19 #include <Library/BaseLib.h> 20 #include <Library/DebugLib.h> 21 #include <Library/BaseMemoryLib.h> 22 #include <Library/HobLib.h> 23 #include <Library/PcdLib.h> 24 #include <Library/FspPlatformInfoLib.h> 25 26 #include <Guid/GuidHobFsp.h> 27 #include <Guid/MemoryTypeInformation.h> 28 #include <Ppi/Capsule.h> 29 30 #include <PlatformFspLib.h> 31 #include <Guid/SmramMemoryReserve.h> 32 EFI_GUID gFspReservedMemoryResourceHobTsegGuid = {0xd038747c, 0xd00c, 0x4980, {0xb3, 0x19, 0x49, 0x01, 0x99, 0xa4, 0x7d, 0x55}}; 33 34 // 35 // Additional pages are used by DXE memory manager. 36 // It should be consistent between RetrieveRequiredMemorySize() and GetPeiMemSize() 37 // 38 #define PEI_ADDITIONAL_MEMORY_SIZE (16 * EFI_PAGE_SIZE) 39 40 /** 41 Get the mem size in memory type infromation table. 42 43 @param PeiServices PEI Services table. 44 45 @return the mem size in memory type infromation table. 46 **/ 47 UINT64 48 GetMemorySizeInMemoryTypeInformation ( 49 IN EFI_PEI_SERVICES **PeiServices 50 ) 51 { 52 EFI_STATUS Status; 53 EFI_PEI_HOB_POINTERS Hob; 54 EFI_MEMORY_TYPE_INFORMATION *MemoryData; 55 UINT8 Index; 56 UINTN TempPageNum; 57 58 MemoryData = NULL; 59 Status = (*PeiServices)->GetHobList (PeiServices, (VOID **) &Hob.Raw); 60 while (!END_OF_HOB_LIST (Hob)) { 61 if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION && 62 CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)) { 63 MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID)); 64 break; 65 } 66 67 Hob.Raw = GET_NEXT_HOB (Hob); 68 } 69 70 if (MemoryData == NULL) { 71 return 0; 72 } 73 74 TempPageNum = 0; 75 for (Index = 0; MemoryData[Index].Type != EfiMaxMemoryType; Index++) { 76 // 77 // Accumulate default memory size requirements 78 // 79 TempPageNum += MemoryData[Index].NumberOfPages; 80 } 81 82 return TempPageNum * EFI_PAGE_SIZE; 83 } 84 85 /** 86 Get the mem size need to be reserved in PEI phase. 87 88 @param PeiServices PEI Services table. 89 90 @return the mem size need to be reserved in PEI phase. 91 **/ 92 UINT64 93 RetrieveRequiredMemorySize ( 94 IN EFI_PEI_SERVICES **PeiServices 95 ) 96 { 97 UINT64 Size; 98 99 Size = GetMemorySizeInMemoryTypeInformation (PeiServices); 100 return Size + PEI_ADDITIONAL_MEMORY_SIZE; 101 } 102 103 /** 104 Get the mem size need to be consumed and reserved in PEI phase. 105 106 @param PeiServices PEI Services table. 107 @param BootMode Current boot mode. 108 109 @return the mem size need to be consumed and reserved in PEI phase. 110 **/ 111 UINT64 112 GetPeiMemSize ( 113 IN EFI_PEI_SERVICES **PeiServices, 114 IN UINT32 BootMode 115 ) 116 { 117 UINT64 Size; 118 UINT64 MinSize; 119 120 if (BootMode == BOOT_IN_RECOVERY_MODE) { 121 return PcdGet32 (PcdPeiRecoveryMinMemSize); 122 } 123 124 Size = GetMemorySizeInMemoryTypeInformation (PeiServices); 125 126 if (BootMode == BOOT_ON_FLASH_UPDATE) { 127 // 128 // Maybe more size when in CapsuleUpdate phase ? 129 // 130 MinSize = PcdGet32 (PcdPeiMinMemSize); 131 } else { 132 MinSize = PcdGet32 (PcdPeiMinMemSize); 133 } 134 135 return MinSize + Size + PEI_ADDITIONAL_MEMORY_SIZE; 136 } 137 138 /** 139 BIOS process FspBobList. 140 141 @param FspHobList Pointer to the HOB data structure produced by FSP. 142 143 @return If platform process the FSP hob list successfully. 144 **/ 145 EFI_STATUS 146 EFIAPI 147 FspHobProcessForMemoryResource ( 148 IN VOID *FspHobList 149 ) 150 { 151 EFI_PEI_HOB_POINTERS Hob; 152 UINT64 LowMemorySize; 153 UINT64 FspMemorySize; 154 EFI_PHYSICAL_ADDRESS FspMemoryBase; 155 UINT64 PeiMemSize; 156 EFI_PHYSICAL_ADDRESS PeiMemBase; 157 UINT64 S3PeiMemSize; 158 EFI_PHYSICAL_ADDRESS S3PeiMemBase; 159 BOOLEAN FoundFspMemHob; 160 EFI_STATUS Status; 161 EFI_BOOT_MODE BootMode; 162 PEI_CAPSULE_PPI *Capsule; 163 VOID *CapsuleBuffer; 164 UINTN CapsuleBufferLength; 165 UINT64 RequiredMemSize; 166 EFI_PEI_SERVICES **PeiServices; 167 UINT64 TsegSize; 168 EFI_PHYSICAL_ADDRESS TsegBase; 169 BOOLEAN FoundTsegHob; 170 171 PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (); 172 173 PeiServicesGetBootMode (&BootMode); 174 175 PeiMemBase = 0; 176 LowMemorySize = 0; 177 FspMemorySize = 0; 178 FspMemoryBase = 0; 179 FoundFspMemHob = FALSE; 180 TsegSize = 0; 181 TsegBase = 0; 182 FoundTsegHob = FALSE; 183 184 // 185 // Parse the hob list from fsp 186 // Report all the resource hob except the memory between 1M and 4G 187 // 188 Hob.Raw = (UINT8 *)(UINTN)FspHobList; 189 DEBUG((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList)); 190 191 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) { 192 DEBUG((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType)); 193 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) || 194 (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) { 195 DEBUG((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute)); 196 DEBUG((DEBUG_INFO, "PhysicalStart: 0x%x\n", Hob.ResourceDescriptor->PhysicalStart)); 197 DEBUG((DEBUG_INFO, "ResourceLength: 0x%x\n", Hob.ResourceDescriptor->ResourceLength)); 198 DEBUG((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner)); 199 } 200 201 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) // Found the low memory length below 4G 202 && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB) 203 && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)) { 204 LowMemorySize += Hob.ResourceDescriptor->ResourceLength; 205 Hob.Raw = GET_NEXT_HOB (Hob); 206 continue; 207 } 208 209 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G 210 && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB) 211 && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB) 212 && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid))) { 213 FoundFspMemHob = TRUE; 214 FspMemoryBase = Hob.ResourceDescriptor->PhysicalStart; 215 FspMemorySize = Hob.ResourceDescriptor->ResourceLength; 216 DEBUG((DEBUG_INFO, "Find fsp mem hob, base 0x%x, len 0x%x\n", FspMemoryBase, FspMemorySize)); 217 } 218 219 if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) // Found the low memory length below 4G 220 && (Hob.ResourceDescriptor->PhysicalStart >= 0x100000) 221 && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= 0x100000000) 222 && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobTsegGuid))) { 223 FoundTsegHob = TRUE; 224 TsegBase = Hob.ResourceDescriptor->PhysicalStart; 225 226 227 if ((Hob.ResourceDescriptor->ResourceLength == 0 ) || (Hob.ResourceDescriptor->ResourceLength > 0x800000)){ 228 Hob.ResourceDescriptor->ResourceLength = 0x800000; 229 } 230 231 232 TsegSize = Hob.ResourceDescriptor->ResourceLength; 233 DEBUG((EFI_D_ERROR, "Find Tseg mem hob, base 0x%lx, len 0x%lx\n", TsegBase, TsegSize)); 234 } 235 236 // 237 // Report the resource hob 238 // 239 BuildResourceDescriptorHob ( 240 Hob.ResourceDescriptor->ResourceType, 241 Hob.ResourceDescriptor->ResourceAttribute, 242 Hob.ResourceDescriptor->PhysicalStart, 243 Hob.ResourceDescriptor->ResourceLength 244 ); 245 246 Hob.Raw = GET_NEXT_HOB (Hob); 247 } 248 249 if (!FoundFspMemHob) { 250 DEBUG((DEBUG_INFO, "Didn't find the fsp used memory information.\n")); 251 //ASSERT(FALSE); 252 } 253 254 DEBUG((DEBUG_INFO, "LowMemorySize: 0x%x.\n", LowMemorySize)); 255 DEBUG((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase)); 256 DEBUG((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize)); 257 258 if (BootMode == BOOT_ON_S3_RESUME) { 259 BuildResourceDescriptorHob ( 260 EFI_RESOURCE_SYSTEM_MEMORY, 261 ( 262 EFI_RESOURCE_ATTRIBUTE_PRESENT | 263 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 264 // EFI_RESOURCE_ATTRIBUTE_TESTED | 265 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 266 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 267 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 268 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 269 ), 270 BASE_1MB, 271 LowMemorySize 272 ); 273 274 Status = GetS3MemoryInfo (&S3PeiMemBase, &S3PeiMemSize); 275 ASSERT_EFI_ERROR (Status); 276 DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize)); 277 278 // 279 // Make sure Stack and PeiMemory are not overlap - JYAO1 280 // 281 282 Status = PeiServicesInstallPeiMemory ( 283 S3PeiMemBase, 284 S3PeiMemSize 285 ); 286 ASSERT_EFI_ERROR (Status); 287 } else { 288 PeiMemSize = GetPeiMemSize (PeiServices, BootMode); 289 DEBUG((DEBUG_INFO, "PEI memory size = %Xh bytes\n", PeiMemSize)); 290 291 // 292 // Capsule mode 293 // 294 Capsule = NULL; 295 CapsuleBuffer = NULL; 296 CapsuleBufferLength = 0; 297 if (BootMode == BOOT_ON_FLASH_UPDATE) { 298 Status = PeiServicesLocatePpi ( 299 &gPeiCapsulePpiGuid, 300 0, 301 NULL, 302 (VOID **) &Capsule 303 ); 304 ASSERT_EFI_ERROR (Status); 305 306 if (Status == EFI_SUCCESS) { 307 // 308 // Make sure Stack and CapsuleBuffer are not overlap - JYAO1 309 // 310 CapsuleBuffer = (VOID *)(UINTN)BASE_1MB; 311 CapsuleBufferLength = (UINTN)(LowMemorySize - PeiMemSize); 312 // 313 // Call the Capsule PPI Coalesce function to coalesce the capsule data. 314 // 315 Status = Capsule->Coalesce (PeiServices, &CapsuleBuffer, &CapsuleBufferLength); 316 } 317 } 318 319 RequiredMemSize = RetrieveRequiredMemorySize (PeiServices); 320 DEBUG((DEBUG_INFO, "Required memory size = %Xh bytes\n", RequiredMemSize)); 321 322 // 323 // Report the main memory 324 // 325 BuildResourceDescriptorHob ( 326 EFI_RESOURCE_SYSTEM_MEMORY, 327 ( 328 EFI_RESOURCE_ATTRIBUTE_PRESENT | 329 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 330 EFI_RESOURCE_ATTRIBUTE_TESTED | 331 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 332 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 333 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 334 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 335 ), 336 BASE_1MB, 337 LowMemorySize 338 ); 339 340 // 341 // Make sure Stack and CapsuleBuffer are not overlap - JYAO1 342 // 343 344 // 345 // Install efi memory 346 // 347 PeiMemBase = BASE_1MB + LowMemorySize - PeiMemSize; 348 Status = PeiServicesInstallPeiMemory ( 349 PeiMemBase, 350 PeiMemSize - RequiredMemSize 351 ); 352 ASSERT_EFI_ERROR (Status); 353 354 if (Capsule != NULL) { 355 Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength); 356 } 357 } 358 359 // 360 // Report GUIDed HOB for reserving SMRAM regions 361 // 362 if (FoundTsegHob) { 363 EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock; 364 365 SmramHobDescriptorBlock = BuildGuidHob ( 366 &gEfiSmmPeiSmramMemoryReserveGuid, 367 sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) 368 ); 369 ASSERT (SmramHobDescriptorBlock != NULL); 370 371 SmramHobDescriptorBlock->NumberOfSmmReservedRegions = 1; 372 373 SmramHobDescriptorBlock->Descriptor[0].PhysicalStart = TsegBase; 374 SmramHobDescriptorBlock->Descriptor[0].CpuStart = TsegBase; 375 SmramHobDescriptorBlock->Descriptor[0].PhysicalSize = TsegSize; 376 SmramHobDescriptorBlock->Descriptor[0].RegionState = EFI_SMRAM_CLOSED; 377 } 378 return EFI_SUCCESS; 379 } 380 381 /** 382 BIOS process FspBobList for other data (not Memory Resource Descriptor). 383 384 @param[in] FspHobList Pointer to the HOB data structure produced by FSP. 385 386 @return If platform process the FSP hob list successfully. 387 **/ 388 EFI_STATUS 389 EFIAPI 390 FspHobProcessForOtherData ( 391 IN VOID *FspHobList 392 ) 393 { 394 EFI_PEI_SERVICES **PeiServices; 395 396 PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer (); 397 398 // 399 // Other hob for platform 400 // 401 PlatformHobCreateFromFsp ( PeiServices, FspHobList); 402 403 return EFI_SUCCESS; 404 } 405 406 /** 407 BIOS process FspBobList. 408 409 @param[in] FspHobList Pointer to the HOB data structure produced by FSP. 410 411 @return If platform process the FSP hob list successfully. 412 **/ 413 EFI_STATUS 414 EFIAPI 415 FspHobProcess ( 416 IN VOID *FspHobList 417 ) 418 { 419 EFI_STATUS Status; 420 421 Status = FspHobProcessForMemoryResource (FspHobList); 422 if (EFI_ERROR (Status)) { 423 return Status; 424 } 425 Status = FspHobProcessForOtherData (FspHobList); 426 427 return Status; 428 } 429