Add FSP2.0 support. This series of patch is to support FSP2.0 specification at https://firmware.intel.com/sites/default/files/FSP_EAS_v2.0_Draft%20External.pdf Some major updates include: 1) One FSP binary is separated to multiple components: FSP-T, FSP-M, FSP-S, and optional FSP-O. Each component has its own configuration data region. 2) All FSP-APIs use same UPD format - FSP_UPD_HEADER. 3) Add EnumInitPhaseEndOfFirmware notifyphase. 4) FSP1.1/FSP1.0 compatibility is NOT maintained. 5) We also add rename Fsp* to FspWrapper* in IntelFsp2WrapperPkg, to indicate that it is for FspWrapper only. IntelFspPkg and IntelFspWrapperPkg will be deprecated. The new Intel platform will follow FSP2.0 and use IntelFsp2Pkg and IntelFsp2WrapperPkg. The old platform can still use IntelFspPkg and IntelFspWrapperPkg for compatibility consideration. Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com> Cc: Maurice Ma <maurice.ma@intel.com> Cc: Ravi P Rangarajan <ravi.p.rangarajan@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Giri P Mudusuru <giri.p.mudusuru@intel.com> Reviewed-by: Maurice Ma <maurice.ma@intel.com> Reviewed-by: Ravi P Rangarajan <ravi.p.rangarajan@intel.com>
		
			
				
	
	
		
			390 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			390 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Sample to provide FSP wrapper hob process related function.
 | |
| 
 | |
|   Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php.
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <PiPei.h>
 | |
| 
 | |
| #include <Library/PeiServicesLib.h>
 | |
| #include <Library/PeiServicesTablePointerLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/HobLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Library/FspWrapperPlatformLib.h>
 | |
| 
 | |
| #include <Guid/GuidHobFspEas.h>
 | |
| #include <Guid/MemoryTypeInformation.h>
 | |
| #include <Guid/PcdDataBaseHobGuid.h>
 | |
| #include <Ppi/Capsule.h>
 | |
| 
 | |
| //
 | |
| // Additional pages are used by DXE memory manager.
 | |
| // It should be consistent between RetrieveRequiredMemorySize() and GetPeiMemSize()
 | |
| //
 | |
| #define PEI_ADDITIONAL_MEMORY_SIZE    (16 * EFI_PAGE_SIZE)
 | |
| 
 | |
| /**
 | |
|   Get the mem size in memory type infromation table.
 | |
| 
 | |
|   @param[in] PeiServices  PEI Services table.
 | |
| 
 | |
|   @return the mem size in memory type infromation table.
 | |
| **/
 | |
| UINT64
 | |
| GetMemorySizeInMemoryTypeInformation (
 | |
|   IN EFI_PEI_SERVICES **PeiServices
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_PEI_HOB_POINTERS        Hob;
 | |
|   EFI_MEMORY_TYPE_INFORMATION *MemoryData;
 | |
|   UINT8                       Index;
 | |
|   UINTN                       TempPageNum;
 | |
| 
 | |
|   MemoryData = NULL;
 | |
|   Status     = (*PeiServices)->GetHobList ((CONST EFI_PEI_SERVICES**)PeiServices, (VOID **) &Hob.Raw);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   while (!END_OF_HOB_LIST (Hob)) {
 | |
|     if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION &&
 | |
|       CompareGuid (&Hob.Guid->Name, &gEfiMemoryTypeInformationGuid)) {
 | |
|       MemoryData = (EFI_MEMORY_TYPE_INFORMATION *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID));
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Hob.Raw = GET_NEXT_HOB (Hob);
 | |
|   }
 | |
| 
 | |
