4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ia32-specific functionality for DxeLoad.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "DxeIpl.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "VirtualMemory.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define IDT_ENTRY_COUNT 32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct _X64_IDT_TABLE {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Reserved 4 bytes preceding PeiService and IdtTable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // since IDT base address should be 8-byte alignment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Reserved;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CONST EFI_PEI_SERVICES **PeiService;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync X64_IDT_GATE_DESCRIPTOR IdtTable[IDT_ENTRY_COUNT];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} X64_IDT_TABLE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Global Descriptor Table (GDT)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries[] = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* selector { Global Segment Descriptor } */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// IA32 Gdt register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (gGdtEntries) - 1,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINTN) gGdtEntries
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync };
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (X64_IDT_GATE_DESCRIPTOR) * IDT_ENTRY_COUNT - 1,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Transfers control to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function performs a CPU architecture specific operations to execute
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the entry point of DxeCore with the parameters of HobList.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param DxeCoreEntryPoint The entry point of DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param HobList The start of HobList passed to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncHandOffToDxeCore (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_PEI_HOB_POINTERS HobList
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PHYSICAL_ADDRESS BaseOfStack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PHYSICAL_ADDRESS TopOfStack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN PageTables;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync X64_IDT_GATE_DESCRIPTOR *IdtTable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN SizeOfTemplate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *TemplateBase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_PHYSICAL_ADDRESS VectorAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync X64_IDT_TABLE *IdtTableForX64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Pre-allocate a 32 bytes which confroms to x64 calling convention.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // register parameters is reserved on the stack, in case the called function
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // wants to spill them; this is important if the function is variadic.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // x64 Calling Conventions requires that the stack must be aligned to 16 bytes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // memory, it may be corrupted when copying FV to high-end memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteGdtr (&gGdt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create page table and save PageMapLevel4 to CR3
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PageTables = CreateIdentityMappingPageTables ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // End of PEI phase signal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteCr3 (PageTables);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdateStackHob (BaseOfStack, STACK_SIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesAllocatePages (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EfiBootServicesData,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_PHYSICAL_ADDRESS *) &IdtTableForX64
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // it may not be gotten correctly after IDT register is re-written.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTableForX64->PeiService = GetPeiServicesTablePointer ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable = IdtTableForX64->IdtTable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16) VectorAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16) (RShiftU64 (VectorAddress, 16));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Offset32To63 = (UINT32) (RShiftU64 (VectorAddress, 32));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Reserved = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VectorAddress += SizeOfTemplate;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gLidtDescriptor.Base = (UINTN) IdtTable;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Disable interrupt of Debug timer, since new IDT table cannot handle it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SaveAndSetDebugTimerInterrupt (FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteIdtr (&gLidtDescriptor);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Go to Long Mode and transfer control to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Interrupts will not get turned on until the CPU AP is loaded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Call x64 drivers passing in single argument, a pointer to the HOBs.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmEnablePaging64 (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SYS_CODE64_SEL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DxeCoreEntryPoint,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TopOfStack
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the top of the stack we were allocated. Pre-allocate a UINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // for safety.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // End of PEI phase signal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UpdateStackHob (BaseOfStack, STACK_SIZE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transfer the control to the entry point of DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SwitchStack (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HobList.Raw,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID *) (UINTN) TopOfStack
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync