]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Don't decompress the FV on S3 resume
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
index c13abe0aec637a822b83f6f799056df9a4b1cfb3..670ad8d763aab0dc3a5f8215ee57c96a3cf7c6dd 100644 (file)
-/** @file
-  Main SEC phase code.  Transitions to PEI.
-
-  Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
-
-  This program and the accompanying materials
-  are licensed and made available under the terms and conditions of the BSD License
-  which accompanies this distribution.  The full text of the license may be found at
-  http://opensource.org/licenses/bsd-license.php
-
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <PiPei.h>
-
-#include <Library/PeimEntryPoint.h>
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/PeiServicesLib.h>
-#include <Library/PcdLib.h>
-#include <Library/UefiCpuLib.h>
-#include <Library/DebugAgentLib.h>
-#include <Library/IoLib.h>
-#include <Library/PeCoffLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PeCoffExtraActionLib.h>
-#include <Library/ExtractGuidedSectionLib.h>
-
-#include <Ppi/TemporaryRamSupport.h>
-
-#define SEC_IDT_ENTRY_COUNT  34
-
-typedef struct _SEC_IDT_TABLE {
-  EFI_PEI_SERVICES          *PeiService;
-  IA32_IDT_GATE_DESCRIPTOR  IdtTable[SEC_IDT_ENTRY_COUNT];
-} SEC_IDT_TABLE;
-
-VOID
-EFIAPI
-SecStartupPhase2 (
-  IN VOID                     *Context
-  );
-
-EFI_STATUS
-EFIAPI
-TemporaryRamMigration (
-  IN CONST EFI_PEI_SERVICES   **PeiServices,
-  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
-  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
-  IN UINTN                    CopySize
-  );
-
-//
-//
-//  
-EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
-  TemporaryRamMigration
-};
-
-EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
-  {
-    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
-    &gEfiTemporaryRamSupportPpiGuid,
-    &mTemporaryRamSupportPpi
-  },
-};
-
-//
-// Template of an IDT entry pointing to 10:FFFFFFE4h.
-//
-IA32_IDT_GATE_DESCRIPTOR  mIdtEntryTemplate = {
-  {                                      // Bits
-    0xffe4,                              // OffsetLow
-    0x10,                                // Selector
-    0x0,                                 // Reserved_0
-    IA32_IDT_GATE_TYPE_INTERRUPT_32,     // GateType
-    0xffff                               // OffsetHigh
-  }    
-};
-
-/**
-  Locates the main boot firmware volume.
-
-  @param[in,out]  BootFv  On input, the base of the BootFv
-                          On output, the decompressed main firmware volume
-
-  @retval EFI_SUCCESS    The main firmware volume was located and decompressed
-  @retval EFI_NOT_FOUND  The main firmware volume was not found
-
-**/
-EFI_STATUS
-FindMainFv (
-  IN OUT  EFI_FIRMWARE_VOLUME_HEADER   **BootFv
-  )
-{
-  EFI_FIRMWARE_VOLUME_HEADER  *Fv;
-  UINTN                       Distance;
-  BOOLEAN                     Found;
-
-  ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);
-
-  Found = FALSE;
-  Fv = *BootFv;
-  Distance = (UINTN) (*BootFv)->FvLength;
-  do {
-    Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);
-    Distance += EFI_PAGE_SIZE;
-    if (Distance > SIZE_32MB) {
-      return EFI_NOT_FOUND;
-    }
-
-    if (Fv->Signature != EFI_FVH_SIGNATURE) {
-      continue;
-    }
-
-    if ((UINTN) Fv->FvLength > Distance) {
-      continue;
-    }
-
-    *BootFv = Fv;
-    return EFI_SUCCESS;
-
-  } while (TRUE);
-}
-
-/**
-  Locates a section within a series of sections
-  with the specified section type.
-
-  @param[in]   Sections        The sections to search
-  @param[in]   SizeOfSections  Total size of all sections
-  @param[in]   SectionType     The section type to locate
-  @param[out]  FoundSection    The FFS section if found
-
-  @retval EFI_SUCCESS           The file and section was found
-  @retval EFI_NOT_FOUND         The file and section was not found
-  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
-
-**/
-EFI_STATUS
-FindFfsSectionInSections (
-  IN  VOID                             *Sections,
-  IN  UINTN                            SizeOfSections,
-  IN  EFI_SECTION_TYPE                 SectionType,
-  OUT EFI_COMMON_SECTION_HEADER        **FoundSection
-  )
-{
-  EFI_PHYSICAL_ADDRESS        CurrentAddress;
-  UINT32                      Size;
-  EFI_PHYSICAL_ADDRESS        EndOfSections;
-  EFI_COMMON_SECTION_HEADER   *Section;
-  EFI_PHYSICAL_ADDRESS        EndOfSection;
-
-  //
-  // Loop through the FFS file sections within the PEI Core FFS file
-  //
-  EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;
-  EndOfSections = EndOfSection + SizeOfSections;
-  for (;;) {
-    if (EndOfSection == EndOfSections) {
-      break;
-    }
-    CurrentAddress = (EndOfSection + 3) & ~(3ULL);
-    if (CurrentAddress >= EndOfSections) {
-      return EFI_VOLUME_CORRUPTED;
-    }
-
-    Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
-    DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type));
-
-    Size = SECTION_SIZE (Section);
-    if (Size < sizeof (*Section)) {
-      return EFI_VOLUME_CORRUPTED;
-    }
-
-    EndOfSection = CurrentAddress + Size;
-    if (EndOfSection > EndOfSections) {
-      return EFI_VOLUME_CORRUPTED;
-    }
-
-    //
-    // Look for the requested section type
-    //
-    if (Section->Type == SectionType) {
-      *FoundSection = Section;
-      return EFI_SUCCESS;
-    }
-    DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));
-  }
-
-  return EFI_NOT_FOUND;
-}
-
-/**
-  Locates a FFS file with the specified file type and a section
-  within that file with the specified section type.
-
-  @param[in]   Fv            The firmware volume to search
-  @param[in]   FileType      The file type to locate
-  @param[in]   SectionType   The section type to locate
-  @param[out]  FoundSection  The FFS section if found
-
-  @retval EFI_SUCCESS           The file and section was found
-  @retval EFI_NOT_FOUND         The file and section was not found
-  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
-
-**/
-EFI_STATUS
-EFIAPI
-FindFfsFileAndSection (
-  IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,
-  IN  EFI_FV_FILETYPE                  FileType,
-  IN  EFI_SECTION_TYPE                 SectionType,
-  OUT EFI_COMMON_SECTION_HEADER        **FoundSection
-  )
-{
-  EFI_STATUS                  Status;
-  EFI_PHYSICAL_ADDRESS        CurrentAddress;
-  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;
-  EFI_FFS_FILE_HEADER         *File;
-  UINT32                      Size;
-  EFI_PHYSICAL_ADDRESS        EndOfFile;
-
-  if (Fv->Signature != EFI_FVH_SIGNATURE) {
-    DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv));
-    return EFI_VOLUME_CORRUPTED;
-  }
-
-  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;
-  EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
-
-  //
-  // Loop through the FFS files in the Boot Firmware Volume
-  //
-  for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
-
-    CurrentAddress = (EndOfFile + 7) & ~(7ULL);
-    if (CurrentAddress > EndOfFirmwareVolume) {
-      return EFI_VOLUME_CORRUPTED;
-    }
-
-    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
-    Size = *(UINT32*) File->Size & 0xffffff;
-    if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
-      return EFI_VOLUME_CORRUPTED;
-    }
-    DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type));
-
-    EndOfFile = CurrentAddress + Size;
-    if (EndOfFile > EndOfFirmwareVolume) {
-      return EFI_VOLUME_CORRUPTED;
-    }
-
-    //
-    // Look for the request file type
-    //
-    if (File->Type != FileType) {
-      DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));
-      continue;
-    }
-
-    Status = FindFfsSectionInSections (
-               (VOID*) (File + 1),
-               (UINTN) EndOfFile - (UINTN) (File + 1),
-               SectionType,
-               FoundSection
-               );
-    if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
-      return Status;
-    }
-  }
-}
-
-/**
-  Locates the compressed main firmware volume and decompresses it.
-
-  @param[in,out]  Fv            On input, the firmware volume to search
-                                On output, the decompressed main FV
-
-  @retval EFI_SUCCESS           The file and section was found
-  @retval EFI_NOT_FOUND         The file and section was not found
-  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
-
-**/
-EFI_STATUS
-EFIAPI
-DecompressGuidedFv (
-  IN OUT EFI_FIRMWARE_VOLUME_HEADER       **Fv
-  )
-{
-  EFI_STATUS                        Status;
-  EFI_GUID_DEFINED_SECTION          *Section;
-  UINT32                            OutputBufferSize;
-  UINT32                            ScratchBufferSize;
-  UINT16                            SectionAttribute;
-  UINT32                            AuthenticationStatus;
-  VOID                              *OutputBuffer;
-  VOID                              *ScratchBuffer;
-  EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;
-  EFI_FIRMWARE_VOLUME_HEADER        *NewFv;
-
-  NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;
-
-  Status = FindFfsFileAndSection (
-             *Fv,
-             EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
-             EFI_SECTION_GUID_DEFINED,
-             (EFI_COMMON_SECTION_HEADER**) &Section
-             );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));
-    return Status;
-  }
-
-  Status = ExtractGuidedSectionGetInfo (
-             Section,
-             &OutputBufferSize,
-             &ScratchBufferSize,
-             &SectionAttribute
-             );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));
-    return Status;
-  }
-
-  //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)
-  OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);
-  ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
-  Status = ExtractGuidedSectionDecode (
-             Section,
-             &OutputBuffer,
-             ScratchBuffer,
-             &AuthenticationStatus
-             );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));
-    return Status;
-  }
-
-  Status = FindFfsSectionInSections (
-             OutputBuffer,
-             OutputBufferSize,
-             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
-             (EFI_COMMON_SECTION_HEADER**) &NewFvSection
-             );
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));
-    return Status;
-  }
-
-  NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);
-  CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));
-
-  if (NewFv->Signature != EFI_FVH_SIGNATURE) {
-    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));
-    CpuDeadLoop ();
-    return EFI_VOLUME_CORRUPTED;
-  }
-
-  *Fv = NewFv;
-  return EFI_SUCCESS;
-}
-
-/**
-  Locates the PEI Core entry point address
-
-  @param[in]  Fv                 The firmware volume to search
-  @param[out] PeiCoreEntryPoint  The entry point of the PEI Core image
-
-  @retval EFI_SUCCESS           The file and section was found
-  @retval EFI_NOT_FOUND         The file and section was not found
-  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
-
-**/
-EFI_STATUS
-EFIAPI
-FindPeiCoreImageBaseInFv (
-  IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,
-  OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase
-  )
-{
-  EFI_STATUS                  Status;
-  EFI_COMMON_SECTION_HEADER   *Section;
-
-  Status = FindFfsFileAndSection (
-             Fv,
-             EFI_FV_FILETYPE_PEI_CORE,
-             EFI_SECTION_PE32,
-             &Section
-             );
-  if (EFI_ERROR (Status)) {
-    Status = FindFfsFileAndSection (
-               Fv,
-               EFI_FV_FILETYPE_PEI_CORE,
-               EFI_SECTION_TE,
-               &Section
-               );
-    if (EFI_ERROR (Status)) {
-      DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));
-      return Status;
-    }
-  }
-
-  *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
-  return EFI_SUCCESS;
-}
-
-/**
-  Locates the PEI Core entry point address
-
-  @param[in,out]  Fv                 The firmware volume to search
-  @param[out]     PeiCoreEntryPoint  The entry point of the PEI Core image
-
-  @retval EFI_SUCCESS           The file and section was found
-  @retval EFI_NOT_FOUND         The file and section was not found
-  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
-
-**/
-VOID
-EFIAPI
-FindPeiCoreImageBase (
-  IN OUT  EFI_FIRMWARE_VOLUME_HEADER       **BootFv,
-     OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase
-  )
-{
-  *PeiCoreImageBase = 0;
-
-  FindMainFv (BootFv);
-
-  DecompressGuidedFv (BootFv);
-
-  FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
-}
-
-/**
-  Find core image base.
-
-**/
-EFI_STATUS
-EFIAPI
-FindImageBase (
-  IN  EFI_FIRMWARE_VOLUME_HEADER       *BootFirmwareVolumePtr,
-  OUT EFI_PHYSICAL_ADDRESS             *SecCoreImageBase
-  )
-{
-  EFI_PHYSICAL_ADDRESS        CurrentAddress;
-  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;
-  EFI_FFS_FILE_HEADER         *File;
-  UINT32                      Size;
-  EFI_PHYSICAL_ADDRESS        EndOfFile;
-  EFI_COMMON_SECTION_HEADER   *Section;
-  EFI_PHYSICAL_ADDRESS        EndOfSection;
-
-  *SecCoreImageBase = 0;
-
-  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
-  EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
-
-  //
-  // Loop through the FFS files in the Boot Firmware Volume
-  //
-  for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
-
-    CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
-    if (CurrentAddress > EndOfFirmwareVolume) {
-      return EFI_NOT_FOUND;
-    }
-
-    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
-    Size = *(UINT32*) File->Size & 0xffffff;
-    if (Size < sizeof (*File)) {
-      return EFI_NOT_FOUND;
-    }
-
-    EndOfFile = CurrentAddress + Size;
-    if (EndOfFile > EndOfFirmwareVolume) {
-      return EFI_NOT_FOUND;
-    }
-
-    //
-    // Look for SEC Core
-    //
-    if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
-      continue;
-    }
-
-    //
-    // Loop through the FFS file sections within the FFS file
-    //
-    EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);
-    for (;;) {
-      CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
-      Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
-
-      Size = *(UINT32*) Section->Size & 0xffffff;
-      if (Size < sizeof (*Section)) {
-        return EFI_NOT_FOUND;
-      }
-
-      EndOfSection = CurrentAddress + Size;
-      if (EndOfSection > EndOfFile) {
-        return EFI_NOT_FOUND;
-      }
-
-      //
-      // Look for executable sections
-      //
-      if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
-        if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
-          *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);
-        }
-        break;
-      }
-    }
-
-    //
-    // SEC Core image found
-    //
-    if (*SecCoreImageBase != 0) {
-      return EFI_SUCCESS;
-    }
-  }
-}
-
-/*
-  Find and return Pei Core entry point.
-
-  It also find SEC and PEI Core file debug inforamtion. It will report them if
-  remote debug is enabled.
-
-**/
-VOID
-EFIAPI
-FindAndReportEntryPoints (
-  IN  EFI_FIRMWARE_VOLUME_HEADER       **BootFirmwareVolumePtr,
-  OUT EFI_PEI_CORE_ENTRY_POINT         *PeiCoreEntryPoint
-  )
-{
-  EFI_STATUS                       Status;
-  EFI_PHYSICAL_ADDRESS             SecCoreImageBase;
-  EFI_PHYSICAL_ADDRESS             PeiCoreImageBase;
-  PE_COFF_LOADER_IMAGE_CONTEXT     ImageContext;
-
-  //
-  // Find SEC Core and PEI Core image base
-   //
-  Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
-  ASSERT_EFI_ERROR (Status);
-
-  FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
-  
-  ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
-  //
-  // Report SEC Core debug information when remote debug is enabled
-  //
-  ImageContext.ImageAddress = SecCoreImageBase;
-  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
-
-  //
-  // Report PEI Core debug information when remote debug is enabled
-  //
-  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
-  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
-  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
-
-  //
-  // Find PEI Core entry point
-  //
-  Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
-  if (EFI_ERROR (Status)) {
-    *PeiCoreEntryPoint = 0;
-  }
-
-  return;
-}
-
-VOID
-EFIAPI
-SecCoreStartupWithStack (
-  IN EFI_FIRMWARE_VOLUME_HEADER       *BootFv,
-  IN VOID                             *TopOfCurrentStack
-  )
-{
-  EFI_SEC_PEI_HAND_OFF        SecCoreData;
-  SEC_IDT_TABLE               IdtTableInStack;
-  IA32_DESCRIPTOR             IdtDescriptor;
-  UINT32                      Index;
-
-  ProcessLibraryConstructorList (NULL, NULL);
-
-  DEBUG ((EFI_D_ERROR,
-    "SecCoreStartupWithStack(0x%x, 0x%x)\n",
-    (UINT32)(UINTN)BootFv,
-    (UINT32)(UINTN)TopOfCurrentStack
-    ));
-
-  //
-  // Initialize floating point operating environment
-  // to be compliant with UEFI spec.
-  //
-  InitializeFloatingPointUnits ();
-
-  //
-  // Initialize IDT
-  //  
-  IdtTableInStack.PeiService = NULL;
-  for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
-    CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
-  }
-
-  IdtDescriptor.Base  = (UINTN)&IdtTableInStack.IdtTable;
-  IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
-
-  AsmWriteIdtr (&IdtDescriptor);
-
-  //
-  // |-------------|       <-- TopOfCurrentStack
-  // |   Stack     | 32k
-  // |-------------|
-  // |    Heap     | 32k
-  // |-------------|       <-- SecCoreData.TemporaryRamBase
-  //
-
-  //
-  // Initialize SEC hand-off state
-  //
-  SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
-
-  SecCoreData.TemporaryRamSize       = SIZE_64KB;
-  SecCoreData.TemporaryRamBase       = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
-
-  SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;
-  SecCoreData.PeiTemporaryRamSize    = SecCoreData.TemporaryRamSize >> 1;
-
-  SecCoreData.StackBase              = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
-  SecCoreData.StackSize              = SecCoreData.TemporaryRamSize >> 1;
-
-  SecCoreData.BootFirmwareVolumeBase = BootFv;
-  SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
-
-  //
-  // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
-  //
-  IoWrite8 (0x21, 0xff);
-  IoWrite8 (0xA1, 0xff);
-  
-  //
-  // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
-  //
-  InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
-}
-  
-/**
-  Caller provided function to be invoked at the end of InitializeDebugAgent().
-
-  Entry point to the C language phase of SEC. After the SEC assembly
-  code has initialized some temporary memory and set up the stack,
-  the control is transferred to this function.
-
-  @param[in] Context    The first input parameter of InitializeDebugAgent().
-
-**/
-VOID
-EFIAPI
-SecStartupPhase2(
-  IN VOID                     *Context
-  )
-{
-  EFI_SEC_PEI_HAND_OFF        *SecCoreData;
-  EFI_FIRMWARE_VOLUME_HEADER  *BootFv;
-  EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;
-  
-  SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
-  
-  //
-  // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
-  // is enabled.
-  //
-  BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
-  FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
-  SecCoreData->BootFirmwareVolumeBase = BootFv;
-  SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
-
-  //
-  // Transfer the control to the PEI core
-  //
-  (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
-  
-  //
-  // If we get here then the PEI Core returned, which is not recoverable.
-  //
-  ASSERT (FALSE);
-  CpuDeadLoop ();
-}
-
-EFI_STATUS
-EFIAPI
-TemporaryRamMigration (
-  IN CONST EFI_PEI_SERVICES   **PeiServices,
-  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
-  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
-  IN UINTN                    CopySize
-  )
-{
-  IA32_DESCRIPTOR                  IdtDescriptor;
-  VOID                             *OldHeap;
-  VOID                             *NewHeap;
-  VOID                             *OldStack;
-  VOID                             *NewStack;
-  DEBUG_AGENT_CONTEXT_POSTMEM_SEC  DebugAgentContext;
-  BOOLEAN                          OldStatus;
-  BASE_LIBRARY_JUMP_BUFFER         JumpBuffer;
-  
-  DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize));
-  
-  OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
-  NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
-  
-  OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
-  NewStack = (VOID*)(UINTN)PermanentMemoryBase;
-
-  DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
-  DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
-  
-  OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
-  InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
-
-  //
-  // Migrate Heap
-  //
-  CopyMem (NewHeap, OldHeap, CopySize >> 1);
-
-  //
-  // Migrate Stack
-  //
-  CopyMem (NewStack, OldStack, CopySize >> 1);
-  
-  //
-  // Rebase IDT table in permanent memory
-  //
-  AsmReadIdtr (&IdtDescriptor);
-  IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
-
-  AsmWriteIdtr (&IdtDescriptor);
-
-  //
-  // Use SetJump()/LongJump() to switch to a new stack.
-  // 
-  if (SetJump (&JumpBuffer) == 0) {
-#if defined (MDE_CPU_IA32)
-    JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
-#endif    
-#if defined (MDE_CPU_X64)
-    JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
-#endif    
-    LongJump (&JumpBuffer, (UINTN)-1);
-  }
-
-  SaveAndSetDebugTimerInterrupt (OldStatus);
-
-  return EFI_SUCCESS;
-}
-
+/** @file\r
+  Main SEC phase code.  Transitions to PEI.\r
+\r
+  Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
+\r
+  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
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+\r
+#include <Library/PeimEntryPoint.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/PeiServicesLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/UefiCpuLib.h>\r
+#include <Library/DebugAgentLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PeCoffLib.h>\r
+#include <Library/PeCoffGetEntryPointLib.h>\r
+#include <Library/PeCoffExtraActionLib.h>\r
+#include <Library/ExtractGuidedSectionLib.h>\r
+\r
+#include <Ppi/TemporaryRamSupport.h>\r
+\r
+#define SEC_IDT_ENTRY_COUNT  34\r
+\r
+typedef struct _SEC_IDT_TABLE {\r
+  EFI_PEI_SERVICES          *PeiService;\r
+  IA32_IDT_GATE_DESCRIPTOR  IdtTable[SEC_IDT_ENTRY_COUNT];\r
+} SEC_IDT_TABLE;\r
+\r
+VOID\r
+EFIAPI\r
+SecStartupPhase2 (\r
+  IN VOID                     *Context\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TemporaryRamMigration (\r
+  IN CONST EFI_PEI_SERVICES   **PeiServices,\r
+  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,\r
+  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,\r
+  IN UINTN                    CopySize\r
+  );\r
+\r
+//\r
+//\r
+//  \r
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {\r
+  TemporaryRamMigration\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {\r
+  {\r
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+    &gEfiTemporaryRamSupportPpiGuid,\r
+    &mTemporaryRamSupportPpi\r
+  },\r
+};\r
+\r
+//\r
+// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
+//\r
+IA32_IDT_GATE_DESCRIPTOR  mIdtEntryTemplate = {\r
+  {                                      // Bits\r
+    0xffe4,                              // OffsetLow\r
+    0x10,                                // Selector\r
+    0x0,                                 // Reserved_0\r
+    IA32_IDT_GATE_TYPE_INTERRUPT_32,     // GateType\r
+    0xffff                               // OffsetHigh\r
+  }    \r
+};\r
+\r
+/**\r
+  Locates the main boot firmware volume.\r
+\r
+  @param[in,out]  BootFv  On input, the base of the BootFv\r
+                          On output, the decompressed main firmware volume\r
+\r
+  @retval EFI_SUCCESS    The main firmware volume was located and decompressed\r
+  @retval EFI_NOT_FOUND  The main firmware volume was not found\r
+\r
+**/\r
+EFI_STATUS\r
+FindMainFv (\r
+  IN OUT  EFI_FIRMWARE_VOLUME_HEADER   **BootFv\r
+  )\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER  *Fv;\r
+  UINTN                       Distance;\r
+\r
+  ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);\r
+\r
+  Fv = *BootFv;\r
+  Distance = (UINTN) (*BootFv)->FvLength;\r
+  do {\r
+    Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);\r
+    Distance += EFI_PAGE_SIZE;\r
+    if (Distance > SIZE_32MB) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
+      continue;\r
+    }\r
+\r
+    if ((UINTN) Fv->FvLength > Distance) {\r
+      continue;\r
+    }\r
+\r
+    *BootFv = Fv;\r
+    return EFI_SUCCESS;\r
+\r
+  } while (TRUE);\r
+}\r
+\r
+/**\r
+  Locates a section within a series of sections\r
+  with the specified section type.\r
+\r
+  The Instance parameter indicates which instance of the section\r
+  type to return. (0 is first instance, 1 is second...)\r
+\r
+  @param[in]   Sections        The sections to search\r
+  @param[in]   SizeOfSections  Total size of all sections\r
+  @param[in]   SectionType     The section type to locate\r
+  @param[in]   Instance        The section instance number\r
+  @param[out]  FoundSection    The FFS section if found\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+EFI_STATUS\r
+FindFfsSectionInstance (\r
+  IN  VOID                             *Sections,\r
+  IN  UINTN                            SizeOfSections,\r
+  IN  EFI_SECTION_TYPE                 SectionType,\r
+  IN  UINTN                            Instance,\r
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS        CurrentAddress;\r
+  UINT32                      Size;\r
+  EFI_PHYSICAL_ADDRESS        EndOfSections;\r
+  EFI_COMMON_SECTION_HEADER   *Section;\r
+  EFI_PHYSICAL_ADDRESS        EndOfSection;\r
+\r
+  //\r
+  // Loop through the FFS file sections within the PEI Core FFS file\r
+  //\r
+  EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;\r
+  EndOfSections = EndOfSection + SizeOfSections;\r
+  for (;;) {\r
+    if (EndOfSection == EndOfSections) {\r
+      break;\r
+    }\r
+    CurrentAddress = (EndOfSection + 3) & ~(3ULL);\r
+    if (CurrentAddress >= EndOfSections) {\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
+\r
+    Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
+\r
+    Size = SECTION_SIZE (Section);\r
+    if (Size < sizeof (*Section)) {\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
+\r
+    EndOfSection = CurrentAddress + Size;\r
+    if (EndOfSection > EndOfSections) {\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
+\r
+    //\r
+    // Look for the requested section type\r
+    //\r
+    if (Section->Type == SectionType) {\r
+      if (Instance == 0) {\r
+        *FoundSection = Section;\r
+        return EFI_SUCCESS;\r
+      } else {\r
+        Instance--;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  Locates a section within a series of sections\r
+  with the specified section type.\r
+\r
+  @param[in]   Sections        The sections to search\r
+  @param[in]   SizeOfSections  Total size of all sections\r
+  @param[in]   SectionType     The section type to locate\r
+  @param[out]  FoundSection    The FFS section if found\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+EFI_STATUS\r
+FindFfsSectionInSections (\r
+  IN  VOID                             *Sections,\r
+  IN  UINTN                            SizeOfSections,\r
+  IN  EFI_SECTION_TYPE                 SectionType,\r
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection\r
+  )\r
+{\r
+  return FindFfsSectionInstance (\r
+           Sections,\r
+           SizeOfSections,\r
+           SectionType,\r
+           0,\r
+           FoundSection\r
+           );\r
+}\r
+\r
+/**\r
+  Locates a FFS file with the specified file type and a section\r
+  within that file with the specified section type.\r
+\r
+  @param[in]   Fv            The firmware volume to search\r
+  @param[in]   FileType      The file type to locate\r
+  @param[in]   SectionType   The section type to locate\r
+  @param[out]  FoundSection  The FFS section if found\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+EFI_STATUS\r
+FindFfsFileAndSection (\r
+  IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,\r
+  IN  EFI_FV_FILETYPE                  FileType,\r
+  IN  EFI_SECTION_TYPE                 SectionType,\r
+  OUT EFI_COMMON_SECTION_HEADER        **FoundSection\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_PHYSICAL_ADDRESS        CurrentAddress;\r
+  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;\r
+  EFI_FFS_FILE_HEADER         *File;\r
+  UINT32                      Size;\r
+  EFI_PHYSICAL_ADDRESS        EndOfFile;\r
+\r
+  if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
+    DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
+\r
+  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;\r
+  EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
+\r
+  //\r
+  // Loop through the FFS files in the Boot Firmware Volume\r
+  //\r
+  for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
+\r
+    CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
+    if (CurrentAddress > EndOfFirmwareVolume) {\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
+\r
+    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
+    Size = *(UINT32*) File->Size & 0xffffff;\r
+    if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
+\r
+    EndOfFile = CurrentAddress + Size;\r
+    if (EndOfFile > EndOfFirmwareVolume) {\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
+\r
+    //\r
+    // Look for the request file type\r
+    //\r
+    if (File->Type != FileType) {\r
+      continue;\r
+    }\r
+\r
+    Status = FindFfsSectionInSections (\r
+               (VOID*) (File + 1),\r
+               (UINTN) EndOfFile - (UINTN) (File + 1),\r
+               SectionType,\r
+               FoundSection\r
+               );\r
+    if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
+      return Status;\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Locates the compressed main firmware volume and decompresses it.\r
+\r
+  @param[in,out]  Fv            On input, the firmware volume to search\r
+                                On output, the decompressed BOOT/PEI FV\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+EFI_STATUS\r
+DecompressMemFvs (\r
+  IN OUT EFI_FIRMWARE_VOLUME_HEADER       **Fv\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  EFI_GUID_DEFINED_SECTION          *Section;\r
+  UINT32                            OutputBufferSize;\r
+  UINT32                            ScratchBufferSize;\r
+  UINT16                            SectionAttribute;\r
+  UINT32                            AuthenticationStatus;\r
+  VOID                              *OutputBuffer;\r
+  VOID                              *ScratchBuffer;\r
+  EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FvSection;\r
+  EFI_FIRMWARE_VOLUME_HEADER        *PeiMemFv;\r
+  EFI_FIRMWARE_VOLUME_HEADER        *DxeMemFv;\r
+\r
+  FvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
+\r
+  Status = FindFfsFileAndSection (\r
+             *Fv,\r
+             EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
+             EFI_SECTION_GUID_DEFINED,\r
+             (EFI_COMMON_SECTION_HEADER**) &Section\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
+    return Status;\r
+  }\r
+\r
+  Status = ExtractGuidedSectionGetInfo (\r
+             Section,\r
+             &OutputBufferSize,\r
+             &ScratchBufferSize,\r
+             &SectionAttribute\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
+    return Status;\r
+  }\r
+\r
+  OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);\r
+  ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
+  Status = ExtractGuidedSectionDecode (\r
+             Section,\r
+             &OutputBuffer,\r
+             ScratchBuffer,\r
+             &AuthenticationStatus\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));\r
+    return Status;\r
+  }\r
+\r
+  Status = FindFfsSectionInstance (\r
+             OutputBuffer,\r
+             OutputBufferSize,\r
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+             0,\r
+             (EFI_COMMON_SECTION_HEADER**) &FvSection\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));\r
+    return Status;\r
+  }\r
+\r
+  ASSERT (SECTION_SIZE (FvSection) ==\r
+          (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection)));\r
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
+\r
+  PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
+  CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));\r
+\r
+  if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {\r
+    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));\r
+    CpuDeadLoop ();\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
+\r
+  Status = FindFfsSectionInstance (\r
+             OutputBuffer,\r
+             OutputBufferSize,\r
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
+             1,\r
+             (EFI_COMMON_SECTION_HEADER**) &FvSection\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));\r
+    return Status;\r
+  }\r
+\r
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
+  ASSERT (SECTION_SIZE (FvSection) ==\r
+          (PcdGet32 (PcdOvmfDxeMemFvSize) + sizeof (*FvSection)));\r
+\r
+  DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase);\r
+  CopyMem (DxeMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfDxeMemFvSize));\r
+\r
+  if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {\r
+    DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));\r
+    CpuDeadLoop ();\r
+    return EFI_VOLUME_CORRUPTED;\r
+  }\r
+\r
+  *Fv = PeiMemFv;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Locates the PEI Core entry point address\r
+\r
+  @param[in]  Fv                 The firmware volume to search\r
+  @param[out] PeiCoreEntryPoint  The entry point of the PEI Core image\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+EFI_STATUS\r
+FindPeiCoreImageBaseInFv (\r
+  IN  EFI_FIRMWARE_VOLUME_HEADER       *Fv,\r
+  OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  EFI_COMMON_SECTION_HEADER   *Section;\r
+\r
+  Status = FindFfsFileAndSection (\r
+             Fv,\r
+             EFI_FV_FILETYPE_PEI_CORE,\r
+             EFI_SECTION_PE32,\r
+             &Section\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    Status = FindFfsFileAndSection (\r
+               Fv,\r
+               EFI_FV_FILETYPE_PEI_CORE,\r
+               EFI_SECTION_TE,\r
+               &Section\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Reads 8-bits of CMOS data.\r
+\r
+  Reads the 8-bits of CMOS data at the location specified by Index.\r
+  The 8-bit read value is returned.\r
+\r
+  @param  Index  The CMOS location to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+STATIC\r
+UINT8\r
+CmosRead8 (\r
+  IN      UINTN                     Index\r
+  )\r
+{\r
+  IoWrite8 (0x70, (UINT8) Index);\r
+  return IoRead8 (0x71);\r
+}\r
+\r
+\r
+STATIC\r
+BOOLEAN\r
+IsS3Resume (\r
+  VOID\r
+  )\r
+{\r
+  return (CmosRead8 (0xF) == 0xFE);\r
+}\r
+\r
+\r
+STATIC\r
+EFI_STATUS\r
+GetS3ResumePeiFv (\r
+  IN OUT EFI_FIRMWARE_VOLUME_HEADER       **PeiFv\r
+  )\r
+{\r
+  *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Locates the PEI Core entry point address\r
+\r
+  @param[in,out]  Fv                 The firmware volume to search\r
+  @param[out]     PeiCoreEntryPoint  The entry point of the PEI Core image\r
+\r
+  @retval EFI_SUCCESS           The file and section was found\r
+  @retval EFI_NOT_FOUND         The file and section was not found\r
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted\r
+\r
+**/\r
+VOID\r
+FindPeiCoreImageBase (\r
+  IN OUT  EFI_FIRMWARE_VOLUME_HEADER       **BootFv,\r
+     OUT  EFI_PHYSICAL_ADDRESS             *PeiCoreImageBase\r
+  )\r
+{\r
+  *PeiCoreImageBase = 0;\r
+\r
+  if (IsS3Resume ()) {\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));\r
+    GetS3ResumePeiFv (BootFv);\r
+  } else {\r
+    DEBUG ((EFI_D_VERBOSE, "SEC: Normal boot\n"));\r
+    FindMainFv (BootFv);\r
+\r
+    DecompressMemFvs (BootFv);\r
+  }\r
+\r
+  FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
+}\r
+\r
+/**\r
+  Find core image base.\r
+\r
+**/\r
+EFI_STATUS\r
+FindImageBase (\r
+  IN  EFI_FIRMWARE_VOLUME_HEADER       *BootFirmwareVolumePtr,\r
+  OUT EFI_PHYSICAL_ADDRESS             *SecCoreImageBase\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS        CurrentAddress;\r
+  EFI_PHYSICAL_ADDRESS        EndOfFirmwareVolume;\r
+  EFI_FFS_FILE_HEADER         *File;\r
+  UINT32                      Size;\r
+  EFI_PHYSICAL_ADDRESS        EndOfFile;\r
+  EFI_COMMON_SECTION_HEADER   *Section;\r
+  EFI_PHYSICAL_ADDRESS        EndOfSection;\r
+\r
+  *SecCoreImageBase = 0;\r
+\r
+  CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
+  EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
+\r
+  //\r
+  // Loop through the FFS files in the Boot Firmware Volume\r
+  //\r
+  for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
+\r
+    CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
+    if (CurrentAddress > EndOfFirmwareVolume) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
+    Size = *(UINT32*) File->Size & 0xffffff;\r
+    if (Size < sizeof (*File)) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    EndOfFile = CurrentAddress + Size;\r
+    if (EndOfFile > EndOfFirmwareVolume) {\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    //\r
+    // Look for SEC Core\r
+    //\r
+    if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Loop through the FFS file sections within the FFS file\r
+    //\r
+    EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
+    for (;;) {\r
+      CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
+      Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
+\r
+      Size = *(UINT32*) Section->Size & 0xffffff;\r
+      if (Size < sizeof (*Section)) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      EndOfSection = CurrentAddress + Size;\r
+      if (EndOfSection > EndOfFile) {\r
+        return EFI_NOT_FOUND;\r
+      }\r
+\r
+      //\r
+      // Look for executable sections\r
+      //\r
+      if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
+        if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
+          *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
+        }\r
+        break;\r
+      }\r
+    }\r
+\r
+    //\r
+    // SEC Core image found\r
+    //\r
+    if (*SecCoreImageBase != 0) {\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+}\r
+\r
+/*\r
+  Find and return Pei Core entry point.\r
+\r
+  It also find SEC and PEI Core file debug inforamtion. It will report them if\r
+  remote debug is enabled.\r
+\r
+**/\r
+VOID\r
+FindAndReportEntryPoints (\r
+  IN  EFI_FIRMWARE_VOLUME_HEADER       **BootFirmwareVolumePtr,\r
+  OUT EFI_PEI_CORE_ENTRY_POINT         *PeiCoreEntryPoint\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  EFI_PHYSICAL_ADDRESS             SecCoreImageBase;\r
+  EFI_PHYSICAL_ADDRESS             PeiCoreImageBase;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT     ImageContext;\r
+\r
+  //\r
+  // Find SEC Core and PEI Core image base\r
+   //\r
+  Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
+  \r
+  ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
+  //\r
+  // Report SEC Core debug information when remote debug is enabled\r
+  //\r
+  ImageContext.ImageAddress = SecCoreImageBase;\r
+  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+\r
+  //\r
+  // Report PEI Core debug information when remote debug is enabled\r
+  //\r
+  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
+  ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
+\r
+  //\r
+  // Find PEI Core entry point\r
+  //\r
+  Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
+  if (EFI_ERROR (Status)) {\r
+    *PeiCoreEntryPoint = 0;\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+VOID\r
+EFIAPI\r
+SecCoreStartupWithStack (\r
+  IN EFI_FIRMWARE_VOLUME_HEADER       *BootFv,\r
+  IN VOID                             *TopOfCurrentStack\r
+  )\r
+{\r
+  EFI_SEC_PEI_HAND_OFF        SecCoreData;\r
+  SEC_IDT_TABLE               IdtTableInStack;\r
+  IA32_DESCRIPTOR             IdtDescriptor;\r
+  UINT32                      Index;\r
+\r
+  ProcessLibraryConstructorList (NULL, NULL);\r
+\r
+  DEBUG ((EFI_D_INFO,\r
+    "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
+    (UINT32)(UINTN)BootFv,\r
+    (UINT32)(UINTN)TopOfCurrentStack\r
+    ));\r
+\r
+  //\r
+  // Initialize floating point operating environment\r
+  // to be compliant with UEFI spec.\r
+  //\r
+  InitializeFloatingPointUnits ();\r
+\r
+  //\r
+  // Initialize IDT\r
+  //  \r
+  IdtTableInStack.PeiService = NULL;\r
+  for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
+    CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
+  }\r
+\r
+  IdtDescriptor.Base  = (UINTN)&IdtTableInStack.IdtTable;\r
+  IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
+\r
+  AsmWriteIdtr (&IdtDescriptor);\r
+\r
+#if defined (MDE_CPU_X64)\r
+  //\r
+  // ASSERT that the Page Tables were set by the reset vector code to\r
+  // the address we expect.\r
+  //\r
+  ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
+#endif\r
+\r
+  //\r
+  // |-------------|       <-- TopOfCurrentStack\r
+  // |   Stack     | 32k\r
+  // |-------------|\r
+  // |    Heap     | 32k\r
+  // |-------------|       <-- SecCoreData.TemporaryRamBase\r
+  //\r
+\r
+  ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
+                   PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
+          (UINTN) TopOfCurrentStack);\r
+\r
+  //\r
+  // Initialize SEC hand-off state\r
+  //\r
+  SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
+\r
+  SecCoreData.TemporaryRamSize       = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
+  SecCoreData.TemporaryRamBase       = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
+\r
+  SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;\r
+  SecCoreData.PeiTemporaryRamSize    = SecCoreData.TemporaryRamSize >> 1;\r
+\r
+  SecCoreData.StackBase              = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
+  SecCoreData.StackSize              = SecCoreData.TemporaryRamSize >> 1;\r
+\r
+  SecCoreData.BootFirmwareVolumeBase = BootFv;\r
+  SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
+\r
+  //\r
+  // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
+  //\r
+  IoWrite8 (0x21, 0xff);\r
+  IoWrite8 (0xA1, 0xff);\r
+  \r
+  //\r
+  // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
+  //\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
+}\r
+  \r
+/**\r
+  Caller provided function to be invoked at the end of InitializeDebugAgent().\r
+\r
+  Entry point to the C language phase of SEC. After the SEC assembly\r
+  code has initialized some temporary memory and set up the stack,\r
+  the control is transferred to this function.\r
+\r
+  @param[in] Context    The first input parameter of InitializeDebugAgent().\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecStartupPhase2(\r
+  IN VOID                     *Context\r
+  )\r
+{\r
+  EFI_SEC_PEI_HAND_OFF        *SecCoreData;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *BootFv;\r
+  EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;\r
+  \r
+  SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
+  \r
+  //\r
+  // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
+  // is enabled.\r
+  //\r
+  BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
+  FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
+  SecCoreData->BootFirmwareVolumeBase = BootFv;\r
+  SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
+\r
+  //\r
+  // Transfer the control to the PEI core\r
+  //\r
+  (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
+  \r
+  //\r
+  // If we get here then the PEI Core returned, which is not recoverable.\r
+  //\r
+  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+TemporaryRamMigration (\r
+  IN CONST EFI_PEI_SERVICES   **PeiServices,\r
+  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,\r
+  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,\r
+  IN UINTN                    CopySize\r
+  )\r
+{\r
+  IA32_DESCRIPTOR                  IdtDescriptor;\r
+  VOID                             *OldHeap;\r
+  VOID                             *NewHeap;\r
+  VOID                             *OldStack;\r
+  VOID                             *NewStack;\r
+  DEBUG_AGENT_CONTEXT_POSTMEM_SEC  DebugAgentContext;\r
+  BOOLEAN                          OldStatus;\r
+  BASE_LIBRARY_JUMP_BUFFER         JumpBuffer;\r
+  \r
+  DEBUG ((EFI_D_INFO,\r
+    "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
+    (UINTN) TemporaryMemoryBase,\r
+    (UINTN) PermanentMemoryBase,\r
+    CopySize\r
+    ));\r
+  \r
+  OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
+  NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
+  \r
+  OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
+  NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
+\r
+  DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
+  DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
+  \r
+  OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
+  InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
+\r
+  //\r
+  // Migrate Heap\r
+  //\r
+  CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
+\r
+  //\r
+  // Migrate Stack\r
+  //\r
+  CopyMem (NewStack, OldStack, CopySize >> 1);\r
+  \r
+  //\r
+  // Rebase IDT table in permanent memory\r
+  //\r
+  AsmReadIdtr (&IdtDescriptor);\r
+  IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
+\r
+  AsmWriteIdtr (&IdtDescriptor);\r
+\r
+  //\r
+  // Use SetJump()/LongJump() to switch to a new stack.\r
+  // \r
+  if (SetJump (&JumpBuffer) == 0) {\r
+#if defined (MDE_CPU_IA32)\r
+    JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
+#endif    \r
+#if defined (MDE_CPU_X64)\r
+    JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
+#endif    \r
+    LongJump (&JumpBuffer, (UINTN)-1);\r
+  }\r
+\r
+  SaveAndSetDebugTimerInterrupt (OldStatus);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r