REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			839 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			839 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Last PEIM.
 | |
|   Responsibility of this module is to load the DXE Core from a Firmware Volume.
 | |
| 
 | |
| Copyright (c) 2016 HP Development Company, L.P.
 | |
| Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "DxeIpl.h"
 | |
| 
 | |
| //
 | |
| // Module Globals used in the DXE to PEI hand off
 | |
| // These must be module globals, so the stack can be switched
 | |
| //
 | |
| CONST EFI_DXE_IPL_PPI  mDxeIplPpi = {
 | |
|   DxeLoadCore
 | |
| };
 | |
| 
 | |
| CONST EFI_PEI_PPI_DESCRIPTOR  mDxeIplPpiList = {
 | |
|   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
 | |
|   &gEfiDxeIplPpiGuid,
 | |
|   (VOID *)&mDxeIplPpi
 | |
| };
 | |
| 
 | |
| CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI  mCustomGuidedSectionExtractionPpi = {
 | |
|   CustomGuidedSectionExtract
 | |
| };
 | |
| 
 | |
| CONST EFI_PEI_DECOMPRESS_PPI  mDecompressPpi = {
 | |
|   Decompress
 | |
| };
 | |
| 
 | |
| CONST EFI_PEI_PPI_DESCRIPTOR  mDecompressPpiList = {
 | |
|   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
 | |
|   &gEfiPeiDecompressPpiGuid,
 | |
|   (VOID *)&mDecompressPpi
 | |
| };
 | |
| 
 | |
