]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Update CustomDecompress library to support algorithm guid and Update DxeIpl and DxeCo...
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / DxeLoad.c
index b749fb18c15aa66e8fee360b596ea404a42502f1..e7359e5684824bc7e04ee754792cbbd6df428011 100644 (file)
@@ -21,12 +21,21 @@ Abstract:
 --*/\r
 \r
 #include "DxeIpl.h"\r
+#include <Ppi/GuidedSectionExtraction.h>\r
 \r
 // porting note remove later\r
-#include "DecompressLibrary.h"\r
 #include "FrameworkPei.h"\r
 // end of remove later\r
 \r
+EFI_STATUS\r
+CustomDecompressExtractSection (\r
+  IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
+  IN CONST  VOID                                  *InputSection,\r
+  OUT       VOID                                  **OutputBuffer,\r
+  OUT       UINTN                                 *OutputSize,\r
+  OUT       UINT32                                *AuthenticationStatus\r
+);\r
+\r
 BOOLEAN gInMemory = FALSE;\r
 \r
 //\r
@@ -41,6 +50,10 @@ static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {
   DxeIplLoadFile\r
 };\r
 \r
+static EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomDecompressExtractiongPpi = {\r
+  CustomDecompressExtractSection\r
+};\r
+\r
 static EFI_PEI_PPI_DESCRIPTOR     mPpiList[] = {\r
   {\r
   EFI_PEI_PPI_DESCRIPTOR_PPI,\r
@@ -60,16 +73,6 @@ static EFI_PEI_PPI_DESCRIPTOR     mPpiSignal = {
   NULL\r
 };\r
 \r
-GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY  gEfiDecompress = {\r
-  UefiDecompressGetInfo,\r
-  UefiDecompress\r
-};\r
-\r
-GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY  gCustomDecompress = {\r
-  CustomDecompressGetInfo,\r
-  CustomDecompress\r
-};\r
-\r
 EFI_STATUS\r
 EFIAPI\r
 PeimInitializeDxeIpl (\r
@@ -96,7 +99,10 @@ Returns:
   EFI_STATUS                                Status;\r
   EFI_PEI_PE_COFF_LOADER_PROTOCOL           *PeiEfiPeiPeCoffLoader;\r
   EFI_BOOT_MODE                             BootMode;\r
-\r
+  EFI_GUID                                  **DecompressGuidList;\r
+  UINT32                                    DecompressMethodNumber;\r
+  EFI_PEI_PPI_DESCRIPTOR                    *GuidPpi;\r
+  \r
   Status = PeiServicesGetBootMode (&BootMode);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
@@ -111,6 +117,35 @@ Returns:
     //\r
     Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);\r
   } else {\r
+    //\r
+    // Get custom decompress method guid list \r
+    //\r
+    DecompressGuidList     = NULL;\r
+    DecompressMethodNumber = 0;\r
+    Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);\r
+    if (Status == EFI_OUT_OF_RESOURCES) {\r
+      DecompressGuidList = (EFI_GUID **) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_GUID *)));\r
+      ASSERT (DecompressGuidList != NULL);\r
+      Status = CustomDecompressGetAlgorithms (DecompressGuidList, &DecompressMethodNumber);\r
+    }\r
+    ASSERT_EFI_ERROR(Status);\r
+\r
+    //\r
+    // Install custom decompress extraction guid ppi\r
+    //\r
+    if (DecompressMethodNumber > 0) {\r
+      GuidPpi = NULL;\r
+      GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePages (EFI_SIZE_TO_PAGES (DecompressMethodNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR)));\r
+      ASSERT (GuidPpi != NULL);\r
+      while (DecompressMethodNumber-- > 0) {\r
+        GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
+        GuidPpi->Ppi   = &mCustomDecompressExtractiongPpi;\r
+        GuidPpi->Guid  = DecompressGuidList [DecompressMethodNumber];\r
+        Status = PeiServicesInstallPpi (GuidPpi++);\r
+        ASSERT_EFI_ERROR(Status);\r
+      }\r
+    }\r
+    \r
     //\r
     // Install FvFileLoader and DxeIpl PPIs.\r
     //\r
