]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
Update all files in DxeIpl Peim to follow doxygen style header.
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / Ia32 / DxeLoadFunc.c
CommitLineData
96226baa 1/** @file\r
2 Ia32-specifc functionality for DxeLoad.\r
95276127 3\r
96226baa 4Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
95276127 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
96226baa 13**/\r
95276127 14\r
95276127 15#include "DxeIpl.h"\r
16#include "VirtualMemory.h"\r
17\r
18//\r
19// Global Descriptor Table (GDT)\r
20//\r
21GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries [] = {\r
22/* selector { Global Segment Descriptor } */ \r
23/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor \r
24/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor\r
25/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor\r
26/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor\r
27/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor\r
28/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor\r
29/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor\r
30/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor\r
31/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor\r
32};\r
33\r
34//\r
35// IA32 Gdt register\r
36//\r
37GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = {\r
38 sizeof (gGdtEntries) - 1,\r
39 (UINTN) gGdtEntries\r
40 };\r
41\r
5d582956 42GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = {\r
43 sizeof (X64_IDT_GATE_DESCRIPTOR) * 32 - 1,\r
44 0\r
45};\r
46\r
95276127 47VOID\r
48HandOffToDxeCore (\r
49 IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,\r
50 IN EFI_PEI_HOB_POINTERS HobList,\r
51 IN EFI_PEI_PPI_DESCRIPTOR *EndOfPeiSignal\r
52 )\r
53{\r
54 EFI_STATUS Status;\r
55 EFI_PHYSICAL_ADDRESS BaseOfStack;\r
56 EFI_PHYSICAL_ADDRESS TopOfStack;\r
57 UINTN PageTables;\r
5d582956 58 X64_IDT_GATE_DESCRIPTOR *IdtTable;\r
59 UINTN SizeOfTemplate;\r
60 VOID *TemplateBase;\r
61 EFI_PHYSICAL_ADDRESS VectorAddress;\r
62 UINT32 Index;\r
95276127 63\r
64 Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
65 ASSERT_EFI_ERROR (Status);\r
66 \r
67 if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {\r
68 //\r
69 // Compute the top of the stack we were allocated, which is used to load X64 dxe core. \r
70 // Pre-allocate a 32 bytes which confroms to x64 calling convention.\r
71 //\r
72 // The first four parameters to a function are passed in rcx, rdx, r8 and r9. \r
73 // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the \r
74 // register parameters is reserved on the stack, in case the called function \r
75 // wants to spill them; this is important if the function is variadic. \r
76 //\r
77 TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;\r
78\r
79 //\r
80 // X64 Calling Conventions requires that the stack must be aligned to 16 bytes\r
81 //\r
82 TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);\r
83\r
84 //\r
85 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA\r
86 // memory, it may be corrupted when copying FV to high-end memory \r
87 //\r
88 AsmWriteGdtr (&gGdt);\r
89 //\r
90 // Create page table and save PageMapLevel4 to CR3\r
91 //\r
92 PageTables = CreateIdentityMappingPageTables ();\r
93\r
94 //\r
95 // End of PEI phase singal\r
96 //\r
97 Status = PeiServicesInstallPpi (EndOfPeiSignal);\r
98 ASSERT_EFI_ERROR (Status);\r
99 \r
100 AsmWriteCr3 (PageTables);\r
5d582956 101\r
30c8f861 102 //\r
103 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
104 // \r
105 UpdateStackHob (BaseOfStack, STACK_SIZE);\r
5d582956 106\r
107 if (FeaturePcdGet (PcdDxeIplEnableIdt)) {\r
108 SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);\r
109 \r
110 Status = PeiServicesAllocatePages (\r
111 EfiBootServicesData, \r
112 EFI_SIZE_TO_PAGES((SizeOfTemplate + sizeof (X64_IDT_GATE_DESCRIPTOR)) * 32), \r
113 &VectorAddress\r
114 );\r
115 \r
116 ASSERT_EFI_ERROR (Status);\r
117 \r
118 IdtTable = (X64_IDT_GATE_DESCRIPTOR *) (UINTN) (VectorAddress + SizeOfTemplate * 32);\r
119 for (Index = 0; Index < 32; Index++) {\r
120 IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e;\r
121 IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0;\r
122 IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL;\r
123 \r
124 IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16) VectorAddress;\r
f0a505a3 125 IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16) (RShiftU64 (VectorAddress, 16));\r
126 IdtTable[Index].Offset32To63 = (UINT32) (RShiftU64 (VectorAddress, 32));\r
5d582956 127 IdtTable[Index].Reserved = 0;\r
128 \r
129 CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate);\r
130 AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index);\r
131 \r
132 VectorAddress += SizeOfTemplate;\r
133 }\r
134 \r
135 gLidtDescriptor.Base = (UINTN) IdtTable;\r
136 AsmWriteIdtr (&gLidtDescriptor);\r
137 }\r
138 //\r
95276127 139 // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded.\r
140 // Call x64 drivers passing in single argument, a pointer to the HOBs.\r
141 // \r
142 AsmEnablePaging64 (\r
143 SYS_CODE64_SEL,\r
144 DxeCoreEntryPoint,\r
145 (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),\r
146 0,\r
147 TopOfStack\r
148 );\r
149 } else {\r
150 //\r
151 // Compute the top of the stack we were allocated. Pre-allocate a UINTN\r
152 // for safety.\r
153 //\r
154 TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;\r
155 TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
156\r
157 //\r
158 // End of PEI phase singal\r
159 //\r
160 Status = PeiServicesInstallPpi (EndOfPeiSignal);\r
161 ASSERT_EFI_ERROR (Status);\r
162\r
30c8f861 163 //\r
164 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
165 // \r
166 UpdateStackHob (BaseOfStack, STACK_SIZE);\r
167\r
95276127 168 SwitchStack (\r
169 (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
170 HobList.Raw,\r
171 NULL,\r
172 (VOID *) (UINTN) TopOfStack\r
173 );\r
174 } \r
175}\r
176\r