]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Core/DxeIplPeim/DxeLoad.c
Introduce PcdDxeIplSwitchToLongMode to DxeIplPeim and remove DxeIplX64Peim.
[mirror_edk2.git] / EdkModulePkg / Core / DxeIplPeim / DxeLoad.c
index fdd6c24b2ee03fba3be644957a91f352fc3774e0..8c3de0522d9ca46f8a84e5cf26f8247b956127ba 100644 (file)
@@ -20,7 +20,11 @@ Abstract:
 \r
 --*/\r
 \r
-#include <DxeIpl.h>\r
+#include "DxeIpl.h"\r
+\r
+#ifndef __GNUC__\r
+#pragma warning( disable : 4305 )\r
+#endif\r
 \r
 BOOLEAN gInMemory = FALSE;\r
 \r
@@ -36,22 +40,17 @@ static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = {
   DxeIplLoadFile\r
 };\r
 \r
-static EFI_PEI_PPI_DESCRIPTOR     mPpiLoadFile = {\r
-  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+static EFI_PEI_PPI_DESCRIPTOR     mPpiList[] = {\r
+  {\r
+  EFI_PEI_PPI_DESCRIPTOR_PPI,\r
   &gEfiPeiFvFileLoaderPpiGuid,\r
   &mLoadFilePpi\r
-};\r
-\r
-static EFI_PEI_PPI_DESCRIPTOR     mPpiList = {\r
+  },\r
+  {\r
   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
   &gEfiDxeIplPpiGuid,\r
   &mDxeIplPpi\r
-};\r
-\r
-static EFI_PEI_PPI_DESCRIPTOR     mPpiPeiInMemory = {\r
-  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gPeiInMemoryGuid,\r
-  NULL\r
+  }\r
 };\r
 \r
 static EFI_PEI_PPI_DESCRIPTOR     mPpiSignal = {\r
@@ -60,38 +59,21 @@ static EFI_PEI_PPI_DESCRIPTOR     mPpiSignal = {
   NULL\r
 };\r
 \r
-DECOMPRESS_LIBRARY  gEfiDecompress = {\r
+GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY  gEfiDecompress = {\r
   UefiDecompressGetInfo,\r
   UefiDecompress\r
 };\r
 \r
-DECOMPRESS_LIBRARY  gTianoDecompress = {\r
+GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY  gTianoDecompress = {\r
   TianoDecompressGetInfo,\r
   TianoDecompress\r
 };\r
 \r
-DECOMPRESS_LIBRARY  gCustomDecompress = {\r
+GLOBAL_REMOVE_IF_UNREFERENCED DECOMPRESS_LIBRARY  gCustomDecompress = {\r
   CustomDecompressGetInfo,\r
   CustomDecompress\r
 };\r
 \r
-STATIC\r
-UINTN\r
-GetOccupiedSize (\r
-  IN UINTN   ActualSize,\r
-  IN UINTN   Alignment\r
-  )\r
-{\r
-  UINTN OccupiedSize;\r
-\r
-  OccupiedSize = ActualSize;\r
-  while ((OccupiedSize & (Alignment - 1)) != 0) {\r
-    OccupiedSize++;\r
-  }\r
-\r
-  return OccupiedSize;\r
-}\r
-\r
 EFI_STATUS\r
 EFIAPI\r
 PeimInitializeDxeIpl (\r
@@ -120,17 +102,9 @@ Returns:
   EFI_BOOT_MODE                             BootMode;\r
 \r
   Status = PeiServicesGetBootMode (&BootMode);\r
-\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  Status = PeiServicesLocatePpi (\r
-             &gPeiInMemoryGuid,\r
-             0,\r
-             NULL,\r
-             NULL\r
-             );\r
-\r
-  if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) {\r
+  if (!gInMemory && (BootMode != BOOT_ON_S3_RESUME)) {   \r
     //\r
     // The DxeIpl has not yet been shadowed\r
     //\r
@@ -140,38 +114,15 @@ Returns:
     // Shadow DxeIpl and then re-run its entry point\r
     //\r
     Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
   } else {\r
-    if (BootMode != BOOT_ON_S3_RESUME) {\r
     //\r
-    // The DxeIpl has been shadowed\r
+    // Install FvFileLoader and DxeIpl PPIs.\r
     //\r
-    gInMemory = TRUE;\r
-\r
-    //\r
-    // Install LoadFile PPI\r
-    //\r
-    Status = PeiServicesInstallPpi (&mPpiLoadFile);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-      }\r
-    }\r
-    //\r
-    // Install DxeIpl PPI\r
-    //\r
-    PeiServicesInstallPpi (&mPpiList);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
+    Status = PeiServicesInstallPpi (mPpiList);\r
+    ASSERT_EFI_ERROR(Status);\r
   }\r
-\r
-  return EFI_SUCCESS;\r
+  \r
+  return Status;\r
 }\r
 \r
 EFI_STATUS\r
@@ -200,12 +151,13 @@ Returns:
 --*/\r
 {\r
   EFI_STATUS                                Status;\r
-  VOID                                      *TopOfStack;\r
-  VOID                                      *BaseOfStack;\r
+  EFI_PHYSICAL_ADDRESS                      TopOfStack;\r
+  EFI_PHYSICAL_ADDRESS                      BaseOfStack;\r
   EFI_PHYSICAL_ADDRESS                      BspStore;\r
   EFI_GUID                                  DxeCoreFileName;\r
   EFI_GUID                                  FirmwareFileName;\r
   VOID                                      *Pe32Data;\r
+  VOID                                      *FvImageData;     \r
   EFI_PHYSICAL_ADDRESS                      DxeCoreAddress;\r
   UINT64                                    DxeCoreSize;\r
   EFI_PHYSICAL_ADDRESS                      DxeCoreEntryPoint;\r
@@ -213,104 +165,32 @@ Returns:
   EFI_BOOT_MODE                             BootMode;\r
   EFI_PEI_RECOVERY_MODULE_PPI               *PeiRecovery;\r
   EFI_PEI_S3_RESUME_PPI                     *S3Resume;\r
+  EFI_PHYSICAL_ADDRESS                      PageTables;\r
 \r
 //  PERF_START (PeiServices, L"DxeIpl", NULL, 0);\r
-  TopOfStack  = NULL;\r
-  BaseOfStack = NULL;\r
+  TopOfStack  = 0;\r
+  BaseOfStack = 0;\r
   BspStore    = 0;\r
-  Status      = EFI_SUCCESS;\r
+  PageTables  = 0;\r
 \r
   //\r
   // if in S3 Resume, restore configure\r
   //\r
   Status = PeiServicesGetBootMode (&BootMode);\r
+  ASSERT_EFI_ERROR(Status);\r
 \r
-  if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) {\r
+  if (BootMode == BOOT_ON_S3_RESUME) {\r
     Status = PeiServicesLocatePpi (\r
                &gEfiPeiS3ResumePpiGuid,\r
                0,\r
                NULL,\r
                (VOID **)&S3Resume\r
                );\r
-\r
     ASSERT_EFI_ERROR (Status);\r
 \r
     Status = S3Resume->S3RestoreConfig (PeiServices);\r
-\r
     ASSERT_EFI_ERROR (Status);\r
-  }\r
-\r
-  Status = EFI_SUCCESS;\r
-\r
-  //\r
-  // Install the PEI Protocols that are shared between PEI and DXE\r
-  //\r
-  PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
-  ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
-\r
-\r
-  //\r
-  // Allocate 128KB for the Stack\r
-  //\r
-  BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));\r
-  ASSERT (BaseOfStack != NULL);\r
-\r
-  //\r
-  // Compute the top of the stack we were allocated. Pre-allocate a UINTN\r
-  // for safety.\r
-  //\r
-  TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);\r
-  TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
-\r
-  //\r
-  // Add architecture-specifc HOBs (including the BspStore HOB)\r
-  //\r
-  Status = CreateArchSpecificHobs (&BspStore);\r
-\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Add HOB for the EFI Decompress Protocol\r
-  //\r
-  BuildGuidDataHob (\r
-    &gEfiDecompressProtocolGuid,\r
-    (VOID *)&gEfiDecompress,\r
-    sizeof (gEfiDecompress)\r
-    );\r
-\r
-  //\r
-  // Add HOB for the Tiano Decompress Protocol\r
-  //\r
-  BuildGuidDataHob (\r
-    &gEfiTianoDecompressProtocolGuid,\r
-    (VOID *)&gTianoDecompress,\r
-    sizeof (gTianoDecompress)\r
-    );\r
-\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
-  // Add HOB for the PE/COFF Loader Protocol\r
-  //\r
-  BuildGuidDataHob (\r
-    &gEfiPeiPeCoffLoaderGuid,\r
-    (VOID *)&PeiEfiPeiPeCoffLoader,\r
-    sizeof (VOID *)\r
-    );\r
-\r
-  //\r
-  // See if we are in crisis recovery\r
-  //\r
-  Status = PeiServicesGetBootMode (&BootMode);\r
-\r
-  if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) {\r
+  } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
 \r
     Status = PeiServicesLocatePpi (\r
                &gEfiPeiRecoveryModulePpiGuid,\r
@@ -318,8 +198,8 @@ Returns:
                NULL,\r
                (VOID **)&PeiRecovery\r
                );\r
-\r
     ASSERT_EFI_ERROR (Status);\r
+\r
     Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);\r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
