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