| CONST EFI_PEI_PPI_DESCRIPTOR  gEndOfPeiSignalPpi = {
 | |
|   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
 | |
|   &gEfiEndOfPeiSignalPpiGuid,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| CONST EFI_PEI_NOTIFY_DESCRIPTOR  mMemoryDiscoveredNotifyList = {
 | |
|   (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
 | |
|   &gEfiPeiMemoryDiscoveredPpiGuid,
 | |
|   InstallIplPermanentMemoryPpis
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Entry point of DXE IPL PEIM.
 | |
| 
 | |
|   This function installs DXE IPL PPI.  It also reloads
 | |
|   itself to memory on non-S3 resume boot path.
 | |
| 
 | |
|   @param  FileHandle  Handle of the file being invoked.
 | |
|   @param  PeiServices Describes the list of possible PEI Services.
 | |
| 
 | |
|   @retval EFI_SUCESS  The entry point of DXE IPL PEIM executes successfully.
 | |
|   @retval Others      Some error occurs during the execution of this function.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| PeimInitializeDxeIpl (
 | |
|   IN       EFI_PEI_FILE_HANDLE  FileHandle,
 | |
|   IN CONST EFI_PEI_SERVICES     **PeiServices
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_BOOT_MODE  BootMode;
 | |
|   VOID           *Dummy;
 | |
| 
 | |
|   BootMode = GetBootModeHob ();
 | |
| 
 | |
|   if (BootMode != BOOT_ON_S3_RESUME) {
 | |
|     Status = PeiServicesRegisterForShadow (FileHandle);
 | |
|     if (Status == EFI_SUCCESS) {
 | |
|       //
 | |
|       // EFI_SUCESS means it is the first time to call register for shadow.
 | |
|       //
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Ensure that DXE IPL is shadowed to permanent memory.
 | |
|     //
 | |
|     ASSERT (Status == EFI_ALREADY_STARTED);
 | |
| 
 | |
|     //
 | |
|     // DXE core load requires permanent memory.
 | |
|     //
 | |
|     Status = PeiServicesLocatePpi (
 | |
|                &gEfiPeiMemoryDiscoveredPpiGuid,
 | |
|                0,
 | |
|                NULL,
 | |
|                (VOID **)&Dummy
 | |
|                );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Now the permanent memory exists, install the PPIs for decompression
 | |
|     // and section extraction.
 | |
|     //
 | |
|     Status = InstallIplPermanentMemoryPpis (NULL, NULL, NULL);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   } else {
 | |
|     //
 | |
|     // Install memory discovered PPI notification to install PPIs for
 | |
|     // decompression and section extraction.
 | |
|     //
 | |
|     Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Install DxeIpl PPI.
 | |
|   //
 | |
|   Status = PeiServicesInstallPpi (&mDxeIplPpiList);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    This function installs the PPIs that require permanent memory.
 | |
| 
 | |
|    @param  PeiServices      Indirect reference to the PEI Services Table.
 | |
|    @param  NotifyDescriptor Address of the notification descriptor data structure.
 | |
|    @param  Ppi              Address of the PPI that was installed.
 | |
| 
 | |
|    @return EFI_SUCCESS      The PPIs were installed successfully.
 | |
|    @return Others           Some error occurs during the execution of this function.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InstallIplPermanentMemoryPpis (
 | |
|   IN EFI_PEI_SERVICES           **PeiServices,
 | |
|   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
 | |
|   IN VOID                       *Ppi
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   EFI_GUID                *ExtractHandlerGuidTable;
 | |
|   UINTN                   ExtractHandlerNumber;
 | |
|   EFI_PEI_PPI_DESCRIPTOR  *GuidPpi;
 | |
| 
 | |
|   //
 | |
|   // Get custom extract guided section method guid list
 | |
|   //
 | |
|   ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
 | |
| 
 | |
|   //
 | |
|   // Install custom guided section extraction PPI
 | |
|   //
 | |
|   if (ExtractHandlerNumber > 0) {
 | |
|     GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *)AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
 | |
|     ASSERT (GuidPpi != NULL);
 | |
|     while (ExtractHandlerNumber-- > 0) {
 | |
|       GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
 | |
|       GuidPpi->Ppi   = (VOID *)&mCustomGuidedSectionExtractionPpi;
 | |
|       GuidPpi->Guid  = &ExtractHandlerGuidTable[ExtractHandlerNumber];
 | |
|       Status         = PeiServicesInstallPpi (GuidPpi++);
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Install Decompress PPI.
 | |
|   //
 | |
|   Status = PeiServicesInstallPpi (&mDecompressPpiList);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    Validate variable data for the MemoryTypeInformation.
 | |
| 
 | |
|    @param MemoryData       Variable data.
 | |
|    @param MemoryDataSize   Variable data length.
 | |
| 
 | |
|    @return TRUE            The variable data is valid.
 | |
|    @return FALSE           The variable data is invalid.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| ValidateMemoryTypeInfoVariable (
 | |
|   IN EFI_MEMORY_TYPE_INFORMATION  *MemoryData,
 | |
|   IN UINTN                        MemoryDataSize
 | |
|   )
 | |
| {
 | |
|   UINTN  Count;
 | |
|   UINTN  Index;
 | |
| 
 | |
|   // Check the input parameter.
 | |
|   if (MemoryData == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   // Get Count
 | |
|   Count = MemoryDataSize / sizeof (*MemoryData);
 | |
| 
 | |
|   // Check Size
 | |
|   if (Count * sizeof (*MemoryData) != MemoryDataSize) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   // Check last entry type filed.
 | |
|   if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   // Check the type filed.
 | |
|   for (Index = 0; Index < Count - 1; Index++) {
 | |
|     if (MemoryData[Index].Type >= EfiMaxMemoryType) {
 | |
|       return FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    Main entry point to last PEIM.
 | |
| 
 | |
|    This function finds DXE Core in the firmware volume and transfer the control to
 | |
|    DXE core.
 | |
| 
 | |
|    @param This          Entry point for DXE IPL PPI.
 | |
|    @param PeiServices   General purpose services available to every PEIM.
 | |
|    @param HobList       Address to the Pei HOB list.
 | |
| 
 | |
|    @return EFI_SUCCESS              DXE core was successfully loaded.
 | |
|    @return EFI_OUT_OF_RESOURCES     There are not enough resources to load DXE core.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DxeLoadCore (
 | |
|   IN CONST EFI_DXE_IPL_PPI  *This,
 | |
|   IN EFI_PEI_SERVICES       **PeiServices,
 | |
|   IN EFI_PEI_HOB_POINTERS   HobList
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                       Status;
 | |
|   EFI_FV_FILE_INFO                 DxeCoreFileInfo;
 | |
|   EFI_PHYSICAL_ADDRESS             DxeCoreAddress;
 | |
|   UINT64                           DxeCoreSize;
 | |
|   EFI_PHYSICAL_ADDRESS             DxeCoreEntryPoint;
 | |
|   EFI_BOOT_MODE                    BootMode;
 | |
|   EFI_PEI_FILE_HANDLE              FileHandle;
 | |
|   EFI_PEI_READ_ONLY_VARIABLE2_PPI  *Variable;
 | |
|   EFI_PEI_LOAD_FILE_PPI            *LoadFile;
 | |
|   UINTN                            Instance;
 | |
|   UINT32                           AuthenticationState;
 | |
|   UINTN                            DataSize;
 | |
|   EFI_PEI_S3_RESUME2_PPI           *S3Resume;
 | |
|   EFI_PEI_RECOVERY_MODULE_PPI      *PeiRecovery;
 | |
|   EDKII_PEI_CAPSULE_ON_DISK_PPI    *PeiCapsuleOnDisk;
 | |
|   EFI_MEMORY_TYPE_INFORMATION      MemoryData[EfiMaxMemoryType + 1];
 | |
|   VOID                             *CapsuleOnDiskModePpi;
 | |
| 
 | |
|   //
 | |
|   // if in S3 Resume, restore configure
 | |
|   //
 | |
|   BootMode = GetBootModeHob ();
 | |
| 
 | |
|   if (BootMode == BOOT_ON_S3_RESUME) {
 | |
|     Status = PeiServicesLocatePpi (
 | |
|                &gEfiPeiS3Resume2PpiGuid,
 | |
|                0,
 | |
|                NULL,
 | |
|                (VOID **)&S3Resume
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Report Status code that S3Resume PPI can not be found
 | |
|       //
 | |
|       REPORT_STATUS_CODE (
 | |
|         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
 | |
|         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND)
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     Status = S3Resume->S3RestoreConfig2 (S3Resume);
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
 | |
|     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN));
 | |
|     Status = PeiServicesLocatePpi (
 | |
|                &gEfiPeiRecoveryModulePpiGuid,
 | |
|                0,
 | |
|                NULL,
 | |
|                (VOID **)&PeiRecovery
 | |
|                );
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "Locate Recovery PPI Failed.(Status = %r)\n", Status));
 | |
|       //
 | |
|       // Report Status code the failure of locating Recovery PPI
 | |
|       //
 | |
|       REPORT_STATUS_CODE (
 | |
|         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
 | |
|         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
 | |
|         );
 | |
|       CpuDeadLoop ();
 | |
|     }
 | |
| 
 | |
|     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD));
 | |
|     Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
 | |
|       //
 | |
|       // Report Status code that recovery image can not be found
 | |
|       //
 | |
|       REPORT_STATUS_CODE (
 | |
|         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
 | |
|         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
 | |
|         );
 | |
|       CpuDeadLoop ();
 | |
|     }
 | |
| 
 | |
|     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
 | |
|     //
 | |
|     // Now should have a HOB with the DXE core
 | |
|     //
 | |
|   } else if (BootMode == BOOT_ON_FLASH_UPDATE) {
 | |
|     //
 | |
|     // If Capsule On Disk mode, call storage stack to read Capsule Relocation file
 | |
|     // IoMmmu is highly recommmended to enable before reading
 | |
|     //
 | |
|     Status = PeiServicesLocatePpi (
 | |
|                &gEdkiiPeiBootInCapsuleOnDiskModePpiGuid,
 | |
|                0,
 | |
|                NULL,
 | |
|                &CapsuleOnDiskModePpi
 | |
|                );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       Status = PeiServicesLocatePpi (
 | |
|                  &gEdkiiPeiCapsuleOnDiskPpiGuid,
 | |
|                  0,
 | |
|                  NULL,
 | |
|                  (VOID **)&PeiCapsuleOnDisk
 | |
|                  );
 | |
| 
 | |
|       //
 | |
|       // Whether failed, still goes to Firmware Update boot path. BDS will clear corresponding indicator and reboot later on
 | |
|       //
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         Status = PeiCapsuleOnDisk->LoadCapsuleOnDisk (PeiServices, PeiCapsuleOnDisk);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) == NULL) {
 | |
|     //
 | |
|     // Don't build GuidHob if GuidHob has been installed.
 | |
|     //
 | |
|     Status = PeiServicesLocatePpi (
 | |
|                &gEfiPeiReadOnlyVariable2PpiGuid,
 | |
|                0,
 | |
|                NULL,
 | |
|                (VOID **)&Variable
 | |
|                );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       DataSize = sizeof (MemoryData);
 | |
|       Status   = Variable->GetVariable (
 | |
|                              Variable,
 | |
|                              EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
 | |
|                              &gEfiMemoryTypeInformationGuid,
 | |
|                              NULL,
 | |
|                              &DataSize,
 | |
|                              &MemoryData
 | |
|                              );
 | |
|       if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable (MemoryData, DataSize)) {
 | |
|         //
 | |
|         // Build the GUID'd HOB for DXE
 | |
|         //
 | |
|         BuildGuidDataHob (
 | |
|           &gEfiMemoryTypeInformationGuid,
 | |
|           MemoryData,
 | |
|           DataSize
 | |
|           );
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Look in all the FVs present in PEI and find the DXE Core FileHandle
 | |
|   //
 | |
|   FileHandle = DxeIplFindDxeCore ();
 | |
| 
 | |
|   //
 | |
|   // Load the DXE Core from a Firmware Volume.
 | |
|   //
 | |
|   Instance = 0;
 | |
|   do {
 | |
|     Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **)&LoadFile);
 | |
|     //
 | |
|     // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.
 | |
|     //
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     Status = LoadFile->LoadFile (
 | |
|                          LoadFile,
 | |
|                          FileHandle,
 | |
|                          &DxeCoreAddress,
 | |
|                          &DxeCoreSize,
 | |
|                          &DxeCoreEntryPoint,
 | |
|                          &AuthenticationState
 | |
|                          );
 | |
|   } while (EFI_ERROR (Status));
 | |
| 
 | |
|   //
 | |
|   // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.
 | |
|   //
 | |
|   Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // Add HOB for the DXE Core
 | |
|   //
 | |
|   BuildModuleHob (
 | |
|     &DxeCoreFileInfo.FileName,
 | |
|     DxeCoreAddress,
 | |
|     ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),
 | |
|     DxeCoreEntryPoint
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
 | |
|   //
 | |
|   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));
 | |
| 
 | |
|   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));
 | |