@@ -332,19 +212,34 @@ Returns:
   }\r
 \r
   //\r
-  // Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block\r
+  // Install the PEI Protocols that are shared between PEI and DXE\r
+  //\r
+  PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol ();\r
+  ASSERT (PeiEfiPeiPeCoffLoader != NULL);\r
+\r
+  //\r
+  // Allocate 128KB for the Stack\r
+  //\r
+  PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
+  ASSERT (BaseOfStack != 0);\r
+\r
+  //\r
+  // Add architecture-specifc HOBs (including the BspStore HOB)\r
+  //\r
+  Status = CreateArchSpecificHobs (&BspStore);\r
+  ASSERT_EFI_ERROR (Status);\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
-  // a normal FV, then a corresponding FV type hob will be built which is provided for DXE\r
-  // core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks\r
-  // for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned\r
-  // status\r
+  // a normal FV, then a corresponding FV type hob will be built. \r
   //\r
   Status = PeiFindFile (\r
-            EFI_FV_FILETYPE_RAW,\r
-            EFI_SECTION_PE32,\r
-            &FirmwareFileName,\r
-            &Pe32Data\r
-            );\r
+             EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+             &FirmwareFileName,\r
+             &FvImageData\r
+             );\r
 \r
   //\r
   // Find the DXE Core in a Firmware Volume\r