@@ -205,7 +240,6 @@ Returns:
   PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
   ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
 \r
-\r
   //\r
   // Find the EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE type compressed Firmware Volume file\r
   // The file found will be processed by PeiProcessFile: It will first be decompressed to\r
@@ -252,6 +286,14 @@ Returns:
     );\r
 \r
   //\r
+  // Add HOB for the PE/COFF Loader Protocol\r
+  //\r
+  BuildGuidDataHob (\r
+    &gEfiPeiPeCoffLoaderGuid,\r
+    (VOID *)&PeiEfiPeiPeCoffLoader,\r
+    sizeof (VOID *)\r
+    );\r
+  //\r
   // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
   //\r
   REPORT_STATUS_CODE (\r
@@ -259,38 +301,6 @@ Returns:
     EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT\r
     );\r
 \r
-  if (FeaturePcdGet (PcdDxeIplBuildShareCodeHobs)) {\r
-    if (FeaturePcdGet (PcdDxeIplSupportEfiDecompress)) {\r
-      //\r
-      // Add HOB for the EFI Decompress Protocol\r
-      //\r
-      BuildGuidDataHob (\r
-        &gEfiDecompressProtocolGuid,\r
-        (VOID *)&gEfiDecompress,\r
-        sizeof (gEfiDecompress)\r
-        );\r
-    }\r
-    if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {\r
-      //\r
-      // Add HOB for the user customized Decompress Protocol\r
-      //\r
-      BuildGuidDataHob (\r
-        &gEfiCustomizedDecompressProtocolGuid,\r
-        (VOID *)&gCustomDecompress,\r
-        sizeof (gCustomDecompress)\r
-        );\r
-    }\r
-\r
-    //\r
-    // Add HOB for the PE/COFF Loader Protocol\r
-    //\r
-    BuildGuidDataHob (\r
-      &gEfiPeiPeCoffLoaderGuid,\r
-      (VOID *)&PeiEfiPeiPeCoffLoader,\r
-      sizeof (VOID *)\r
-      );\r
-  }\r
-\r
   //\r
   // Transfer control to the DXE Core\r
   // The handoff state is simply a pointer to the HOB list\r
@@ -311,7 +321,7 @@ Returns:
 EFI_STATUS\r
 PeiFindFile (\r
   IN  UINT8                  Type,\r
-  IN  UINT16                 SectionType,\r
+  IN  EFI_SECTION_TYPE       SectionType,\r
   OUT EFI_GUID               *FileName,\r
   OUT VOID                   **Pe32Data\r
   )\r
