]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/FwVol/FwVol.c
Fix the issue that accessing for unaligned address break IPF
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
index 06c08f9bc4373e747f68a673a47d7ef7290166ec..d2bd6c493ef45e17877bfac9cb7d53243f51deac 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Pei Core Firmware File System service routines.\r
   \r
-Copyright (c) 2006 - 2009, Intel Corporation                                                         \r
+Copyright (c) 2006 - 2010, Intel Corporation                                                         \r
 All rights reserved. This program and the accompanying materials                          \r
 are licensed and made available under the terms and conditions of the BSD License         \r
 which accompanies this distribution.  The full text of the license may be found at        \r
@@ -309,7 +309,23 @@ PeiInitializeFv (
            (UINTN)BfvHeader->FvLength,\r
            &FvHandle\r
            );\r
-                        \r
+\r
+  //\r
+  // Update internal PEI_CORE_FV array.\r
+  //\r
+  PrivateData->Fv[PrivateData->FvCount].FvHeader = BfvHeader;\r
+  PrivateData->Fv[PrivateData->FvCount].FvPpi    = FvPpi;\r
+  PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
+  DEBUG ((\r
+    EFI_D_INFO, \r
+    "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
+    (UINT32) PrivateData->FvCount, \r
+    (VOID *) BfvHeader, \r
+    BfvHeader->FvLength,\r
+    FvHandle\r
+    ));    \r
+  PrivateData->FvCount ++;\r
+                            \r
   //\r
   // Post a call-back for the FvInfoPPI services to expose\r
   // additional Fvs to PeiCore.\r
@@ -346,6 +362,8 @@ FirmwareVolmeInfoPpiNotifyCallback (
   EFI_STATUS                            Status;\r
   EFI_PEI_FV_HANDLE                     FvHandle;\r
   UINTN                                 FvIndex;\r
+  EFI_PEI_FILE_HANDLE                   FileHandle;\r
+  VOID                                  *DepexData;\r
   \r
   Status       = EFI_SUCCESS;\r
   PrivateData  = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
@@ -373,33 +391,71 @@ FirmwareVolmeInfoPpiNotifyCallback (
     //\r
     Status = FvPpi->ProcessVolume (FvPpi, FvInfoPpi->FvInfo, FvInfoPpi->FvInfoSize, &FvHandle);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!"));\r
+      DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));\r
       return Status;\r
     }\r
-    DEBUG ((EFI_D_INFO, "Found and process new FV %p, all fv's count is %d\n", FvHandle, PrivateData->FvCount));\r
-  } else {\r
-    DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi->FvInfo));\r
-    \r
-    //\r
-    // If can not find EFI_FIRMWARE_VOLUME_PPI to process firmware to get FvHandle, \r
-    // use the address of FV buffer as its handle.\r
-    //\r
-    FvHandle = FvInfoPpi->FvInfo;\r
-    \r
+\r
     //\r
     // Check whether the FV has already been processed.\r
     //\r
     for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
       if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {\r
-        DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvHandle));\r
+        DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfoPpi->FvInfo));\r
         return EFI_SUCCESS;\r
       }\r
-    }    \r
-    \r
+    }\r
+\r
+    //\r
+    // Update internal PEI_CORE_FV array.\r
+    //\r
     PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo;\r
-    PrivateData->Fv[PrivateData->FvCount].FvPpi    = NULL;\r
+    PrivateData->Fv[PrivateData->FvCount].FvPpi    = FvPpi;\r
     PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
+    DEBUG ((\r
+      EFI_D_INFO, \r
+      "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
+      (UINT32) PrivateData->FvCount, \r
+      (VOID *) FvInfoPpi->FvInfo, \r
+      FvInfoPpi->FvInfoSize,\r
+      FvHandle\r
+      ));    \r
     PrivateData->FvCount ++;\r
+\r
+    //\r
+    // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE \r
+    //\r
+    FileHandle = NULL;\r
+    do {\r
+      Status = FvPpi->FindFileByType (\r
+                        FvPpi,\r
+                        EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
+                        FvHandle,\r
+                        &FileHandle\r
+                       );\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = FvPpi->FindSectionByType (\r
+                          FvPpi,\r
+                          EFI_SECTION_PEI_DEPEX,\r
+                          FileHandle,\r
+                          (VOID**)&DepexData\r
+                          );\r
+        if (!EFI_ERROR (Status)) {\r
+          if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
+            //\r
+            // Dependency is not satisfied.\r
+            //\r
+            continue;\r
+          }\r
+        }\r
+        \r
+        DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));\r
+        ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
+      }\r
+    } while (FileHandle != NULL);\r
+  } else {\r
+    DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi->FvInfo));\r
+    \r
+    AddUnknownFormatFvInfo (PrivateData, &FvInfoPpi->FvFormat, FvInfoPpi->FvInfo, FvInfoPpi->FvInfoSize);\r
   }\r
   \r
   return EFI_SUCCESS;\r
