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>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/PeimEntryPoint.h>
14 #include <Library/BaseLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/PeiServicesLib.h>
18 #include <Library/PcdLib.h>
19 #include <Library/UefiCpuLib.h>
20 #include <Library/DebugAgentLib.h>
21 #include <Library/IoLib.h>
22 #include <Library/PeCoffLib.h>
23 #include <Library/PeCoffGetEntryPointLib.h>
24 #include <Library/PeCoffExtraActionLib.h>
25 #include <Library/ExtractGuidedSectionLib.h>
26 #include <Library/LocalApicLib.h>
27 #include <Library/CpuExceptionHandlerLib.h>
28 #include <Register/Amd/Ghcb.h>
29 #include <Register/Amd/Msr.h>
31 #include <Ppi/TemporaryRamSupport.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
];
40 typedef struct _SEC_SEV_ES_WORK_AREA
{
42 } SEC_SEV_ES_WORK_AREA
;
52 TemporaryRamMigration (
53 IN CONST EFI_PEI_SERVICES
**PeiServices
,
54 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
55 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
62 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi
= {
66 EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable
[] = {
68 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
69 &gEfiTemporaryRamSupportPpiGuid
,
70 &mTemporaryRamSupportPpi
75 // Template of an IDT entry pointing to 10:FFFFFFE4h.
77 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate
= {
82 IA32_IDT_GATE_TYPE_INTERRUPT_32
, // GateType
88 Locates the main boot firmware volume.
90 @param[in,out] BootFv On input, the base of the BootFv
91 On output, the decompressed main firmware volume
93 @retval EFI_SUCCESS The main firmware volume was located and decompressed
94 @retval EFI_NOT_FOUND The main firmware volume was not found
99 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**BootFv
102 EFI_FIRMWARE_VOLUME_HEADER
*Fv
;
105 ASSERT (((UINTN
) *BootFv
& EFI_PAGE_MASK
) == 0);
108 Distance
= (UINTN
) (*BootFv
)->FvLength
;
110 Fv
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) Fv
- EFI_PAGE_SIZE
);
111 Distance
+= EFI_PAGE_SIZE
;
112 if (Distance
> SIZE_32MB
) {
113 return EFI_NOT_FOUND
;
116 if (Fv
->Signature
!= EFI_FVH_SIGNATURE
) {
120 if ((UINTN
) Fv
->FvLength
> Distance
) {
131 Locates a section within a series of sections
132 with the specified section type.
134 The Instance parameter indicates which instance of the section
135 type to return. (0 is first instance, 1 is second...)
137 @param[in] Sections The sections to search
138 @param[in] SizeOfSections Total size of all sections
139 @param[in] SectionType The section type to locate
140 @param[in] Instance The section instance number
141 @param[out] FoundSection The FFS section if found
143 @retval EFI_SUCCESS The file and section was found
144 @retval EFI_NOT_FOUND The file and section was not found
145 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
149 FindFfsSectionInstance (
151 IN UINTN SizeOfSections
,
152 IN EFI_SECTION_TYPE SectionType
,
154 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
157 EFI_PHYSICAL_ADDRESS CurrentAddress
;
159 EFI_PHYSICAL_ADDRESS EndOfSections
;
160 EFI_COMMON_SECTION_HEADER
*Section
;
161 EFI_PHYSICAL_ADDRESS EndOfSection
;
164 // Loop through the FFS file sections within the PEI Core FFS file
166 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Sections
;
167 EndOfSections
= EndOfSection
+ SizeOfSections
;
169 if (EndOfSection
== EndOfSections
) {
172 CurrentAddress
= (EndOfSection
+ 3) & ~(3ULL);
173 if (CurrentAddress
>= EndOfSections
) {
174 return EFI_VOLUME_CORRUPTED
;
177 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
) CurrentAddress
;
179 Size
= SECTION_SIZE (Section
);
180 if (Size
< sizeof (*Section
)) {
181 return EFI_VOLUME_CORRUPTED
;
184 EndOfSection
= CurrentAddress
+ Size
;
185 if (EndOfSection
> EndOfSections
) {
186 return EFI_VOLUME_CORRUPTED
;
190 // Look for the requested section type
192 if (Section
->Type
== SectionType
) {
194 *FoundSection
= Section
;
202 return EFI_NOT_FOUND
;
206 Locates a section within a series of sections
207 with the specified section type.
209 @param[in] Sections The sections to search
210 @param[in] SizeOfSections Total size of all sections
211 @param[in] SectionType The section type to locate
212 @param[out] FoundSection The FFS section if found
214 @retval EFI_SUCCESS The file and section was found
215 @retval EFI_NOT_FOUND The file and section was not found
216 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
220 FindFfsSectionInSections (
222 IN UINTN SizeOfSections
,
223 IN EFI_SECTION_TYPE SectionType
,
224 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
227 return FindFfsSectionInstance (
237 Locates a FFS file with the specified file type and a section
238 within that file with the specified section type.
240 @param[in] Fv The firmware volume to search
241 @param[in] FileType The file type to locate
242 @param[in] SectionType The section type to locate
243 @param[out] FoundSection The FFS section if found
245 @retval EFI_SUCCESS The file and section was found
246 @retval EFI_NOT_FOUND The file and section was not found
247 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
251 FindFfsFileAndSection (
252 IN EFI_FIRMWARE_VOLUME_HEADER
*Fv
,
253 IN EFI_FV_FILETYPE FileType
,
254 IN EFI_SECTION_TYPE SectionType
,
255 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
259 EFI_PHYSICAL_ADDRESS CurrentAddress
;
260 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume
;
261 EFI_FFS_FILE_HEADER
*File
;
263 EFI_PHYSICAL_ADDRESS EndOfFile
;
265 if (Fv
->Signature
!= EFI_FVH_SIGNATURE
) {
266 DEBUG ((DEBUG_ERROR
, "FV at %p does not have FV header signature\n", Fv
));
267 return EFI_VOLUME_CORRUPTED
;
270 CurrentAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Fv
;
271 EndOfFirmwareVolume
= CurrentAddress
+ Fv
->FvLength
;
274 // Loop through the FFS files in the Boot Firmware Volume
276 for (EndOfFile
= CurrentAddress
+ Fv
->HeaderLength
; ; ) {
278 CurrentAddress
= (EndOfFile
+ 7) & ~(7ULL);
279 if (CurrentAddress
> EndOfFirmwareVolume
) {
280 return EFI_VOLUME_CORRUPTED
;
283 File
= (EFI_FFS_FILE_HEADER
*)(UINTN
) CurrentAddress
;
284 Size
= FFS_FILE_SIZE (File
);
285 if (Size
< (sizeof (*File
) + sizeof (EFI_COMMON_SECTION_HEADER
))) {
286 return EFI_VOLUME_CORRUPTED
;
289 EndOfFile
= CurrentAddress
+ Size
;
290 if (EndOfFile
> EndOfFirmwareVolume
) {
291 return EFI_VOLUME_CORRUPTED
;
295 // Look for the request file type
297 if (File
->Type
!= FileType
) {
301 Status
= FindFfsSectionInSections (
303 (UINTN
) EndOfFile
- (UINTN
) (File
+ 1),
307 if (!EFI_ERROR (Status
) || (Status
== EFI_VOLUME_CORRUPTED
)) {
314 Locates the compressed main firmware volume and decompresses it.
316 @param[in,out] Fv On input, the firmware volume to search
317 On output, the decompressed BOOT/PEI FV
319 @retval EFI_SUCCESS The file and section was found
320 @retval EFI_NOT_FOUND The file and section was not found
321 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
326 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**Fv
330 EFI_GUID_DEFINED_SECTION
*Section
;
331 UINT32 OutputBufferSize
;
332 UINT32 ScratchBufferSize
;
333 UINT16 SectionAttribute
;
334 UINT32 AuthenticationStatus
;
337 EFI_COMMON_SECTION_HEADER
*FvSection
;
338 EFI_FIRMWARE_VOLUME_HEADER
*PeiMemFv
;
339 EFI_FIRMWARE_VOLUME_HEADER
*DxeMemFv
;
341 UINT32 FvSectionSize
;
343 FvSection
= (EFI_COMMON_SECTION_HEADER
*) NULL
;
345 Status
= FindFfsFileAndSection (
347 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
348 EFI_SECTION_GUID_DEFINED
,
349 (EFI_COMMON_SECTION_HEADER
**) &Section
351 if (EFI_ERROR (Status
)) {
352 DEBUG ((DEBUG_ERROR
, "Unable to find GUID defined section\n"));
356 Status
= ExtractGuidedSectionGetInfo (
362 if (EFI_ERROR (Status
)) {
363 DEBUG ((DEBUG_ERROR
, "Unable to GetInfo for GUIDed section\n"));
367 OutputBuffer
= (VOID
*) ((UINT8
*)(UINTN
) PcdGet32 (PcdOvmfDxeMemFvBase
) + SIZE_1MB
);
368 ScratchBuffer
= ALIGN_POINTER ((UINT8
*) OutputBuffer
+ OutputBufferSize
, SIZE_1MB
);
370 DEBUG ((DEBUG_VERBOSE
, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
371 "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__
, OutputBuffer
,
372 OutputBufferSize
, ScratchBuffer
, ScratchBufferSize
,
373 PcdGet32 (PcdOvmfDecompressionScratchEnd
)));
374 ASSERT ((UINTN
)ScratchBuffer
+ ScratchBufferSize
==
375 PcdGet32 (PcdOvmfDecompressionScratchEnd
));
377 Status
= ExtractGuidedSectionDecode (
381 &AuthenticationStatus
383 if (EFI_ERROR (Status
)) {
384 DEBUG ((DEBUG_ERROR
, "Error during GUID section decode\n"));
388 Status
= FindFfsSectionInstance (
391 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
395 if (EFI_ERROR (Status
)) {
396 DEBUG ((DEBUG_ERROR
, "Unable to find PEI FV section\n"));
400 ASSERT (SECTION_SIZE (FvSection
) ==
401 (PcdGet32 (PcdOvmfPeiMemFvSize
) + sizeof (*FvSection
)));
402 ASSERT (FvSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
);
404 PeiMemFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
) PcdGet32 (PcdOvmfPeiMemFvBase
);
405 CopyMem (PeiMemFv
, (VOID
*) (FvSection
+ 1), PcdGet32 (PcdOvmfPeiMemFvSize
));
407 if (PeiMemFv
->Signature
!= EFI_FVH_SIGNATURE
) {
408 DEBUG ((DEBUG_ERROR
, "Extracted FV at %p does not have FV header signature\n", PeiMemFv
));
410 return EFI_VOLUME_CORRUPTED
;
413 Status
= FindFfsSectionInstance (
416 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
420 if (EFI_ERROR (Status
)) {
421 DEBUG ((DEBUG_ERROR
, "Unable to find DXE FV section\n"));
425 ASSERT (FvSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
);
427 if (IS_SECTION2 (FvSection
)) {
428 FvSectionSize
= SECTION2_SIZE (FvSection
);
429 FvHeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
431 FvSectionSize
= SECTION_SIZE (FvSection
);
432 FvHeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
435 ASSERT (FvSectionSize
== (PcdGet32 (PcdOvmfDxeMemFvSize
) + FvHeaderSize
));
437 DxeMemFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
) PcdGet32 (PcdOvmfDxeMemFvBase
);
438 CopyMem (DxeMemFv
, (VOID
*) ((UINTN
)FvSection
+ FvHeaderSize
), PcdGet32 (PcdOvmfDxeMemFvSize
));
440 if (DxeMemFv
->Signature
!= EFI_FVH_SIGNATURE
) {
441 DEBUG ((DEBUG_ERROR
, "Extracted FV at %p does not have FV header signature\n", DxeMemFv
));
443 return EFI_VOLUME_CORRUPTED
;
451 Locates the PEI Core entry point address
453 @param[in] Fv The firmware volume to search
454 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
456 @retval EFI_SUCCESS The file and section was found
457 @retval EFI_NOT_FOUND The file and section was not found
458 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
462 FindPeiCoreImageBaseInFv (
463 IN EFI_FIRMWARE_VOLUME_HEADER
*Fv
,
464 OUT EFI_PHYSICAL_ADDRESS
*PeiCoreImageBase
468 EFI_COMMON_SECTION_HEADER
*Section
;
470 Status
= FindFfsFileAndSection (
472 EFI_FV_FILETYPE_PEI_CORE
,
476 if (EFI_ERROR (Status
)) {
477 Status
= FindFfsFileAndSection (
479 EFI_FV_FILETYPE_PEI_CORE
,
483 if (EFI_ERROR (Status
)) {
484 DEBUG ((DEBUG_ERROR
, "Unable to find PEI Core image\n"));
489 *PeiCoreImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(Section
+ 1);
495 Reads 8-bits of CMOS data.
497 Reads the 8-bits of CMOS data at the location specified by Index.
498 The 8-bit read value is returned.
500 @param Index The CMOS location to read.
502 @return The value read.
511 IoWrite8 (0x70, (UINT8
) Index
);
512 return IoRead8 (0x71);
522 return (CmosRead8 (0xF) == 0xFE);
529 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**PeiFv
532 *PeiFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
) PcdGet32 (PcdOvmfPeiMemFvBase
);
538 Locates the PEI Core entry point address
540 @param[in,out] Fv The firmware volume to search
541 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
543 @retval EFI_SUCCESS The file and section was found
544 @retval EFI_NOT_FOUND The file and section was not found
545 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
549 FindPeiCoreImageBase (
550 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**BootFv
,
551 OUT EFI_PHYSICAL_ADDRESS
*PeiCoreImageBase
556 *PeiCoreImageBase
= 0;
558 S3Resume
= IsS3Resume ();
559 if (S3Resume
&& !FeaturePcdGet (PcdSmmSmramRequire
)) {
561 // A malicious runtime OS may have injected something into our previously
562 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
564 DEBUG ((DEBUG_VERBOSE
, "SEC: S3 resume\n"));
565 GetS3ResumePeiFv (BootFv
);
568 // We're either not resuming, or resuming "securely" -- we'll decompress
569 // both PEI FV and DXE FV from pristine flash.
571 DEBUG ((DEBUG_VERBOSE
, "SEC: %a\n",
572 S3Resume
? "S3 resume (with PEI decompression)" : "Normal boot"));
575 DecompressMemFvs (BootFv
);
578 FindPeiCoreImageBaseInFv (*BootFv
, PeiCoreImageBase
);
582 Find core image base.
587 IN EFI_FIRMWARE_VOLUME_HEADER
*BootFirmwareVolumePtr
,
588 OUT EFI_PHYSICAL_ADDRESS
*SecCoreImageBase
591 EFI_PHYSICAL_ADDRESS CurrentAddress
;
592 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume
;
593 EFI_FFS_FILE_HEADER
*File
;
595 EFI_PHYSICAL_ADDRESS EndOfFile
;
596 EFI_COMMON_SECTION_HEADER
*Section
;
597 EFI_PHYSICAL_ADDRESS EndOfSection
;
599 *SecCoreImageBase
= 0;
601 CurrentAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) BootFirmwareVolumePtr
;
602 EndOfFirmwareVolume
= CurrentAddress
+ BootFirmwareVolumePtr
->FvLength
;
605 // Loop through the FFS files in the Boot Firmware Volume
607 for (EndOfFile
= CurrentAddress
+ BootFirmwareVolumePtr
->HeaderLength
; ; ) {
609 CurrentAddress
= (EndOfFile
+ 7) & 0xfffffffffffffff8ULL
;
610 if (CurrentAddress
> EndOfFirmwareVolume
) {
611 return EFI_NOT_FOUND
;
614 File
= (EFI_FFS_FILE_HEADER
*)(UINTN
) CurrentAddress
;
615 Size
= FFS_FILE_SIZE (File
);
616 if (Size
< sizeof (*File
)) {
617 return EFI_NOT_FOUND
;
620 EndOfFile
= CurrentAddress
+ Size
;
621 if (EndOfFile
> EndOfFirmwareVolume
) {
622 return EFI_NOT_FOUND
;
628 if (File
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
) {
633 // Loop through the FFS file sections within the FFS file
635 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) (File
+ 1);
637 CurrentAddress
= (EndOfSection
+ 3) & 0xfffffffffffffffcULL
;
638 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
) CurrentAddress
;
640 Size
= SECTION_SIZE (Section
);
641 if (Size
< sizeof (*Section
)) {
642 return EFI_NOT_FOUND
;
645 EndOfSection
= CurrentAddress
+ Size
;
646 if (EndOfSection
> EndOfFile
) {
647 return EFI_NOT_FOUND
;
651 // Look for executable sections
653 if (Section
->Type
== EFI_SECTION_PE32
|| Section
->Type
== EFI_SECTION_TE
) {
654 if (File
->Type
== EFI_FV_FILETYPE_SECURITY_CORE
) {
655 *SecCoreImageBase
= (PHYSICAL_ADDRESS
) (UINTN
) (Section
+ 1);
662 // SEC Core image found
664 if (*SecCoreImageBase
!= 0) {
671 Find and return Pei Core entry point.
673 It also find SEC and PEI Core file debug information. It will report them if
674 remote debug is enabled.
678 FindAndReportEntryPoints (
679 IN EFI_FIRMWARE_VOLUME_HEADER
**BootFirmwareVolumePtr
,
680 OUT EFI_PEI_CORE_ENTRY_POINT
*PeiCoreEntryPoint
684 EFI_PHYSICAL_ADDRESS SecCoreImageBase
;
685 EFI_PHYSICAL_ADDRESS PeiCoreImageBase
;
686 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
689 // Find SEC Core and PEI Core image base
691 Status
= FindImageBase (*BootFirmwareVolumePtr
, &SecCoreImageBase
);
692 ASSERT_EFI_ERROR (Status
);
694 FindPeiCoreImageBase (BootFirmwareVolumePtr
, &PeiCoreImageBase
);
696 ZeroMem ((VOID
*) &ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
698 // Report SEC Core debug information when remote debug is enabled
700 ImageContext
.ImageAddress
= SecCoreImageBase
;
701 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
702 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
705 // Report PEI Core debug information when remote debug is enabled
707 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PeiCoreImageBase
;
708 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
709 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
712 // Find PEI Core entry point
714 Status
= PeCoffLoaderGetEntryPoint ((VOID
*) (UINTN
) PeiCoreImageBase
, (VOID
**) PeiCoreEntryPoint
);
715 if (EFI_ERROR (Status
)) {
716 *PeiCoreEntryPoint
= 0;
723 Handle an SEV-ES/GHCB protocol check failure.
725 Notify the hypervisor using the VMGEXIT instruction that the SEV-ES guest
726 wishes to be terminated.
728 @param[in] ReasonCode Reason code to provide to the hypervisor for the
734 SevEsProtocolFailure (
738 MSR_SEV_ES_GHCB_REGISTER Msr
;
741 // Use the GHCB MSR Protocol to request termination by the hypervisor
743 Msr
.GhcbPhysicalAddress
= 0;
744 Msr
.GhcbTerminate
.Function
= GHCB_INFO_TERMINATE_REQUEST
;
745 Msr
.GhcbTerminate
.ReasonCodeSet
= GHCB_TERMINATE_GHCB
;
746 Msr
.GhcbTerminate
.ReasonCode
= ReasonCode
;
747 AsmWriteMsr64 (MSR_SEV_ES_GHCB
, Msr
.GhcbPhysicalAddress
);
756 Validate the SEV-ES/GHCB protocol level.
758 Verify that the level of SEV-ES/GHCB protocol supported by the hypervisor
759 and the guest intersect. If they don't intersect, request termination.
768 MSR_SEV_ES_GHCB_REGISTER Msr
;
772 // Use the GHCB MSR Protocol to obtain the GHCB SEV-ES Information for
775 Msr
.GhcbPhysicalAddress
= 0;
776 Msr
.GhcbInfo
.Function
= GHCB_INFO_SEV_INFO_GET
;
777 AsmWriteMsr64 (MSR_SEV_ES_GHCB
, Msr
.GhcbPhysicalAddress
);
781 Msr
.GhcbPhysicalAddress
= AsmReadMsr64 (MSR_SEV_ES_GHCB
);
783 if (Msr
.GhcbInfo
.Function
!= GHCB_INFO_SEV_INFO
) {
784 SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL
);
787 if (Msr
.GhcbProtocol
.SevEsProtocolMin
> Msr
.GhcbProtocol
.SevEsProtocolMax
) {
788 SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL
);
791 if ((Msr
.GhcbProtocol
.SevEsProtocolMin
> GHCB_VERSION_MAX
) ||
792 (Msr
.GhcbProtocol
.SevEsProtocolMax
< GHCB_VERSION_MIN
)) {
793 SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL
);
797 // SEV-ES protocol checking succeeded, set the initial GHCB address
799 Msr
.GhcbPhysicalAddress
= FixedPcdGet32 (PcdOvmfSecGhcbBase
);
800 AsmWriteMsr64 (MSR_SEV_ES_GHCB
, Msr
.GhcbPhysicalAddress
);
803 SetMem (Ghcb
, sizeof (*Ghcb
), 0);
806 // Set the version to the maximum that can be supported
808 Ghcb
->ProtocolVersion
= MIN (Msr
.GhcbProtocol
.SevEsProtocolMax
, GHCB_VERSION_MAX
);
809 Ghcb
->GhcbUsage
= GHCB_STANDARD_USAGE
;
813 Determine if SEV-ES is active.
815 During early booting, SEV-ES support code will set a flag to indicate that
816 SEV-ES is enabled. Return the value of this flag as an indicator that SEV-ES
819 @retval TRUE SEV-ES is enabled
820 @retval FALSE SEV-ES is not enabled
829 SEC_SEV_ES_WORK_AREA
*SevEsWorkArea
;
831 SevEsWorkArea
= (SEC_SEV_ES_WORK_AREA
*) FixedPcdGet32 (PcdSevEsWorkAreaBase
);
833 return ((SevEsWorkArea
!= NULL
) && (SevEsWorkArea
->SevEsEnabled
!= 0));
838 SecCoreStartupWithStack (
839 IN EFI_FIRMWARE_VOLUME_HEADER
*BootFv
,
840 IN VOID
*TopOfCurrentStack
843 EFI_SEC_PEI_HAND_OFF SecCoreData
;
844 SEC_IDT_TABLE IdtTableInStack
;
845 IA32_DESCRIPTOR IdtDescriptor
;
847 volatile UINT8
*Table
;
850 // To ensure SMM can't be compromised on S3 resume, we must force re-init of
851 // the BaseExtractGuidedSectionLib. Since this is before library contructors
852 // are called, we must use a loop rather than SetMem.
854 Table
= (UINT8
*)(UINTN
)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress
);
856 Index
< FixedPcdGet32 (PcdGuidedExtractHandlerTableSize
);
862 // Initialize IDT - Since this is before library constructors are called,
863 // we use a loop rather than CopyMem.
865 IdtTableInStack
.PeiService
= NULL
;
866 for (Index
= 0; Index
< SEC_IDT_ENTRY_COUNT
; Index
++) {
871 Src
= (UINT8
*) &mIdtEntryTemplate
;
872 Dst
= (UINT8
*) &IdtTableInStack
.IdtTable
[Index
];
873 for (Byte
= 0; Byte
< sizeof (mIdtEntryTemplate
); Byte
++) {
874 Dst
[Byte
] = Src
[Byte
];
878 IdtDescriptor
.Base
= (UINTN
)&IdtTableInStack
.IdtTable
;
879 IdtDescriptor
.Limit
= (UINT16
)(sizeof (IdtTableInStack
.IdtTable
) - 1);
881 if (SevEsIsEnabled ()) {
882 SevEsProtocolCheck ();
885 // For SEV-ES guests, the exception handler is needed before calling
886 // ProcessLibraryConstructorList() because some of the library constructors
887 // perform some functions that result in #VC exceptions being generated.
889 // Due to this code executing before library constructors, *all* library
890 // API calls are theoretically interface contract violations. However,
891 // because this is SEC (executing in flash), those constructors cannot
892 // write variables with static storage duration anyway. Furthermore, only
893 // a small, restricted set of APIs, such as AsmWriteIdtr() and
894 // InitializeCpuExceptionHandlers(), are called, where we require that the
895 // underlying library not require constructors to have been invoked and
896 // that the library instance not trigger any #VC exceptions.
898 AsmWriteIdtr (&IdtDescriptor
);
899 InitializeCpuExceptionHandlers (NULL
);
902 ProcessLibraryConstructorList (NULL
, NULL
);
904 if (!SevEsIsEnabled ()) {
906 // For non SEV-ES guests, just load the IDTR.
908 AsmWriteIdtr (&IdtDescriptor
);
912 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
913 (UINT32
)(UINTN
)BootFv
,
914 (UINT32
)(UINTN
)TopOfCurrentStack
918 // Initialize floating point operating environment
919 // to be compliant with UEFI spec.
921 InitializeFloatingPointUnits ();
923 #if defined (MDE_CPU_X64)
925 // ASSERT that the Page Tables were set by the reset vector code to
926 // the address we expect.
928 ASSERT (AsmReadCr3 () == (UINTN
) PcdGet32 (PcdOvmfSecPageTablesBase
));
932 // |-------------| <-- TopOfCurrentStack
936 // |-------------| <-- SecCoreData.TemporaryRamBase
939 ASSERT ((UINTN
) (PcdGet32 (PcdOvmfSecPeiTempRamBase
) +
940 PcdGet32 (PcdOvmfSecPeiTempRamSize
)) ==
941 (UINTN
) TopOfCurrentStack
);
944 // Initialize SEC hand-off state
946 SecCoreData
.DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
948 SecCoreData
.TemporaryRamSize
= (UINTN
) PcdGet32 (PcdOvmfSecPeiTempRamSize
);
949 SecCoreData
.TemporaryRamBase
= (VOID
*)((UINT8
*)TopOfCurrentStack
- SecCoreData
.TemporaryRamSize
);
951 SecCoreData
.PeiTemporaryRamBase
= SecCoreData
.TemporaryRamBase
;
952 SecCoreData
.PeiTemporaryRamSize
= SecCoreData
.TemporaryRamSize
>> 1;
954 SecCoreData
.StackBase
= (UINT8
*)SecCoreData
.TemporaryRamBase
+ SecCoreData
.PeiTemporaryRamSize
;
955 SecCoreData
.StackSize
= SecCoreData
.TemporaryRamSize
>> 1;
957 SecCoreData
.BootFirmwareVolumeBase
= BootFv
;
958 SecCoreData
.BootFirmwareVolumeSize
= (UINTN
) BootFv
->FvLength
;
961 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
963 IoWrite8 (0x21, 0xff);
964 IoWrite8 (0xA1, 0xff);
967 // Initialize Local APIC Timer hardware and disable Local APIC Timer
968 // interrupts before initializing the Debug Agent and the debug timer is
971 InitializeApicTimer (0, MAX_UINT32
, TRUE
, 5);
972 DisableApicTimerInterrupt ();
975 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
977 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC
, &SecCoreData
, SecStartupPhase2
);
981 Caller provided function to be invoked at the end of InitializeDebugAgent().
983 Entry point to the C language phase of SEC. After the SEC assembly
984 code has initialized some temporary memory and set up the stack,
985 the control is transferred to this function.
987 @param[in] Context The first input parameter of InitializeDebugAgent().
996 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
997 EFI_FIRMWARE_VOLUME_HEADER
*BootFv
;
998 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
;
1000 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*) Context
;
1003 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
1006 BootFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
;
1007 FindAndReportEntryPoints (&BootFv
, &PeiCoreEntryPoint
);
1008 SecCoreData
->BootFirmwareVolumeBase
= BootFv
;
1009 SecCoreData
->BootFirmwareVolumeSize
= (UINTN
) BootFv
->FvLength
;
1012 // Transfer the control to the PEI core
1014 (*PeiCoreEntryPoint
) (SecCoreData
, (EFI_PEI_PPI_DESCRIPTOR
*)&mPrivateDispatchTable
);
1017 // If we get here then the PEI Core returned, which is not recoverable.
1025 TemporaryRamMigration (
1026 IN CONST EFI_PEI_SERVICES
**PeiServices
,
1027 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
1028 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
1032 IA32_DESCRIPTOR IdtDescriptor
;
1037 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext
;
1039 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
1042 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
1043 TemporaryMemoryBase
,
1044 PermanentMemoryBase
,
1048 OldHeap
= (VOID
*)(UINTN
)TemporaryMemoryBase
;
1049 NewHeap
= (VOID
*)((UINTN
)PermanentMemoryBase
+ (CopySize
>> 1));
1051 OldStack
= (VOID
*)((UINTN
)TemporaryMemoryBase
+ (CopySize
>> 1));
1052 NewStack
= (VOID
*)(UINTN
)PermanentMemoryBase
;
1054 DebugAgentContext
.HeapMigrateOffset
= (UINTN
)NewHeap
- (UINTN
)OldHeap
;
1055 DebugAgentContext
.StackMigrateOffset
= (UINTN
)NewStack
- (UINTN
)OldStack
;
1057 OldStatus
= SaveAndSetDebugTimerInterrupt (FALSE
);
1058 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC
, (VOID
*) &DebugAgentContext
, NULL
);
1063 CopyMem (NewHeap
, OldHeap
, CopySize
>> 1);
1068 CopyMem (NewStack
, OldStack
, CopySize
>> 1);
1071 // Rebase IDT table in permanent memory
1073 AsmReadIdtr (&IdtDescriptor
);
1074 IdtDescriptor
.Base
= IdtDescriptor
.Base
- (UINTN
)OldStack
+ (UINTN
)NewStack
;
1076 AsmWriteIdtr (&IdtDescriptor
);
1079 // Use SetJump()/LongJump() to switch to a new stack.
1081 if (SetJump (&JumpBuffer
) == 0) {
1082 #if defined (MDE_CPU_IA32)
1083 JumpBuffer
.Esp
= JumpBuffer
.Esp
+ DebugAgentContext
.StackMigrateOffset
;
1084 JumpBuffer
.Ebp
= JumpBuffer
.Ebp
+ DebugAgentContext
.StackMigrateOffset
;
1086 #if defined (MDE_CPU_X64)
1087 JumpBuffer
.Rsp
= JumpBuffer
.Rsp
+ DebugAgentContext
.StackMigrateOffset
;
1088 JumpBuffer
.Rbp
= JumpBuffer
.Rbp
+ DebugAgentContext
.StackMigrateOffset
;
1090 LongJump (&JumpBuffer
, (UINTN
)-1);
1093 SaveAndSetDebugTimerInterrupt (OldStatus
);