2 Main SEC phase code. Transitions to PEI.
4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
14 #include <Library/PeimEntryPoint.h>
15 #include <Library/BaseLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/PeiServicesLib.h>
19 #include <Library/PcdLib.h>
20 #include <Library/UefiCpuLib.h>
21 #include <Library/DebugAgentLib.h>
22 #include <Library/IoLib.h>
23 #include <Library/PeCoffLib.h>
24 #include <Library/PeCoffGetEntryPointLib.h>
25 #include <Library/PeCoffExtraActionLib.h>
26 #include <Library/ExtractGuidedSectionLib.h>
27 #include <Library/LocalApicLib.h>
28 #include <Library/CpuExceptionHandlerLib.h>
29 #include <Ppi/TemporaryRamSupport.h>
30 #include <Library/PlatformInitLib.h>
33 #define SEC_IDT_ENTRY_COUNT 34
35 typedef struct _SEC_IDT_TABLE
{
36 EFI_PEI_SERVICES
*PeiService
;
37 IA32_IDT_GATE_DESCRIPTOR IdtTable
[SEC_IDT_ENTRY_COUNT
];
48 TemporaryRamMigration (
49 IN CONST EFI_PEI_SERVICES
**PeiServices
,
50 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
51 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
58 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi
= {
62 EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable
[] = {
64 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
65 &gEfiTemporaryRamSupportPpiGuid
,
66 &mTemporaryRamSupportPpi
71 // Template of an IDT entry pointing to 10:FFFFFFE4h.
73 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate
= {
78 IA32_IDT_GATE_TYPE_INTERRUPT_32
, // GateType
84 Locates the main boot firmware volume.
86 @param[in,out] BootFv On input, the base of the BootFv
87 On output, the decompressed main firmware volume
89 @retval EFI_SUCCESS The main firmware volume was located and decompressed
90 @retval EFI_NOT_FOUND The main firmware volume was not found
95 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**BootFv
98 EFI_FIRMWARE_VOLUME_HEADER
*Fv
;
101 ASSERT (((UINTN
)*BootFv
& EFI_PAGE_MASK
) == 0);
104 Distance
= (UINTN
)(*BootFv
)->FvLength
;
106 Fv
= (EFI_FIRMWARE_VOLUME_HEADER
*)((UINT8
*)Fv
- EFI_PAGE_SIZE
);
107 Distance
+= EFI_PAGE_SIZE
;
108 if (Distance
> SIZE_32MB
) {
109 return EFI_NOT_FOUND
;
112 if (Fv
->Signature
!= EFI_FVH_SIGNATURE
) {
116 if ((UINTN
)Fv
->FvLength
> Distance
) {
126 Locates a section within a series of sections
127 with the specified section type.
129 The Instance parameter indicates which instance of the section
130 type to return. (0 is first instance, 1 is second...)
132 @param[in] Sections The sections to search
133 @param[in] SizeOfSections Total size of all sections
134 @param[in] SectionType The section type to locate
135 @param[in] Instance The section instance number
136 @param[out] FoundSection The FFS section if found
138 @retval EFI_SUCCESS The file and section was found
139 @retval EFI_NOT_FOUND The file and section was not found
140 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
144 FindFfsSectionInstance (
146 IN UINTN SizeOfSections
,
147 IN EFI_SECTION_TYPE SectionType
,
149 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
152 EFI_PHYSICAL_ADDRESS CurrentAddress
;
154 EFI_PHYSICAL_ADDRESS EndOfSections
;
155 EFI_COMMON_SECTION_HEADER
*Section
;
156 EFI_PHYSICAL_ADDRESS EndOfSection
;
159 // Loop through the FFS file sections within the PEI Core FFS file
161 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Sections
;
162 EndOfSections
= EndOfSection
+ SizeOfSections
;
164 if (EndOfSection
== EndOfSections
) {
168 CurrentAddress
= (EndOfSection
+ 3) & ~(3ULL);
169 if (CurrentAddress
>= EndOfSections
) {
170 return EFI_VOLUME_CORRUPTED
;
173 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
)CurrentAddress
;
175 Size
= SECTION_SIZE (Section
);
176 if (Size
< sizeof (*Section
)) {
177 return EFI_VOLUME_CORRUPTED
;
180 EndOfSection
= CurrentAddress
+ Size
;
181 if (EndOfSection
> EndOfSections
) {
182 return EFI_VOLUME_CORRUPTED
;
186 // Look for the requested section type
188 if (Section
->Type
== SectionType
) {
190 *FoundSection
= Section
;
198 return EFI_NOT_FOUND
;
202 Locates a section within a series of sections
203 with the specified section type.
205 @param[in] Sections The sections to search
206 @param[in] SizeOfSections Total size of all sections
207 @param[in] SectionType The section type to locate
208 @param[out] FoundSection The FFS section if found
210 @retval EFI_SUCCESS The file and section was found
211 @retval EFI_NOT_FOUND The file and section was not found
212 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
216 FindFfsSectionInSections (
218 IN UINTN SizeOfSections
,
219 IN EFI_SECTION_TYPE SectionType
,
220 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
223 return FindFfsSectionInstance (
233 Locates a FFS file with the specified file type and a section
234 within that file with the specified section type.
236 @param[in] Fv The firmware volume to search
237 @param[in] FileType The file type to locate
238 @param[in] SectionType The section type to locate
239 @param[out] FoundSection The FFS section if found
241 @retval EFI_SUCCESS The file and section was found
242 @retval EFI_NOT_FOUND The file and section was not found
243 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
247 FindFfsFileAndSection (
248 IN EFI_FIRMWARE_VOLUME_HEADER
*Fv
,
249 IN EFI_FV_FILETYPE FileType
,
250 IN EFI_SECTION_TYPE SectionType
,
251 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
255 EFI_PHYSICAL_ADDRESS CurrentAddress
;
256 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume
;
257 EFI_FFS_FILE_HEADER
*File
;
259 EFI_PHYSICAL_ADDRESS EndOfFile
;
261 if (Fv
->Signature
!= EFI_FVH_SIGNATURE
) {
262 DEBUG ((DEBUG_ERROR
, "FV at %p does not have FV header signature\n", Fv
));
263 return EFI_VOLUME_CORRUPTED
;
266 CurrentAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)Fv
;
267 EndOfFirmwareVolume
= CurrentAddress
+ Fv
->FvLength
;
270 // Loop through the FFS files in the Boot Firmware Volume
272 for (EndOfFile
= CurrentAddress
+ Fv
->HeaderLength
; ; ) {
273 CurrentAddress
= (EndOfFile
+ 7) & ~(7ULL);
274 if (CurrentAddress
> EndOfFirmwareVolume
) {
275 return EFI_VOLUME_CORRUPTED
;
278 File
= (EFI_FFS_FILE_HEADER
*)(UINTN
)CurrentAddress
;
279 Size
= FFS_FILE_SIZE (File
);
280 if (Size
< (sizeof (*File
) + sizeof (EFI_COMMON_SECTION_HEADER
))) {
281 return EFI_VOLUME_CORRUPTED
;
284 EndOfFile
= CurrentAddress
+ Size
;
285 if (EndOfFile
> EndOfFirmwareVolume
) {
286 return EFI_VOLUME_CORRUPTED
;
290 // Look for the request file type
292 if (File
->Type
!= FileType
) {
296 Status
= FindFfsSectionInSections (
298 (UINTN
)EndOfFile
- (UINTN
)(File
+ 1),
302 if (!EFI_ERROR (Status
) || (Status
== EFI_VOLUME_CORRUPTED
)) {
309 Locates the compressed main firmware volume and decompresses it.
311 @param[in,out] Fv On input, the firmware volume to search
312 On output, the decompressed BOOT/PEI FV
314 @retval EFI_SUCCESS The file and section was found
315 @retval EFI_NOT_FOUND The file and section was not found
316 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
321 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**Fv
325 EFI_GUID_DEFINED_SECTION
*Section
;
326 UINT32 OutputBufferSize
;
327 UINT32 ScratchBufferSize
;
328 UINT16 SectionAttribute
;
329 UINT32 AuthenticationStatus
;
332 EFI_COMMON_SECTION_HEADER
*FvSection
;
333 EFI_FIRMWARE_VOLUME_HEADER
*PeiMemFv
;
334 EFI_FIRMWARE_VOLUME_HEADER
*DxeMemFv
;
336 UINT32 FvSectionSize
;
338 FvSection
= (EFI_COMMON_SECTION_HEADER
*)NULL
;
340 Status
= FindFfsFileAndSection (
342 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
343 EFI_SECTION_GUID_DEFINED
,
344 (EFI_COMMON_SECTION_HEADER
**)&Section
346 if (EFI_ERROR (Status
)) {
347 DEBUG ((DEBUG_ERROR
, "Unable to find GUID defined section\n"));
351 Status
= ExtractGuidedSectionGetInfo (
357 if (EFI_ERROR (Status
)) {
358 DEBUG ((DEBUG_ERROR
, "Unable to GetInfo for GUIDed section\n"));
362 OutputBuffer
= (VOID
*)((UINT8
*)(UINTN
)PcdGet32 (PcdOvmfDxeMemFvBase
) + SIZE_1MB
);
363 ScratchBuffer
= ALIGN_POINTER ((UINT8
*)OutputBuffer
+ OutputBufferSize
, SIZE_1MB
);
367 "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
368 "PcdOvmfDecompressionScratchEnd=0x%x\n",
374 PcdGet32 (PcdOvmfDecompressionScratchEnd
)
377 (UINTN
)ScratchBuffer
+ ScratchBufferSize
==
378 PcdGet32 (PcdOvmfDecompressionScratchEnd
)
381 Status
= ExtractGuidedSectionDecode (
385 &AuthenticationStatus
387 if (EFI_ERROR (Status
)) {
388 DEBUG ((DEBUG_ERROR
, "Error during GUID section decode\n"));
392 Status
= FindFfsSectionInstance (
395 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
399 if (EFI_ERROR (Status
)) {
400 DEBUG ((DEBUG_ERROR
, "Unable to find PEI FV section\n"));
405 SECTION_SIZE (FvSection
) ==
406 (PcdGet32 (PcdOvmfPeiMemFvSize
) + sizeof (*FvSection
))
408 ASSERT (FvSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
);
410 PeiMemFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)PcdGet32 (PcdOvmfPeiMemFvBase
);
411 CopyMem (PeiMemFv
, (VOID
*)(FvSection
+ 1), PcdGet32 (PcdOvmfPeiMemFvSize
));
413 if (PeiMemFv
->Signature
!= EFI_FVH_SIGNATURE
) {
414 DEBUG ((DEBUG_ERROR
, "Extracted FV at %p does not have FV header signature\n", PeiMemFv
));
416 return EFI_VOLUME_CORRUPTED
;
419 Status
= FindFfsSectionInstance (
422 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
426 if (EFI_ERROR (Status
)) {
427 DEBUG ((DEBUG_ERROR
, "Unable to find DXE FV section\n"));
431 ASSERT (FvSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
);
433 if (IS_SECTION2 (FvSection
)) {
434 FvSectionSize
= SECTION2_SIZE (FvSection
);
435 FvHeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
437 FvSectionSize
= SECTION_SIZE (FvSection
);
438 FvHeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
441 ASSERT (FvSectionSize
== (PcdGet32 (PcdOvmfDxeMemFvSize
) + FvHeaderSize
));
443 DxeMemFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)PcdGet32 (PcdOvmfDxeMemFvBase
);
444 CopyMem (DxeMemFv
, (VOID
*)((UINTN
)FvSection
+ FvHeaderSize
), PcdGet32 (PcdOvmfDxeMemFvSize
));
446 if (DxeMemFv
->Signature
!= EFI_FVH_SIGNATURE
) {
447 DEBUG ((DEBUG_ERROR
, "Extracted FV at %p does not have FV header signature\n", DxeMemFv
));
449 return EFI_VOLUME_CORRUPTED
;
457 Locates the PEI Core entry point address
459 @param[in] Fv The firmware volume to search
460 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
462 @retval EFI_SUCCESS The file and section was found
463 @retval EFI_NOT_FOUND The file and section was not found
464 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
468 FindPeiCoreImageBaseInFv (
469 IN EFI_FIRMWARE_VOLUME_HEADER
*Fv
,
470 OUT EFI_PHYSICAL_ADDRESS
*PeiCoreImageBase
474 EFI_COMMON_SECTION_HEADER
*Section
;
476 Status
= FindFfsFileAndSection (
478 EFI_FV_FILETYPE_PEI_CORE
,
482 if (EFI_ERROR (Status
)) {
483 Status
= FindFfsFileAndSection (
485 EFI_FV_FILETYPE_PEI_CORE
,
489 if (EFI_ERROR (Status
)) {
490 DEBUG ((DEBUG_ERROR
, "Unable to find PEI Core image\n"));
495 *PeiCoreImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(Section
+ 1);
500 Reads 8-bits of CMOS data.
502 Reads the 8-bits of CMOS data at the location specified by Index.
503 The 8-bit read value is returned.
505 @param Index The CMOS location to read.
507 @return The value read.
516 IoWrite8 (0x70, (UINT8
)Index
);
517 return IoRead8 (0x71);
526 return (CmosRead8 (0xF) == 0xFE);
532 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**PeiFv
535 *PeiFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
)PcdGet32 (PcdOvmfPeiMemFvBase
);
540 Locates the PEI Core entry point address
542 @param[in,out] Fv The firmware volume to search
543 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
545 @retval EFI_SUCCESS The file and section was found
546 @retval EFI_NOT_FOUND The file and section was not found
547 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
551 FindPeiCoreImageBase (
552 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**BootFv
,
553 OUT EFI_PHYSICAL_ADDRESS
*PeiCoreImageBase
558 *PeiCoreImageBase
= 0;
560 S3Resume
= IsS3Resume ();
561 if (S3Resume
&& !FeaturePcdGet (PcdSmmSmramRequire
)) {
563 // A malicious runtime OS may have injected something into our previously
564 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
566 DEBUG ((DEBUG_VERBOSE
, "SEC: S3 resume\n"));
567 GetS3ResumePeiFv (BootFv
);
570 // We're either not resuming, or resuming "securely" -- we'll decompress
571 // both PEI FV and DXE FV from pristine flash.
576 S3Resume
? "S3 resume (with PEI decompression)" : "Normal boot"
580 DecompressMemFvs (BootFv
);
583 FindPeiCoreImageBaseInFv (*BootFv
, PeiCoreImageBase
);
587 Find core image base.
592 IN EFI_FIRMWARE_VOLUME_HEADER
*BootFirmwareVolumePtr
,
593 OUT EFI_PHYSICAL_ADDRESS
*SecCoreImageBase
596 EFI_PHYSICAL_ADDRESS CurrentAddress
;
597 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume
;
598 EFI_FFS_FILE_HEADER
*File
;
600 EFI_PHYSICAL_ADDRESS EndOfFile
;
601 EFI_COMMON_SECTION_HEADER
*Section
;
602 EFI_PHYSICAL_ADDRESS EndOfSection
;
604 *SecCoreImageBase
= 0;
606 CurrentAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)BootFirmwareVolumePtr
;
607 EndOfFirmwareVolume
= CurrentAddress
+ BootFirmwareVolumePtr
->FvLength
;
610 // Loop through the FFS files in the Boot Firmware Volume
612 for (EndOfFile
= CurrentAddress
+ BootFirmwareVolumePtr
->HeaderLength
; ; ) {
613 CurrentAddress
= (EndOfFile
+ 7) & 0xfffffffffffffff8ULL
;
614 if (CurrentAddress
> EndOfFirmwareVolume
) {
615 return EFI_NOT_FOUND
;
618 File
= (EFI_FFS_FILE_HEADER
*)(UINTN
)CurrentAddress
;
619 Size
= FFS_FILE_SIZE (File
);
620 if (Size
< sizeof (*File
)) {
621 return EFI_NOT_FOUND
;
624 EndOfFile
= CurrentAddress
+ Size
;
625 if (EndOfFile
> EndOfFirmwareVolume
) {
626 return EFI_NOT_FOUND
;
632 if (File
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
) {
637 // Loop through the FFS file sections within the FFS file
639 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(File
+ 1);
641 CurrentAddress
= (EndOfSection
+ 3) & 0xfffffffffffffffcULL
;
642 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
)CurrentAddress
;
644 Size
= SECTION_SIZE (Section
);
645 if (Size
< sizeof (*Section
)) {
646 return EFI_NOT_FOUND
;
649 EndOfSection
= CurrentAddress
+ Size
;
650 if (EndOfSection
> EndOfFile
) {
651 return EFI_NOT_FOUND
;
655 // Look for executable sections
657 if ((Section
->Type
== EFI_SECTION_PE32
) || (Section
->Type
== EFI_SECTION_TE
)) {
658 if (File
->Type
== EFI_FV_FILETYPE_SECURITY_CORE
) {
659 *SecCoreImageBase
= (PHYSICAL_ADDRESS
)(UINTN
)(Section
+ 1);
667 // SEC Core image found
669 if (*SecCoreImageBase
!= 0) {
676 Find and return Pei Core entry point.
678 It also find SEC and PEI Core file debug information. It will report them if
679 remote debug is enabled.
683 FindAndReportEntryPoints (
684 IN EFI_FIRMWARE_VOLUME_HEADER
**BootFirmwareVolumePtr
,
685 OUT EFI_PEI_CORE_ENTRY_POINT
*PeiCoreEntryPoint
689 EFI_PHYSICAL_ADDRESS SecCoreImageBase
;
690 EFI_PHYSICAL_ADDRESS PeiCoreImageBase
;
691 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
694 // Find SEC Core and PEI Core image base
696 Status
= FindImageBase (*BootFirmwareVolumePtr
, &SecCoreImageBase
);
697 ASSERT_EFI_ERROR (Status
);
699 FindPeiCoreImageBase (BootFirmwareVolumePtr
, &PeiCoreImageBase
);
701 ZeroMem ((VOID
*)&ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
703 // Report SEC Core debug information when remote debug is enabled
705 ImageContext
.ImageAddress
= SecCoreImageBase
;
706 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageContext
.ImageAddress
);
707 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
710 // Report PEI Core debug information when remote debug is enabled
712 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PeiCoreImageBase
;
713 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageContext
.ImageAddress
);
714 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
717 // Find PEI Core entry point
719 Status
= PeCoffLoaderGetEntryPoint ((VOID
*)(UINTN
)PeiCoreImageBase
, (VOID
**)PeiCoreEntryPoint
);
720 if (EFI_ERROR (Status
)) {
721 *PeiCoreEntryPoint
= 0;
729 SecCoreStartupWithStack (
730 IN EFI_FIRMWARE_VOLUME_HEADER
*BootFv
,
731 IN VOID
*TopOfCurrentStack
734 EFI_SEC_PEI_HAND_OFF SecCoreData
;
735 SEC_IDT_TABLE IdtTableInStack
;
736 IA32_DESCRIPTOR IdtDescriptor
;
738 volatile UINT8
*Table
;
740 #if defined (TDX_GUEST_SUPPORTED)
741 if (TdIsEnabled ()) {
743 // For Td guests, the memory map info is in TdHobLib. It should be processed
744 // first so that the memory is accepted. Otherwise access to the unaccepted
745 // memory will trigger tripple fault.
747 if (ProcessTdxHobList () != EFI_SUCCESS
) {
755 // To ensure SMM can't be compromised on S3 resume, we must force re-init of
756 // the BaseExtractGuidedSectionLib. Since this is before library contructors
757 // are called, we must use a loop rather than SetMem.
759 Table
= (UINT8
*)(UINTN
)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress
);
761 Index
< FixedPcdGet32 (PcdGuidedExtractHandlerTableSize
);
768 // Initialize IDT - Since this is before library constructors are called,
769 // we use a loop rather than CopyMem.
771 IdtTableInStack
.PeiService
= NULL
;
773 for (Index
= 0; Index
< SEC_IDT_ENTRY_COUNT
; Index
++) {
775 // Declare the local variables that actually move the data elements as
776 // volatile to prevent the optimizer from replacing this function with
777 // the intrinsic memcpy()
783 Src
= (CONST UINT8
*)&mIdtEntryTemplate
;
784 Dst
= (volatile UINT8
*)&IdtTableInStack
.IdtTable
[Index
];
785 for (Byte
= 0; Byte
< sizeof (mIdtEntryTemplate
); Byte
++) {
786 Dst
[Byte
] = Src
[Byte
];
790 IdtDescriptor
.Base
= (UINTN
)&IdtTableInStack
.IdtTable
;
791 IdtDescriptor
.Limit
= (UINT16
)(sizeof (IdtTableInStack
.IdtTable
) - 1);
793 if (SevEsIsEnabled ()) {
794 SevEsProtocolCheck ();
797 // For SEV-ES guests, the exception handler is needed before calling
798 // ProcessLibraryConstructorList() because some of the library constructors
799 // perform some functions that result in #VC exceptions being generated.
801 // Due to this code executing before library constructors, *all* library
802 // API calls are theoretically interface contract violations. However,
803 // because this is SEC (executing in flash), those constructors cannot
804 // write variables with static storage duration anyway. Furthermore, only
805 // a small, restricted set of APIs, such as AsmWriteIdtr() and
806 // InitializeCpuExceptionHandlers(), are called, where we require that the
807 // underlying library not require constructors to have been invoked and
808 // that the library instance not trigger any #VC exceptions.
810 AsmWriteIdtr (&IdtDescriptor
);
811 InitializeCpuExceptionHandlers (NULL
);
814 ProcessLibraryConstructorList (NULL
, NULL
);
816 if (!SevEsIsEnabled ()) {
818 // For non SEV-ES guests, just load the IDTR.
820 AsmWriteIdtr (&IdtDescriptor
);
823 // Under SEV-ES, the hypervisor can't modify CR0 and so can't enable
824 // caching in order to speed up the boot. Enable caching early for
830 #if defined (TDX_GUEST_SUPPORTED)
831 if (TdIsEnabled ()) {
833 // InitializeCpuExceptionHandlers () should be called in Td guests so that
834 // #VE exceptions can be handled correctly.
836 InitializeCpuExceptionHandlers (NULL
);
843 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
844 (UINT32
)(UINTN
)BootFv
,
845 (UINT32
)(UINTN
)TopOfCurrentStack
849 // Initialize floating point operating environment
850 // to be compliant with UEFI spec.
852 InitializeFloatingPointUnits ();
854 #if defined (MDE_CPU_X64)
856 // ASSERT that the Page Tables were set by the reset vector code to
857 // the address we expect.
859 ASSERT (AsmReadCr3 () == (UINTN
)PcdGet32 (PcdOvmfSecPageTablesBase
));
863 // |-------------| <-- TopOfCurrentStack
867 // |-------------| <-- SecCoreData.TemporaryRamBase
871 (UINTN
)(PcdGet32 (PcdOvmfSecPeiTempRamBase
) +
872 PcdGet32 (PcdOvmfSecPeiTempRamSize
)) ==
873 (UINTN
)TopOfCurrentStack
877 // Initialize SEC hand-off state
879 SecCoreData
.DataSize
= sizeof (EFI_SEC_PEI_HAND_OFF
);
881 SecCoreData
.TemporaryRamSize
= (UINTN
)PcdGet32 (PcdOvmfSecPeiTempRamSize
);
882 SecCoreData
.TemporaryRamBase
= (VOID
*)((UINT8
*)TopOfCurrentStack
- SecCoreData
.TemporaryRamSize
);
884 SecCoreData
.PeiTemporaryRamBase
= SecCoreData
.TemporaryRamBase
;
885 SecCoreData
.PeiTemporaryRamSize
= SecCoreData
.TemporaryRamSize
>> 1;
887 SecCoreData
.StackBase
= (UINT8
*)SecCoreData
.TemporaryRamBase
+ SecCoreData
.PeiTemporaryRamSize
;
888 SecCoreData
.StackSize
= SecCoreData
.TemporaryRamSize
>> 1;
890 SecCoreData
.BootFirmwareVolumeBase
= BootFv
;
891 SecCoreData
.BootFirmwareVolumeSize
= (UINTN
)BootFv
->FvLength
;
894 // Validate the System RAM used in the SEC Phase
896 SecValidateSystemRam ();
899 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
901 IoWrite8 (0x21, 0xff);
902 IoWrite8 (0xA1, 0xff);
905 // Initialize Local APIC Timer hardware and disable Local APIC Timer
906 // interrupts before initializing the Debug Agent and the debug timer is
909 InitializeApicTimer (0, MAX_UINT32
, TRUE
, 5);
910 DisableApicTimerInterrupt ();
913 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
915 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC
, &SecCoreData
, SecStartupPhase2
);
919 Caller provided function to be invoked at the end of InitializeDebugAgent().
921 Entry point to the C language phase of SEC. After the SEC assembly
922 code has initialized some temporary memory and set up the stack,
923 the control is transferred to this function.
925 @param[in] Context The first input parameter of InitializeDebugAgent().
934 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
935 EFI_FIRMWARE_VOLUME_HEADER
*BootFv
;
936 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
;
938 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*)Context
;
941 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
944 BootFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
;
945 FindAndReportEntryPoints (&BootFv
, &PeiCoreEntryPoint
);
946 SecCoreData
->BootFirmwareVolumeBase
= BootFv
;
947 SecCoreData
->BootFirmwareVolumeSize
= (UINTN
)BootFv
->FvLength
;
950 // Transfer the control to the PEI core
952 (*PeiCoreEntryPoint
)(SecCoreData
, (EFI_PEI_PPI_DESCRIPTOR
*)&mPrivateDispatchTable
);
955 // If we get here then the PEI Core returned, which is not recoverable.
963 TemporaryRamMigration (
964 IN CONST EFI_PEI_SERVICES
**PeiServices
,
965 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
966 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
970 IA32_DESCRIPTOR IdtDescriptor
;
975 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext
;
977 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
981 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
987 OldHeap
= (VOID
*)(UINTN
)TemporaryMemoryBase
;
988 NewHeap
= (VOID
*)((UINTN
)PermanentMemoryBase
+ (CopySize
>> 1));
990 OldStack
= (VOID
*)((UINTN
)TemporaryMemoryBase
+ (CopySize
>> 1));
991 NewStack
= (VOID
*)(UINTN
)PermanentMemoryBase
;
993 DebugAgentContext
.HeapMigrateOffset
= (UINTN
)NewHeap
- (UINTN
)OldHeap
;
994 DebugAgentContext
.StackMigrateOffset
= (UINTN
)NewStack
- (UINTN
)OldStack
;
996 OldStatus
= SaveAndSetDebugTimerInterrupt (FALSE
);
997 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC
, (VOID
*)&DebugAgentContext
, NULL
);
1002 CopyMem (NewHeap
, OldHeap
, CopySize
>> 1);
1007 CopyMem (NewStack
, OldStack
, CopySize
>> 1);
1010 // Rebase IDT table in permanent memory
1012 AsmReadIdtr (&IdtDescriptor
);
1013 IdtDescriptor
.Base
= IdtDescriptor
.Base
- (UINTN
)OldStack
+ (UINTN
)NewStack
;
1015 AsmWriteIdtr (&IdtDescriptor
);
1018 // Use SetJump()/LongJump() to switch to a new stack.
1020 if (SetJump (&JumpBuffer
) == 0) {
1021 #if defined (MDE_CPU_IA32)
1022 JumpBuffer
.Esp
= JumpBuffer
.Esp
+ DebugAgentContext
.StackMigrateOffset
;
1023 JumpBuffer
.Ebp
= JumpBuffer
.Ebp
+ DebugAgentContext
.StackMigrateOffset
;
1025 #if defined (MDE_CPU_X64)
1026 JumpBuffer
.Rsp
= JumpBuffer
.Rsp
+ DebugAgentContext
.StackMigrateOffset
;
1027 JumpBuffer
.Rbp
= JumpBuffer
.Rbp
+ DebugAgentContext
.StackMigrateOffset
;
1029 LongJump (&JumpBuffer
, (UINTN
)-1);
1032 SaveAndSetDebugTimerInterrupt (OldStatus
);