]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
CommitLineData
bb4aa855
JJ
1/** @file\r
2 Main SEC phase code. Transitions to PEI.\r
3\r
f3e34b9d 4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
5e443e37 5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
b78de543 6 Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>\r
bb4aa855 7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
bb4aa855
JJ
9\r
10**/\r
11\r
12#include <PiPei.h>\r
13\r
14#include <Library/PeimEntryPoint.h>\r
15#include <Library/BaseLib.h>\r
16#include <Library/DebugLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/PeiServicesLib.h>\r
19#include <Library/PcdLib.h>\r
1783b099 20#include <Library/CpuLib.h>\r
bb4aa855
JJ
21#include <Library/UefiCpuLib.h>\r
22#include <Library/DebugAgentLib.h>\r
23#include <Library/IoLib.h>\r
24#include <Library/PeCoffLib.h>\r
25#include <Library/PeCoffGetEntryPointLib.h>\r
26#include <Library/PeCoffExtraActionLib.h>\r
27#include <Library/ExtractGuidedSectionLib.h>\r
f3e34b9d 28#include <Library/LocalApicLib.h>\r
13e5492b 29#include <Library/CpuExceptionHandlerLib.h>\r
bb4aa855 30#include <Ppi/TemporaryRamSupport.h>\r
b63a49e0 31#include <Ppi/MpInitLibDep.h>\r
c0984d1f 32#include <Library/TdxHelperLib.h>\r
76fda1de 33#include <Library/CcProbeLib.h>\r
2ddacfb6
BS
34#include "AmdSev.h"\r
35\r
bb4aa855
JJ
36#define SEC_IDT_ENTRY_COUNT 34\r
37\r
38typedef struct _SEC_IDT_TABLE {\r
ac0a286f
MK
39 EFI_PEI_SERVICES *PeiService;\r
40 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];\r
bb4aa855
JJ
41} SEC_IDT_TABLE;\r
42\r
43VOID\r
44EFIAPI\r
45SecStartupPhase2 (\r
ac0a286f 46 IN VOID *Context\r
bb4aa855
JJ
47 );\r
48\r
49EFI_STATUS\r
50EFIAPI\r
51TemporaryRamMigration (\r
ac0a286f
MK
52 IN CONST EFI_PEI_SERVICES **PeiServices,\r
53 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
54 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
55 IN UINTN CopySize\r
bb4aa855
JJ
56 );\r
57\r
58//\r
59//\r
4040754d 60//\r
ac0a286f 61EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {\r
bb4aa855
JJ
62 TemporaryRamMigration\r
63};\r
64\r
b63a49e0
MX
65EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTableMp[] = {\r
66 {\r
67 (EFI_PEI_PPI_DESCRIPTOR_PPI),\r
68 &gEfiTemporaryRamSupportPpiGuid,\r
69 &mTemporaryRamSupportPpi\r
70 },\r
bb4aa855
JJ
71 {\r
72 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
b63a49e0
MX
73 &gEfiPeiMpInitLibMpDepPpiGuid,\r
74 NULL\r
75 },\r
76};\r
77\r
78EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTableUp[] = {\r
79 {\r
80 (EFI_PEI_PPI_DESCRIPTOR_PPI),\r
bb4aa855
JJ
81 &gEfiTemporaryRamSupportPpiGuid,\r
82 &mTemporaryRamSupportPpi\r
83 },\r
b63a49e0
MX
84 {\r
85 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
86 &gEfiPeiMpInitLibUpDepPpiGuid,\r
87 NULL\r
88 },\r
bb4aa855
JJ
89};\r
90\r
91//\r
92// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
93//\r
94IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {\r
95 { // Bits\r
96 0xffe4, // OffsetLow\r
97 0x10, // Selector\r
98 0x0, // Reserved_0\r
99 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType\r
100 0xffff // OffsetHigh\r
4040754d 101 }\r
bb4aa855
JJ
102};\r
103\r
104/**\r
105 Locates the main boot firmware volume.\r
106\r
107 @param[in,out] BootFv On input, the base of the BootFv\r
108 On output, the decompressed main firmware volume\r
109\r
110 @retval EFI_SUCCESS The main firmware volume was located and decompressed\r
111 @retval EFI_NOT_FOUND The main firmware volume was not found\r
112\r
113**/\r
114EFI_STATUS\r
115FindMainFv (\r
ac0a286f 116 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv\r
bb4aa855
JJ
117 )\r
118{\r
119 EFI_FIRMWARE_VOLUME_HEADER *Fv;\r
120 UINTN Distance;\r
121\r
ac0a286f 122 ASSERT (((UINTN)*BootFv & EFI_PAGE_MASK) == 0);\r
bb4aa855 123\r
ac0a286f
MK
124 Fv = *BootFv;\r
125 Distance = (UINTN)(*BootFv)->FvLength;\r
bb4aa855 126 do {\r
ac0a286f 127 Fv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)Fv - EFI_PAGE_SIZE);\r
bb4aa855
JJ
128 Distance += EFI_PAGE_SIZE;\r
129 if (Distance > SIZE_32MB) {\r
130 return EFI_NOT_FOUND;\r
131 }\r
132\r
133 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
134 continue;\r
135 }\r
136\r
ac0a286f 137 if ((UINTN)Fv->FvLength > Distance) {\r
bb4aa855
JJ
138 continue;\r
139 }\r
140\r
141 *BootFv = Fv;\r
142 return EFI_SUCCESS;\r
bb4aa855
JJ
143 } while (TRUE);\r
144}\r
145\r
146/**\r
147 Locates a section within a series of sections\r
148 with the specified section type.\r
149\r
4b4b783d
JJ
150 The Instance parameter indicates which instance of the section\r
151 type to return. (0 is first instance, 1 is second...)\r
152\r
bb4aa855
JJ
153 @param[in] Sections The sections to search\r
154 @param[in] SizeOfSections Total size of all sections\r
155 @param[in] SectionType The section type to locate\r
4b4b783d 156 @param[in] Instance The section instance number\r
bb4aa855
JJ
157 @param[out] FoundSection The FFS section if found\r
158\r
159 @retval EFI_SUCCESS The file and section was found\r
160 @retval EFI_NOT_FOUND The file and section was not found\r
161 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
162\r
163**/\r
164EFI_STATUS\r
4b4b783d 165FindFfsSectionInstance (\r
ac0a286f
MK
166 IN VOID *Sections,\r
167 IN UINTN SizeOfSections,\r
168 IN EFI_SECTION_TYPE SectionType,\r
169 IN UINTN Instance,\r
170 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
bb4aa855
JJ
171 )\r
172{\r
ac0a286f
MK
173 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
174 UINT32 Size;\r
175 EFI_PHYSICAL_ADDRESS EndOfSections;\r
176 EFI_COMMON_SECTION_HEADER *Section;\r
177 EFI_PHYSICAL_ADDRESS EndOfSection;\r
bb4aa855
JJ
178\r
179 //\r
180 // Loop through the FFS file sections within the PEI Core FFS file\r
181 //\r
ac0a286f 182 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections;\r
bb4aa855 183 EndOfSections = EndOfSection + SizeOfSections;\r
ac0a286f 184 for ( ; ;) {\r
bb4aa855
JJ
185 if (EndOfSection == EndOfSections) {\r
186 break;\r
187 }\r
ac0a286f 188\r
bb4aa855
JJ
189 CurrentAddress = (EndOfSection + 3) & ~(3ULL);\r
190 if (CurrentAddress >= EndOfSections) {\r
191 return EFI_VOLUME_CORRUPTED;\r
192 }\r
193\r
ac0a286f 194 Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;\r
bb4aa855
JJ
195\r
196 Size = SECTION_SIZE (Section);\r
197 if (Size < sizeof (*Section)) {\r
198 return EFI_VOLUME_CORRUPTED;\r
199 }\r
200\r
201 EndOfSection = CurrentAddress + Size;\r
202 if (EndOfSection > EndOfSections) {\r
203 return EFI_VOLUME_CORRUPTED;\r
204 }\r
205\r
206 //\r
207 // Look for the requested section type\r
208 //\r
209 if (Section->Type == SectionType) {\r
4b4b783d
JJ
210 if (Instance == 0) {\r
211 *FoundSection = Section;\r
212 return EFI_SUCCESS;\r
213 } else {\r
214 Instance--;\r
215 }\r
bb4aa855 216 }\r
bb4aa855
JJ
217 }\r
218\r
219 return EFI_NOT_FOUND;\r
220}\r
221\r
4b4b783d
JJ
222/**\r
223 Locates a section within a series of sections\r
224 with the specified section type.\r
225\r
226 @param[in] Sections The sections to search\r
227 @param[in] SizeOfSections Total size of all sections\r
228 @param[in] SectionType The section type to locate\r
229 @param[out] FoundSection The FFS section if found\r
230\r
231 @retval EFI_SUCCESS The file and section was found\r
232 @retval EFI_NOT_FOUND The file and section was not found\r
233 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
234\r
235**/\r
236EFI_STATUS\r
237FindFfsSectionInSections (\r
ac0a286f
MK
238 IN VOID *Sections,\r
239 IN UINTN SizeOfSections,\r
240 IN EFI_SECTION_TYPE SectionType,\r
241 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
4b4b783d
JJ
242 )\r
243{\r
244 return FindFfsSectionInstance (\r
245 Sections,\r
246 SizeOfSections,\r
247 SectionType,\r
248 0,\r
249 FoundSection\r
250 );\r
251}\r
252\r
bb4aa855
JJ
253/**\r
254 Locates a FFS file with the specified file type and a section\r
255 within that file with the specified section type.\r
256\r
257 @param[in] Fv The firmware volume to search\r
258 @param[in] FileType The file type to locate\r
259 @param[in] SectionType The section type to locate\r
260 @param[out] FoundSection The FFS section if found\r
261\r
262 @retval EFI_SUCCESS The file and section was found\r
263 @retval EFI_NOT_FOUND The file and section was not found\r
264 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
265\r
266**/\r
267EFI_STATUS\r
bb4aa855 268FindFfsFileAndSection (\r
ac0a286f
MK
269 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
270 IN EFI_FV_FILETYPE FileType,\r
271 IN EFI_SECTION_TYPE SectionType,\r
272 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
bb4aa855
JJ
273 )\r
274{\r
ac0a286f
MK
275 EFI_STATUS Status;\r
276 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
277 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
278 EFI_FFS_FILE_HEADER *File;\r
279 UINT32 Size;\r
280 EFI_PHYSICAL_ADDRESS EndOfFile;\r
bb4aa855
JJ
281\r
282 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
70d5086c 283 DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
bb4aa855
JJ
284 return EFI_VOLUME_CORRUPTED;\r
285 }\r
286\r
ac0a286f 287 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv;\r
bb4aa855
JJ
288 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
289\r
290 //\r
291 // Loop through the FFS files in the Boot Firmware Volume\r
292 //\r
293 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
bb4aa855
JJ
294 CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
295 if (CurrentAddress > EndOfFirmwareVolume) {\r
296 return EFI_VOLUME_CORRUPTED;\r
297 }\r
298\r
ac0a286f 299 File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;\r
b9d4847e 300 Size = FFS_FILE_SIZE (File);\r
bb4aa855
JJ
301 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
302 return EFI_VOLUME_CORRUPTED;\r
303 }\r
bb4aa855
JJ
304\r
305 EndOfFile = CurrentAddress + Size;\r
306 if (EndOfFile > EndOfFirmwareVolume) {\r
307 return EFI_VOLUME_CORRUPTED;\r
308 }\r
309\r
310 //\r
311 // Look for the request file type\r
312 //\r
313 if (File->Type != FileType) {\r
bb4aa855
JJ
314 continue;\r
315 }\r
316\r
317 Status = FindFfsSectionInSections (\r
ac0a286f
MK
318 (VOID *)(File + 1),\r
319 (UINTN)EndOfFile - (UINTN)(File + 1),\r
bb4aa855
JJ
320 SectionType,\r
321 FoundSection\r
322 );\r
323 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
324 return Status;\r
325 }\r
326 }\r
327}\r
328\r
329/**\r
330 Locates the compressed main firmware volume and decompresses it.\r
331\r
332 @param[in,out] Fv On input, the firmware volume to search\r
b36f701d 333 On output, the decompressed BOOT/PEI FV\r
bb4aa855
JJ
334\r
335 @retval EFI_SUCCESS The file and section was found\r
336 @retval EFI_NOT_FOUND The file and section was not found\r
337 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
338\r
339**/\r
340EFI_STATUS\r
b36f701d 341DecompressMemFvs (\r
ac0a286f 342 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv\r
bb4aa855
JJ
343 )\r
344{\r
ac0a286f
MK
345 EFI_STATUS Status;\r
346 EFI_GUID_DEFINED_SECTION *Section;\r
347 UINT32 OutputBufferSize;\r
348 UINT32 ScratchBufferSize;\r
349 UINT16 SectionAttribute;\r
350 UINT32 AuthenticationStatus;\r
351 VOID *OutputBuffer;\r
352 VOID *ScratchBuffer;\r
353 EFI_COMMON_SECTION_HEADER *FvSection;\r
354 EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;\r
355 EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;\r
356 UINT32 FvHeaderSize;\r
357 UINT32 FvSectionSize;\r
358\r
359 FvSection = (EFI_COMMON_SECTION_HEADER *)NULL;\r
bb4aa855
JJ
360\r
361 Status = FindFfsFileAndSection (\r
362 *Fv,\r
363 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
364 EFI_SECTION_GUID_DEFINED,\r
ac0a286f 365 (EFI_COMMON_SECTION_HEADER **)&Section\r
bb4aa855
JJ
366 );\r
367 if (EFI_ERROR (Status)) {\r
70d5086c 368 DEBUG ((DEBUG_ERROR, "Unable to find GUID defined section\n"));\r
bb4aa855
JJ
369 return Status;\r
370 }\r
371\r
372 Status = ExtractGuidedSectionGetInfo (\r
373 Section,\r
374 &OutputBufferSize,\r
375 &ScratchBufferSize,\r
376 &SectionAttribute\r
377 );\r
378 if (EFI_ERROR (Status)) {\r
70d5086c 379 DEBUG ((DEBUG_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
bb4aa855
JJ
380 return Status;\r
381 }\r
382\r
ac0a286f
MK
383 OutputBuffer = (VOID *)((UINT8 *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);\r
384 ScratchBuffer = ALIGN_POINTER ((UINT8 *)OutputBuffer + OutputBufferSize, SIZE_1MB);\r
385\r
386 DEBUG ((\r
387 DEBUG_VERBOSE,\r
388 "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "\r
389 "PcdOvmfDecompressionScratchEnd=0x%x\n",\r
390 __FUNCTION__,\r
391 OutputBuffer,\r
392 OutputBufferSize,\r
393 ScratchBuffer,\r
394 ScratchBufferSize,\r
395 PcdGet32 (PcdOvmfDecompressionScratchEnd)\r
396 ));\r
397 ASSERT (\r
398 (UINTN)ScratchBuffer + ScratchBufferSize ==\r
399 PcdGet32 (PcdOvmfDecompressionScratchEnd)\r
400 );\r
9beac0d8 401\r
bb4aa855
JJ
402 Status = ExtractGuidedSectionDecode (\r
403 Section,\r
404 &OutputBuffer,\r
405 ScratchBuffer,\r
406 &AuthenticationStatus\r
407 );\r
408 if (EFI_ERROR (Status)) {\r
70d5086c 409 DEBUG ((DEBUG_ERROR, "Error during GUID section decode\n"));\r
bb4aa855
JJ
410 return Status;\r
411 }\r
412\r
b36f701d 413 Status = FindFfsSectionInstance (\r
bb4aa855
JJ
414 OutputBuffer,\r
415 OutputBufferSize,\r
416 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
b36f701d 417 0,\r
5e443e37 418 &FvSection\r
bb4aa855
JJ
419 );\r
420 if (EFI_ERROR (Status)) {\r
70d5086c 421 DEBUG ((DEBUG_ERROR, "Unable to find PEI FV section\n"));\r
bb4aa855
JJ
422 return Status;\r
423 }\r
424\r
ac0a286f
MK
425 ASSERT (\r
426 SECTION_SIZE (FvSection) ==\r
427 (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection))\r
428 );\r
b36f701d 429 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
bb4aa855 430\r
ac0a286f
MK
431 PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase);\r
432 CopyMem (PeiMemFv, (VOID *)(FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));\r
b36f701d
JJ
433\r
434 if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {\r
70d5086c 435 DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));\r
b36f701d
JJ
436 CpuDeadLoop ();\r
437 return EFI_VOLUME_CORRUPTED;\r
438 }\r
439\r
440 Status = FindFfsSectionInstance (\r
441 OutputBuffer,\r
442 OutputBufferSize,\r
443 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
444 1,\r
5e443e37 445 &FvSection\r
b36f701d
JJ
446 );\r
447 if (EFI_ERROR (Status)) {\r
70d5086c 448 DEBUG ((DEBUG_ERROR, "Unable to find DXE FV section\n"));\r
b36f701d
JJ
449 return Status;\r
450 }\r
451\r
452 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
39dbc4d5
TP
453\r
454 if (IS_SECTION2 (FvSection)) {\r
455 FvSectionSize = SECTION2_SIZE (FvSection);\r
ac0a286f 456 FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
39dbc4d5
TP
457 } else {\r
458 FvSectionSize = SECTION_SIZE (FvSection);\r
ac0a286f 459 FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
39dbc4d5
TP
460 }\r
461\r
462 ASSERT (FvSectionSize == (PcdGet32 (PcdOvmfDxeMemFvSize) + FvHeaderSize));\r
b36f701d 463\r
ac0a286f
MK
464 DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase);\r
465 CopyMem (DxeMemFv, (VOID *)((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdOvmfDxeMemFvSize));\r
b36f701d
JJ
466\r
467 if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {\r
70d5086c 468 DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));\r
bb4aa855
JJ
469 CpuDeadLoop ();\r
470 return EFI_VOLUME_CORRUPTED;\r
471 }\r
472\r
b36f701d 473 *Fv = PeiMemFv;\r
bb4aa855
JJ
474 return EFI_SUCCESS;\r
475}\r
476\r
477/**\r
478 Locates the PEI Core entry point address\r
479\r
480 @param[in] Fv The firmware volume to search\r
481 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
482\r
483 @retval EFI_SUCCESS The file and section was found\r
484 @retval EFI_NOT_FOUND The file and section was not found\r
485 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
486\r
487**/\r
488EFI_STATUS\r
bb4aa855 489FindPeiCoreImageBaseInFv (\r
ac0a286f
MK
490 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
491 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
bb4aa855
JJ
492 )\r
493{\r
ac0a286f
MK
494 EFI_STATUS Status;\r
495 EFI_COMMON_SECTION_HEADER *Section;\r
bb4aa855
JJ
496\r
497 Status = FindFfsFileAndSection (\r
498 Fv,\r
499 EFI_FV_FILETYPE_PEI_CORE,\r
500 EFI_SECTION_PE32,\r
501 &Section\r
502 );\r
503 if (EFI_ERROR (Status)) {\r
504 Status = FindFfsFileAndSection (\r
505 Fv,\r
506 EFI_FV_FILETYPE_PEI_CORE,\r
507 EFI_SECTION_TE,\r
508 &Section\r
509 );\r
510 if (EFI_ERROR (Status)) {\r
70d5086c 511 DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n"));\r
bb4aa855
JJ
512 return Status;\r
513 }\r
514 }\r
515\r
516 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
517 return EFI_SUCCESS;\r
518}\r
519\r
a781f709
JJ
520/**\r
521 Reads 8-bits of CMOS data.\r
522\r
523 Reads the 8-bits of CMOS data at the location specified by Index.\r
524 The 8-bit read value is returned.\r
525\r
526 @param Index The CMOS location to read.\r
527\r
528 @return The value read.\r
529\r
530**/\r
531STATIC\r
532UINT8\r
533CmosRead8 (\r
ac0a286f 534 IN UINTN Index\r
a781f709
JJ
535 )\r
536{\r
ac0a286f 537 IoWrite8 (0x70, (UINT8)Index);\r
a781f709
JJ
538 return IoRead8 (0x71);\r
539}\r
540\r
a781f709
JJ
541STATIC\r
542BOOLEAN\r
543IsS3Resume (\r
544 VOID\r
545 )\r
546{\r
547 return (CmosRead8 (0xF) == 0xFE);\r
548}\r
549\r
a781f709
JJ
550STATIC\r
551EFI_STATUS\r
552GetS3ResumePeiFv (\r
ac0a286f 553 IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv\r
a781f709
JJ
554 )\r
555{\r
ac0a286f 556 *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase);\r
a781f709
JJ
557 return EFI_SUCCESS;\r
558}\r
559\r
bb4aa855
JJ
560/**\r
561 Locates the PEI Core entry point address\r
562\r
563 @param[in,out] Fv The firmware volume to search\r
564 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
565\r
566 @retval EFI_SUCCESS The file and section was found\r
567 @retval EFI_NOT_FOUND The file and section was not found\r
568 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
569\r
570**/\r
571VOID\r
bb4aa855 572FindPeiCoreImageBase (\r
ac0a286f
MK
573 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
574 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
bb4aa855
JJ
575 )\r
576{\r
ac0a286f 577 BOOLEAN S3Resume;\r
efb0f16e 578\r
bb4aa855
JJ
579 *PeiCoreImageBase = 0;\r
580\r
efb0f16e
LE
581 S3Resume = IsS3Resume ();\r
582 if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {\r
583 //\r
584 // A malicious runtime OS may have injected something into our previously\r
585 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.\r
586 //\r
70d5086c 587 DEBUG ((DEBUG_VERBOSE, "SEC: S3 resume\n"));\r
a781f709
JJ
588 GetS3ResumePeiFv (BootFv);\r
589 } else {\r
efb0f16e
LE
590 //\r
591 // We're either not resuming, or resuming "securely" -- we'll decompress\r
592 // both PEI FV and DXE FV from pristine flash.\r
593 //\r
ac0a286f
MK
594 DEBUG ((\r
595 DEBUG_VERBOSE,\r
596 "SEC: %a\n",\r
597 S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"\r
598 ));\r
a781f709 599 FindMainFv (BootFv);\r
bb4aa855 600\r
a781f709
JJ
601 DecompressMemFvs (BootFv);\r
602 }\r
bb4aa855
JJ
603\r
604 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
605}\r
606\r
607/**\r
608 Find core image base.\r
609\r
610**/\r
611EFI_STATUS\r
bb4aa855 612FindImageBase (\r
ac0a286f
MK
613 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
614 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
bb4aa855
JJ
615 )\r
616{\r
ac0a286f
MK
617 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
618 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
619 EFI_FFS_FILE_HEADER *File;\r
620 UINT32 Size;\r
621 EFI_PHYSICAL_ADDRESS EndOfFile;\r
622 EFI_COMMON_SECTION_HEADER *Section;\r
623 EFI_PHYSICAL_ADDRESS EndOfSection;\r
bb4aa855
JJ
624\r
625 *SecCoreImageBase = 0;\r
626\r
ac0a286f 627 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr;\r
bb4aa855
JJ
628 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
629\r
630 //\r
631 // Loop through the FFS files in the Boot Firmware Volume\r
632 //\r
633 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
bb4aa855
JJ
634 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
635 if (CurrentAddress > EndOfFirmwareVolume) {\r
636 return EFI_NOT_FOUND;\r
637 }\r
638\r
ac0a286f 639 File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;\r
b9d4847e 640 Size = FFS_FILE_SIZE (File);\r
bb4aa855
JJ
641 if (Size < sizeof (*File)) {\r
642 return EFI_NOT_FOUND;\r
643 }\r
644\r
645 EndOfFile = CurrentAddress + Size;\r
646 if (EndOfFile > EndOfFirmwareVolume) {\r
647 return EFI_NOT_FOUND;\r
648 }\r
649\r
650 //\r
651 // Look for SEC Core\r
652 //\r
653 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
654 continue;\r
655 }\r
656\r
657 //\r
658 // Loop through the FFS file sections within the FFS file\r
659 //\r
ac0a286f
MK
660 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)(File + 1);\r
661 for ( ; ;) {\r
bb4aa855 662 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
ac0a286f 663 Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;\r
bb4aa855 664\r
b9d4847e 665 Size = SECTION_SIZE (Section);\r
bb4aa855
JJ
666 if (Size < sizeof (*Section)) {\r
667 return EFI_NOT_FOUND;\r
668 }\r
669\r
670 EndOfSection = CurrentAddress + Size;\r
671 if (EndOfSection > EndOfFile) {\r
672 return EFI_NOT_FOUND;\r
673 }\r
674\r
675 //\r
676 // Look for executable sections\r
677 //\r
ac0a286f 678 if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {\r
bb4aa855 679 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
ac0a286f 680 *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
bb4aa855 681 }\r
ac0a286f 682\r
bb4aa855
JJ
683 break;\r
684 }\r
685 }\r
686\r
687 //\r
688 // SEC Core image found\r
689 //\r
690 if (*SecCoreImageBase != 0) {\r
691 return EFI_SUCCESS;\r
692 }\r
693 }\r
694}\r
695\r
696/*\r
697 Find and return Pei Core entry point.\r
698\r
f17c0ab6 699 It also find SEC and PEI Core file debug information. It will report them if\r
bb4aa855
JJ
700 remote debug is enabled.\r
701\r
702**/\r
703VOID\r
bb4aa855 704FindAndReportEntryPoints (\r
ac0a286f
MK
705 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
706 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
bb4aa855
JJ
707 )\r
708{\r
ac0a286f
MK
709 EFI_STATUS Status;\r
710 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
711 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
712 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
bb4aa855
JJ
713\r
714 //\r
715 // Find SEC Core and PEI Core image base\r
ac0a286f 716 //\r
bb4aa855
JJ
717 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
718 ASSERT_EFI_ERROR (Status);\r
719\r
720 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
4040754d 721\r
ac0a286f 722 ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
bb4aa855
JJ
723 //\r
724 // Report SEC Core debug information when remote debug is enabled\r
725 //\r
726 ImageContext.ImageAddress = SecCoreImageBase;\r
ac0a286f 727 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);\r
bb4aa855
JJ
728 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
729\r
730 //\r
731 // Report PEI Core debug information when remote debug is enabled\r
732 //\r
733 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
ac0a286f 734 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);\r
bb4aa855
JJ
735 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
736\r
737 //\r
738 // Find PEI Core entry point\r
739 //\r
ac0a286f 740 Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint);\r
bb4aa855
JJ
741 if (EFI_ERROR (Status)) {\r
742 *PeiCoreEntryPoint = 0;\r
743 }\r
744\r
745 return;\r
746}\r
747\r
748VOID\r
749EFIAPI\r
750SecCoreStartupWithStack (\r
ac0a286f
MK
751 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
752 IN VOID *TopOfCurrentStack\r
bb4aa855
JJ
753 )\r
754{\r
ac0a286f
MK
755 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
756 SEC_IDT_TABLE IdtTableInStack;\r
757 IA32_DESCRIPTOR IdtDescriptor;\r
758 UINT32 Index;\r
759 volatile UINT8 *Table;\r
320b4f08 760\r
2b80269d 761 #if defined (TDX_GUEST_SUPPORTED)\r
76fda1de 762 if (CcProbe () == CcGuestTypeIntelTdx) {\r
6ea50514
MX
763 //\r
764 // From the security perspective all the external input should be measured before\r
765 // it is consumed. TdHob and Configuration FV (Cfv) image are passed from VMM\r
766 // and should be measured here.\r
767 //\r
768 if (EFI_ERROR (TdxHelperMeasureTdHob ())) {\r
769 CpuDeadLoop ();\r
770 }\r
771\r
772 if (EFI_ERROR (TdxHelperMeasureCfvImage ())) {\r
773 CpuDeadLoop ();\r
774 }\r
775\r
2b80269d
MX
776 //\r
777 // For Td guests, the memory map info is in TdHobLib. It should be processed\r
778 // first so that the memory is accepted. Otherwise access to the unaccepted\r
779 // memory will trigger tripple fault.\r
780 //\r
c0984d1f 781 if (TdxHelperProcessTdHob () != EFI_SUCCESS) {\r
2b80269d
MX
782 CpuDeadLoop ();\r
783 }\r
784 }\r
785\r
786 #endif\r
787\r
320b4f08
LE
788 //\r
789 // To ensure SMM can't be compromised on S3 resume, we must force re-init of\r
790 // the BaseExtractGuidedSectionLib. Since this is before library contructors\r
791 // are called, we must use a loop rather than SetMem.\r
792 //\r
ac0a286f 793 Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);\r
320b4f08
LE
794 for (Index = 0;\r
795 Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);\r
ac0a286f
MK
796 ++Index)\r
797 {\r
320b4f08
LE
798 Table[Index] = 0;\r
799 }\r
bb4aa855 800\r
13e5492b
TL
801 //\r
802 // Initialize IDT - Since this is before library constructors are called,\r
803 // we use a loop rather than CopyMem.\r
804 //\r
805 IdtTableInStack.PeiService = NULL;\r
2b80269d 806\r
ac0a286f 807 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {\r
ccca1c2d
MX
808 //\r
809 // Declare the local variables that actually move the data elements as\r
810 // volatile to prevent the optimizer from replacing this function with\r
811 // the intrinsic memcpy()\r
812 //\r
813 CONST UINT8 *Src;\r
814 volatile UINT8 *Dst;\r
815 UINTN Byte;\r
13e5492b 816\r
ccca1c2d
MX
817 Src = (CONST UINT8 *)&mIdtEntryTemplate;\r
818 Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];\r
13e5492b
TL
819 for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {\r
820 Dst[Byte] = Src[Byte];\r
821 }\r
822 }\r
823\r
824 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
825 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
826\r
827 if (SevEsIsEnabled ()) {\r
828 SevEsProtocolCheck ();\r
829\r
830 //\r
831 // For SEV-ES guests, the exception handler is needed before calling\r
832 // ProcessLibraryConstructorList() because some of the library constructors\r
833 // perform some functions that result in #VC exceptions being generated.\r
834 //\r
835 // Due to this code executing before library constructors, *all* library\r
836 // API calls are theoretically interface contract violations. However,\r
837 // because this is SEC (executing in flash), those constructors cannot\r
838 // write variables with static storage duration anyway. Furthermore, only\r
839 // a small, restricted set of APIs, such as AsmWriteIdtr() and\r
840 // InitializeCpuExceptionHandlers(), are called, where we require that the\r
841 // underlying library not require constructors to have been invoked and\r
842 // that the library instance not trigger any #VC exceptions.\r
843 //\r
844 AsmWriteIdtr (&IdtDescriptor);\r
845 InitializeCpuExceptionHandlers (NULL);\r
846 }\r
847\r
bb4aa855
JJ
848 ProcessLibraryConstructorList (NULL, NULL);\r
849\r
13e5492b
TL
850 if (!SevEsIsEnabled ()) {\r
851 //\r
852 // For non SEV-ES guests, just load the IDTR.\r
853 //\r
854 AsmWriteIdtr (&IdtDescriptor);\r
e2db781f
TL
855 } else {\r
856 //\r
857 // Under SEV-ES, the hypervisor can't modify CR0 and so can't enable\r
858 // caching in order to speed up the boot. Enable caching early for\r
859 // an SEV-ES guest.\r
860 //\r
861 AsmEnableCache ();\r
13e5492b
TL
862 }\r
863\r
2b80269d 864 #if defined (TDX_GUEST_SUPPORTED)\r
76fda1de 865 if (CcProbe () == CcGuestTypeIntelTdx) {\r
2b80269d
MX
866 //\r
867 // InitializeCpuExceptionHandlers () should be called in Td guests so that\r
868 // #VE exceptions can be handled correctly.\r
869 //\r
870 InitializeCpuExceptionHandlers (NULL);\r
871 }\r
872\r
873 #endif\r
874\r
ac0a286f
MK
875 DEBUG ((\r
876 DEBUG_INFO,\r
bb4aa855
JJ
877 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
878 (UINT32)(UINTN)BootFv,\r
879 (UINT32)(UINTN)TopOfCurrentStack\r
880 ));\r
881\r
882 //\r
883 // Initialize floating point operating environment\r
884 // to be compliant with UEFI spec.\r
885 //\r
886 InitializeFloatingPointUnits ();\r
887\r
ac0a286f 888 #if defined (MDE_CPU_X64)\r
b382ede3
JJ
889 //\r
890 // ASSERT that the Page Tables were set by the reset vector code to\r
891 // the address we expect.\r
892 //\r
ac0a286f
MK
893 ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));\r
894 #endif\r
b382ede3 895\r
bb4aa855
JJ
896 //\r
897 // |-------------| <-- TopOfCurrentStack\r
898 // | Stack | 32k\r
899 // |-------------|\r
900 // | Heap | 32k\r
901 // |-------------| <-- SecCoreData.TemporaryRamBase\r
902 //\r
903\r
ac0a286f
MK
904 ASSERT (\r
905 (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
906 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
907 (UINTN)TopOfCurrentStack\r
908 );\r
7cb6b0e0 909\r
bb4aa855
JJ
910 //\r
911 // Initialize SEC hand-off state\r
912 //\r
ac0a286f 913 SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);\r
bb4aa855 914\r
ac0a286f
MK
915 SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
916 SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
bb4aa855 917\r
ac0a286f
MK
918 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
919 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
bb4aa855 920\r
ac0a286f
MK
921 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
922 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
bb4aa855
JJ
923\r
924 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
ac0a286f 925 SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;\r
bb4aa855 926\r
202fb22b
BS
927 //\r
928 // Validate the System RAM used in the SEC Phase\r
929 //\r
930 SecValidateSystemRam ();\r
931\r
bb4aa855
JJ
932 //\r
933 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
934 //\r
935 IoWrite8 (0x21, 0xff);\r
936 IoWrite8 (0xA1, 0xff);\r
f3e34b9d
MK
937\r
938 //\r
939 // Initialize Local APIC Timer hardware and disable Local APIC Timer\r
940 // interrupts before initializing the Debug Agent and the debug timer is\r
941 // enabled.\r
942 //\r
943 InitializeApicTimer (0, MAX_UINT32, TRUE, 5);\r
944 DisableApicTimerInterrupt ();\r
4040754d 945\r
bb4aa855
JJ
946 //\r
947 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
948 //\r
949 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
950}\r
4040754d 951\r
bb4aa855
JJ
952/**\r
953 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
954\r
955 Entry point to the C language phase of SEC. After the SEC assembly\r
956 code has initialized some temporary memory and set up the stack,\r
957 the control is transferred to this function.\r
958\r
959 @param[in] Context The first input parameter of InitializeDebugAgent().\r
960\r
961**/\r
962VOID\r
963EFIAPI\r
ac0a286f
MK
964SecStartupPhase2 (\r
965 IN VOID *Context\r
bb4aa855
JJ
966 )\r
967{\r
968 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
969 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
970 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
b63a49e0 971 EFI_PEI_PPI_DESCRIPTOR *EfiPeiPpiDescriptor;\r
4040754d 972\r
ac0a286f 973 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;\r
4040754d 974\r
bb4aa855
JJ
975 //\r
976 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
977 // is enabled.\r
978 //\r
979 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
980 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
981 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
ac0a286f 982 SecCoreData->BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;\r
bb4aa855 983\r
b63a49e0
MX
984 //\r
985 // Td guest is required to use the MpInitLibUp (unique-processor version).\r
986 // Other guests use the MpInitLib (multi-processor version).\r
987 //\r
988 if (CcProbe () == CcGuestTypeIntelTdx) {\r
989 EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableUp;\r
990 } else {\r
991 EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableMp;\r
992 }\r
993\r
bb4aa855
JJ
994 //\r
995 // Transfer the control to the PEI core\r
996 //\r
b63a49e0 997 (*PeiCoreEntryPoint)(SecCoreData, EfiPeiPpiDescriptor);\r
4040754d 998\r
bb4aa855
JJ
999 //\r
1000 // If we get here then the PEI Core returned, which is not recoverable.\r
1001 //\r
1002 ASSERT (FALSE);\r
1003 CpuDeadLoop ();\r
1004}\r
1005\r
1006EFI_STATUS\r
1007EFIAPI\r
1008TemporaryRamMigration (\r
ac0a286f
MK
1009 IN CONST EFI_PEI_SERVICES **PeiServices,\r
1010 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
1011 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
1012 IN UINTN CopySize\r
bb4aa855
JJ
1013 )\r
1014{\r
1015 IA32_DESCRIPTOR IdtDescriptor;\r
1016 VOID *OldHeap;\r
1017 VOID *NewHeap;\r
1018 VOID *OldStack;\r
1019 VOID *NewStack;\r
1020 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
1021 BOOLEAN OldStatus;\r
1022 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
4040754d 1023\r
ac0a286f
MK
1024 DEBUG ((\r
1025 DEBUG_INFO,\r
6394c35a
LE
1026 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",\r
1027 TemporaryMemoryBase,\r
1028 PermanentMemoryBase,\r
1029 (UINT64)CopySize\r
c67178b7 1030 ));\r
4040754d 1031\r
ac0a286f
MK
1032 OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;\r
1033 NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
4040754d 1034\r
ac0a286f
MK
1035 OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
1036 NewStack = (VOID *)(UINTN)PermanentMemoryBase;\r
bb4aa855 1037\r
ac0a286f 1038 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
bb4aa855 1039 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
4040754d 1040\r
bb4aa855 1041 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
ac0a286f 1042 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *)&DebugAgentContext, NULL);\r
bb4aa855
JJ
1043\r
1044 //\r
1045 // Migrate Heap\r
1046 //\r
1047 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
1048\r
1049 //\r
1050 // Migrate Stack\r
1051 //\r
1052 CopyMem (NewStack, OldStack, CopySize >> 1);\r
4040754d 1053\r
bb4aa855
JJ
1054 //\r
1055 // Rebase IDT table in permanent memory\r
1056 //\r
1057 AsmReadIdtr (&IdtDescriptor);\r
1058 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
1059\r
1060 AsmWriteIdtr (&IdtDescriptor);\r
1061\r
1062 //\r
1063 // Use SetJump()/LongJump() to switch to a new stack.\r
4040754d 1064 //\r
bb4aa855 1065 if (SetJump (&JumpBuffer) == 0) {\r
ac0a286f 1066 #if defined (MDE_CPU_IA32)\r
bb4aa855 1067 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
89796c69 1068 JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset;\r
ac0a286f
MK
1069 #endif\r
1070 #if defined (MDE_CPU_X64)\r
bb4aa855 1071 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
89796c69 1072 JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset;\r
ac0a286f 1073 #endif\r
bb4aa855
JJ
1074 LongJump (&JumpBuffer, (UINTN)-1);\r
1075 }\r
1076\r
1077 SaveAndSetDebugTimerInterrupt (OldStatus);\r
1078\r
1079 return EFI_SUCCESS;\r
1080}\r