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