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