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