@@ -355,20 +250,18 @@ Returns:
             &DxeCoreFileName,\r
             &Pe32Data\r
             );\r
-\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
   // Load the DXE Core from a Firmware Volume\r
   //\r
   Status = PeiLoadFile (\r
-            PeiEfiPeiPeCoffLoader,\r
-            Pe32Data,\r
-            &DxeCoreAddress,\r
-            &DxeCoreSize,\r
-            &DxeCoreEntryPoint\r
-            );\r
-\r
+             PeiEfiPeiPeCoffLoader,\r
+             Pe32Data,\r
+             &DxeCoreAddress,\r
+             &DxeCoreSize,\r
+             &DxeCoreEntryPoint\r
+             );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
@@ -377,7 +270,6 @@ Returns:
   //\r
 \r
   Status = PeiServicesInstallPpi (&mPpiSignal);\r
-\r
   ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
@@ -399,14 +291,93 @@ Returns:
     );\r
 \r
   DEBUG ((EFI_D_INFO, "DXE Core Entry\n"));\r
-  SwitchIplStacks (\r
-    (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
-    HobList.Raw,\r
-    NULL,\r
-    TopOfStack,\r
-    (VOID *) (UINTN) BspStore\r
-    );\r
+  if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {\r
+    //\r
+    // Compute the top of the stack we were allocated, which is used to load X64 dxe core. \r
+    // Pre-allocate a 32 bytes which confroms to x64 calling convention.\r
+    //\r
+    // The first four parameters to a function are passed in rcx, rdx, r8 and r9. \r
+    // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the \r
+    // register parameters is reserved on the stack, in case the called function \r
+    // wants to spill them; this is important if the function is variadic. \r
+    //\r
+    TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;\r
+\r
+    //\r
+    //  X64 Calling Conventions requires that the stack must be aligned to 16 bytes\r
+    //\r
+    TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);\r
+    //\r
+    // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA\r
+    // memory, it may be corrupted when copying FV to high-end memory \r
+    //\r
+    LoadGo64Gdt();\r
+    //\r
+    // Limit to 36 bits of addressing for debug. Should get it from CPU\r
+    //\r
+    PageTables = CreateIdentityMappingPageTables (36);\r
+    //\r
+    // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.\r
+    // Call x64 drivers passing in single argument, a pointer to the HOBs.\r
+    //\r
+    ActivateLongMode (\r
+      PageTables, \r
+      (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), \r
+      TopOfStack,\r
+      0x00000000,\r
+      DxeCoreEntryPoint\r
+      );\r
+  } else {\r
+    //\r
+    // Add HOB for the EFI Decompress Protocol\r
+    //\r
+    BuildGuidDataHob (\r
+      &gEfiDecompressProtocolGuid,\r
+      (VOID *)&gEfiDecompress,\r
+      sizeof (gEfiDecompress)\r
+      );\r
 \r
+    //\r
+    // Add HOB for the Tiano Decompress Protocol\r
+    //\r
+    BuildGuidDataHob (\r
+      &gEfiTianoDecompressProtocolGuid,\r
+      (VOID *)&gTianoDecompress,\r
+      sizeof (gTianoDecompress)\r
+      );\r
+\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
+    // Add HOB for the PE/COFF Loader Protocol\r
+    //\r
+    BuildGuidDataHob (\r
+      &gEfiPeiPeCoffLoaderGuid,\r
+      (VOID *)&PeiEfiPeiPeCoffLoader,\r
+      sizeof (VOID *)\r
+      );\r
+    //\r
+    // Compute the top of the stack we were allocated. Pre-allocate a UINTN\r
+    // for safety.\r
+    //\r
+    TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;\r
+    TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
+\r
+    SwitchIplStacks (\r
+      (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
+      HobList.Raw,\r
+      NULL,\r
+      (VOID *) (UINTN) TopOfStack,\r
+      (VOID *) (UINTN) BspStore\r
+      );\r
+  } \r
   //\r
   // If we get here, then the DXE Core returned.  This is an error\r
   // Dxe Core should not return.\r
@@ -462,10 +433,11 @@ Returns:
   FwVolHeader   = NULL;\r
   FfsFileHeader = NULL;\r
   SectionData   = NULL;\r
+  Status        = EFI_SUCCESS;\r
 \r
   //\r
-  // Foreach Firmware Volume, look for a specified type\r
-  // of file and break out when one is found\r
+  // For each Firmware Volume, look for a specified type\r
+  // of file and break out until no one is found \r
   //\r
   Hob.Raw = GetHobList ();\r
   while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) {\r
@@ -478,11 +450,14 @@ Returns:
     if (!EFI_ERROR (Status)) {\r
       Status = PeiProcessFile (\r
                  SectionType,\r
-                 &FfsFileHeader,\r
-                 Pe32Data\r
+                 FfsFileHeader,\r
+                 Pe32Data,\r
+                 &Hob\r
                  );\r
       CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID));\r