|   if (MemoryData == NULL) {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   TempPageNum = 0;
 | |
|   for (Index = 0; MemoryData[Index].Type != EfiMaxMemoryType; Index++) {
 | |
|     //
 | |
|     // Accumulate default memory size requirements
 | |
|     //
 | |
|     TempPageNum += MemoryData[Index].NumberOfPages;
 | |
|   }
 | |
| 
 | |
|   return TempPageNum * EFI_PAGE_SIZE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the mem size need to be reserved in PEI phase.
 | |
| 
 | |
|   @param[in] PeiServices  PEI Services table.
 | |
| 
 | |
|   @return the mem size need to be reserved in PEI phase.
 | |
| **/
 | |
| UINT64
 | |
| RetrieveRequiredMemorySize (
 | |
|   IN EFI_PEI_SERVICES **PeiServices
 | |
|   )
 | |
| {
 | |
|   UINT64                      Size;
 | |
| 
 | |
|   Size = GetMemorySizeInMemoryTypeInformation (PeiServices);
 | |
|   return Size + PEI_ADDITIONAL_MEMORY_SIZE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the mem size need to be consumed and reserved in PEI phase.
 | |
| 
 | |
|   @param[in] PeiServices  PEI Services table.
 | |
|   @param[in] BootMode     Current boot mode.
 | |
| 
 | |
|   @return the mem size need to be consumed and reserved in PEI phase.
 | |
| **/
 | |
| UINT64
 | |
| GetPeiMemSize (
 | |
|   IN EFI_PEI_SERVICES **PeiServices,
 | |
|   IN UINT32           BootMode
 | |
|   )
 | |
| {
 | |
|   UINT64                      Size;
 | |
|   UINT64                      MinSize;
 | |
| 
 | |
|   if (BootMode == BOOT_IN_RECOVERY_MODE) {
 | |
|     return PcdGet32 (PcdPeiRecoveryMinMemSize);
 | |
|   }
 | |
| 
 | |
|   Size = GetMemorySizeInMemoryTypeInformation (PeiServices);
 | |
| 
 | |
|   if (BootMode == BOOT_ON_FLASH_UPDATE) {
 | |
|     //
 | |
|     // Maybe more size when in CapsuleUpdate phase ?
 | |
|     //
 | |
|     MinSize = PcdGet32 (PcdPeiMinMemSize);
 | |
|   } else {
 | |
|     MinSize = PcdGet32 (PcdPeiMinMemSize);
 | |
|   }
 | |
| 
 | |
|   return MinSize + Size + PEI_ADDITIONAL_MEMORY_SIZE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Post FSP-M HOB process for Memory Resource Descriptor.
 | |
| 
 | |
|   @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
 | |
| 
 | |
|   @return If platform process the FSP hob list successfully.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PostFspmHobProcess (
 | |
|   IN VOID                 *FspHobList
 | |
|   )
 | |
| {
 | |
|   EFI_PEI_HOB_POINTERS Hob;
 | |
|   UINT64               LowMemorySize;
 | |
|   UINT64               FspMemorySize;
 | |
|   EFI_PHYSICAL_ADDRESS FspMemoryBase;
 | |
|   UINT64               PeiMemSize;
 | |
|   EFI_PHYSICAL_ADDRESS PeiMemBase;
 | |
|   UINT64               S3PeiMemSize;
 | |
|   EFI_PHYSICAL_ADDRESS S3PeiMemBase;
 | |
|   BOOLEAN              FoundFspMemHob;
 | |
|   EFI_STATUS           Status;
 | |
|   EFI_BOOT_MODE        BootMode;
 | |
|   EFI_PEI_CAPSULE_PPI  *Capsule;
 | |
|   VOID                 *CapsuleBuffer;
 | |
|   UINTN                CapsuleBufferLength;
 | |
|   UINT64               RequiredMemSize;
 | |
|   EFI_PEI_SERVICES     **PeiServices;
 | |
| 
 | |
|   PeiServices = (EFI_PEI_SERVICES **)GetPeiServicesTablePointer ();
 | |
| 
 | |
|   PeiServicesGetBootMode (&BootMode);
 | |
| 
 | |
|   PeiMemBase = 0;
 | |
|   LowMemorySize = 0;
 | |
|   FspMemorySize = 0;
 | |
|   FspMemoryBase = 0;
 | |
|   FoundFspMemHob = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Parse the hob list from fsp
 | |
|   // Report all the resource hob except the memory between 1M and 4G
 | |
|   //
 | |
|   Hob.Raw = (UINT8 *)(UINTN)FspHobList;
 | |
|   DEBUG((DEBUG_INFO, "FspHobList - 0x%x\n", FspHobList));
 | |
| 
 | |
|   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, Hob.Raw)) != NULL) {
 | |
|     DEBUG((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));
 | |
|     if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) ||
 | |
|         (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)) {
 | |
|       DEBUG((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));
 | |
|       DEBUG((DEBUG_INFO, "PhysicalStart: 0x%x\n", Hob.ResourceDescriptor->PhysicalStart));
 | |
|       DEBUG((DEBUG_INFO, "ResourceLength: 0x%x\n", Hob.ResourceDescriptor->ResourceLength));
 | |
|       DEBUG((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));
 | |
|     }
 | |
