+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. 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
-Module Name:\r
-\r
- DxeLoadFunc.c\r
-\r
-Abstract:\r
-\r
- Ia32-specifc functionality for DxeLoad.\r
-\r
---*/\r
-\r
-#include "DxeIpl.h"\r
-#include "VirtualMemory.h"\r
-\r
-//\r
-// Global Descriptor Table (GDT)
-//
-GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries [] = {\r
-/* selector { Global Segment Descriptor } */ \r
-/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor \r
-/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor\r
-/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor\r
-/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor\r
-/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor\r
-/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor\r
-/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor\r
-/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor\r
-/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor\r
-};\r
-\r
-//\r
-// IA32 Gdt register\r
-//\r
-GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = {\r
- sizeof (gGdtEntries) - 1,\r
- (UINTN) gGdtEntries\r
- };\r
-\r
-VOID\r
-HandOffToDxeCore (\r
- IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,\r
- IN EFI_PEI_HOB_POINTERS HobList,\r
- IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PHYSICAL_ADDRESS BaseOfStack;\r
- EFI_PHYSICAL_ADDRESS TopOfStack;\r
- UINTN PageTables;\r
-\r
- Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
- ASSERT_EFI_ERROR (Status);\r
- \r
- if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {\r
- //\r
- // Compute the top of the stack we were allocated, which is used to load X64 dxe core. \r
- // Pre-allocate a 32 bytes which confroms to x64 calling convention.\r
- //\r
- // The first four parameters to a function are passed in rcx, rdx, r8 and r9. \r
- // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the \r
- // register parameters is reserved on the stack, in case the called function \r
- // wants to spill them; this is important if the function is variadic. \r
- //\r
- TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;\r
-\r
- //\r
- // X64 Calling Conventions requires that the stack must be aligned to 16 bytes\r
- //\r
- TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);\r
-\r
- //\r
- // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA\r
- // memory, it may be corrupted when copying FV to high-end memory \r
- //\r
- AsmWriteGdtr (&gGdt);\r
- //\r
- // Create page table and save PageMapLevel4 to CR3\r
- //\r
- PageTables = CreateIdentityMappingPageTables ();\r
-\r
- //\r
- // End of PEI phase singal\r
- //\r
- Status = PeiServicesInstallPpi (EndOfPeiSignal);\r
- ASSERT_EFI_ERROR (Status);\r
- \r
- AsmWriteCr3 (PageTables);\r
- //\r
- // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.\r
- // Call x64 drivers passing in single argument, a pointer to the HOBs.\r
- // \r
- AsmEnablePaging64 (\r
- SYS_CODE64_SEL,\r
- DxeCoreEntryPoint,\r
- (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),\r
- 0,\r
- TopOfStack\r
- );\r
- } else {\r
- //\r
- // Compute the top of the stack we were allocated. Pre-allocate a UINTN\r
- // for safety.\r
- //\r
- TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;\r
- TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
-\r
- //\r
- // End of PEI phase singal\r
- //\r
- Status = PeiServicesInstallPpi (EndOfPeiSignal);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- SwitchStack (\r
- (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
- HobList.Raw,\r
- NULL,\r
- (VOID *) (UINTN) TopOfStack\r
- );\r
- } \r
-}\r
-\r