@@ -578,7 +634,7 @@ PeiFfsFindSectionData (
   @param PeiServices     An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.\r
   @param SearchType      Filter to find only files of this type.\r
                          Type EFI_FV_FILETYPE_ALL causes no filtering to be done.\r
-  @param VolumeHandle    Handle of firmware volume in which to search.\r
+  @param FvHandle        Handle of firmware volume in which to search.\r
   @param FileHandle      On entry, points to the current handle from which to begin searching or NULL to start\r
                          at the beginning of the firmware volume. On exit, points the file handle of the next file\r
                          in the volume or NULL if there are no more files.\r
@@ -642,6 +698,10 @@ PeiFfsFindNextVolume (
   PEI_CORE_INSTANCE  *Private;\r
   PEI_CORE_FV_HANDLE *CoreFvHandle;\r
   \r
+  if (VolumeHandle == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
   Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
   \r
   CoreFvHandle = FindNextCoreFvHandle (Private, Instance);\r
@@ -730,12 +790,19 @@ PeiFfsGetFileInfo (
 /**\r
   Returns information about the specified volume.\r
 \r
-  @param VolumeHandle    Handle of the volume.\r
-  @param VolumeInfo      Upon exit, points to the volume’s information.\r
+  This function returns information about a specific firmware\r
+  volume, including its name, type, attributes, starting address\r
+  and size.\r
+\r
+  @param VolumeHandle   Handle of the volume.\r
+  @param VolumeInfo     Upon exit, points to the volume's information.\r
+\r
+  @retval EFI_SUCCESS             Volume information returned.\r
+  @retval EFI_INVALID_PARAMETER   If VolumeHandle does not represent a valid volume.\r
+  @retval EFI_INVALID_PARAMETER   If VolumeHandle is NULL.\r
+  @retval EFI_SUCCESS             Information successfully returned.\r
+  @retval EFI_INVALID_PARAMETER   The volume designated by the VolumeHandle is not available.\r
 \r
-  @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.\r
-  @retval EFI_INVALID_PARAMETER If VolumeInfo is NULL.\r
-  @retval EFI_SUCCESS           Volume information returned.\r
 **/\r
 EFI_STATUS\r
 EFIAPI \r
@@ -746,7 +813,7 @@ PeiFfsGetVolumeInfo (
 {\r
   PEI_CORE_FV_HANDLE                     *CoreHandle;\r
   \r
-  if (VolumeInfo == NULL) {\r
+  if ((VolumeInfo == NULL) || (VolumeHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
@@ -786,6 +853,7 @@ ProcessFvFile (
   EFI_PEI_FV_HANDLE             ParentFvHandle;\r
   EFI_FIRMWARE_VOLUME_HEADER    *FvHeader;\r
   EFI_FV_FILE_INFO              FileInfo;\r
+  UINT64                        FvLength;\r
   \r
   //\r
   // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
@@ -823,7 +891,7 @@ ProcessFvFile (
   //\r
   // FvAlignment must be more than 8 bytes required by FvHeader structure.\r
   //\r
-  FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
+  FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);\r
   if (FvAlignment < 8) {\r
     FvAlignment = 8;\r
   }\r
@@ -832,11 +900,12 @@ ProcessFvFile (
   // Check FvImage\r
   //\r
   if ((UINTN) FvHeader % FvAlignment != 0) {\r
-    NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvHeader->FvLength), FvAlignment);\r
+    FvLength    = ReadUnaligned64 (&FvHeader->FvLength);\r
+    NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvLength), FvAlignment);\r
     if (NewFvBuffer == NULL) {\r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
-    CopyMem (NewFvBuffer, FvHeader, (UINTN) FvHeader->FvLength);\r
+    CopyMem (NewFvBuffer, FvHeader, (UINTN) FvLength);\r
     FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;\r
   }\r
   \r
@@ -913,14 +982,12 @@ PeiFfs2FvPpiProcessVolume (
   )\r
 {\r
   EFI_STATUS          Status;\r
-  PEI_CORE_INSTANCE   *PrivateData;\r
-  EFI_PEI_FILE_HANDLE FileHandle;\r
-  VOID                *DepexData;\r
-  EFI_PEI_SERVICES    **PeiServices;\r
-  UINTN               FvIndex;\r
   \r
-  PeiServices = (EFI_PEI_SERVICES**) GetPeiServicesTablePointer ();\r
-  PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
+  ASSERT (FvHandle != NULL);\r
+  \r
+  if (Buffer == NULL) {\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
   \r
   //\r
   // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2 support memory-mapped\r
@@ -937,61 +1004,6 @@ PeiFfs2FvPpiProcessVolume (
     return EFI_VOLUME_CORRUPTED;\r
   }\r
 \r
-  //\r
-  // Check whether the FV has already been processed.\r
-  //\r
-  for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
-    if (PrivateData->Fv[FvIndex].FvHandle == *FvHandle) {\r
-      DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!", Buffer));\r
-      return EFI_SUCCESS;\r
-    }\r
-  }\r
-  \r
-  //\r
-  // Update internal PEI_CORE_FV array.\r
-  //\r
-  PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) Buffer;\r
-  PrivateData->Fv[PrivateData->FvCount].FvPpi    = (EFI_PEI_FIRMWARE_VOLUME_PPI*) This;\r
-  PrivateData->Fv[PrivateData->FvCount].FvHandle = *FvHandle;\r
-  \r
-  DEBUG ((EFI_D_INFO, \r
-          "The %dth FV start address is 0x%11p and size is 0x%08x\n", \r
-          (UINT32) PrivateData->FvCount, \r
-          (VOID *) Buffer, \r
-          BufferSize\r
-          ));\r
-  PrivateData->FvCount ++;\r
-  \r
-  FileHandle = NULL;\r
-  \r
-  do {\r
-    Status = This->FindFileByType (\r
-                     This,\r
-                     EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
-                     *FvHandle,\r
-                     &FileHandle\r
-                     );\r
-    if (!EFI_ERROR (Status)) {\r
-      Status = This->FindSectionByType (\r
-                       This,\r
-                       EFI_SECTION_PEI_DEPEX,\r
-                       FileHandle,\r
-                       (VOID**)&DepexData\r
-                       );\r
-      if (!EFI_ERROR (Status)) {\r
-        if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
-          //\r
-          // Dependency is not satisfied.\r
-          //\r
-          continue;\r
-        }\r
-      }\r
-      \r
-      DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p", FileHandle, PrivateData->FvCount - 1, *FvHandle));\r
-      ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
-    }\r
-  } while (FileHandle != NULL);\r
-\r
   return EFI_SUCCESS;\r
 }  \r
 \r
@@ -1091,6 +1103,7 @@ PeiFfs2FvPpiFindFileByName (
         Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);\r
         if (!EFI_ERROR (Status)) {\r
           *FvHandle = PrivateData->Fv[Index].FvHandle;\r
+          break;\r
         }\r
       }\r
     }\r
@@ -1196,7 +1209,7 @@ PeiFfs2FvPpiGetVolumeInfo (
   EFI_FIRMWARE_VOLUME_HEADER             FwVolHeader;\r
   EFI_FIRMWARE_VOLUME_EXT_HEADER         *FwVolExHeaderInfo;\r
 \r
-  if (VolumeInfo == NULL) {\r
+  if ((VolumeInfo == NULL) || (FvHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   \r
@@ -1363,3 +1376,261 @@ FindNextCoreFvHandle (
 \r
   return &Private->Fv[Instance];\r
 }  \r
+\r
+/**\r
+  After PeiCore image is shadowed into permanent memory, all build-in FvPpi should\r
+  be re-installed with the instance in permanent memory and all cached FvPpi pointers in \r
+  PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant\r
+  memory.\r
+  \r
+  @param PrivateData   Pointer to PEI_CORE_INSTANCE.\r
+**/  \r
+VOID\r
+PeiReinitializeFv (\r
+  IN  PEI_CORE_INSTANCE           *PrivateData\r
+  )\r
+{\r
+  VOID                    *OldFfs2FvPpi;\r
+  EFI_PEI_PPI_DESCRIPTOR  *OldDescriptor;\r
+  UINTN                   Index;\r
+  EFI_STATUS              Status;\r
+\r
+  //\r
+  // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which\r
+  // in flash.\r
+  //\r
+  Status = PeiServicesLocatePpi (\r
+            &gEfiFirmwareFileSystem2Guid,\r
+            0,\r
+            &OldDescriptor,\r
+            &OldFfs2FvPpi\r
+            );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2\r
+  // which is shadowed from flash to permanent memory within PeiCore image.\r
+  //\r
+  Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // Fixup all FvPpi pointers for the implementation in flash to permanent memory.\r
+  //\r
+  for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {\r
+    if (PrivateData->Fv[Index].FvPpi == OldFfs2FvPpi) {\r
+      PrivateData->Fv[Index].FvPpi = &mPeiFfs2FvPpi;\r
+    }\r
+  }\r
+}  \r
+\r
+/**\r
+  Report the information for a new discoveried FV in unknown third-party format.\r
+  \r
+  If the EFI_PEI_FIRMWARE_VOLUME_PPI has not been installed for third-party FV format, but\r
+  the FV in this format has been discoveried, then this FV's information will be cached into \r
+  PEI_CORE_INSTANCE's UnknownFvInfo array.\r
+  Also a notification would be installed for unknown third-party FV format guid, if EFI_PEI_FIRMWARE_VOLUME_PPI\r
+  is installed later by platform's PEIM, the original unknown third-party FV will be processed by\r
+  using new installed EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+  \r
+  @param PrivateData  Point to instance of PEI_CORE_INSTANCE\r
+  @param Format       Point to the unknown third-party format guid.\r
+  @param FvInfo       Point to FvInfo buffer.\r
+  @param FvInfoSize   The size of FvInfo buffer.\r
+  \r
+  @retval EFI_OUT_OF_RESOURCES  The FV info array in PEI_CORE_INSTANCE has no more spaces.\r
+  @retval EFI_SUCCESS           Success to add the information for unknown FV.\r
+**/\r
+EFI_STATUS\r
+AddUnknownFormatFvInfo (\r
+  IN PEI_CORE_INSTANCE *PrivateData,\r
+  IN EFI_GUID          *Format,\r
+  IN VOID              *FvInfo,\r
+  IN UINT32            FvInfoSize\r
+  )\r
+{\r
+  PEI_CORE_UNKNOW_FORMAT_FV_INFO    *NewUnknownFv;\r
+  \r
+  if (PrivateData->UnknownFvInfoCount + 1 >= FixedPcdGet32 (PcdPeiCoreMaxPeimPerFv)) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
+  NewUnknownFv = &PrivateData->UnknownFvInfo[PrivateData->UnknownFvInfoCount];\r
+  PrivateData->UnknownFvInfoCount ++;\r
+  \r
+  CopyGuid (&NewUnknownFv->FvFormat, Format);\r
+  NewUnknownFv->FvInfo     = FvInfo;\r
+  NewUnknownFv->FvInfoSize = FvInfoSize;\r
+  NewUnknownFv->NotifyDescriptor.Flags  = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);\r
+  NewUnknownFv->NotifyDescriptor.Guid   = &NewUnknownFv->FvFormat;\r
+  NewUnknownFv->NotifyDescriptor.Notify = ThirdPartyFvPpiNotifyCallback;\r
+  \r
+  PeiServicesNotifyPpi (&NewUnknownFv->NotifyDescriptor);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Find the FV information according to third-party FV format guid.\r
+  \r
+  This routine also will remove the FV information found by given FV format guid from\r
+  PrivateData->UnknownFvInfo[].\r
+  \r
+  @param PrivateData      Point to instance of PEI_CORE_INSTANCE\r
+  @param Format           Point to given FV format guid\r
+  @param FvInfo           On return, the pointer of FV information buffer\r
+  @param FvInfoSize       On return, the size of FV information buffer.\r
+  \r
+  @retval EFI_NOT_FOUND  The FV is not found for new installed EFI_PEI_FIRMWARE_VOLUME_PPI\r
+  @retval EFI_SUCCESS    Success to find a FV which could be processed by new installed EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+**/\r
+EFI_STATUS\r
+FindUnknownFormatFvInfo (\r
+  IN  PEI_CORE_INSTANCE *PrivateData,\r
+  IN  EFI_GUID          *Format,\r
+  OUT VOID              **FvInfo,\r
+  OUT UINT32            *FvInfoSize\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINTN Index2;\r
+\r
+  Index = 0;\r
+  for (; Index < PrivateData->UnknownFvInfoCount; Index ++) {\r
+    if (CompareGuid (Format, &PrivateData->UnknownFvInfo[Index].FvFormat)) {\r
+      break;\r
+    }\r
+  }\r
+  \r
+  if (Index == PrivateData->UnknownFvInfoCount) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  \r
+  *FvInfo     = PrivateData->UnknownFvInfo[Index].FvInfo;\r
+  *FvInfoSize = PrivateData->UnknownFvInfo[Index].FvInfoSize;\r
+  \r
+  //\r
+  // Remove an entry from UnknownFvInfo array.\r
+  //\r
+  Index2 = Index + 1;\r
+  for (;Index2 < PrivateData->UnknownFvInfoCount; Index2 ++, Index ++) {\r
+    CopyMem (&PrivateData->UnknownFvInfo[Index], &PrivateData->UnknownFvInfo[Index2], sizeof (PEI_CORE_UNKNOW_FORMAT_FV_INFO));\r
+  }\r
+  PrivateData->UnknownFvInfoCount --;\r
+  return EFI_SUCCESS;\r
+}  \r
+\r
+/**\r
+  Notification callback function for EFI_PEI_FIRMWARE_VOLUME_PPI.\r
+  \r
+  When a EFI_PEI_FIRMWARE_VOLUME_PPI is installed to support new FV format, this \r
+  routine is called to process all discoveried FVs in this format.\r
+  \r
+  @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
+  @param NotifyDescriptor  Address of the notification descriptor data structure.\r
+  @param Ppi               Address of the PPI that was installed.\r
+  \r
+  @retval EFI_SUCCESS  The notification callback is processed correctly.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ThirdPartyFvPpiNotifyCallback (\r
+  IN EFI_PEI_SERVICES              **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR     *NotifyDescriptor,\r
+  IN VOID                          *Ppi\r
+  )\r
+{\r
+  PEI_CORE_INSTANCE            *PrivateData;\r
+  EFI_PEI_FIRMWARE_VOLUME_PPI  *FvPpi;\r
+  VOID                         *FvInfo;\r
+  UINT32                       FvInfoSize;\r
+  EFI_STATUS                   Status;\r
+  EFI_PEI_FV_HANDLE            FvHandle;\r
+  BOOLEAN                      IsProcessed;\r
+  UINTN                        FvIndex;\r
+  EFI_PEI_FILE_HANDLE          FileHandle;\r
+  VOID                         *DepexData;  \r
+  \r
+  PrivateData  = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);\r
+  FvPpi = (EFI_PEI_FIRMWARE_VOLUME_PPI*) Ppi;\r
+  \r
+  do {\r
+    Status = FindUnknownFormatFvInfo (PrivateData, NotifyDescriptor->Guid, &FvInfo, &FvInfoSize);\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_SUCCESS;\r
+    }\r
+    \r
+    //\r
+    // Process new found FV and get FV handle.\r
+    //\r
+    Status = FvPpi->ProcessVolume (FvPpi, FvInfo, FvInfoSize, &FvHandle);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Fail to process the FV 0x%p, FV may be corrupted!\n", FvInfo));\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Check whether the FV has already been processed.\r
+    //\r
+    IsProcessed = FALSE;\r
+    for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {\r
+      if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {\r
+        DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfo));\r
+        IsProcessed = TRUE;\r
+        break;\r
+      }\r
+    }\r
+  \r
+    if (IsProcessed) {\r
+      continue;\r
+    }\r
+    \r
+    //\r
+    // Update internal PEI_CORE_FV array.\r
+    //\r
+    PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfo;\r
+    PrivateData->Fv[PrivateData->FvCount].FvPpi    = FvPpi;\r
+    PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;\r
+    DEBUG ((\r
+      EFI_D_INFO, \r
+      "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n", \r
+      (UINT32) PrivateData->FvCount, \r
+      (VOID *) FvInfo, \r
+      FvInfoSize,\r
+      FvHandle\r
+      ));    \r
+    PrivateData->FvCount ++;\r
+\r
+    //\r
+    // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE \r
+    //\r
+    FileHandle = NULL;\r
+    do {\r
+      Status = FvPpi->FindFileByType (\r
+                        FvPpi,\r
+                        EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
+                        FvHandle,\r
+                        &FileHandle\r
+                       );\r
+      if (!EFI_ERROR (Status)) {\r
+        Status = FvPpi->FindSectionByType (\r
+                          FvPpi,\r
+                          EFI_SECTION_PEI_DEPEX,\r
+                          FileHandle,\r
+                          (VOID**)&DepexData\r
+                          );\r
+        if (!EFI_ERROR (Status)) {\r
+          if (!PeimDispatchReadiness (PeiServices, DepexData)) {\r
+            //\r
+            // Dependency is not satisfied.\r
+            //\r
+            continue;\r
+          }\r
+        }\r
+        \r
+        DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));\r
+        ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);\r
+      }\r
+    } while (FileHandle != NULL);\r
+  } while (TRUE);\r
+}\r