| 
 | |
|   //
 | |
|   // Transfer control to the DXE Core
 | |
|   // The hand off state is simply a pointer to the HOB list
 | |
|   //
 | |
|   HandOffToDxeCore (DxeCoreEntryPoint, HobList);
 | |
|   //
 | |
|   // If we get here, then the DXE Core returned.  This is an error
 | |
|   // DxeCore should not return.
 | |
|   //
 | |
|   ASSERT (FALSE);
 | |
|   CpuDeadLoop ();
 | |
| 
 | |
|   return EFI_OUT_OF_RESOURCES;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    Searches DxeCore in all firmware Volumes and loads the first
 | |
|    instance that contains DxeCore.
 | |
| 
 | |
|    @return FileHandle of DxeCore to load DxeCore.
 | |
| 
 | |
| **/
 | |
| EFI_PEI_FILE_HANDLE
 | |
| DxeIplFindDxeCore (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS           Status;
 | |
|   UINTN                Instance;
 | |
|   EFI_PEI_FV_HANDLE    VolumeHandle;
 | |
|   EFI_PEI_FILE_HANDLE  FileHandle;
 | |
| 
 | |
|   Instance = 0;
 | |
|   while (TRUE) {
 | |
|     //
 | |
|     // Traverse all firmware volume instances
 | |
|     //
 | |
|     Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
 | |
|     //
 | |
|     // If some error occurs here, then we cannot find any firmware
 | |
|     // volume that may contain DxeCore.
 | |
|     //
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));
 | |