@@ -609,7 +619,7 @@ Returns:
 \r
 EFI_STATUS\r
 PeiProcessFile (\r
-  IN      UINT16                 SectionType,\r
+  IN      EFI_SECTION_TYPE       SectionType,\r
   IN      EFI_FFS_FILE_HEADER    *FfsFileHeader,\r
   OUT     VOID                   **Pe32Data,\r
   IN      EFI_PEI_HOB_POINTERS   *OrigHob\r
@@ -635,8 +645,6 @@ Returns:
 --*/\r
 {\r
   EFI_STATUS                      Status;\r
-  VOID                            *SectionData;\r
-  DECOMPRESS_LIBRARY              *DecompressLibrary;\r
   UINT8                           *DstBuffer;\r
   UINT8                           *ScratchBuffer;\r
   UINT32                          DstBufferSize;\r
@@ -649,327 +657,367 @@ Returns:
   EFI_COMMON_SECTION_HEADER       *Section;\r
   UINTN                           SectionLength;\r
   UINTN                           OccupiedSectionLength;\r
-  UINT64                          FileSize;\r
-  UINT32                          AuthenticationStatus;\r
-  EFI_PEI_SECTION_EXTRACTION_PPI  *SectionExtract;\r
-  UINT32                          BufferSize;\r
-  UINT8                           *Buffer;\r
-  EFI_PEI_SECURITY_PPI            *Security;\r
-  BOOLEAN                         StartCrisisRecovery;\r
-  EFI_GUID                        TempGuid;\r
+  UINTN                           FileSize;\r
   EFI_FIRMWARE_VOLUME_HEADER      *FvHeader;\r
   EFI_COMPRESSION_SECTION         *CompressionSection;\r
+  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI  *SectionExtract;\r
+  UINT32                          AuthenticationStatus;\r
 \r
   //\r
-  // Initialize local variables.\r
+  // First try to find the required section in this ffs file.\r
   //\r
-  DecompressLibrary = NULL;\r
-  DstBuffer         = NULL;\r
-  DstBufferSize     = 0;\r
-\r
   Status = PeiServicesFfsFindSectionData (\r
-             EFI_SECTION_COMPRESSION,\r
+             SectionType,\r
              FfsFileHeader,\r
-             &SectionData\r
+             Pe32Data\r
              );\r
-\r
+  if (!EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  \r
   //\r
-  // First process the compression section\r
+  // If not found, the required section may be in guided or compressed section.\r
+  // So, search guided or compressed section to process\r
   //\r
-  if (!EFI_ERROR (Status)) {\r
+  Section   = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));\r
+  FileSize  = FfsFileHeader->Size[0] & 0xFF;\r
+  FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;\r
+  FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
+  FileSize &= 0x00FFFFFF;\r
+  OccupiedSectionLength = 0;\r
+\r
+  do {\r
     //\r
-    // Yes, there is a compression section, so extract the contents\r
-    // Decompress the image here\r
+    // Initialize local variables.\r
     //\r
-    Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER));\r
+    DstBuffer         = NULL;\r
+    DstBufferSize     = 0; \r
 \r
-    do {\r
-      SectionLength         = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
-      OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
+    Section               = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
+    SectionLength         = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
+    OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
 \r
+    //\r
+    // Was the DXE Core file encapsulated in a GUID'd section?\r
+    //\r
+    if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
       //\r
-      // Was the DXE Core file encapsulated in a GUID'd section?\r
+      // Set a default authenticatino state\r
       //\r
-      if (Section->Type == EFI_SECTION_GUID_DEFINED) {\r
+      AuthenticationStatus = 0;\r
+      //\r
+      // Locate extract guid section ppi\r
+      //\r
+      Status = PeiServicesLocatePpi (\r
+                 (EFI_GUID *) (Section + 1),\r
+                 0,\r
+                 NULL,\r
+                 (VOID **)&SectionExtract\r
+                 );\r
 \r
+      if (EFI_ERROR (Status)) {\r
         //\r
-        // This following code constitutes the addition of the security model\r
-        // to the DXE IPL.\r
+        // ignore the unknown guid section\r
         //\r
+        continue;\r
+      }\r
+      //\r
+      // Extract the contents from guid section\r
+      //\r
+      Status = SectionExtract->ExtractSection (\r
+                                SectionExtract,\r
+                                (VOID *) Section,\r
+                                (VOID **) &DstBuffer,\r
+                                &DstBufferSize,\r
+                                &AuthenticationStatus\r
+                                );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "Extract section content failed - %r\n", Status));\r
+        return Status;\r
+      }\r
+      //\r
+      // Todo check AuthenticationStatus and do the verify\r
+      //\r
+    } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
+      //\r
+      // This is a compression set, expand it\r
+      //\r
+      CompressionSection  = (EFI_COMPRESSION_SECTION *) Section;\r
+\r
+      switch (CompressionSection->CompressionType) {\r
+      case EFI_STANDARD_COMPRESSION:\r
         //\r
-        // Set a default authenticatino state\r
+        // Load EFI standard compression.\r
+        // For compressed data, decompress them to dstbuffer.\r
         //\r
-        AuthenticationStatus = 0;\r
-\r
-        Status = PeiServicesLocatePpi (\r
-                   &gEfiPeiSectionExtractionPpiGuid,\r
-                   0,\r
-                   NULL,\r
-                   (VOID **)&SectionExtract\r
+        Status = UefiDecompressGetInfo (\r
+                   (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
+                   (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
+                   &DstBufferSize,\r
+                   &ScratchBufferSize\r
                    );\r
-\r
         if (EFI_ERROR (Status)) {\r
-          return Status;\r
+          //\r
+          // GetInfo failed\r
+          //\r
+          DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
+          return EFI_NOT_FOUND;\r
         }\r
         //\r
-        // Verify Authentication State\r
+        // Allocate scratch buffer\r
         //\r
-        CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID));\r
-\r
-        Status = SectionExtract->PeiGetSection (\r
-                                  GetPeiServicesTablePointer(),\r
-                                  SectionExtract,\r
-                                  (EFI_SECTION_TYPE *) &SectionType,\r
-                                  &TempGuid,\r
-                                  0,\r
-                                  (VOID **) &Buffer,\r
-                                  &BufferSize,\r
-                                  &AuthenticationStatus\r
-                                  );\r
-\r
-        if (EFI_ERROR (Status)) {\r
-          return Status;\r
+        ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
+        if (ScratchBuffer == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
         }\r
         //\r
-        // If not ask the Security PPI, if exists, for disposition\r
+        // Allocate destination buffer\r
+        //\r
+        DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
+        if (DstBuffer == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
         //\r
+        // Call decompress function\r
         //\r
-        Status = PeiServicesLocatePpi (\r
-                   &gEfiPeiSecurityPpiGuid,\r
-                   0,\r
-                   NULL,\r
-                   (VOID **)&Security\r
-                   );\r
+        Status = UefiDecompress (\r
+                    (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
+                    DstBuffer,\r
+                    ScratchBuffer\r
+                    );\r
         if (EFI_ERROR (Status)) {\r
-          return Status;\r
+          //\r
+          // Decompress failed\r
+          //\r
+          DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
+          return EFI_NOT_FOUND;\r
         }\r
+        break;\r
 \r
-        Status = Security->AuthenticationState (\r
-                            GetPeiServicesTablePointer(),\r
-                            (struct _EFI_PEI_SECURITY_PPI *) Security,\r
-                            AuthenticationStatus,\r
-                            FfsFileHeader,\r
-                            &StartCrisisRecovery\r
-                            );\r
+      // porting note the original branch for customized compress is removed, it should be change to use GUID compress\r
 \r
-        if (EFI_ERROR (Status)) {\r
-          return Status;\r
-        }\r
+      case EFI_NOT_COMPRESSED:\r
         //\r
-        // If there is a security violation, report to caller and have\r
-        // the upper-level logic possible engender a crisis recovery\r
+        // Allocate destination buffer\r
         //\r
-        if (StartCrisisRecovery) {\r
-          return EFI_SECURITY_VIOLATION;\r
+        DstBufferSize = CompressionSection->UncompressedLength;\r
+        DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
+        if (DstBuffer == NULL) {\r
+          return EFI_OUT_OF_RESOURCES;\r
         }\r
-      }\r
-\r
-      if (Section->Type == EFI_SECTION_PE32) {\r
         //\r
-        // This is what we want\r
+        // stream is not actually compressed, just encapsulated.  So just copy it.\r
         //\r
-        *Pe32Data = (VOID *) (Section + 1);\r
-        return EFI_SUCCESS;\r
-      } else if (Section->Type == EFI_SECTION_COMPRESSION) {\r
+        CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
+        break;\r
+\r
+      default:\r
         //\r
-        // This is a compression set, expand it\r
+        // Don't support other unknown compression type.\r
         //\r
-        CompressionSection  = (EFI_COMPRESSION_SECTION *) Section;\r
-\r
-        switch (CompressionSection->CompressionType) {\r
-        case EFI_STANDARD_COMPRESSION:\r
-          //\r
-          // Load EFI standard compression.\r
-          //\r
-          if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {\r
-            DecompressLibrary = &gEfiDecompress;\r
-          } else {\r
-            ASSERT (FALSE);\r
-            return EFI_NOT_FOUND;\r
-          }\r
-          break;\r
-\r
-        // porting note the original branch for customized compress is removed, it should be change to use GUID compress\r
+        ASSERT_EFI_ERROR (Status);\r
+        return EFI_NOT_FOUND;\r
+      }\r
+    } else {\r
+      //\r
+      // ignore other type sections\r
+      //\r
+      continue;\r
+    }\r
 \r
-        case EFI_NOT_COMPRESSED:\r
-          //\r
-          // Allocate destination buffer\r
-          //\r
-          DstBufferSize = CompressionSection->UncompressedLength;\r
-          DstBuffer     = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
-          if (DstBuffer == NULL) {\r
-            return EFI_OUT_OF_RESOURCES;\r
-          }\r
-          //\r
-          // stream is not actually compressed, just encapsulated.  So just copy it.\r
+    //\r
+    // Extract contents from guided or compressed sections.\r
+    // Loop the decompressed data searching for expected section.\r
+    //\r
+    CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
+    CmpFileData = (VOID *) DstBuffer;\r
+    CmpFileSize = DstBufferSize;\r
+    do {\r
+      CmpSectionLength          = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;\r
+      if (CmpSection->Type == SectionType) {\r
+        //\r
+        // This is what we want\r
+        //\r
+        if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
+          // \r
+          // Firmware Volume Image in this Section\r
+          // Skip the section header to get FvHeader\r
           //\r
-          CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
-          break;\r
+          FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);\r
 \r
-        default:\r
-          //\r
-          // Don't support other unknown compression type.\r
-          //\r
-          ASSERT_EFI_ERROR (Status);\r
-          return EFI_NOT_FOUND;\r
-        }\r
-        \r
-        if (CompressionSection->CompressionType != EFI_NOT_COMPRESSED) {\r
-          //\r
-          // For compressed data, decompress them to dstbuffer.\r
-          //\r
-          Status = DecompressLibrary->GetInfo (\r
-                     (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
-                     (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
-                     &DstBufferSize,\r
-                     &ScratchBufferSize\r
-                     );\r
-          if (EFI_ERROR (Status)) {\r
+          if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
             //\r
-            // GetInfo failed\r
+            // Because FvLength in FvHeader is UINT64 type, \r
+            // so FvHeader must meed at least 8 bytes alignment.\r
+            // If current FvImage base address doesn't meet its alignment,\r
+            // we need to reload this FvImage to another correct memory address.\r
             //\r
-            DEBUG ((EFI_D_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
-            return EFI_NOT_FOUND;\r
-          }\r
-  \r
-          //\r
-          // Allocate scratch buffer\r
-          //\r
-          ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
-          if (ScratchBuffer == NULL) {\r
-            return EFI_OUT_OF_RESOURCES;\r
-          }\r
-  \r
-          //\r
-          // Allocate destination buffer\r
-          //\r
-          DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize));\r
-          if (DstBuffer == NULL) {\r
-            return EFI_OUT_OF_RESOURCES;\r
-          }\r
-  \r
-          //\r
-          // Call decompress function\r
-          //\r
-          Status = DecompressLibrary->Decompress (\r
-                      (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
-                      DstBuffer,\r
-                      ScratchBuffer\r
-                      );\r
-          if (EFI_ERROR (Status)) {\r
+            if (((UINTN) FvHeader % sizeof (UINT64)) != 0) {\r
+              CopyMem (DstBuffer, FvHeader, (UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER));\r
+              FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;  \r
+            }\r
+\r
             //\r
-            // Decompress failed\r
+            // Build new FvHob for new decompressed Fv image.\r
             //\r
-            DEBUG ((EFI_D_ERROR, "Decompress Failed - %r\n", Status));\r
-            return EFI_NOT_FOUND;\r
-          }\r
-        }\r
-\r
-        //\r
-        // Decompress successfully.\r
-        // Loop the decompressed data searching for expected section.\r
-        //\r
-        CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
-        CmpFileData = (VOID *) DstBuffer;\r
-        CmpFileSize = DstBufferSize;\r
-        do {\r
-          CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff;\r
-          if (CmpSection->Type == SectionType) {\r
+            BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
+            \r
             //\r
-            // This is what we want\r
+            // Set the original FvHob to unused.\r
             //\r
-            if (SectionType == EFI_SECTION_PE32) {\r
-              *Pe32Data = (VOID *) (CmpSection + 1);\r
-              return EFI_SUCCESS;\r
-            } else if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
-              // \r
-              // Firmware Volume Image in this Section\r
-              // Skip the section header to get FvHeader\r
-              //\r
-              FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);\r
-    \r
-              if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
-                //\r
-                // Because FvLength in FvHeader is UINT64 type, \r
-                // so FvHeader must meed at least 8 bytes alignment.\r
-                // If current FvImage base address doesn't meet its alignment,\r
-                // we need to reload this FvImage to another correct memory address.\r
-                //\r
-                if (((UINTN) FvHeader % sizeof (UINT64)) != 0) {\r
-                  DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER)), sizeof (UINT64));\r
-                  if (DstBuffer == NULL) {\r
-                    return EFI_OUT_OF_RESOURCES;\r
-                  }\r
-                  CopyMem (DstBuffer, FvHeader, (UINTN) CmpSectionLength - sizeof (EFI_COMMON_SECTION_HEADER));\r
-                  FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) DstBuffer;  \r
-                }\r
-\r
-                //\r
-                // Build new FvHob for new decompressed Fv image.\r
-                //\r
-                BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength);\r
-                \r
-                //\r
-                // Set the original FvHob to unused.\r
-                //\r
-                if (OrigHob != NULL) {\r
-                  OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;\r
-                }\r
-                \r
-                //\r
-                // return found FvImage data.\r
-                //\r
-                *Pe32Data = (VOID *) FvHeader;\r
-                return EFI_SUCCESS;\r
-              }\r
+            if (OrigHob != NULL) {\r
+              OrigHob->Header->HobType = EFI_HOB_TYPE_UNUSED;\r
             }\r
+            //\r
+            // return found FvImage data.\r
+            //\r
+            *Pe32Data = (VOID *) FvHeader;\r
+            return EFI_SUCCESS;\r
           }\r
-          OccupiedCmpSectionLength  = GET_OCCUPIED_SIZE (CmpSectionLength, 4);\r
-          CmpSection                = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
-        } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
+        } else {\r
+          //\r
+          // direct return the found section.\r
+          //\r
+          *Pe32Data = (VOID *) (CmpSection + 1);\r
+          return EFI_SUCCESS;\r
+        }\r
       }\r
-      //\r
-      // End of the decompression activity\r
-      //\r
+      OccupiedCmpSectionLength  = GET_OCCUPIED_SIZE (CmpSectionLength, 4);\r
+      CmpSection                = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength);\r
+    } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize);\r
+  } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section + OccupiedSectionLength - (UINT8 *) FfsFileHeader) < FileSize);\r
 \r
-      Section   = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
-      FileSize  = FfsFileHeader->Size[0] & 0xFF;\r
-      FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00;\r
-      FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
-      FileSize &= 0x00FFFFFF;\r
-    } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
-    \r
-    //\r
-    // search all sections (compression and non compression) in this FFS, don't \r
-    // find expected section.\r
-    //\r
-    return EFI_NOT_FOUND;\r
-  } else {\r
+  //\r
+  // search all sections (compression and non compression) in this FFS, don't \r
+  // find expected section.\r
+  //\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  The ExtractSection() function processes the input section and\r
+  returns a pointer to the section contents. If the section being\r
+  extracted does not require processing (if the section\r
+  GuidedSectionHeader.Attributes has the\r
+  EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
+  OutputBuffer is just updated to point to the start of the\r
+  section's contents. Otherwise, *Buffer must be allocated\r
+  from PEI permanent memory.\r
+\r
+  @param This                   Indicates the\r
+                                EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
+                                Buffer containing the input GUIDed section to be\r
+                                processed. OutputBuffer OutputBuffer is\r
+                                allocated from PEI permanent memory and contains\r
+                                the new section stream.\r
+  \r
+  @param OutputSize             A pointer to a caller-allocated\r
+                                UINTN in which the size of *OutputBuffer\r
+                                allocation is stored. If the function\r
+                                returns anything other than EFI_SUCCESS,\r
+                                the value of OutputSize is undefined.\r
+  \r
+  @param AuthenticationStatus   A pointer to a caller-allocated\r
+                                UINT32 that indicates the\r
+                                authentication status of the\r
+                                output buffer. If the input\r
+                                section's GuidedSectionHeader.\r
+                                Attributes field has the\r
+                                EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
+                                bit as clear,\r
+                                AuthenticationStatus must return\r
+                                zero. These bits reflect the\r
+                                status of the extraction\r
+                                operation. If the function\r
+                                returns anything other than\r
+                                EFI_SUCCESS, the value of\r
+                                AuthenticationStatus is\r
+                                undefined.\r
+  \r
+  @retval EFI_SUCCESS           The InputSection was\r
+                                successfully processed and the\r
+                                section contents were returned.\r
+  \r
+  @retval EFI_OUT_OF_RESOURCES  The system has insufficient\r
+                                resources to process the request.\r
+  \r
+  @reteval EFI_INVALID_PARAMETER The GUID in InputSection does\r
+                                not match this instance of the\r
+                                GUIDed Section Extraction PPI.\r
+**/\r
+EFI_STATUS\r
+CustomDecompressExtractSection (\r
+  IN CONST  EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
+  IN CONST  VOID                                  *InputSection,\r
+  OUT       VOID                                  **OutputBuffer,\r
+  OUT       UINTN                                 *OutputSize,\r
+  OUT       UINT32                                *AuthenticationStatus\r
+)\r
+{\r
+  EFI_STATUS      Status;\r
+  UINT8           *ScratchBuffer;\r
+  UINT32          ScratchSize;\r
+  UINT32          SectionLength;  \r
+  \r
+  //\r
+  // Set authentic value to zero.\r
+  //\r
+  *AuthenticationStatus = 0;\r
+  //\r
+  // Calculate Section data Size\r
+  //\r
+  SectionLength   = *(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size) & 0x00ffffff;\r
+  //\r
+  // Get compressed data information\r
+  //\r
+  Status = CustomDecompressGetInfo (\r
+             (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),\r
+             (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),\r
+             SectionLength - sizeof (EFI_GUID_DEFINED_SECTION),\r
+             OutputSize,\r
+             &ScratchSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
     //\r
-    // For those FFS that doesn't contain compression section, directly search \r
-    // PE or TE section in this FFS.\r
+    // GetInfo failed\r
     //\r
+    DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
+    return Status;\r
+  }\r
 \r
-    Status = PeiServicesFfsFindSectionData (\r
-               EFI_SECTION_PE32,\r
-               FfsFileHeader,\r
-               &SectionData\r
-               );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      Status = PeiServicesFfsFindSectionData (\r
-                 EFI_SECTION_TE,\r
-                 FfsFileHeader,\r
-                 &SectionData\r
-                 );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    }\r
+  //\r
+  // Allocate scratch buffer\r
+  //\r
+  ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchSize));\r
+  if (ScratchBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  //\r
+  // Allocate destination buffer\r
+  //\r
+  *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (*OutputSize));\r
+  if (*OutputBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  *Pe32Data = SectionData;\r
+  //\r
+  // Call decompress function\r
+  //\r
+  Status = CustomDecompress (\r
+             (GUID *) ((UINT8 *) InputSection + sizeof (EFI_COMMON_SECTION_HEADER)),\r
+             (UINT8 *) InputSection + sizeof (EFI_GUID_DEFINED_SECTION),\r
+             *OutputBuffer,\r
+             ScratchBuffer\r
+             );\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Decompress failed\r
+    //\r
+    DEBUG ((EFI_D_ERROR, "Extract guided section Failed - %r\n", Status));\r
+    return Status;\r
+  }\r
+  \r
   return EFI_SUCCESS;\r
 }\r
-\r