Guomin,

See my 16 comments embedded below.

About PcdMigrateTemporaryRamFirmwareVolumes, I think we need more
discussions on its use scenario along with PcdShadowPeimOnBoot and
PcdShadowPeimOnS3Boot. Currently it need all of them enabled to make
this solution work, which is a bit complex and confusion to me.

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Guomin
> Jiang
> Sent: Thursday, July 09, 2020 9:57 AM
> To: devel@edk2.groups.io
> Cc: Michael Kubacki <michael.a.kuba...@intel.com>; Wang, Jian J
> <jian.j.w...@intel.com>; Wu, Hao A <hao.a...@intel.com>; Bi, Dandan
> <dandan...@intel.com>; Gao, Liming <liming....@intel.com>; De, Debkumar
> <debkumar...@intel.com>; Han, Harry <harry....@intel.com>; West,
> Catharine <catharine.w...@intel.com>
> Subject: [edk2-devel] [PATCH v5 2/9] MdeModulePkg/PeiCore: Enable T-RAM
> evacuation in PeiCore (CVE-2019-11098)
> 
> From: Michael Kubacki <michael.a.kuba...@intel.com>
> 
> REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614
> 
> Introduces new changes to PeiCore to move the contents of temporary
> RAM visible to the PeiCore to permanent memory. This expands on
> pre-existing shadowing support in the PeiCore to perform the following
> additional actions:
> 
>  1. Migrate pointers in PPIs installed in PeiCore to the permanent
>     memory copy of PeiCore.
> 
>  2. Copy all installed firmware volumes to permanent memory.
> 
>  3. Relocate and fix up the PEIMs within the firmware volumes.
> 
>  4. Convert all PPIs into the migrated firmware volume to the corresponding
>     PPI address in the permanent memory location.
> 
>     This applies to PPIs and PEI notifications.
> 
>  5. Convert all status code callbacks in the migrated firmware volume to
>     the corresponding address in the permanent memory location.
> 
>  6. Update the FV HOB to the corresponding firmware volume in permanent
>     memory.
> 
>  7. Add PcdMigrateTemporaryRamFirmwareVolumes to control if enable the
>     feature or not. when the PCD disable, the EvacuateTempRam() will
>     never be called.
> 
> The function control flow as below:
>   PeiCore()
>     DumpPpiList()
>     EvacuateTempRam()
>       ConvertPeiCorePpiPointers()
>         ConvertPpiPointersFv()
>       MigratePeimsInFv()
>         MigratePeim()
>           PeiGetPe32Data()
>           LoadAndRelocatePeCoffImageInPlace()
>       MigrateSecModulesInFv()
>       ConvertPpiPointersFv()
>       ConvertStatusCodeCallbacks()
>       ConvertFvHob()
>       RemoveFvHobsInTemporaryMemory()
>     DumpPpiList()
> 
> Cc: Jian J Wang <jian.j.w...@intel.com>
> Cc: Hao A Wu <hao.a...@intel.com>
> Cc: Dandan Bi <dandan...@intel.com>
> Cc: Liming Gao <liming....@intel.com>
> Cc: Debkumar De <debkumar...@intel.com>
> Cc: Harry Han <harry....@intel.com>
> Cc: Catharine West <catharine.w...@intel.com>
> Signed-off-by: Michael Kubacki <michael.a.kuba...@intel.com>
> ---
>  MdeModulePkg/Core/Pei/PeiMain.inf             |   2 +
>  MdeModulePkg/Core/Pei/PeiMain.h               | 168 ++++++++
>  MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 402 ++++++++++++++++++
>  MdeModulePkg/Core/Pei/Image/Image.c           | 115 +++++
>  MdeModulePkg/Core/Pei/Memory/MemoryServices.c |  82 ++++
>  MdeModulePkg/Core/Pei/PeiMain/PeiMain.c       |  24 ++
>  MdeModulePkg/Core/Pei/Ppi/Ppi.c               | 287 +++++++++++++
>  7 files changed, 1080 insertions(+)
> 
> diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf
> b/MdeModulePkg/Core/Pei/PeiMain.inf
> index 6e25cc40232a..5b36d516b3fa 100644
> --- a/MdeModulePkg/Core/Pei/PeiMain.inf
> +++ b/MdeModulePkg/Core/Pei/PeiMain.inf
> @@ -76,6 +76,7 @@ [Guids]
>    ## CONSUMES   ## UNDEFINED # Locate PPI
>    ## CONSUMES   ## GUID      # Used to compare with FV's file system GUID and
> get the FV's file system format
>    gEfiFirmwareFileSystem3Guid
> +  gStatusCodeCallbackGuid
> 
>  [Ppis]
>    gEfiPeiStatusCodePpiGuid                      ## SOMETIMES_CONSUMES #
> PeiReportStatusService is not ready if this PPI doesn't exist
> @@ -109,6 +110,7 @@ [Pcd]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot                      
> ##
> CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot                        
> ##
> CONSUMES
>    gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack                    
> ##
> CONSUMES
> +
> gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolum
> es      ## CONSUMES
> 
>  # [BootMode]
>  # S3_RESUME             ## SOMETIMES_CONSUMES
> diff --git a/MdeModulePkg/Core/Pei/PeiMain.h
> b/MdeModulePkg/Core/Pei/PeiMain.h
> index 56b3bd85793d..b0101dba5e30 100644
> --- a/MdeModulePkg/Core/Pei/PeiMain.h
> +++ b/MdeModulePkg/Core/Pei/PeiMain.h
> @@ -394,6 +394,41 @@ PeimDispatchReadiness (
>    IN VOID               *DependencyExpression
>    );
> 
> +/**
> +  Migrate a PEIM from Temporary RAM to permanent memory.

1) 'Temporary' -> 'temporary'

> +
> +  @param PeimFileHandle       Pointer to the FFS file header of the image.
> +  @param MigratedFileHandle   Pointer to the FFS file header of the migrated
> image.
> +
> +  @retval EFI_SUCCESS         Sucessfully migrated the PEIM to permanent
> memory.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +MigratePeim (
> +  IN  EFI_PEI_FILE_HANDLE     FileHandle,
> +  IN  EFI_PEI_FILE_HANDLE     MigratedFileHandle
> +  );
> +
> +/**
> +  Migrate FVs out of Temporary RAM before the cache is flushed.

2) 'Temporary' -> 'temporary'

> +
> +  @param Private         PeiCore's private data structure
> +  @param SecCoreData     Points to a data structure containing information
> about the PEI core's operating
> +                         environment, such as the size and location of 
> temporary RAM,
> the stack location and
> +                         the BFV location.
> +
> +  @retval EFI_SUCCESS           Succesfully migrated installed FVs from 
> Temporary
> RAM to permanent memory.

3) 'Temporary' -> 'temporary'

> +  @retval EFI_OUT_OF_RESOURCES  Insufficient memory exists to allocate
> needed pages.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EvacuateTempRam (
> +  IN PEI_CORE_INSTANCE            *Private,
> +  IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData
> +  );
> +
>  /**
>    Conduct PEIM dispatch.
> 
> @@ -477,6 +512,50 @@ ConvertPpiPointers (
>    IN PEI_CORE_INSTANCE           *PrivateData
>    );
> 
> +/**
> +
> +  Migrate Notify Pointers inside an FV from temporary memory to permanent
> memory.
> +
> +  @param PrivateData      Pointer to PeiCore's private data structure.
> +  @param OrgFvHandle      Address of FV Handle in temporary memory.
> +  @param FvHandle         Address of FV Handle in permanent memory.
> +  @param FvSize           Size of the FV.
> +
> +**/
> +VOID
> +ConvertPpiPointersFv (
> +  IN  PEI_CORE_INSTANCE       *PrivateData,
> +  IN  UINTN                   OrgFvHandle,
> +  IN  UINTN                   FvHandle,
> +  IN  UINTN                   FvSize
> +  );
> +
> +/**
> +
> +  Migrate PPI Pointers of PEI_CORE from temporary memory to permanent
> memory.
> +
> +  @param PrivateData      Pointer to PeiCore's private data structure.
> +  @param CoreFvHandle     Address of PEI_CORE FV Handle in temporary
> memory.
> +
> +**/
> +VOID
> +ConvertPeiCorePpiPointers (
> +  IN  PEI_CORE_INSTANCE        *PrivateData,
> +  PEI_CORE_FV_HANDLE           CoreFvHandle
> +  );
> +
> +/**
> +
> +  Dumps the PPI lists to debug output.
> +
> +  @param PrivateData     Points to PeiCore's private instance data.
> +
> +**/
> +VOID
> +DumpPpiList (
> +  IN PEI_CORE_INSTANCE    *PrivateData
> +  );
> +
>  /**
> 
>    Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi.
> @@ -808,6 +887,37 @@ PeiFfsFindNextFile (
>    IN OUT EFI_PEI_FILE_HANDLE     *FileHandle
>    );
> 
> +/**
> +  Go through the file to search SectionType section.
> +  Search within encapsulation sections (compression and GUIDed) recursively,
> +  until the match section is found.
> +
> +  @param PeiServices       An indirect pointer to the EFI_PEI_SERVICES table
> published by the PEI Foundation.
> +  @param SectionType       Filter to find only section of this type.
> +  @param SectionInstance   Pointer to the filter to find the specific 
> instance of
> section.
> +  @param Section           From where to search.
> +  @param SectionSize       The file size to search.
> +  @param OutputBuffer      A pointer to the discovered section, if 
> successful.
> +                           NULL if section not found

4) Missing '.' at the end

> +  @param AuthenticationStatus Updated upon return to point to the
> authentication status for this section.

5) Please align the start of parameter description

> +  @param IsFfs3Fv          Indicates the FV format.
> +
> +  @return EFI_NOT_FOUND    The match section is not found.
> +  @return EFI_SUCCESS      The match section is found.
> +
> +**/
> +EFI_STATUS
> +ProcessSection (
> +  IN CONST EFI_PEI_SERVICES     **PeiServices,
> +  IN EFI_SECTION_TYPE           SectionType,
> +  IN OUT UINTN                  *SectionInstance,
> +  IN EFI_COMMON_SECTION_HEADER  *Section,
> +  IN UINTN                      SectionSize,
> +  OUT VOID                      **OutputBuffer,
> +  OUT UINT32                    *AuthenticationStatus,
> +  IN BOOLEAN                    IsFfs3Fv
> +  );
> +
>  /**
>    Searches for the next matching section within the specified file.
> 
> @@ -931,6 +1041,33 @@ MigrateMemoryPages (
>    IN BOOLEAN                TemporaryRamMigrated
>    );
> 
> +/**
> +  Removes any FV HOBs whose base address is not in PEI installed memory.
> +
> +  @param[in] Private          Pointer to PeiCore's private data structure.
> +
> +**/
> +VOID
> +RemoveFvHobsInTemporaryMemory (
> +  IN PEI_CORE_INSTANCE        *Private
> +  );
> +
> +/**
> +  Migrate the base address in firmware volume allocation HOBs
> +  from temporary memory to PEI installed memory.
> +
> +  @param[in] PrivateData      Pointer to PeiCore's private data structure.
> +  @param[in] OrgFvHandle      Address of FV Handle in temporary memory.
> +  @param[in] FvHandle         Address of FV Handle in permanent memory.
> +
> +**/
> +VOID
> +ConvertFvHob (
> +  IN PEI_CORE_INSTANCE          *PrivateData,
> +  IN UINTN                      OrgFvHandle,
> +  IN UINTN                      FvHandle
> +  );
> +
>  /**
>    Migrate MemoryBaseAddress in memory allocation HOBs
>    from the temporary memory to PEI installed memory.
> @@ -1249,6 +1386,37 @@ InitializeImageServices (
>    IN  PEI_CORE_INSTANCE   *OldCoreData
>    );
> 
> +/**
> +  Loads and relocates a PE/COFF image in place.
> +
> +  @param Pe32Data         The base address of the PE/COFF file that is to be
> loaded and relocated
> +  @param ImageAddress     The base address of the relocated PE/COFF image
> +
> +  @retval EFI_SUCCESS     The file was loaded and relocated
> +
> +**/
> +EFI_STATUS
> +LoadAndRelocatePeCoffImageInPlace (
> +  IN  VOID    *Pe32Data,
> +  IN  VOID    *ImageAddress
> +  );
> +
> +/**
> +  Find the PE32 Data for an FFS file.
> +
> +  @param FileHandle       Pointer to the FFS file header of the image.
> +  @param Pe32Data         Pointer to a (VOID *) PE32 Data pointer.
> +
> +  @retval EFI_SUCCESS      Image is successfully loaded.
> +  @retval EFI_NOT_FOUND    Fail to locate PE32 Data.
> +
> +**/
> +EFI_STATUS
> +PeiGetPe32Data (
> +  IN     EFI_PEI_FILE_HANDLE          FileHandle,
> +  OUT    VOID                         **Pe32Data
> +  );
> +
>  /**
>    The wrapper function of PeiLoadImageLoadImage().
> 
> diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
> b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
> index 4c2eac1384e8..ef88b3423376 100644
> --- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
> +++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
> @@ -952,6 +952,408 @@ PeiCheckAndSwitchStack (
>    }
>  }
> 
> +/**
> +  Migrate a PEIM from Temporary RAM to permanent memory.

6) 'Temporary' -> 'temporary'

> +
> +  @param PeimFileHandle       Pointer to the FFS file header of the image.
> +  @param MigratedFileHandle   Pointer to the FFS file header of the migrated
> image.
> +
> +  @retval EFI_SUCCESS         Sucessfully migrated the PEIM to permanent
> memory.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +MigratePeim (
> +  IN  EFI_PEI_FILE_HANDLE     FileHandle,
> +  IN  EFI_PEI_FILE_HANDLE     MigratedFileHandle
> +  )
> +{
> +  EFI_STATUS                Status;
> +  EFI_FFS_FILE_HEADER       *FileHeader;
> +  VOID                      *Pe32Data;
> +  VOID                      *ImageAddress;
> +  CHAR8                     *AsciiString;
> +  UINTN                     Index;
> +
> +  Status = EFI_SUCCESS;
> +
> +  FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;
> +  ASSERT (!IS_FFS_FILE2 (FileHeader));
> +
> +  ImageAddress = NULL;
> +  PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
> +  if (ImageAddress != NULL) {
> +    AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
> +    for (Index = 0; AsciiString[Index] != 0; Index++) {
> +      if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {
> +        AsciiString = AsciiString + Index + 1;
> +        Index = 0;
> +      } else if (AsciiString[Index] == '.') {
> +        AsciiString[Index] = 0;
> +      }
> +    }
> +    DEBUG ((DEBUG_INFO, "%a", AsciiString));

7) Above code (from the line below 'if' to 'DEBUG') are used for
debug only. Suggest to put them into DEBUG_CODE();

> +
> +    Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle +
> (UINTN) FileHandle);
> +    Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
> +    ASSERT_EFI_ERROR (Status);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Migrate Status Code Callback function pointers inside an FV from temporary
> memory to permanent memory.
> +
> +  @param OrgFvHandle      Address of FV Handle in temporary memory.

8) 'Handle' -> 'handle'

> +  @param FvHandle         Address of FV Handle in permanent memory.

9) 'Handle' -> 'handle'

> +  @param FvSize           Size of the FV.
> +
> +**/
> +VOID
> +ConvertStatusCodeCallbacks (
> +  IN  UINTN                   OrgFvHandle,
> +  IN  UINTN                   FvHandle,
> +  IN  UINTN                   FvSize
> +  )
> +{
> +  EFI_PEI_HOB_POINTERS    Hob;
> +  UINTN                   *NumberOfEntries;
> +  UINTN                   *CallbackEntry;
> +  UINTN                   Index;
> +
> +  Hob.Raw  = GetFirstGuidHob (&gStatusCodeCallbackGuid);
> +  while (Hob.Raw != NULL) {
> +    NumberOfEntries = GET_GUID_HOB_DATA (Hob);
> +    CallbackEntry   = NumberOfEntries + 1;
> +    for (Index = 0; Index < *NumberOfEntries; Index++) {
> +      if (((VOID *) CallbackEntry[Index]) != NULL) {
> +        if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] <
> (OrgFvHandle + FvSize))) {
> +          DEBUG ((DEBUG_INFO, "Migrating CallbackEntry[%d] from 0x%08X to ",
> Index, CallbackEntry[Index]));

CallbackEntry is defined as pointer to UINTN, which is 4-byte with 32-bit PEI.
Using %08X might be not a good idea. Suggest to use %p instead.

> +          if (OrgFvHandle > FvHandle) {
> +            CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - 
> FvHandle);
> +          } else {
> +            CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - 
> OrgFvHandle);
> +          }
> +          DEBUG ((DEBUG_INFO, "0x%08X\n", CallbackEntry[Index]));