|     }
 | |
| 
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|     //
 | |
|     // Find the DxeCore file type from the beginning in this firmware volume.
 | |
|     //
 | |
|     FileHandle = NULL;
 | |
|     Status     = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Find DxeCore FileHandle in this volume, then we skip other firmware volume and
 | |
|       // return the FileHandle.
 | |
|       //
 | |
|       return FileHandle;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // We cannot find DxeCore in this firmware volume, then search the next volume.
 | |
|     //
 | |
|     Instance++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The ExtractSection() function processes the input section and
 | |
|   returns a pointer to the section contents. If the section being
 | |
|   extracted does not require processing (if the section
 | |
|   GuidedSectionHeader.Attributes has the
 | |
|   EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
 | |
|   OutputBuffer is just updated to point to the start of the
 | |
|   section's contents. Otherwise, *Buffer must be allocated
 | |
|   from PEI permanent memory.
 | |
| 
 | |
|   @param This                   Indicates the
 | |
|                                 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
 | |
|                                 Buffer containing the input GUIDed section to be
 | |
|                                 processed. OutputBuffer OutputBuffer is
 | |
|                                 allocated from PEI permanent memory and contains
 | |
|                                 the new section stream.
 | |
|   @param InputSection           A pointer to the input buffer, which contains
 | |
|                                 the input section to be processed.
 | |
|   @param OutputBuffer           A pointer to a caller-allocated buffer, whose
 | |
|                                 size is specified by the contents of OutputSize.
 | |
|   @param OutputSize             A pointer to a caller-allocated
 | |
|                                 UINTN in which the size of *OutputBuffer
 | |
|                                 allocation is stored. If the function
 | |
|                                 returns anything other than EFI_SUCCESS,
 | |
|                                 the value of OutputSize is undefined.
 | |
|   @param AuthenticationStatus   A pointer to a caller-allocated
 | |
|                                 UINT32 that indicates the
 | |
|                                 authentication status of the
 | |
|                                 output buffer. If the input
 | |
|                                 section's GuidedSectionHeader.
 | |
|                                 Attributes field has the
 | |
|                                 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
 | |
|                                 bit as clear,
 | |
|                                 AuthenticationStatus must return
 | |
|                                 zero. These bits reflect the
 | |
|                                 status of the extraction
 | |
|                                 operation. If the function
 | |
|                                 returns anything other than
 | |
|                                 EFI_SUCCESS, the value of
 | |
|                                 AuthenticationStatus is
 | |
|                                 undefined.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The InputSection was
 | |
|                                 successfully processed and the
 | |
|                                 section contents were returned.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES  The system has insufficient
 | |
|                                 resources to process the request.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER The GUID in InputSection does
 | |
|                                 not match this instance of the
 | |
|                                 GUIDed Section Extraction PPI.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| CustomGuidedSectionExtract (
 | |
|   IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI  *This,
 | |
|   IN CONST  VOID                                   *InputSection,
 | |
|   OUT       VOID                                   **OutputBuffer,
 | |
|   OUT       UINTN                                  *OutputSize,
 | |
|   OUT       UINT32                                 *AuthenticationStatus
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       *ScratchBuffer;
 | |
|   UINT32      ScratchBufferSize;
 | |
|   UINT32      OutputBufferSize;
 | |
|   UINT16      SectionAttribute;
 | |
| 
 | |
|   //
 | |
|   // Init local variable
 | |
|   //
 | |
|   ScratchBuffer = NULL;
 | |
| 
 | |
|   //
 | |
|   // Call GetInfo to get the size and attribute of input guided section data.
 | |
|   //
 | |
|   Status = ExtractGuidedSectionGetInfo (
 | |
|              InputSection,
 | |
|              &OutputBufferSize,
 | |
|              &ScratchBufferSize,
 | |
|              &SectionAttribute
 | |
|              );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (ScratchBufferSize != 0) {
 | |
|     //
 | |
|     // Allocate scratch buffer
 | |
|     //
 | |
|     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
 | |
|     if (ScratchBuffer == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && (OutputBufferSize > 0)) {
 | |
|     //
 | |
|     // Allocate output buffer
 | |
|     //
 | |
|     *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize));
 | |
|     if (*OutputBuffer == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
 | |
|   }
 | |
| 
 | |
|   Status = ExtractGuidedSectionDecode (
 | |
|              InputSection,
 | |
|              OutputBuffer,
 | |
|              ScratchBuffer,
 | |
|              AuthenticationStatus
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Decode failed
 | |
|     //
 | |
|     DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   *OutputSize = (UINTN)OutputBufferSize;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    Decompresses a section to the output buffer.
 | |
| 
 | |
|    This function looks up the compression type field in the input section and
 | |
|    applies the appropriate compression algorithm to compress the section to a
 | |
|    callee allocated buffer.
 | |
| 
 | |
|    @param  This                  Points to this instance of the
 | |
|                                  EFI_PEI_DECOMPRESS_PEI PPI.
 | |
|    @param  CompressionSection    Points to the compressed section.
 | |
|    @param  OutputBuffer          Holds the returned pointer to the decompressed
 | |
|                                  sections.
 | |
|    @param  OutputSize            Holds the returned size of the decompress
 | |
|                                  section streams.
 | |
| 
 | |
|    @retval EFI_SUCCESS           The section was decompressed successfully.
 | |
|                                  OutputBuffer contains the resulting data and
 | |
|                                  OutputSize contains the resulting size.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| Decompress (
 | |
|   IN CONST  EFI_PEI_DECOMPRESS_PPI   *This,
 | |
|   IN CONST  EFI_COMPRESSION_SECTION  *CompressionSection,
 | |
|   OUT       VOID                     **OutputBuffer,
 | |
|   OUT       UINTN                    *OutputSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       *DstBuffer;
 | |
|   UINT8       *ScratchBuffer;
 | |
|   UINT32      DstBufferSize;
 | |
|   UINT32      ScratchBufferSize;
 | |
|   VOID        *CompressionSource;
 | |
|   UINT32      CompressionSourceSize;
 | |
|   UINT32      UncompressedLength;
 | |
|   UINT8       CompressionType;
 | |
| 
 | |
|   if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
 | |
|     ASSERT (FALSE);
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (IS_SECTION2 (CompressionSection)) {
 | |
|     CompressionSource     = (VOID *)((UINT8 *)CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
 | |
|     CompressionSourceSize = (UINT32)(SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
 | |
|     UncompressedLength    = ((EFI_COMPRESSION_SECTION2 *)CompressionSection)->UncompressedLength;
 | |
|     CompressionType       = ((EFI_COMPRESSION_SECTION2 *)CompressionSection)->CompressionType;
 | |
|   } else {
 | |
|     CompressionSource     = (VOID *)((UINT8 *)CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
 | |
|     CompressionSourceSize = (UINT32)(SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
 | |
|     UncompressedLength    = CompressionSection->UncompressedLength;
 | |
|     CompressionType       = CompressionSection->CompressionType;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // This is a compression set, expand it
 | |
|   //
 | |
|   switch (CompressionType) {
 | |
|     case EFI_STANDARD_COMPRESSION:
 | |
|       if (FeaturePcdGet (PcdDxeIplSupportUefiDecompress)) {
 | |
|         //
 | |
|         // Load EFI standard compression.
 | |
|         // For compressed data, decompress them to destination buffer.
 | |
|         //
 | |
|         Status = UefiDecompressGetInfo (
 | |
|                    CompressionSource,
 | |
|                    CompressionSourceSize,
 | |
|                    &DstBufferSize,
 | |
|                    &ScratchBufferSize
 | |
|                    );
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           //
 | |
|           // GetInfo failed
 | |
|           //
 | |
|           DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
 | |
|           return EFI_NOT_FOUND;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Allocate scratch buffer
 | |
|         //
 | |
|         ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
 | |
|         if (ScratchBuffer == NULL) {
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Allocate destination buffer
 | |
|         //
 | |
|         DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
 | |
|         if (DstBuffer == NULL) {
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Call decompress function
 | |
|         //
 | |
|         Status = UefiDecompress (
 | |
|                    CompressionSource,
 | |
|                    DstBuffer,
 | |
|                    ScratchBuffer
 | |
|                    );
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           //
 | |
|           // Decompress failed
 | |
|           //
 | |
|           DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
 | |
|           return EFI_NOT_FOUND;
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       } else {
 | |
|         //
 | |
|         // PcdDxeIplSupportUefiDecompress is FALSE
 | |
|         // Don't support UEFI decompression algorithm.
 | |
|         //
 | |
|         ASSERT (FALSE);
 | |
|         return EFI_NOT_FOUND;
 | |
|       }
 | |
| 
 | |
|     case EFI_NOT_COMPRESSED:
 | |
|       //
 | |
|       // Allocate destination buffer
 | |
|       //
 | |
|       DstBufferSize = UncompressedLength;
 | |
|       DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));
 | |
|       if (DstBuffer == NULL) {
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // stream is not actually compressed, just encapsulated.  So just copy it.
 | |
|       //
 | |
|       CopyMem (DstBuffer, CompressionSource, DstBufferSize);
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       //
 | |
|       // Don't support other unknown compression type.
 | |
|       //
 | |
|       ASSERT (FALSE);
 | |
|       return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   *OutputSize   = DstBufferSize;
 | |
|   *OutputBuffer = DstBuffer;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    Updates the Stack HOB passed to DXE phase.
 | |
| 
 | |
|    This function traverses the whole HOB list and update the stack HOB to
 | |
|    reflect the real stack that is used by DXE core.
 | |
| 
 | |
|    @param BaseAddress           The lower address of stack used by DxeCore.
 | |
|    @param Length                The length of stack used by DxeCore.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateStackHob (
 | |
|   IN EFI_PHYSICAL_ADDRESS  BaseAddress,
 | |
|   IN UINT64                Length
 | |
|   )
 | |
| {
 | |
|   EFI_PEI_HOB_POINTERS  Hob;
 | |
| 
 | |
|   Hob.Raw = GetHobList ();
 | |
|   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
 | |
|     if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
 | |
|       //
 | |
|       // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to
 | |
|       // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some
 | |
|       // PEIMs may also keep key information on stack
 | |
|       //
 | |
|       BuildMemoryAllocationHob (
 | |
|         Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
 | |
|         Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
 | |
|         EfiBootServicesData
 | |
|         );
 | |
|       //
 | |
|       // Update the BSP Stack Hob to reflect the new stack info.
 | |
|       //
 | |
|       Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
 | |
|       Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength      = Length;
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Hob.Raw = GET_NEXT_HOB (Hob);
 | |
|   }
 | |
| }
 |