| 
 | |
|     if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY)  // Found the low memory length below 4G
 | |
|         && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
 | |
|         && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)) {
 | |
|         LowMemorySize += Hob.ResourceDescriptor->ResourceLength;
 | |
|       Hob.Raw = GET_NEXT_HOB (Hob);
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED)  // Found the low memory length below 4G
 | |
|         && (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB)
 | |
|         && (Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength <= BASE_4GB)
 | |
|         && (CompareGuid (&Hob.ResourceDescriptor->Owner, &gFspReservedMemoryResourceHobGuid))) {
 | |
|       FoundFspMemHob = TRUE;
 | |
|       FspMemoryBase = Hob.ResourceDescriptor->PhysicalStart;
 | |
|       FspMemorySize = Hob.ResourceDescriptor->ResourceLength;
 | |
|       DEBUG((DEBUG_INFO, "Find fsp mem hob, base 0x%x, len 0x%x\n", FspMemoryBase, FspMemorySize));
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Report the resource hob
 | |
|     //
 | |
|     BuildResourceDescriptorHob (
 | |
|       Hob.ResourceDescriptor->ResourceType,
 | |
|       Hob.ResourceDescriptor->ResourceAttribute,
 | |
|       Hob.ResourceDescriptor->PhysicalStart,
 | |
|       Hob.ResourceDescriptor->ResourceLength
 | |
|       );
 | |
| 
 | |
|     Hob.Raw = GET_NEXT_HOB (Hob);
 | |
|   }
 | |
| 
 | |
|   if (!FoundFspMemHob) {
 | |
|     DEBUG((DEBUG_INFO, "Didn't find the fsp used memory information.\n"));
 | |
|     //ASSERT(FALSE);
 | |
|   }
 | |
| 
 | |
|   DEBUG((DEBUG_INFO, "LowMemorySize: 0x%x.\n", LowMemorySize));
 | |
|   DEBUG((DEBUG_INFO, "FspMemoryBase: 0x%x.\n", FspMemoryBase));
 | |
|   DEBUG((DEBUG_INFO, "FspMemorySize: 0x%x.\n", FspMemorySize));
 | |
| 
 | |