-      return Status;\r
+      if (!EFI_ERROR (Status)) {\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
     Hob.Raw = GET_NEXT_HOB (Hob);\r
   }\r
@@ -608,7 +583,7 @@ Returns:
 \r
   while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) {\r
     SectionLength         = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
-    OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);\r
+    OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
     Section               = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
   }\r
   //\r
@@ -624,14 +599,9 @@ Returns:
 \r
   if (Status == EFI_SUCCESS) {\r
     //\r
-    // Install PeiInMemory to indicate the Dxeipl is shadowed\r
+    // Set gInMemory global variable to TRUE to indicate the dxeipl is shadowed.\r
     //\r
-    Status = PeiServicesInstallPpi (&mPpiPeiInMemory);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-\r
+    *(BOOLEAN *) ((UINTN) &gInMemory + (UINTN) DxeIplEntryPoint - (UINTN) _ModuleEntryPoint) = TRUE;\r
     Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer());\r
   }\r
 \r
@@ -689,8 +659,9 @@ Returns:
   //\r
   Status = PeiProcessFile (\r
             EFI_SECTION_PE32,\r
-            &FfsHeader,\r
-            &Pe32Data\r
+            FfsHeader,\r
+            &Pe32Data,\r
+            NULL\r
             );\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -713,8 +684,9 @@ Returns:
 EFI_STATUS\r
 PeiProcessFile (\r
   IN      UINT16                 SectionType,\r
-  IN OUT  EFI_FFS_FILE_HEADER    **RealFfsFileHeader,\r
-  OUT     VOID                   **Pe32Data\r
+  IN      EFI_FFS_FILE_HEADER    *FfsFileHeader,\r
+  OUT     VOID                   **Pe32Data,\r
+  IN      EFI_PEI_HOB_POINTERS   *OrigHob\r
   )\r
 /*++\r
 \r
@@ -762,9 +734,7 @@ Returns:
   EFI_GUID                        TempGuid;\r
   EFI_FIRMWARE_VOLUME_HEADER      *FvHeader;\r
   EFI_COMPRESSION_SECTION         *CompressionSection;\r
-  EFI_FFS_FILE_HEADER             *FfsFileHeader;\r
-\r
-  FfsFileHeader = *RealFfsFileHeader;\r
+  UINT32                          FvAlignment;\r
 \r
   Status = PeiServicesFfsFindSectionData (\r
              EFI_SECTION_COMPRESSION,\r
@@ -773,7 +743,7 @@ Returns:
              );\r
 \r
   //\r
-  // Upon finding a DXE Core file, see if there is first a compression section\r
+  // First process the compression section\r
   //\r
   if (!EFI_ERROR (Status)) {\r
     //\r
@@ -784,7 +754,7 @@ Returns:
 \r
     do {\r
       SectionLength         = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
-      OccupiedSectionLength = GetOccupiedSize (SectionLength, 4);\r
+      OccupiedSectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);\r
 \r
       //\r
       // Was the DXE Core file encapsulated in a GUID'd section?\r
@@ -881,14 +851,24 @@ Returns:
 \r
         switch (CompressionSection->CompressionType) {\r
         case EFI_STANDARD_COMPRESSION:\r
-          DecompressLibrary = &gTianoDecompress;\r
+          if (FeaturePcdGet (PcdDxeIplSupportTianoDecompress)) {\r
+            DecompressLibrary = &gTianoDecompress;\r
+          } else {\r
+            ASSERT (FALSE);\r
+            return EFI_NOT_FOUND;\r
+          }\r
           break;\r
 \r
         case EFI_CUSTOMIZED_COMPRESSION:\r
           //\r
           // Load user customized compression protocol.\r
           //\r
-          DecompressLibrary = &gCustomDecompress;\r
+          if (FeaturePcdGet (PcdDxeIplSupportCustomDecompress)) {\r
+            DecompressLibrary = &gCustomDecompress;\r
+          } else {\r
+            ASSERT (FALSE);\r
+            return EFI_NOT_FOUND;\r
+          }\r
           break;\r
 \r
         case EFI_NOT_COMPRESSED:\r
@@ -939,31 +919,64 @@ Returns:
                     );\r
 \r
         CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer;\r
-        if (CmpSection->Type == EFI_SECTION_RAW) {\r
-          //\r
-          // Skip the section header and\r
-          // adjust the pointer alignment to 16\r
+        if (CmpSection->Type == 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 *) (DstBuffer + 16);\r
+          FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (CmpSection + 1);\r
 \r
-          if (FvHeader->Signature == EFI_FVH_SIGNATURE) {\r
-            FfsFileHeader = NULL;\r
+          if (FvHeader->Signature == EFI_FVH_SIGNATURE) {            \r
+            //\r
+            // Adjust Fv Base Address Alignment based on Align Attributes in Fv Header\r
+            //\r
+            \r
+            //\r
+            // When FvImage support Alignment, we need to check whether \r
+            // its alignment is correct. \r
+            //\r
+            if (FvHeader->Attributes | EFI_FVB_ALIGNMENT_CAP) {\r
+              \r
+              //\r
+              // Calculate the mini alignment for this FvImage\r
+              //\r
+              FvAlignment = 1 << (LowBitSet32 (FvHeader->Attributes >> 16) + 1);\r
+              \r
+              //\r
+              // If current FvImage base address doesn't meet the its alignment,\r
+              // we need to reload this FvImage to another correct memory address.\r
+              //\r
+              if (((UINTN) FvHeader % FvAlignment) != 0) {\r
+                DstBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), FvAlignment);\r
+                if (DstBuffer == NULL) {\r
+                  return EFI_OUT_OF_RESOURCES;\r
+                }\r
+                CopyMem (DstBuffer, FvHeader, (UINTN) FvHeader->FvLength);\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
-            Status = PeiServicesFfsFindNextFile (\r
-                       EFI_FV_FILETYPE_DXE_CORE,\r
-                       FvHeader,\r
-                       &FfsFileHeader\r
-                       );\r
-\r
-            if (EFI_ERROR (Status)) {\r
-              return EFI_NOT_FOUND;\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
             //\r
-            // Reture the FfsHeader that contain Pe32Data.\r
+            // when search FvImage Section return true.\r
             //\r
-            *RealFfsFileHeader = FfsFileHeader;\r
-            return PeiProcessFile (SectionType, RealFfsFileHeader, Pe32Data);\r
+            if (SectionType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
+              *Pe32Data = (VOID *) FvHeader;\r
+              return EFI_SUCCESS;\r
+            } else {\r
+              return EFI_NOT_FOUND;\r
+            }\r
+\r
           }\r
         }\r
         //\r
@@ -982,10 +995,13 @@ Returns:
             return EFI_SUCCESS;\r
           }\r
 \r
-          OccupiedCmpSectionLength  = GetOccupiedSize (CmpSectionLength, 4);\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
       }\r
+      //\r
+      // End of the decompression activity\r
+      //\r
 \r
       Section   = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength);\r
       FileSize  = FfsFileHeader->Size[0] & 0xFF;\r
@@ -993,11 +1009,17 @@ Returns:
       FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000;\r
       FileSize &= 0x00FFFFFF;\r
     } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize);\r
-\r
+    \r
     //\r
-    // End of the decompression activity\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
+    // For those FFS that doesn't contain compression section, directly search \r
+    // PE or TE section in this FFS.\r
+    //\r
 \r
     Status = PeiServicesFfsFindSectionData (\r
                EFI_SECTION_PE32,\r
@@ -1021,3 +1043,4 @@ Returns:
 \r
   return EFI_SUCCESS;\r
 }\r
+\r