Home | History | Annotate | Download | only in DxeIplPeim
      1 /** @file
      2   Last PEIM.
      3   Responsibility of this module is to load the DXE Core from a Firmware Volume.
      4 
      5 Copyright (c) 2016 HP Development Company, L.P.
      6 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      7 This program and the accompanying materials
      8 are licensed and made available under the terms and conditions of the BSD License
      9 which accompanies this distribution.  The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "DxeIpl.h"
     18 
     19 
     20 //
     21 // Module Globals used in the DXE to PEI hand off
     22 // These must be module globals, so the stack can be switched
     23 //
     24 CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
     25   DxeLoadCore
     26 };
     27 
     28 CONST EFI_PEI_PPI_DESCRIPTOR mDxeIplPpiList = {
     29   EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
     30   &gEfiDxeIplPpiGuid,
     31   (VOID *) &mDxeIplPpi
     32 };
     33 
     34 CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
     35   CustomGuidedSectionExtract
     36 };
     37 
     38 CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
     39   Decompress
     40 };
     41 
     42 CONST EFI_PEI_PPI_DESCRIPTOR mDecompressPpiList = {
     43   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     44   &gEfiPeiDecompressPpiGuid,
     45   (VOID *) &mDecompressPpi
     46 };
     47 
     48 CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
     49   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     50   &gEfiEndOfPeiSignalPpiGuid,
     51   NULL
     52 };
     53 
     54 CONST EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList = {
     55   (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     56   &gEfiPeiMemoryDiscoveredPpiGuid,
     57   InstallIplPermanentMemoryPpis
     58 };
     59 
     60 /**
     61   Entry point of DXE IPL PEIM.
     62 
     63   This function installs DXE IPL PPI.  It also reloads
     64   itself to memory on non-S3 resume boot path.
     65 
     66   @param  FileHandle  Handle of the file being invoked.
     67   @param  PeiServices Describes the list of possible PEI Services.
     68 
     69   @retval EFI_SUCESS  The entry point of DXE IPL PEIM executes successfully.
     70   @retval Others      Some error occurs during the execution of this function.
     71 
     72 **/
     73 EFI_STATUS
     74 EFIAPI
     75 PeimInitializeDxeIpl (
     76   IN       EFI_PEI_FILE_HANDLE  FileHandle,
     77   IN CONST EFI_PEI_SERVICES     **PeiServices
     78   )
     79 {
     80   EFI_STATUS                                Status;
     81   EFI_BOOT_MODE                             BootMode;
     82   VOID                                      *Dummy;
     83 
     84   BootMode = GetBootModeHob ();
     85 
     86   if (BootMode != BOOT_ON_S3_RESUME) {
     87     Status = PeiServicesRegisterForShadow (FileHandle);
     88     if (Status == EFI_SUCCESS) {
     89       //
     90       // EFI_SUCESS means it is the first time to call register for shadow.
     91       //
     92       return Status;
     93     }
     94 
     95     //
     96     // Ensure that DXE IPL is shadowed to permanent memory.
     97     //
     98     ASSERT (Status == EFI_ALREADY_STARTED);
     99 
    100     //
    101     // DXE core load requires permanent memory.
    102     //
    103     Status = PeiServicesLocatePpi (
    104                &gEfiPeiMemoryDiscoveredPpiGuid,
    105                0,
    106                NULL,
    107                (VOID **) &Dummy
    108                );
    109     ASSERT_EFI_ERROR (Status);
    110     if (EFI_ERROR (Status)) {
    111       return Status;
    112     }
    113 
    114     //
    115     // Now the permanent memory exists, install the PPIs for decompression
    116     // and section extraction.
    117     //
    118     Status = InstallIplPermanentMemoryPpis (NULL, NULL, NULL);
    119     ASSERT_EFI_ERROR (Status);
    120   } else {
    121     //
    122     // Install memory discovered PPI notification to install PPIs for
    123     // decompression and section extraction.
    124     //
    125     Status = PeiServicesNotifyPpi (&mMemoryDiscoveredNotifyList);
    126     ASSERT_EFI_ERROR (Status);
    127   }
    128 
    129   //
    130   // Install DxeIpl PPI.
    131   //
    132   Status = PeiServicesInstallPpi (&mDxeIplPpiList);
    133   ASSERT_EFI_ERROR(Status);
    134 
    135   return Status;
    136 }
    137 
    138 /**
    139    This function installs the PPIs that require permanent memory.
    140 
    141    @param  PeiServices      Indirect reference to the PEI Services Table.
    142    @param  NotifyDescriptor Address of the notification descriptor data structure.
    143    @param  Ppi              Address of the PPI that was installed.
    144 
    145    @return EFI_SUCCESS      The PPIs were installed successfully.
    146    @return Others           Some error occurs during the execution of this function.
    147 
    148 **/
    149 EFI_STATUS
    150 EFIAPI
    151 InstallIplPermanentMemoryPpis (
    152   IN EFI_PEI_SERVICES           **PeiServices,
    153   IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
    154   IN VOID                       *Ppi
    155   )
    156 {
    157   EFI_STATUS                    Status;
    158   EFI_GUID                      *ExtractHandlerGuidTable;
    159   UINTN                         ExtractHandlerNumber;
    160   EFI_PEI_PPI_DESCRIPTOR        *GuidPpi;
    161 
    162   //
    163   // Get custom extract guided section method guid list
    164   //
    165   ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
    166 
    167   //
    168   // Install custom guided section extraction PPI
    169   //
    170   if (ExtractHandlerNumber > 0) {
    171     GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
    172     ASSERT (GuidPpi != NULL);
    173     while (ExtractHandlerNumber-- > 0) {
    174       GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
    175       GuidPpi->Ppi   = (VOID *) &mCustomGuidedSectionExtractionPpi;
    176       GuidPpi->Guid  = &ExtractHandlerGuidTable[ExtractHandlerNumber];
    177       Status = PeiServicesInstallPpi (GuidPpi++);
    178       ASSERT_EFI_ERROR(Status);
    179     }
    180   }
    181 
    182   //
    183   // Install Decompress PPI.
    184   //
    185   Status = PeiServicesInstallPpi (&mDecompressPpiList);
    186   ASSERT_EFI_ERROR(Status);
    187 
    188   return Status;
    189 }
    190 
    191 /**
    192    Validate variable data for the MemoryTypeInformation.
    193 
    194    @param MemoryData       Variable data.
    195    @param MemoryDataSize   Variable data length.
    196 
    197    @return TRUE            The variable data is valid.
    198    @return FALSE           The variable data is invalid.
    199 
    200 **/
    201 BOOLEAN
    202 ValidateMemoryTypeInfoVariable (
    203   IN EFI_MEMORY_TYPE_INFORMATION      *MemoryData,
    204   IN UINTN                            MemoryDataSize
    205   )
    206 {
    207   UINTN                       Count;
    208   UINTN                       Index;
    209 
    210   // Check the input parameter.
    211   if (MemoryData == NULL) {
    212     return FALSE;
    213   }
    214 
    215   // Get Count
    216   Count = MemoryDataSize / sizeof (*MemoryData);
    217 
    218   // Check Size
    219   if (Count * sizeof(*MemoryData) != MemoryDataSize) {
    220     return FALSE;
    221   }
    222 
    223   // Check last entry type filed.
    224   if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {
    225     return FALSE;
    226   }
    227 
    228   // Check the type filed.
    229   for (Index = 0; Index < Count - 1; Index++) {
    230     if (MemoryData[Index].Type >= EfiMaxMemoryType) {
    231       return FALSE;
    232     }
    233   }
    234 
    235   return TRUE;
    236 }
    237 
    238 /**
    239    Main entry point to last PEIM.
    240 
    241    This function finds DXE Core in the firmware volume and transfer the control to
    242    DXE core.
    243 
    244    @param This          Entry point for DXE IPL PPI.
    245    @param PeiServices   General purpose services available to every PEIM.
    246    @param HobList       Address to the Pei HOB list.
    247 
    248    @return EFI_SUCCESS              DXE core was successfully loaded.
    249    @return EFI_OUT_OF_RESOURCES     There are not enough resources to load DXE core.
    250 
    251 **/
    252 EFI_STATUS
    253 EFIAPI
    254 DxeLoadCore (
    255   IN CONST EFI_DXE_IPL_PPI *This,
    256   IN EFI_PEI_SERVICES      **PeiServices,
    257   IN EFI_PEI_HOB_POINTERS  HobList
    258   )
    259 {
    260   EFI_STATUS                                Status;
    261   EFI_FV_FILE_INFO                          DxeCoreFileInfo;
    262   EFI_PHYSICAL_ADDRESS                      DxeCoreAddress;
    263   UINT64                                    DxeCoreSize;
    264   EFI_PHYSICAL_ADDRESS                      DxeCoreEntryPoint;
    265   EFI_BOOT_MODE                             BootMode;
    266   EFI_PEI_FILE_HANDLE                       FileHandle;
    267   EFI_PEI_READ_ONLY_VARIABLE2_PPI           *Variable;
    268   EFI_PEI_LOAD_FILE_PPI                     *LoadFile;
    269   UINTN                                     Instance;
    270   UINT32                                    AuthenticationState;
    271   UINTN                                     DataSize;
    272   EFI_PEI_S3_RESUME2_PPI                    *S3Resume;
    273   EFI_PEI_RECOVERY_MODULE_PPI               *PeiRecovery;
    274   EFI_MEMORY_TYPE_INFORMATION               MemoryData[EfiMaxMemoryType + 1];
    275 
    276   //
    277   // if in S3 Resume, restore configure
    278   //
    279   BootMode = GetBootModeHob ();
    280 
    281   if (BootMode == BOOT_ON_S3_RESUME) {
    282     Status = PeiServicesLocatePpi (
    283                &gEfiPeiS3Resume2PpiGuid,
    284                0,
    285                NULL,
    286                (VOID **) &S3Resume
    287                );
    288     if (EFI_ERROR (Status)) {
    289       //
    290       // Report Status code that S3Resume PPI can not be found
    291       //
    292       REPORT_STATUS_CODE (
    293         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
    294         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND)
    295         );
    296     }
    297     ASSERT_EFI_ERROR (Status);
    298 
    299     Status = S3Resume->S3RestoreConfig2 (S3Resume);
    300     ASSERT_EFI_ERROR (Status);
    301   } else if (BootMode == BOOT_IN_RECOVERY_MODE) {
    302     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN));
    303     Status = PeiServicesLocatePpi (
    304                &gEfiPeiRecoveryModulePpiGuid,
    305                0,
    306                NULL,
    307                (VOID **) &PeiRecovery
    308                );
    309 
    310     if (EFI_ERROR (Status)) {
    311       DEBUG ((DEBUG_ERROR, "Locate Recovery PPI Failed.(Status = %r)\n", Status));
    312       //
    313       // Report Status code the failure of locating Recovery PPI
    314       //
    315       REPORT_STATUS_CODE (
    316         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
    317         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)
    318         );
    319       CpuDeadLoop ();
    320     }
    321 
    322     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD));
    323     Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);
    324     if (EFI_ERROR (Status)) {
    325       DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));
    326       //
    327       // Report Status code that recovery image can not be found
    328       //
    329       REPORT_STATUS_CODE (
    330         EFI_ERROR_CODE | EFI_ERROR_MAJOR,
    331         (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)
    332         );
    333       CpuDeadLoop ();
    334     }
    335     REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));
    336     //
    337     // Now should have a HOB with the DXE core
    338     //
    339   }
    340 
    341   if (GetFirstGuidHob ((CONST EFI_GUID *)&gEfiMemoryTypeInformationGuid) == NULL) {
    342     //
    343     // Don't build GuidHob if GuidHob has been installed.
    344     //
    345     Status = PeiServicesLocatePpi (
    346                &gEfiPeiReadOnlyVariable2PpiGuid,
    347                0,
    348                NULL,
    349                (VOID **)&Variable
    350                );
    351     if (!EFI_ERROR (Status)) {
    352       DataSize = sizeof (MemoryData);
    353       Status = Variable->GetVariable (
    354                            Variable,
    355                            EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
    356                            &gEfiMemoryTypeInformationGuid,
    357                            NULL,
    358                            &DataSize,
    359                            &MemoryData
    360                            );
    361       if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {
    362         //
    363         // Build the GUID'd HOB for DXE
    364         //
    365         BuildGuidDataHob (
    366           &gEfiMemoryTypeInformationGuid,
    367           MemoryData,
    368           DataSize
    369           );
    370       }
    371     }
    372   }
    373 
    374   //
    375   // Look in all the FVs present in PEI and find the DXE Core FileHandle
    376   //
    377   FileHandle = DxeIplFindDxeCore ();
    378 
    379   //
    380   // Load the DXE Core from a Firmware Volume.
    381   //
    382   Instance = 0;
    383   do {
    384     Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile);
    385     //
    386     // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.
    387     //
    388     ASSERT_EFI_ERROR (Status);
    389 
    390     Status = LoadFile->LoadFile (
    391                          LoadFile,
    392                          FileHandle,
    393                          &DxeCoreAddress,
    394                          &DxeCoreSize,
    395                          &DxeCoreEntryPoint,
    396                          &AuthenticationState
    397                          );
    398   } while (EFI_ERROR (Status));
    399 
    400   //
    401   // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.
    402   //
    403   Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);
    404   ASSERT_EFI_ERROR (Status);
    405 
    406   //
    407   // Add HOB for the DXE Core
    408   //
    409   BuildModuleHob (
    410     &DxeCoreFileInfo.FileName,
    411     DxeCoreAddress,
    412     ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),
    413     DxeCoreEntryPoint
    414     );
    415 
    416   //
    417   // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
    418   //
    419   REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));
    420 
    421   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));
    422 
    423   //
    424   // Transfer control to the DXE Core
    425   // The hand off state is simply a pointer to the HOB list
    426   //
    427   HandOffToDxeCore (DxeCoreEntryPoint, HobList);
    428   //
    429   // If we get here, then the DXE Core returned.  This is an error
    430   // DxeCore should not return.
    431   //
    432   ASSERT (FALSE);
    433   CpuDeadLoop ();
    434 
    435   return EFI_OUT_OF_RESOURCES;
    436 }
    437 
    438 
    439 /**
    440    Searches DxeCore in all firmware Volumes and loads the first
    441    instance that contains DxeCore.
    442 
    443    @return FileHandle of DxeCore to load DxeCore.
    444 
    445 **/
    446 EFI_PEI_FILE_HANDLE
    447 DxeIplFindDxeCore (
    448   VOID
    449   )
    450 {
    451   EFI_STATUS            Status;
    452   UINTN                 Instance;
    453   EFI_PEI_FV_HANDLE     VolumeHandle;
    454   EFI_PEI_FILE_HANDLE   FileHandle;
    455 
    456   Instance    = 0;
    457   while (TRUE) {
    458     //
    459     // Traverse all firmware volume instances
    460     //
    461     Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);
    462     //
    463     // If some error occurs here, then we cannot find any firmware
    464     // volume that may contain DxeCore.
    465     //
    466     if (EFI_ERROR (Status)) {
    467       REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));
    468     }
    469     ASSERT_EFI_ERROR (Status);
    470 
    471     //
    472     // Find the DxeCore file type from the beginning in this firmware volume.
    473     //
    474     FileHandle = NULL;
    475     Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
    476     if (!EFI_ERROR (Status)) {
    477       //
    478       // Find DxeCore FileHandle in this volume, then we skip other firmware volume and
    479       // return the FileHandle.
    480       //
    481       return FileHandle;
    482     }
    483     //
    484     // We cannot find DxeCore in this firmware volume, then search the next volume.
    485     //
    486     Instance++;
    487   }
    488 }
    489 
    490 
    491 
    492 /**
    493   The ExtractSection() function processes the input section and
    494   returns a pointer to the section contents. If the section being
    495   extracted does not require processing (if the section
    496   GuidedSectionHeader.Attributes has the
    497   EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
    498   OutputBuffer is just updated to point to the start of the
    499   section's contents. Otherwise, *Buffer must be allocated
    500   from PEI permanent memory.
    501 
    502   @param This                   Indicates the
    503                                 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
    504                                 Buffer containing the input GUIDed section to be
    505                                 processed. OutputBuffer OutputBuffer is
    506                                 allocated from PEI permanent memory and contains
    507                                 the new section stream.
    508   @param InputSection           A pointer to the input buffer, which contains
    509                                 the input section to be processed.
    510   @param OutputBuffer           A pointer to a caller-allocated buffer, whose
    511                                 size is specified by the contents of OutputSize.
    512   @param OutputSize             A pointer to a caller-allocated
    513                                 UINTN in which the size of *OutputBuffer
    514                                 allocation is stored. If the function
    515                                 returns anything other than EFI_SUCCESS,
    516                                 the value of OutputSize is undefined.
    517   @param AuthenticationStatus   A pointer to a caller-allocated
    518                                 UINT32 that indicates the
    519                                 authentication status of the
    520                                 output buffer. If the input
    521                                 section's GuidedSectionHeader.
    522                                 Attributes field has the
    523                                 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
    524                                 bit as clear,
    525                                 AuthenticationStatus must return
    526                                 zero. These bits reflect the
    527                                 status of the extraction
    528                                 operation. If the function
    529                                 returns anything other than
    530                                 EFI_SUCCESS, the value of
    531                                 AuthenticationStatus is
    532                                 undefined.
    533 
    534   @retval EFI_SUCCESS           The InputSection was
    535                                 successfully processed and the
    536                                 section contents were returned.
    537 
    538   @retval EFI_OUT_OF_RESOURCES  The system has insufficient
    539                                 resources to process the request.
    540 
    541   @retval EFI_INVALID_PARAMETER The GUID in InputSection does
    542                                 not match this instance of the
    543                                 GUIDed Section Extraction PPI.
    544 
    545 **/
    546 EFI_STATUS
    547 EFIAPI
    548 CustomGuidedSectionExtract (
    549   IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
    550   IN CONST  VOID                                  *InputSection,
    551   OUT       VOID                                  **OutputBuffer,
    552   OUT       UINTN                                 *OutputSize,
    553   OUT       UINT32                                *AuthenticationStatus
    554 )
    555 {
    556   EFI_STATUS      Status;
    557   UINT8           *ScratchBuffer;
    558   UINT32          ScratchBufferSize;
    559   UINT32          OutputBufferSize;
    560   UINT16          SectionAttribute;
    561 
    562   //
    563   // Init local variable
    564   //
    565   ScratchBuffer = NULL;
    566 
    567   //
    568   // Call GetInfo to get the size and attribute of input guided section data.
    569   //
    570   Status = ExtractGuidedSectionGetInfo (
    571              InputSection,
    572              &OutputBufferSize,
    573              &ScratchBufferSize,
    574              &SectionAttribute
    575              );
    576 
    577   if (EFI_ERROR (Status)) {
    578     DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
    579     return Status;
    580   }
    581 
    582   if (ScratchBufferSize != 0) {
    583     //
    584     // Allocate scratch buffer
    585     //
    586     ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
    587     if (ScratchBuffer == NULL) {
    588       return EFI_OUT_OF_RESOURCES;
    589     }
    590   }
    591 
    592   if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
    593     //
    594     // Allocate output buffer
    595     //
    596     *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
    597     if (*OutputBuffer == NULL) {
    598       return EFI_OUT_OF_RESOURCES;
    599     }
    600     DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
    601     //
    602     // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
    603     // skip EFI section header to make section data at page alignment.
    604     //
    605     *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
    606   }
    607 
    608   Status = ExtractGuidedSectionDecode (
    609              InputSection,
    610              OutputBuffer,
    611              ScratchBuffer,
    612              AuthenticationStatus
    613              );
    614   if (EFI_ERROR (Status)) {
    615     //
    616     // Decode failed
    617     //
    618     DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
    619     return Status;
    620   }
    621 
    622   *OutputSize = (UINTN) OutputBufferSize;
    623 
    624   return EFI_SUCCESS;
    625 }
    626 
    627 
    628 
    629 /**
    630    Decompresses a section to the output buffer.
    631 
    632    This function looks up the compression type field in the input section and
    633    applies the appropriate compression algorithm to compress the section to a
    634    callee allocated buffer.
    635 
    636    @param  This                  Points to this instance of the
    637                                  EFI_PEI_DECOMPRESS_PEI PPI.
    638    @param  CompressionSection    Points to the compressed section.
    639    @param  OutputBuffer          Holds the returned pointer to the decompressed
    640                                  sections.
    641    @param  OutputSize            Holds the returned size of the decompress
    642                                  section streams.
    643 
    644    @retval EFI_SUCCESS           The section was decompressed successfully.
    645                                  OutputBuffer contains the resulting data and
    646                                  OutputSize contains the resulting size.
    647 
    648 **/
    649 EFI_STATUS
    650 EFIAPI
    651 Decompress (
    652   IN CONST  EFI_PEI_DECOMPRESS_PPI  *This,
    653   IN CONST  EFI_COMPRESSION_SECTION *CompressionSection,
    654   OUT       VOID                    **OutputBuffer,
    655   OUT       UINTN                   *OutputSize
    656  )
    657 {
    658   EFI_STATUS                      Status;
    659   UINT8                           *DstBuffer;
    660   UINT8                           *ScratchBuffer;
    661   UINT32                          DstBufferSize;
    662   UINT32                          ScratchBufferSize;
    663   VOID                            *CompressionSource;
    664   UINT32                          CompressionSourceSize;
    665   UINT32                          UncompressedLength;
    666   UINT8                           CompressionType;
    667 
    668   if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
    669     ASSERT (FALSE);
    670     return EFI_INVALID_PARAMETER;
    671   }
    672 
    673   if (IS_SECTION2 (CompressionSection)) {
    674     CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
    675     CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
    676     UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;
    677     CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;
    678   } else {
    679     CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
    680     CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
    681     UncompressedLength = CompressionSection->UncompressedLength;
    682     CompressionType = CompressionSection->CompressionType;
    683   }
    684 
    685   //
    686   // This is a compression set, expand it
    687   //
    688   switch (CompressionType) {
    689   case EFI_STANDARD_COMPRESSION:
    690     if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {
    691       //
    692       // Load EFI standard compression.
    693       // For compressed data, decompress them to destination buffer.
    694       //
    695       Status = UefiDecompressGetInfo (
    696                  CompressionSource,
    697                  CompressionSourceSize,
    698                  &DstBufferSize,
    699                  &ScratchBufferSize
    700                  );
    701       if (EFI_ERROR (Status)) {
    702         //
    703         // GetInfo failed
    704         //
    705         DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
    706         return EFI_NOT_FOUND;
    707       }
    708       //
    709       // Allocate scratch buffer
    710       //
    711       ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
    712       if (ScratchBuffer == NULL) {
    713         return EFI_OUT_OF_RESOURCES;
    714       }
    715       //
    716       // Allocate destination buffer, extra one page for adjustment
    717       //
    718       DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
    719       if (DstBuffer == NULL) {
    720         return EFI_OUT_OF_RESOURCES;
    721       }
    722       //
    723       // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
    724       // to make section data at page alignment.
    725       //
    726       DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
    727       //
    728       // Call decompress function
    729       //
    730       Status = UefiDecompress (
    731                   CompressionSource,
    732                   DstBuffer,
    733                   ScratchBuffer
    734                   );
    735       if (EFI_ERROR (Status)) {
    736         //
    737         // Decompress failed
    738         //
    739         DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
    740         return EFI_NOT_FOUND;
    741       }
    742       break;
    743     } else {
    744       //
    745       // PcdDxeIplSupportUefiDecompress is FALSE
    746       // Don't support UEFI decompression algorithm.
    747       //
    748       ASSERT (FALSE);
    749       return EFI_NOT_FOUND;
    750     }
    751 
    752   case EFI_NOT_COMPRESSED:
    753     //
    754     // Allocate destination buffer
    755     //
    756     DstBufferSize = UncompressedLength;
    757     DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
    758     if (DstBuffer == NULL) {
    759       return EFI_OUT_OF_RESOURCES;
    760     }
    761     //
    762     // Adjust DstBuffer offset, skip EFI section header
    763     // to make section data at page alignment.
    764     //
    765     DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
    766     //
    767     // stream is not actually compressed, just encapsulated.  So just copy it.
    768     //
    769     CopyMem (DstBuffer, CompressionSource, DstBufferSize);
    770     break;
    771 
    772   default:
    773     //
    774     // Don't support other unknown compression type.
    775     //
    776     ASSERT (FALSE);
    777     return EFI_NOT_FOUND;
    778   }
    779 
    780   *OutputSize = DstBufferSize;
    781   *OutputBuffer = DstBuffer;
    782 
    783   return EFI_SUCCESS;
    784 }
    785 
    786 
    787 /**
    788    Updates the Stack HOB passed to DXE phase.
    789 
    790    This function traverses the whole HOB list and update the stack HOB to
    791    reflect the real stack that is used by DXE core.
    792 
    793    @param BaseAddress           The lower address of stack used by DxeCore.
    794    @param Length                The length of stack used by DxeCore.
    795 
    796 **/
    797 VOID
    798 UpdateStackHob (
    799   IN EFI_PHYSICAL_ADDRESS        BaseAddress,
    800   IN UINT64                      Length
    801   )
    802 {
    803   EFI_PEI_HOB_POINTERS           Hob;
    804 
    805   Hob.Raw = GetHobList ();
    806   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
    807     if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
    808       //
    809       // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to
    810       // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some
    811       // PEIMs may also keep key information on stack
    812       //
    813       BuildMemoryAllocationHob (
    814         Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
    815         Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
    816         EfiBootServicesData
    817         );
    818       //
    819       // Update the BSP Stack Hob to reflect the new stack info.
    820       //
    821       Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
    822       Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
    823       break;
    824     }
    825     Hob.Raw = GET_NEXT_HOB (Hob);
    826   }
    827 }
    828