|   if (BootMode == BOOT_ON_S3_RESUME) {
 | |
|     BuildResourceDescriptorHob (
 | |
|       EFI_RESOURCE_SYSTEM_MEMORY,
 | |
|       (
 | |
|          EFI_RESOURCE_ATTRIBUTE_PRESENT |
 | |
|          EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
 | |
|          // EFI_RESOURCE_ATTRIBUTE_TESTED |
 | |
|          EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
 | |
|       ),
 | |
|       BASE_1MB,
 | |
|       LowMemorySize
 | |
|       );
 | |
| 
 | |
|     S3PeiMemBase = 0;
 | |
|     S3PeiMemSize = 0;
 | |
|     Status = GetS3MemoryInfo (&S3PeiMemSize, &S3PeiMemBase);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     DEBUG((DEBUG_INFO, "S3 memory %Xh - %Xh bytes\n", S3PeiMemBase, S3PeiMemSize));
 | |
| 
 | |
|     //
 | |
|     // Make sure Stack and PeiMemory are not overlap
 | |
|     //
 | |
| 
 | |
|     Status = PeiServicesInstallPeiMemory (
 | |
|                S3PeiMemBase,
 | |
|                S3PeiMemSize
 | |
|                );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   } else {
 | |
|     PeiMemSize = GetPeiMemSize (PeiServices, BootMode);
 | |
|     DEBUG((DEBUG_INFO, "PEI memory size = %Xh bytes\n", PeiMemSize));
 | |
| 
 | |
|     //
 | |
|     // Capsule mode
 | |
|     //
 | |
|     Capsule = NULL;
 | |
|     CapsuleBuffer = NULL;
 | |
|     CapsuleBufferLength = 0;
 | |
|     if (BootMode == BOOT_ON_FLASH_UPDATE) {
 | |
|       Status = PeiServicesLocatePpi (
 | |
|                  &gEfiPeiCapsulePpiGuid,
 | |
|                  0,
 | |
|                  NULL,
 | |
|                  (VOID **) &Capsule
 | |
|                  );
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|       if (Status == EFI_SUCCESS) {
 | |
|         //
 | |
|         // Make sure Stack and CapsuleBuffer are not overlap
 | |
|         //
 | |
|         CapsuleBuffer = (VOID *)(UINTN)BASE_1MB;
 | |
|         CapsuleBufferLength = (UINTN)(LowMemorySize - PeiMemSize);
 | |
|         //
 | |
|         // Call the Capsule PPI Coalesce function to coalesce the capsule data.
 | |
|         //
 | |
|         Status = Capsule->Coalesce (PeiServices, &CapsuleBuffer, &CapsuleBufferLength);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     RequiredMemSize = RetrieveRequiredMemorySize (PeiServices);
 | |
|     DEBUG((DEBUG_INFO, "Required memory size = %Xh bytes\n", RequiredMemSize));
 | |
| 
 | |
|     //
 | |
|     // Report the main memory
 | |
|     //
 | |
|     BuildResourceDescriptorHob (
 | |
|       EFI_RESOURCE_SYSTEM_MEMORY,
 | |
|       (
 | |
|          EFI_RESOURCE_ATTRIBUTE_PRESENT |
 | |
|          EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
 | |
|          EFI_RESOURCE_ATTRIBUTE_TESTED |
 | |
|          EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
 | |
|          EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
 | |
|       ),
 | |
|       BASE_1MB,
 | |
|       LowMemorySize
 | |
|       );
 | |
| 
 | |
|     //
 | |
|     // Make sure Stack and CapsuleBuffer are not overlap
 | |
|     //
 | |
| 
 | |
|     //
 | |
|     // Install efi memory
 | |
|     //
 | |
|     PeiMemBase = BASE_1MB + LowMemorySize - PeiMemSize;
 | |
|     Status = PeiServicesInstallPeiMemory (
 | |
|                PeiMemBase,
 | |
|                PeiMemSize - RequiredMemSize
 | |
|                );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     if (Capsule != NULL) {
 | |
|       Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Process FSP HOB list
 | |
| 
 | |
|   @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| ProcessFspHobList (
 | |
|   IN VOID                 *FspHobList
 | |
|   )
 | |
| {
 | |
|   EFI_PEI_HOB_POINTERS  FspHob;
 | |
| 
 | |
|   FspHob.Raw = FspHobList;
 | |
| 
 | |
|   //
 | |
|   // Add all the HOBs from FSP binary to FSP wrapper
 | |
|   //
 | |
|   while (!END_OF_HOB_LIST (FspHob)) {
 | |
|     if (FspHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
 | |
|       //
 | |
|       // Skip FSP binary creates PcdDataBaseHobGuid
 | |
|       //
 | |
|       if (!CompareGuid(&FspHob.Guid->Name, &gPcdDataBaseHobGuid)) { 
 | |
|         BuildGuidDataHob (
 | |
|           &FspHob.Guid->Name,
 | |
|           GET_GUID_HOB_DATA(FspHob),
 | |
|           GET_GUID_HOB_DATA_SIZE(FspHob)
 | |
|         );
 | |
|       }
 | |
|     }
 | |
|     FspHob.Raw = GET_NEXT_HOB (FspHob);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Post FSP-S HOB process (not Memory Resource Descriptor).
 | |
| 
 | |
|   @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.
 | |
| 
 | |
|   @return If platform process the FSP hob list successfully.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PostFspsHobProcess (
 | |
|   IN VOID                 *FspHobList
 | |
|   )
 | |
| {
 | |
|   ProcessFspHobList (FspHobList);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| } |