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