4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Ia32-specific functionality for DxeLoad.
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
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 // Reserved 4 bytes preceding PeiService and IdtTable,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // since IDT base address should be 8-byte alignment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Global Descriptor Table (GDT)
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// IA32 Gdt register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncGLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (X64_IDT_GATE_DESCRIPTOR) * IDT_ENTRY_COUNT - 1,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Transfers control to DxeCore.
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 @param DxeCoreEntryPoint The entry point of DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param HobList The start of HobList passed to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
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 // 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 TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // x64 Calling Conventions requires that the stack must be aligned to 16 bytes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);
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 // Create page table and save PageMapLevel4 to CR3
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // End of PEI phase signal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT),
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 IdtTableForX64->PeiService = GetPeiServicesTablePointer ();
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL;
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 CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Disable interrupt of Debug timer, since new IDT table cannot handle it.
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 // Compute the top of the stack we were allocated. Pre-allocate a UINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // for safety.
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 // End of PEI phase signal
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transfer the control to the entry point of DxeCore.