10) The same as above.

> +        }
> +      }
> +    }
> +    Hob.Raw = GET_NEXT_HOB (Hob);
> +    Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
> +  }
> +}
> +
> +/**
> +  Migrates SEC modules in the given firmware volume.
> +
> +  Migrating SECURITY_CORE files requires special treatment since they are not
> tracked for PEI dispatch.
> +
> +  This functioun should be called after the FV has been copied to its post-
> memory location and the PEI Core FV list has
> +  been updated.
> +
> +  @param Private          Pointer to the PeiCore's private data structure.
> +  @param FvIndex          The firmware volume index to migrate.
> +  @param OrgFvHandle      The handle to the firmware volume in temporary
> memory.
> +
> +  @retval   EFI_SUCCESS           SEC modules were migrated successfully
> +  @retval   EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is

11) There's EFI_NOT_FOUND returned in the function body.

> invalid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +MigrateSecModulesInFv (
> +  IN PEI_CORE_INSTANCE    *Private,
> +  IN  UINTN               FvIndex,
> +  IN  UINTN               OrgFvHandle
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_STATUS                  FindFileStatus;
> +  EFI_PEI_FILE_HANDLE         MigratedFileHandle;
> +  EFI_PEI_FILE_HANDLE         FileHandle;
> +  UINT32                      SectionAuthenticationStatus;
> +  UINT32                      FileSize;
> +  VOID                        *OrgPe32SectionData;
> +  VOID                        *Pe32SectionData;
> +  EFI_FFS_FILE_HEADER         *FfsFileHeader;
> +  EFI_COMMON_SECTION_HEADER   *Section;
> +  BOOLEAN                     IsFfs3Fv;
> +  UINTN                       SectionInstance;
> +
> +  if (Private == NULL || FvIndex >= Private->FvCount) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  do {
> +    FindFileStatus =  PeiFfsFindNextFile (
> +                        GetPeiServicesTablePointer (),
> +                        EFI_FV_FILETYPE_SECURITY_CORE,
> +                        Private->Fv[FvIndex].FvHandle,
> +                        &MigratedFileHandle
> +                        );
> +    if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {
> +      FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - 
> (UINTN)
> Private->Fv[FvIndex].FvHandle + OrgFvHandle);
> +      FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;
> +
> +      DEBUG ((DEBUG_VERBOSE, "    Migrating SEC_CORE MigratedFileHandle at
> 0x%x.\n", (UINTN) MigratedFileHandle));
> +      DEBUG ((DEBUG_VERBOSE, "                       FileHandle at 0x%x.\n", 
> (UINTN)
> FileHandle));
> +
> +      IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid,
> &gEfiFirmwareFileSystem3Guid);
> +      if (IS_FFS_FILE2 (FfsFileHeader)) {
> +        ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
> +        if (!IsFfs3Fv) {
> +          DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3
> formatted FV.\n", &FfsFileHeader->Name));
> +          return EFI_NOT_FOUND;
> +        }
> +        Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader +
> sizeof (EFI_FFS_FILE_HEADER2));
> +        FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof 
> (EFI_FFS_FILE_HEADER2);
> +      } else {
> +        Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader +
> sizeof (EFI_FFS_FILE_HEADER));
> +        FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof 
> (EFI_FFS_FILE_HEADER);
> +      }
> +
> +      SectionInstance = 1;
> +      SectionAuthenticationStatus = 0;
> +      Status = ProcessSection (
> +                GetPeiServicesTablePointer (),
> +                EFI_SECTION_PE32,
> +                &SectionInstance,
> +                Section,
> +                FileSize,
> +                &Pe32SectionData,
> +                &SectionAuthenticationStatus,
> +                IsFfs3Fv
> +                );
> +
> +      if (!EFI_ERROR (Status)) {
> +        OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN)
> MigratedFileHandle + (UINTN) FileHandle);
> +        DEBUG ((DEBUG_VERBOSE, "      PE32 section in migrated file at 
> 0x%x.\n",
> (UINTN) Pe32SectionData));
> +        DEBUG ((DEBUG_VERBOSE, "      PE32 section in original file at 
> 0x%x.\n",
> (UINTN) OrgPe32SectionData));
> +        Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData,
> Pe32SectionData);
> +        ASSERT_EFI_ERROR (Status);
> +      }
> +    }
> +  } while (!EFI_ERROR (FindFileStatus));
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Migrates PEIMs in the given firmware volume.
> +
> +  @param Private          Pointer to the PeiCore's private data structure.
> +  @param FvIndex          The firmware volume index to migrate.
> +  @param OrgFvHandle      The handle to the firmware volume in temporary
> memory.
> +  @param FvHandle         The handle to the firmware volume in permanent
> memory.
> +
> +  @retval   EFI_SUCCESS           The PEIMs in the FV were migrated 
> successfully
> +  @retval   EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is
> invalid.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +MigratePeimsInFv (
> +  IN PEI_CORE_INSTANCE    *Private,
> +  IN  UINTN               FvIndex,
> +  IN  UINTN               OrgFvHandle,
> +  IN  UINTN               FvHandle
> +  )
> +{
> +  EFI_STATUS              Status;
> +  volatile UINTN          FileIndex;
> +  EFI_PEI_FILE_HANDLE     MigratedFileHandle;
> +  EFI_PEI_FILE_HANDLE     FileHandle;
> +
> +  if (Private == NULL || FvIndex >= Private->FvCount) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (Private->Fv[FvIndex].ScanFv) {
> +    for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; 
> FileIndex++) {
> +      if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {
> +        FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];
> +
> +        MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle -
> OrgFvHandle + FvHandle);
> +
> +        DEBUG ((DEBUG_VERBOSE, "    Migrating FileHandle %2d ", FileIndex));
> +        Status = MigratePeim (FileHandle, MigratedFileHandle);
> +        DEBUG ((DEBUG_INFO, "\n"));

DEBUG_VERBOSE is used line above but DEBUG_INFO here.

> +        ASSERT_EFI_ERROR (Status);
> +
> +        if (!EFI_ERROR (Status)) {
> +          // if (Private->Fv[FvIndex].PeimState[FileIndex] ==
> PEIM_STATE_REGISTER_FOR_SHADOW) {
> +          //   Private->Fv[FvIndex].PeimState[FileIndex]++;
> +          // }

12) Remove the code which have been commented out.

> +          Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;
> +          if (FvIndex == Private->CurrentPeimFvCount) {
> +            Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;
> +          }
> +        }
> +      }
> +    }
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Migrate FVs out of temporary RAM before the cache is flushed.
> +
> +  @param Private         PeiCore's private data structure
> +  @param SecCoreData     Points to a data structure containing information
> about the PEI core's operating
> +                         environment, such as the size and location of 
> temporary RAM,
> the stack location and
> +                         the BFV location.
> +
> +  @retval EFI_SUCCESS           Succesfully migrated installed FVs from 
> temporary
> RAM to permanent memory.
> +  @retval EFI_OUT_OF_RESOURCES  Insufficient memory exists to allocate
> needed pages.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +EvacuateTempRam (
> +  IN PEI_CORE_INSTANCE            *Private,
> +  IN CONST EFI_SEC_PEI_HAND_OFF   *SecCoreData
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  volatile UINTN                FvIndex;
> +  volatile UINTN                FvChildIndex;
> +  UINTN                         ChildFvOffset;
> +  EFI_FIRMWARE_VOLUME_HEADER    *FvHeader;
> +  EFI_FIRMWARE_VOLUME_HEADER    *ChildFvHeader;
> +  EFI_FIRMWARE_VOLUME_HEADER    *MigratedFvHeader;
> +  EFI_FIRMWARE_VOLUME_HEADER    *MigratedChildFvHeader;
> +
> +  PEI_CORE_FV_HANDLE            PeiCoreFvHandle;
> +  EFI_PEI_CORE_FV_LOCATION_PPI  *PeiCoreFvLocationPpi;
> +
> +  ASSERT (Private->PeiMemoryInstalled);
> +
> +  DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary
> RAM.\n"));
> +
> +  //
> +  // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded
> PEI_CORE in permanent memory.
> +  //
> +  Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps,
> &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);
> +  if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation !=
> NULL)) {
> +    PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi-
> >PeiCoreFvLocation;
> +  } else {
> +    PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData-
> >BootFirmwareVolumeBase;
> +  }
> +  for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
> +    if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
> +      PeiCoreFvHandle = Private->Fv[FvIndex];
> +      break;
> +    }
> +  }
> +  Status = EFI_SUCCESS;
> +
> +  ConvertPeiCorePpiPointers (Private, PeiCoreFvHandle);
> +
> +  for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
> +    FvHeader = Private->Fv[FvIndex].FvHeader;
> +    ASSERT (FvHeader != NULL);
> +    ASSERT (FvIndex < Private->FvCount);
> +
> +    DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN)
> FvHeader));
> +    if (
> +      !(
> +        ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private-
> >PhysicalMemoryBegin) &&
> +        (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1))
> < Private->FreePhysicalMemoryTop)
> +        )
> +      ) {
> +      Status =  PeiServicesAllocatePages (
> +                  EfiBootServicesCode,
> +                  EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
> +                  (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader
> +                  );
> +      ASSERT_EFI_ERROR (Status);
> +
> +      DEBUG ((
> +        DEBUG_VERBOSE,
> +        "  Migrating FV[%d] from 0x%08X to 0x%08X\n",
> +        FvIndex,
> +        (UINTN) FvHeader,
> +        (UINTN) MigratedFvHeader
> +        ));
> +
> +      CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);
> +
> +      //
> +      // Migrate any children for this FV now
> +      //
> +      for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount;
> FvChildIndex++) {
> +        ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;
> +        if (
> +          ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&
> +          (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN)
> FvHeader) + FvHeader->FvLength)
> +          ) {
> +          DEBUG ((DEBUG_VERBOSE, "    Child FV[%02d] is being migrated.\n",
> FvChildIndex));
> +          ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;
> +          DEBUG ((DEBUG_VERBOSE, "    Child FV offset = 0x%x.\n", 
> ChildFvOffset));
> +          MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN)
> MigratedFvHeader + ChildFvOffset);
> +          Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;
> +          Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE)
> MigratedChildFvHeader;
> +          DEBUG ((DEBUG_VERBOSE, "    Child migrated FV header at 0x%x.\n",
> (UINTN) MigratedChildFvHeader));
> +
> +          // @todo: find issue with file and section alignment in SEC PE32 
> images
> for migration
> +          //        (alignment in P32 is given as 32-bit when actual 
> alignment is 16-bit)
> +          //        SEC PPIs are currently re-installed with a dedicated PEIM
> +          // Status = MigrateSecModulesInFv (Private, FvChildIndex, (UINTN)
> ChildFvHeader);
> +          // ASSERT_EFI_ERROR (Status);

13) Remove the code which have been commented out.

> +          Status =  MigratePeimsInFv (Private, FvChildIndex, (UINTN) 
> ChildFvHeader,
> (UINTN) MigratedChildFvHeader);
> +          ASSERT_EFI_ERROR (Status);
> +
> +          ConvertPpiPointersFv (
> +            Private,
> +            (UINTN) ChildFvHeader,
> +            (UINTN) MigratedChildFvHeader,
> +            (UINTN) ChildFvHeader->FvLength - 1
> +            );
> +
> +          ConvertStatusCodeCallbacks (
> +            (UINTN) ChildFvHeader,
> +            (UINTN) MigratedChildFvHeader,
> +            (UINTN) ChildFvHeader->FvLength - 1
> +            );
> +
> +          ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN)
> MigratedChildFvHeader);
> +        }
> +      }
> +      Private->Fv[FvIndex].FvHeader = MigratedFvHeader;
> +      Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;
> +
> +      // @todo: find issue with file and section alignment in SEC PE32 
> images for
> migration
> +      //        (alignment in P32 is given as 32-bit when actual alignment 
> is 16-bit)
> +      //        SEC PPIs are currently re-installed with a dedicated PEIM
> +      // Status = MigrateSecModulesInFv (Private, FvIndex, (UINTN) FvHeader);
> +      // ASSERT_EFI_ERROR (Status);

14) Remove the code which have been commented out.

> +      Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN)
> MigratedFvHeader);
> +      ASSERT_EFI_ERROR (Status);
> +
> +      ConvertPpiPointersFv (
> +        Private,
> +        (UINTN) FvHeader,
> +        (UINTN) MigratedFvHeader,
> +        (UINTN) FvHeader->FvLength - 1
> +        );
> +
> +      ConvertStatusCodeCallbacks (
> +        (UINTN) FvHeader,
> +        (UINTN) MigratedFvHeader,
> +        (UINTN) FvHeader->FvLength - 1
> +        );
> +
> +      ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
> +    }
> +  }
> +
> +  RemoveFvHobsInTemporaryMemory (Private);
> +
> +  return Status;
> +}
> +
>  /**
>    Conduct PEIM dispatch.
> 
> diff --git a/MdeModulePkg/Core/Pei/Image/Image.c
> b/MdeModulePkg/Core/Pei/Image/Image.c
> index e3ee3699337f..612797722a3e 100644
> --- a/MdeModulePkg/Core/Pei/Image/Image.c
> +++ b/MdeModulePkg/Core/Pei/Image/Image.c
> @@ -444,6 +444,121 @@ LoadAndRelocatePeCoffImage (
>    return ReturnStatus;
>  }
> 
> +/**
> +  Loads and relocates a PE/COFF image in place.
> +
> +  @param Pe32Data         The base address of the PE/COFF file that is to be
> loaded and relocated
> +  @param ImageAddress     The base address of the relocated PE/COFF image
> +
> +  @retval EFI_SUCCESS     The file was loaded and relocated

15) There're other return values from PeCoffLoaderLoadImage()
and PeCoffLoaderRelocateImage().

> +
> +**/
> +EFI_STATUS
> +LoadAndRelocatePeCoffImageInPlace (
> +  IN  VOID    *Pe32Data,
> +  IN  VOID    *ImageAddress
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  PE_COFF_LOADER_IMAGE_CONTEXT    ImageContext;
> +
> +  ZeroMem (&ImageContext, sizeof (ImageContext));
> +  ImageContext.Handle = Pe32Data;
> +  ImageContext.ImageRead = PeiImageRead;
> +
> +  Status = PeCoffLoaderGetImageInfo (&ImageContext);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    return Status;
> +  }
> +
> +  ImageContext.ImageAddress   = (PHYSICAL_ADDRESS)(UINTN) ImageAddress;
> +
> +  //
> +  // Load the image in place
> +  //
> +  Status = PeCoffLoaderLoadImage (&ImageContext);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    return Status;
> +  }
> +
> +  //
> +  // Relocate the image in place
> +  //
> +  Status = PeCoffLoaderRelocateImage (&ImageContext);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    return Status;
> +  }
> +
> +  //
> +  // Flush the instruction cache so the image data is written before we 
> execute
> it
> +  //
> +  if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)
> Pe32Data) {
> +    InvalidateInstructionCacheRange ((VOID
> *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Find the PE32 Data for an FFS file.
> +
> +  @param FileHandle       Pointer to the FFS file header of the image.
> +  @param Pe32Data         Pointer to a (VOID *) PE32 Data pointer.
> +
> +  @retval EFI_SUCCESS      Image is successfully loaded.
> +  @retval EFI_NOT_FOUND    Fail to locate PE32 Data.
> +
> +**/
> +EFI_STATUS
> +PeiGetPe32Data (
> +  IN     EFI_PEI_FILE_HANDLE  FileHandle,
> +  OUT    VOID                 **Pe32Data
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  EFI_SECTION_TYPE            SearchType1;
> +  EFI_SECTION_TYPE            SearchType2;
> +  UINT32                      AuthenticationState;
> +
> +  *Pe32Data = NULL;
> +
> +  if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
> +    SearchType1 = EFI_SECTION_TE;
> +    SearchType2 = EFI_SECTION_PE32;
> +  } else {
> +    SearchType1 = EFI_SECTION_PE32;
> +    SearchType2 = EFI_SECTION_TE;
> +  }
> +
> +  //
> +  // Try to find a first exe section (if
> PcdPeiCoreImageLoaderSearchTeSectionFirst
> +  // is true, TE will be searched first).
> +  //
> +  Status = PeiServicesFfsFindSectionData3 (
> +             SearchType1,
> +             0,
> +             FileHandle,
> +             Pe32Data,
> +             &AuthenticationState
> +             );
> +  //
> +  // If we didn't find a first exe section, try to find the second exe 
> section.
> +  //
> +  if (EFI_ERROR (Status)) {
> +    Status = PeiServicesFfsFindSectionData3 (
> +               SearchType2,
> +               0,
> +               FileHandle,
> +               Pe32Data,
> +               &AuthenticationState
> +               );
> +  }
> +  return Status;
> +}
> +
>  /**
>    Loads a PEIM into memory for subsequent execution. If there are compressed
>    images or images that need to be relocated into memory for performance
> reasons,
> diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
> b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
> index 6b3a64a811cd..9d933f0393a8 100644
> --- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
> +++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
> @@ -166,6 +166,88 @@ MigrateMemoryPages (
>    Private->FreePhysicalMemoryTop = NewMemPagesBase;
>  }
> 
> +/**
> +  Removes any FV HOBs whose base address is not in PEI installed memory.
> +
> +  @param[in] Private          Pointer to PeiCore's private data structure.
> +
> +**/
> +VOID
> +RemoveFvHobsInTemporaryMemory (
> +  IN PEI_CORE_INSTANCE        *Private
> +  )
> +{
> +  EFI_PEI_HOB_POINTERS        Hob;
> +  EFI_HOB_FIRMWARE_VOLUME     *FirmwareVolumeHob;
> +
> +  DEBUG ((DEBUG_INFO, "Removing FVs in FV HOB not already migrated to
> permanent memory.\n"));
> +
> +  for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw =
> GET_NEXT_HOB (Hob)) {
> +    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV || GET_HOB_TYPE (Hob) ==
> EFI_HOB_TYPE_FV2 || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
> +      FirmwareVolumeHob = Hob.FirmwareVolume;
> +      DEBUG ((DEBUG_INFO, "  Found FV HOB.\n"));
> +      DEBUG ((
> +          DEBUG_INFO,
> +          "    BA=%016lx  L=%016lx\n",
> +          FirmwareVolumeHob->BaseAddress,
> +          FirmwareVolumeHob->Length
> +          ));
> +      if (
> +        !(
> +          ((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob-
> >BaseAddress >= Private->PhysicalMemoryBegin) &&
> +          (((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress
> + (FirmwareVolumeHob->Length - 1)) < Private->FreePhysicalMemoryTop)
> +          )
> +        ) {
> +        DEBUG ((DEBUG_INFO, "      Removing FV HOB to an FV in T-RAM (was not
> migrated).\n"));
> +        Hob.Header->HobType = EFI_HOB_TYPE_UNUSED;
> +      }
> +    }
> +  }
> +}
> +
> +/**
> +  Migrate the base address in firmware volume allocation HOBs
> +  from temporary memory to PEI installed memory.
> +
> +  @param[in] PrivateData      Pointer to PeiCore's private data structure.
> +  @param[in] OrgFvHandle      Address of FV Handle in temporary memory.
> +  @param[in] FvHandle         Address of FV Handle in permanent memory.
> +
> +**/
> +VOID
> +ConvertFvHob (
> +  IN PEI_CORE_INSTANCE          *PrivateData,
> +  IN UINTN                      OrgFvHandle,
> +  IN UINTN                      FvHandle
> +  )
> +{
> +  EFI_PEI_HOB_POINTERS        Hob;
> +  EFI_HOB_FIRMWARE_VOLUME     *FirmwareVolumeHob;
> +  EFI_HOB_FIRMWARE_VOLUME2    *FirmwareVolume2Hob;
> +  EFI_HOB_FIRMWARE_VOLUME3    *FirmwareVolume3Hob;
> +
> +  DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n"));
> +
> +  for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw =
> GET_NEXT_HOB (Hob)) {
> +    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
> +      FirmwareVolumeHob = Hob.FirmwareVolume;
> +      if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) {
> +        FirmwareVolumeHob->BaseAddress = FvHandle;
> +      }
> +    } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
> +      FirmwareVolume2Hob = Hob.FirmwareVolume2;
> +      if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) {
> +        FirmwareVolume2Hob->BaseAddress = FvHandle;
> +      }
> +    } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
> +      FirmwareVolume3Hob = Hob.FirmwareVolume3;
> +      if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) {
> +        FirmwareVolume3Hob->BaseAddress = FvHandle;
> +      }
> +    }
> +  }
> +}
> +
>  /**
>    Migrate MemoryBaseAddress in memory allocation HOBs
>    from the temporary memory to PEI installed memory.
> diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
> b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
> index cca57c4c0686..4a0671f87604 100644
> --- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
> +++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
> @@ -176,6 +176,9 @@ PeiCore (
>    EFI_HOB_HANDOFF_INFO_TABLE  *HandoffInformationTable;
>    EFI_PEI_TEMPORARY_RAM_DONE_PPI *TemporaryRamDonePpi;
>    UINTN                       Index;
> +  BOOLEAN                     Shadow;

16) Suggest to use different name other than Shadow. It's mainly for migrate
temporary ram, not exactly the same as PcdShadowPeimOnBoot.

Regards,
Jian

> +
> +  Shadow = FALSE;
> 
>    //
>    // Retrieve context passed into PEI Core
> @@ -418,6 +421,27 @@ PeiCore (
>        ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps,
> PpiList);
>      }
>    } else {
> +    if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
> +      if (PrivateData.HobList.HandoffInformationTable->BootMode ==
> BOOT_ON_S3_RESUME) {
> +        Shadow = PcdGetBool (PcdShadowPeimOnS3Boot);
> +      } else {
> +        Shadow = PcdGetBool (PcdShadowPeimOnBoot);
> +      }
> +    }
> +
> +    if (Shadow) {
> +      DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM
> evacuation:\n"));
> +      DumpPpiList (&PrivateData);
> +
> +      //
> +      // Migrate installed content from Temporary RAM to Permanent RAM
> +      //
> +      EvacuateTempRam (&PrivateData, SecCoreData);
> +
> +      DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n"));
> +      DumpPpiList (&PrivateData);
> +    }
> +
>      //
>      // Try to locate Temporary RAM Done Ppi.
>      //
> diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c
> b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
> index 1ffe718c4702..018b25f86470 100644
> --- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c
> +++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c
> @@ -198,6 +198,227 @@ ConvertPpiPointers (
>    }
>  }
> 
> +/**
> +
> +  Migrate Notify Pointers inside an FV from temporary memory to permanent
> memory.
> +
> +  @param PrivateData      Pointer to PeiCore's private data structure.
> +  @param OrgFvHandle      Address of FV Handle in temporary memory.
> +  @param FvHandle         Address of FV Handle in permanent memory.
> +  @param FvSize           Size of the FV.
> +
> +**/
> +VOID
> +ConvertPpiPointersFv (
> +  IN  PEI_CORE_INSTANCE       *PrivateData,
> +  IN  UINTN                   OrgFvHandle,
> +  IN  UINTN                   FvHandle,
> +  IN  UINTN                   FvSize
> +  )
> +{
> +  UINT8                             Index;
> +  UINTN                             Offset;
> +  BOOLEAN                           OffsetPositive;
> +  EFI_PEI_FIRMWARE_VOLUME_INFO_PPI  *FvInfoPpi;
> +  UINT8                             GuidIndex;
> +  EFI_GUID                          *Guid;
> +  EFI_GUID                          *GuidCheckList[2];
> +
> +  GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;
> +  GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;
> +
> +  if (FvHandle > OrgFvHandle) {
> +    OffsetPositive = TRUE;
> +    Offset = FvHandle - OrgFvHandle;
> +  } else {
> +    OffsetPositive = FALSE;
> +    Offset = OrgFvHandle - FvHandle;
> +  }
> +
> +  DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));
> +  DEBUG ((
> +    DEBUG_VERBOSE,
> +    "  OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
> +    (UINTN) OrgFvHandle,
> +    (UINTN) FvHandle,
> +    FvSize
> +    ));
> +  DEBUG ((
> +    DEBUG_VERBOSE,
> +    "    OrgFvHandle range: 0x%08x - 0x%08x\n",
> +    OrgFvHandle,
> +    OrgFvHandle + FvSize
> +    ));
> +
> +  for (Index = 0; Index < 
> PrivateData->PpiData.CallbackNotifyList.CurrentCount;
> Index++) {
> +      ConvertPointer (
> +        (VOID **) &PrivateData-
> >PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
> +        OrgFvHandle,
> +        OrgFvHandle + FvSize,
> +        Offset,
> +        OffsetPositive
> +        );
> +      ConvertPointer (
> +        (VOID **) &PrivateData-
> >PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
> +        OrgFvHandle,
> +        OrgFvHandle + FvSize,
> +        Offset,
> +        OffsetPositive
> +        );
> +      ConvertPointer (
> +        (VOID **) &PrivateData-
> >PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,
> +        OrgFvHandle,
> +        OrgFvHandle + FvSize,
> +        Offset,
> +        OffsetPositive
> +        );
> +  }
> +
> +  for (Index = 0; Index < 
> PrivateData->PpiData.DispatchNotifyList.CurrentCount;
> Index++) {
> +    ConvertPointer (
> +      (VOID **) 
> &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
> +      OrgFvHandle,
> +      OrgFvHandle + FvSize,
> +      Offset,
> +      OffsetPositive
> +      );
> +    ConvertPointer (
> +      (VOID **) &PrivateData-
> >PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
> +      OrgFvHandle,
> +      OrgFvHandle + FvSize,
> +      Offset,
> +      OffsetPositive
> +      );
> +    ConvertPointer (
> +      (VOID **) &PrivateData-
> >PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,
> +      OrgFvHandle,
> +      OrgFvHandle + FvSize,
> +      Offset,
> +      OffsetPositive
> +      );
> +  }
> +
> +  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; 
> Index++) {
> +    ConvertPointer (
> +      (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
> +      OrgFvHandle,
> +      OrgFvHandle + FvSize,
> +      Offset,
> +      OffsetPositive
> +      );
> +    ConvertPointer (
> +      (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
> +      OrgFvHandle,
> +      OrgFvHandle + FvSize,
> +      Offset,
> +      OffsetPositive
> +      );
> +    ConvertPointer (
> +      (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,
> +      OrgFvHandle,
> +      OrgFvHandle + FvSize,
> +      Offset,
> +      OffsetPositive
> +      );
> +
> +    Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;
> +    for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) 
> {
> +      //
> +      // Don't use CompareGuid function here for performance reasons.
> +      // Instead we compare the GUID as INT32 at a time and branch
> +      // on the first failed comparison.
> +      //
> +      if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&
> +          (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&
> +          (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&
> +          (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {
> +        FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;
> +        DEBUG ((DEBUG_VERBOSE, "      FvInfo: %p -> ", FvInfoPpi->FvInfo));
> +        if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {
> +          ConvertPointer (
> +            (VOID **)&FvInfoPpi->FvInfo,
> +            OrgFvHandle,
> +            OrgFvHandle + FvSize,
> +            Offset,
> +            OffsetPositive
> +            );
> +          DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));
> +        }
> +        DEBUG ((DEBUG_VERBOSE, "\n"));
> +        break;
> +      }
> +    }
> +  }
> +}
> +
> +/**
> +
> +  Dumps the PPI lists to debug output.
> +
> +  @param PrivateData     Points to PeiCore's private instance data.
> +
> +**/
> +VOID
> +DumpPpiList (
> +  IN PEI_CORE_INSTANCE    *PrivateData
> +  )
> +{
> +  DEBUG_CODE_BEGIN ();
> +  UINTN   Index;
> +
> +  if (PrivateData == NULL) {
> +    return;
> +  }
> +
> +  for (Index = 0; Index < 
> PrivateData->PpiData.CallbackNotifyList.CurrentCount;
> Index++) {
> +    DEBUG ((
> +      DEBUG_VERBOSE,
> +      "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
> +      Index,
> +      PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
> +      (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
> +      (
> +        !(
> +          ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData-
> >PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData-
> >PhysicalMemoryBegin) &&
> +          (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData-
> >PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof
> (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
> +          )
> +        ? "CAR" : "Post-Memory"
> +        )
> +      ));
> +  }
> +  for (Index = 0; Index < 
> PrivateData->PpiData.DispatchNotifyList.CurrentCount;
> Index++) {
> +    DEBUG ((DEBUG_VERBOSE,
> +    "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
> +    Index,
> +    PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
> +    (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
> +    (
> +      !(
> +        ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData-
> >PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData-
> >PhysicalMemoryBegin) &&
> +        (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData-
> >PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof
> (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
> +        )
> +      ? "CAR" : "Post-Memory"
> +      )
> +    ));
> +  }
> +  for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; 
> Index++) {
> +    DEBUG ((DEBUG_VERBOSE,
> +    "PPI[%2d] {%g} at 0x%x (%a)\n",
> +    Index,
> +    PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
> +    (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
> +    (
> +      !(
> +        ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData-
> >PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
> +        (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData-
> >PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) <
> PrivateData->FreePhysicalMemoryTop)
> +        )
> +      ? "CAR" : "Post-Memory"
> +      )
> +    ));
> +  }
> +  DEBUG_CODE_END ();
> +}
> +
>  /**
> 
>    This function installs an interface in the PEI PPI database by GUID.
> @@ -830,3 +1051,69 @@ ProcessPpiListFromSec (
>    }
>  }
> 
> +/**
> +
> +  Migrate PPI Pointers of PEI_CORE from temporary memory to permanent
> memory.
> +
> +  @param PrivateData      Pointer to PeiCore's private data structure.
> +  @param CoreFvHandle     Address of PEI_CORE FV Handle in temporary
> memory.
> +
> +**/
> +
> +VOID
> +ConvertPeiCorePpiPointers (
> +  IN  PEI_CORE_INSTANCE        *PrivateData,
> +  PEI_CORE_FV_HANDLE           CoreFvHandle
> +  )
> +{
> +  EFI_FV_FILE_INFO      FileInfo;
> +  EFI_PHYSICAL_ADDRESS  OrgImageBase;
> +  EFI_PHYSICAL_ADDRESS  MigratedImageBase;
> +  UINTN                 PeiCoreModuleSize;
> +  EFI_PEI_FILE_HANDLE   PeiCoreFileHandle;
> +  VOID                  *PeiCoreImageBase;
> +  VOID                  *PeiCoreEntryPoint;
> +  EFI_STATUS            Status;
> +
> +  PeiCoreFileHandle = NULL;
> +
> +  //
> +  // Find the PEI Core in the BFV in temporary memory.
> +  //
> +  Status =  CoreFvHandle.FvPpi->FindFileByType (
> +                                  CoreFvHandle.FvPpi,
> +                                  EFI_FV_FILETYPE_PEI_CORE,
> +                                  CoreFvHandle.FvHandle,
> +                                  &PeiCoreFileHandle
> +                                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  if (!EFI_ERROR (Status)) {
> +    Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi,
> PeiCoreFileHandle, &FileInfo);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    //
> +    // Find PEI Core EntryPoint in the BFV in temporary memory.
> +    //
> +    Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase,
> &PeiCoreEntryPoint);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    OrgImageBase = (UINTN) PeiCoreImageBase;
> +    MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN)
> PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);
> +
> +    //
> +    // Size of loaded PEI_CORE in permanent memory.
> +    //
> +    PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase -
> (UINTN) FileInfo.Buffer);
> +
> +    //
> +    // Migrate PEI_CORE PPI pointers from temporary memory to newly
> +    // installed PEI_CORE in permanent memory.
> +    //
> +    ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN)
> MigratedImageBase, PeiCoreModuleSize);
> +  }
> +}
> +
> --
> 2.25.1.windows.1
> 
> 
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#62392): https://edk2.groups.io/g/devel/message/62392
Mute This Topic: https://groups.io/mt/75390174/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub  [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to