diff options
Diffstat (limited to 'OvmfPkg/Sec')
-rw-r--r-- | OvmfPkg/Sec/SecMain.c | 1530 |
1 files changed, 765 insertions, 765 deletions
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index 3882dadd63..e235b964a8 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -1,765 +1,765 @@ -/** @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; - - ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0); - - 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
+ 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;
+
+ ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);
+
+ 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;
+}
+
|