]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / Ia32 / DxeLoadFunc.c
CommitLineData
96226baa 1/** @file\r
48557c65 2 Ia32-specific functionality for DxeLoad.\r
95276127 3\r
d1102dba 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
5997daf7
LD
5Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
6\r
9d510e61 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
95276127 8\r
96226baa 9**/\r
95276127 10\r
95276127 11#include "DxeIpl.h"\r
12#include "VirtualMemory.h"\r
13\r
1436aea4 14#define IDT_ENTRY_COUNT 32\r
e7af83ae 15\r
bdfbe63e 16typedef struct _X64_IDT_TABLE {\r
17 //\r
18 // Reserved 4 bytes preceding PeiService and IdtTable,\r
19 // since IDT base address should be 8-byte alignment.\r
20 //\r
1436aea4
MK
21 UINT32 Reserved;\r
22 CONST EFI_PEI_SERVICES **PeiService;\r
23 X64_IDT_GATE_DESCRIPTOR IdtTable[IDT_ENTRY_COUNT];\r
bdfbe63e 24} X64_IDT_TABLE;\r
25\r
95276127 26//\r
27// Global Descriptor Table (GDT)\r
28//\r
1436aea4
MK
29GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries[] = {\r
30 /* selector { Global Segment Descriptor } */\r
31 /* 0x00 */ {\r
32 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }\r
33 }, // null descriptor\r
34 /* 0x08 */ {\r
35 { 0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }\r
36 }, // linear data segment descriptor\r
37 /* 0x10 */ {\r
38 { 0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }\r
39 }, // linear code segment descriptor\r
40 /* 0x18 */ {\r
41 { 0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }\r
42 }, // system data segment descriptor\r
43 /* 0x20 */ {\r
44 { 0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }\r
45 }, // system code segment descriptor\r
46 /* 0x28 */ {\r
47 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }\r
48 }, // spare segment descriptor\r
49 /* 0x30 */ {\r
50 { 0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0 }\r
51 }, // system data segment descriptor\r
52 /* 0x38 */ {\r
53 { 0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0 }\r
54 }, // system code segment descriptor\r
55 /* 0x40 */ {\r
56 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }\r
57 }, // spare segment descriptor\r
95276127 58};\r
59\r
60//\r
61// IA32 Gdt register\r
62//\r
1436aea4 63GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = {\r
95276127 64 sizeof (gGdtEntries) - 1,\r
1436aea4
MK
65 (UINTN)gGdtEntries\r
66};\r
95276127 67\r
1436aea4 68GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = {\r
e7af83ae 69 sizeof (X64_IDT_GATE_DESCRIPTOR) * IDT_ENTRY_COUNT - 1,\r
5d582956 70 0\r
71};\r
72\r
5630cdfe
SZ
73/**\r
74 Allocates and fills in the Page Directory and Page Table Entries to\r
75 establish a 4G page table.\r
76\r
77 @param[in] StackBase Stack base address.\r
78 @param[in] StackSize Stack size.\r
79\r
80 @return The address of page table.\r
81\r
82**/\r
83UINTN\r
84Create4GPageTablesIa32Pae (\r
1436aea4
MK
85 IN EFI_PHYSICAL_ADDRESS StackBase,\r
86 IN UINTN StackSize\r
5630cdfe 87 )\r
d1102dba 88{\r
1436aea4
MK
89 UINT8 PhysicalAddressBits;\r
90 EFI_PHYSICAL_ADDRESS PhysicalAddress;\r
91 UINTN IndexOfPdpEntries;\r
92 UINTN IndexOfPageDirectoryEntries;\r
93 UINT32 NumberOfPdpEntriesNeeded;\r
94 PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;\r
95 PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;\r
96 PAGE_TABLE_ENTRY *PageDirectoryEntry;\r
97 UINTN TotalPagesNum;\r
98 UINTN PageAddress;\r
99 UINT64 AddressEncMask;\r
5997daf7
LD
100\r
101 //\r
102 // Make sure AddressEncMask is contained to smallest supported address field\r
103 //\r
104 AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;\r
5630cdfe
SZ
105\r
106 PhysicalAddressBits = 32;\r
107\r
108 //\r
109 // Calculate the table entries needed.\r
110 //\r
1436aea4 111 NumberOfPdpEntriesNeeded = (UINT32)LShiftU64 (1, (PhysicalAddressBits - 30));\r
5630cdfe
SZ
112\r
113 TotalPagesNum = NumberOfPdpEntriesNeeded + 1;\r
1436aea4 114 PageAddress = (UINTN)AllocatePageTableMemory (TotalPagesNum);\r
5630cdfe
SZ
115 ASSERT (PageAddress != 0);\r
116\r
1436aea4 117 PageMap = (VOID *)PageAddress;\r
5630cdfe
SZ
118 PageAddress += SIZE_4KB;\r
119\r
120 PageDirectoryPointerEntry = PageMap;\r
1436aea4 121 PhysicalAddress = 0;\r
5630cdfe
SZ
122\r
123 for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
124 //\r
125 // Each Directory Pointer entries points to a page of Page Directory entires.\r
126 // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.\r
d1102dba 127 //\r
1436aea4
MK
128 PageDirectoryEntry = (VOID *)PageAddress;\r
129 PageAddress += SIZE_4KB;\r
5630cdfe
SZ
130\r
131 //\r
132 // Fill in a Page Directory Pointer Entries\r
133 //\r
1436aea4 134 PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask;\r
5630cdfe
SZ
135 PageDirectoryPointerEntry->Bits.Present = 1;\r
136\r
137 for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {\r
1436aea4
MK
138 if ( (IsNullDetectionEnabled () && (PhysicalAddress == 0))\r
139 || ( (PhysicalAddress < StackBase + StackSize)\r
140 && ((PhysicalAddress + SIZE_2MB) > StackBase)))\r
141 {\r
5630cdfe
SZ
142 //\r
143 // Need to split this 2M page that covers stack range.\r
144 //\r
1436aea4 145 Split2MPageTo4K (PhysicalAddress, (UINT64 *)PageDirectoryEntry, StackBase, StackSize, 0, 0);\r
5630cdfe
SZ
146 } else {\r
147 //\r
148 // Fill in the Page Directory entries\r
149 //\r
1436aea4 150 PageDirectoryEntry->Uint64 = (UINT64)PhysicalAddress | AddressEncMask;\r
5630cdfe 151 PageDirectoryEntry->Bits.ReadWrite = 1;\r
1436aea4
MK
152 PageDirectoryEntry->Bits.Present = 1;\r
153 PageDirectoryEntry->Bits.MustBe1 = 1;\r
5630cdfe
SZ
154 }\r
155 }\r
156 }\r
157\r
1436aea4 158 for ( ; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {\r
5630cdfe
SZ
159 ZeroMem (\r
160 PageDirectoryPointerEntry,\r
161 sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)\r
162 );\r
163 }\r
164\r
2ac1730b
JW
165 //\r
166 // Protect the page table by marking the memory used for page table to be\r
167 // read-only.\r
168 //\r
169 EnablePageTableProtection ((UINTN)PageMap, FALSE);\r
170\r
1436aea4 171 return (UINTN)PageMap;\r
5630cdfe
SZ
172}\r
173\r
174/**\r
175 The function will check if IA32 PAE is supported.\r
176\r
177 @retval TRUE IA32 PAE is supported.\r
178 @retval FALSE IA32 PAE is not supported.\r
179\r
180**/\r
181BOOLEAN\r
182IsIa32PaeSupport (\r
183 VOID\r
184 )\r
185{\r
1436aea4
MK
186 UINT32 RegEax;\r
187 UINT32 RegEdx;\r
188 BOOLEAN Ia32PaeSupport;\r
5630cdfe
SZ
189\r
190 Ia32PaeSupport = FALSE;\r
191 AsmCpuid (0x0, &RegEax, NULL, NULL, NULL);\r
192 if (RegEax >= 0x1) {\r
193 AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx);\r
194 if ((RegEdx & BIT6) != 0) {\r
195 Ia32PaeSupport = TRUE;\r
196 }\r
197 }\r
198\r
199 return Ia32PaeSupport;\r
200}\r
201\r
e63da9f0
JW
202/**\r
203 The function will check if page table should be setup or not.\r
204\r
205 @retval TRUE Page table should be created.\r
206 @retval FALSE Page table should not be created.\r
207\r
208**/\r
209BOOLEAN\r
210ToBuildPageTable (\r
211 VOID\r
212 )\r
213{\r
214 if (!IsIa32PaeSupport ()) {\r
215 return FALSE;\r
216 }\r
217\r
218 if (IsNullDetectionEnabled ()) {\r
219 return TRUE;\r
220 }\r
221\r
222 if (PcdGet8 (PcdHeapGuardPropertyMask) != 0) {\r
223 return TRUE;\r
224 }\r
225\r
50255363
JW
226 if (PcdGetBool (PcdCpuStackGuard)) {\r
227 return TRUE;\r
228 }\r
229\r
52679261 230 if (IsEnableNonExecNeeded ()) {\r
e63da9f0
JW
231 return TRUE;\r
232 }\r
233\r
234 return FALSE;\r
235}\r
236\r
91d92e25 237/**\r
238 Transfers control to DxeCore.\r
239\r
240 This function performs a CPU architecture specific operations to execute\r
241 the entry point of DxeCore with the parameters of HobList.\r
48557c65 242 It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.\r
91d92e25 243\r
48557c65 244 @param DxeCoreEntryPoint The entry point of DxeCore.\r
91d92e25 245 @param HobList The start of HobList passed to DxeCore.\r
91d92e25 246\r
247**/\r
95276127 248VOID\r
249HandOffToDxeCore (\r
1436aea4
MK
250 IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,\r
251 IN EFI_PEI_HOB_POINTERS HobList\r
95276127 252 )\r
253{\r
1436aea4
MK
254 EFI_STATUS Status;\r
255 EFI_PHYSICAL_ADDRESS BaseOfStack;\r
256 EFI_PHYSICAL_ADDRESS TopOfStack;\r
257 UINTN PageTables;\r
258 X64_IDT_GATE_DESCRIPTOR *IdtTable;\r
259 UINTN SizeOfTemplate;\r
260 VOID *TemplateBase;\r
261 EFI_PHYSICAL_ADDRESS VectorAddress;\r
262 UINT32 Index;\r
263 X64_IDT_TABLE *IdtTableForX64;\r
264 EFI_VECTOR_HANDOFF_INFO *VectorInfo;\r
265 EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;\r
266 BOOLEAN BuildPageTablesIa32Pae;\r
95276127 267\r
f9d0e5da
JW
268 //\r
269 // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.\r
270 //\r
9189ec20
JW
271 if (IsNullDetectionEnabled ()) {\r
272 ClearFirst4KPage (HobList.Raw);\r
f9d0e5da 273 BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);\r
9189ec20
JW
274 }\r
275\r
95276127 276 Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);\r
277 ASSERT_EFI_ERROR (Status);\r
0cf27ce0 278\r
1436aea4 279 if (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {\r
95276127 280 //\r
0cf27ce0 281 // Compute the top of the stack we were allocated, which is used to load X64 dxe core.\r
95276127 282 // Pre-allocate a 32 bytes which confroms to x64 calling convention.\r
283 //\r
0cf27ce0 284 // The first four parameters to a function are passed in rcx, rdx, r8 and r9.\r
285 // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the\r
286 // register parameters is reserved on the stack, in case the called function\r
287 // wants to spill them; this is important if the function is variadic.\r
95276127 288 //\r
289 TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;\r
290\r
291 //\r
b98da1b1 292 // x64 Calling Conventions requires that the stack must be aligned to 16 bytes\r
95276127 293 //\r
1436aea4 294 TopOfStack = (EFI_PHYSICAL_ADDRESS)(UINTN)ALIGN_POINTER (TopOfStack, 16);\r
95276127 295\r
296 //\r
297 // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA\r
0cf27ce0 298 // memory, it may be corrupted when copying FV to high-end memory\r
95276127 299 //\r
300 AsmWriteGdtr (&gGdt);\r
301 //\r
302 // Create page table and save PageMapLevel4 to CR3\r
303 //\r
b098f5e9 304 PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE, 0, 0);\r
95276127 305\r
306 //\r
48557c65 307 // End of PEI phase signal\r
95276127 308 //\r
98d20e44 309 PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);\r
9b937a73 310 Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
98d20e44 311 PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);\r
95276127 312 ASSERT_EFI_ERROR (Status);\r
0cf27ce0 313\r
2af2988f
JW
314 //\r
315 // Paging might be already enabled. To avoid conflict configuration,\r
316 // disable paging first anyway.\r
317 //\r
318 AsmWriteCr0 (AsmReadCr0 () & (~BIT31));\r
95276127 319 AsmWriteCr3 (PageTables);\r
5d582956 320\r
30c8f861 321 //\r
322 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
0cf27ce0 323 //\r
30c8f861 324 UpdateStackHob (BaseOfStack, STACK_SIZE);\r
5d582956 325\r
4bfa7dc4 326 SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);\r
327\r
328 Status = PeiServicesAllocatePages (\r
0cf27ce0 329 EfiBootServicesData,\r
1436aea4 330 EFI_SIZE_TO_PAGES (sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT),\r
b028c102 331 &VectorAddress\r
4bfa7dc4 332 );\r
333 ASSERT_EFI_ERROR (Status);\r
334\r
bdfbe63e 335 //\r
336 // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that\r
337 // it may not be gotten correctly after IDT register is re-written.\r
338 //\r
1436aea4 339 IdtTableForX64 = (X64_IDT_TABLE *)(UINTN)VectorAddress;\r
bdfbe63e 340 IdtTableForX64->PeiService = GetPeiServicesTablePointer ();\r
341\r
1436aea4 342 VectorAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(IdtTableForX64 + 1);\r
bdfbe63e 343 IdtTable = IdtTableForX64->IdtTable;\r
e7af83ae 344 for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) {\r
1436aea4
MK
345 IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e;\r
346 IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0;\r
347 IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL;\r
4bfa7dc4 348\r
1436aea4
MK
349 IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16)VectorAddress;\r
350 IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16)(RShiftU64 (VectorAddress, 16));\r
351 IdtTable[Index].Offset32To63 = (UINT32)(RShiftU64 (VectorAddress, 32));\r
352 IdtTable[Index].Reserved = 0;\r
4bfa7dc4 353\r
1436aea4
MK
354 CopyMem ((VOID *)(UINTN)VectorAddress, TemplateBase, SizeOfTemplate);\r
355 AsmVectorFixup ((VOID *)(UINTN)VectorAddress, (UINT8)Index);\r
4bfa7dc4 356\r
357 VectorAddress += SizeOfTemplate;\r
5d582956 358 }\r
4bfa7dc4 359\r
1436aea4 360 gLidtDescriptor.Base = (UINTN)IdtTable;\r
0cf27ce0 361\r
e7af83ae 362 //\r
363 // Disable interrupt of Debug timer, since new IDT table cannot handle it.\r
364 //\r
365 SaveAndSetDebugTimerInterrupt (FALSE);\r
366\r
4bfa7dc4 367 AsmWriteIdtr (&gLidtDescriptor);\r
368\r
6fb389d0
JF
369 DEBUG ((\r
370 DEBUG_INFO,\r
371 "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",\r
372 __FUNCTION__,\r
373 BaseOfStack,\r
374 STACK_SIZE\r
375 ));\r
376\r
5d582956 377 //\r
b98da1b1 378 // Go to Long Mode and transfer control to DxeCore.\r
379 // Interrupts will not get turned on until the CPU AP is loaded.\r
95276127 380 // Call x64 drivers passing in single argument, a pointer to the HOBs.\r
0cf27ce0 381 //\r
95276127 382 AsmEnablePaging64 (\r
383 SYS_CODE64_SEL,\r
384 DxeCoreEntryPoint,\r
385 (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),\r
386 0,\r
387 TopOfStack\r
388 );\r
389 } else {\r
57f360f2
JF
390 //\r
391 // Get Vector Hand-off Info PPI and build Guided HOB\r
392 //\r
393 Status = PeiServicesLocatePpi (\r
394 &gEfiVectorHandoffInfoPpiGuid,\r
395 0,\r
396 NULL,\r
397 (VOID **)&VectorHandoffInfoPpi\r
398 );\r
399 if (Status == EFI_SUCCESS) {\r
87000d77 400 DEBUG ((DEBUG_INFO, "Vector Hand-off Info PPI is gotten, GUIDed HOB is created!\n"));\r
57f360f2 401 VectorInfo = VectorHandoffInfoPpi->Info;\r
1436aea4 402 Index = 1;\r
57f360f2 403 while (VectorInfo->Attribute != EFI_VECTOR_HANDOFF_LAST_ENTRY) {\r
1436aea4
MK
404 VectorInfo++;\r
405 Index++;\r
57f360f2 406 }\r
1436aea4 407\r
57f360f2
JF
408 BuildGuidDataHob (\r
409 &gEfiVectorHandoffInfoPpiGuid,\r
410 VectorHandoffInfoPpi->Info,\r
411 sizeof (EFI_VECTOR_HANDOFF_INFO) * Index\r
412 );\r
413 }\r
414\r
95276127 415 //\r
416 // Compute the top of the stack we were allocated. Pre-allocate a UINTN\r
417 // for safety.\r
418 //\r
419 TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT;\r
1436aea4 420 TopOfStack = (EFI_PHYSICAL_ADDRESS)(UINTN)ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
95276127 421\r
1436aea4 422 PageTables = 0;\r
e63da9f0 423 BuildPageTablesIa32Pae = ToBuildPageTable ();\r
5630cdfe
SZ
424 if (BuildPageTablesIa32Pae) {\r
425 PageTables = Create4GPageTablesIa32Pae (BaseOfStack, STACK_SIZE);\r
52679261 426 if (IsEnableNonExecNeeded ()) {\r
1436aea4 427 EnableExecuteDisableBit ();\r
9189ec20 428 }\r
5630cdfe
SZ
429 }\r
430\r
95276127 431 //\r
48557c65 432 // End of PEI phase signal\r
95276127 433 //\r
98d20e44 434 PERF_EVENT_SIGNAL_BEGIN (gEndOfPeiSignalPpi.Guid);\r
9b937a73 435 Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
98d20e44 436 PERF_EVENT_SIGNAL_END (gEndOfPeiSignalPpi.Guid);\r
95276127 437 ASSERT_EFI_ERROR (Status);\r
438\r
5630cdfe 439 if (BuildPageTablesIa32Pae) {\r
2af2988f
JW
440 //\r
441 // Paging might be already enabled. To avoid conflict configuration,\r
442 // disable paging first anyway.\r
443 //\r
444 AsmWriteCr0 (AsmReadCr0 () & (~BIT31));\r
5630cdfe
SZ
445 AsmWriteCr3 (PageTables);\r
446 //\r
447 // Set Physical Address Extension (bit 5 of CR4).\r
448 //\r
449 AsmWriteCr4 (AsmReadCr4 () | BIT5);\r
450 }\r
451\r
30c8f861 452 //\r
453 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.\r
0cf27ce0 454 //\r
30c8f861 455 UpdateStackHob (BaseOfStack, STACK_SIZE);\r
0cf27ce0 456\r
6fb389d0
JF
457 DEBUG ((\r
458 DEBUG_INFO,\r
459 "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",\r
460 __FUNCTION__,\r
461 BaseOfStack,\r
462 STACK_SIZE\r
463 ));\r
464\r
b98da1b1 465 //\r
466 // Transfer the control to the entry point of DxeCore.\r
467 //\r
5630cdfe
SZ
468 if (BuildPageTablesIa32Pae) {\r
469 AsmEnablePaging32 (\r
470 (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
471 HobList.Raw,\r
472 NULL,\r
1436aea4 473 (VOID *)(UINTN)TopOfStack\r
5630cdfe
SZ
474 );\r
475 } else {\r
476 SwitchStack (\r
477 (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,\r
478 HobList.Raw,\r
479 NULL,\r
1436aea4 480 (VOID *)(UINTN)TopOfStack\r
5630cdfe
SZ
481 );\r
482 }\r
0cf27ce0 483 }\r
95276127 484}\r