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