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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Library/PeimEntryPoint.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/PeiServicesLib.h>
24 #include <Library/PcdLib.h>
25 #include <Library/UefiCpuLib.h>
26 #include <Library/DebugAgentLib.h>
27 #include <Library/IoLib.h>
28 #include <Library/PeCoffLib.h>
29 #include <Library/PeCoffGetEntryPointLib.h>
30 #include <Library/PeCoffExtraActionLib.h>
31 #include <Library/ExtractGuidedSectionLib.h>
32 #include <Library/LocalApicLib.h>
34 #include <Ppi/TemporaryRamSupport.h>
36 #define SEC_IDT_ENTRY_COUNT 34
38 typedef struct _SEC_IDT_TABLE
{
39 EFI_PEI_SERVICES
*PeiService
;
40 IA32_IDT_GATE_DESCRIPTOR IdtTable
[SEC_IDT_ENTRY_COUNT
];
51 TemporaryRamMigration (
52 IN CONST EFI_PEI_SERVICES
**PeiServices
,
53 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
54 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
61 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi
= {
65 EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable
[] = {
67 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
68 &gEfiTemporaryRamSupportPpiGuid
,
69 &mTemporaryRamSupportPpi
74 // Template of an IDT entry pointing to 10:FFFFFFE4h.
76 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate
= {
81 IA32_IDT_GATE_TYPE_INTERRUPT_32
, // GateType
87 Locates the main boot firmware volume.
89 @param[in,out] BootFv On input, the base of the BootFv
90 On output, the decompressed main firmware volume
92 @retval EFI_SUCCESS The main firmware volume was located and decompressed
93 @retval EFI_NOT_FOUND The main firmware volume was not found
98 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**BootFv
101 EFI_FIRMWARE_VOLUME_HEADER
*Fv
;
104 ASSERT (((UINTN
) *BootFv
& EFI_PAGE_MASK
) == 0);
107 Distance
= (UINTN
) (*BootFv
)->FvLength
;
109 Fv
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINT8
*) Fv
- EFI_PAGE_SIZE
);
110 Distance
+= EFI_PAGE_SIZE
;
111 if (Distance
> SIZE_32MB
) {
112 return EFI_NOT_FOUND
;
115 if (Fv
->Signature
!= EFI_FVH_SIGNATURE
) {
119 if ((UINTN
) Fv
->FvLength
> Distance
) {
130 Locates a section within a series of sections
131 with the specified section type.
133 The Instance parameter indicates which instance of the section
134 type to return. (0 is first instance, 1 is second...)
136 @param[in] Sections The sections to search
137 @param[in] SizeOfSections Total size of all sections
138 @param[in] SectionType The section type to locate
139 @param[in] Instance The section instance number
140 @param[out] FoundSection The FFS section if found
142 @retval EFI_SUCCESS The file and section was found
143 @retval EFI_NOT_FOUND The file and section was not found
144 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
148 FindFfsSectionInstance (
150 IN UINTN SizeOfSections
,
151 IN EFI_SECTION_TYPE SectionType
,
153 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
156 EFI_PHYSICAL_ADDRESS CurrentAddress
;
158 EFI_PHYSICAL_ADDRESS EndOfSections
;
159 EFI_COMMON_SECTION_HEADER
*Section
;
160 EFI_PHYSICAL_ADDRESS EndOfSection
;
163 // Loop through the FFS file sections within the PEI Core FFS file
165 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Sections
;
166 EndOfSections
= EndOfSection
+ SizeOfSections
;
168 if (EndOfSection
== EndOfSections
) {
171 CurrentAddress
= (EndOfSection
+ 3) & ~(3ULL);
172 if (CurrentAddress
>= EndOfSections
) {
173 return EFI_VOLUME_CORRUPTED
;
176 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
) CurrentAddress
;
178 Size
= SECTION_SIZE (Section
);
179 if (Size
< sizeof (*Section
)) {
180 return EFI_VOLUME_CORRUPTED
;
183 EndOfSection
= CurrentAddress
+ Size
;
184 if (EndOfSection
> EndOfSections
) {
185 return EFI_VOLUME_CORRUPTED
;
189 // Look for the requested section type
191 if (Section
->Type
== SectionType
) {
193 *FoundSection
= Section
;
201 return EFI_NOT_FOUND
;
205 Locates a section within a series of sections
206 with the specified section type.
208 @param[in] Sections The sections to search
209 @param[in] SizeOfSections Total size of all sections
210 @param[in] SectionType The section type to locate
211 @param[out] FoundSection The FFS section if found
213 @retval EFI_SUCCESS The file and section was found
214 @retval EFI_NOT_FOUND The file and section was not found
215 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
219 FindFfsSectionInSections (
221 IN UINTN SizeOfSections
,
222 IN EFI_SECTION_TYPE SectionType
,
223 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
226 return FindFfsSectionInstance (
236 Locates a FFS file with the specified file type and a section
237 within that file with the specified section type.
239 @param[in] Fv The firmware volume to search
240 @param[in] FileType The file type to locate
241 @param[in] SectionType The section type to locate
242 @param[out] FoundSection The FFS section if found
244 @retval EFI_SUCCESS The file and section was found
245 @retval EFI_NOT_FOUND The file and section was not found
246 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
250 FindFfsFileAndSection (
251 IN EFI_FIRMWARE_VOLUME_HEADER
*Fv
,
252 IN EFI_FV_FILETYPE FileType
,
253 IN EFI_SECTION_TYPE SectionType
,
254 OUT EFI_COMMON_SECTION_HEADER
**FoundSection
258 EFI_PHYSICAL_ADDRESS CurrentAddress
;
259 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume
;
260 EFI_FFS_FILE_HEADER
*File
;
262 EFI_PHYSICAL_ADDRESS EndOfFile
;
264 if (Fv
->Signature
!= EFI_FVH_SIGNATURE
) {
265 DEBUG ((EFI_D_ERROR
, "FV at %p does not have FV header signature\n", Fv
));
266 return EFI_VOLUME_CORRUPTED
;
269 CurrentAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) Fv
;
270 EndOfFirmwareVolume
= CurrentAddress
+ Fv
->FvLength
;
273 // Loop through the FFS files in the Boot Firmware Volume
275 for (EndOfFile
= CurrentAddress
+ Fv
->HeaderLength
; ; ) {
277 CurrentAddress
= (EndOfFile
+ 7) & ~(7ULL);
278 if (CurrentAddress
> EndOfFirmwareVolume
) {
279 return EFI_VOLUME_CORRUPTED
;
282 File
= (EFI_FFS_FILE_HEADER
*)(UINTN
) CurrentAddress
;
283 Size
= *(UINT32
*) File
->Size
& 0xffffff;
284 if (Size
< (sizeof (*File
) + sizeof (EFI_COMMON_SECTION_HEADER
))) {
285 return EFI_VOLUME_CORRUPTED
;
288 EndOfFile
= CurrentAddress
+ Size
;
289 if (EndOfFile
> EndOfFirmwareVolume
) {
290 return EFI_VOLUME_CORRUPTED
;
294 // Look for the request file type
296 if (File
->Type
!= FileType
) {
300 Status
= FindFfsSectionInSections (
302 (UINTN
) EndOfFile
- (UINTN
) (File
+ 1),
306 if (!EFI_ERROR (Status
) || (Status
== EFI_VOLUME_CORRUPTED
)) {
313 Locates the compressed main firmware volume and decompresses it.
315 @param[in,out] Fv On input, the firmware volume to search
316 On output, the decompressed BOOT/PEI FV
318 @retval EFI_SUCCESS The file and section was found
319 @retval EFI_NOT_FOUND The file and section was not found
320 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
325 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**Fv
329 EFI_GUID_DEFINED_SECTION
*Section
;
330 UINT32 OutputBufferSize
;
331 UINT32 ScratchBufferSize
;
332 UINT16 SectionAttribute
;
333 UINT32 AuthenticationStatus
;
336 EFI_COMMON_SECTION_HEADER
*FvSection
;
337 EFI_FIRMWARE_VOLUME_HEADER
*PeiMemFv
;
338 EFI_FIRMWARE_VOLUME_HEADER
*DxeMemFv
;
340 FvSection
= (EFI_COMMON_SECTION_HEADER
*) NULL
;
342 Status
= FindFfsFileAndSection (
344 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
,
345 EFI_SECTION_GUID_DEFINED
,
346 (EFI_COMMON_SECTION_HEADER
**) &Section
348 if (EFI_ERROR (Status
)) {
349 DEBUG ((EFI_D_ERROR
, "Unable to find GUID defined section\n"));
353 Status
= ExtractGuidedSectionGetInfo (
359 if (EFI_ERROR (Status
)) {
360 DEBUG ((EFI_D_ERROR
, "Unable to GetInfo for GUIDed section\n"));
364 OutputBuffer
= (VOID
*) ((UINT8
*)(UINTN
) PcdGet32 (PcdOvmfDxeMemFvBase
) + SIZE_1MB
);
365 ScratchBuffer
= ALIGN_POINTER ((UINT8
*) OutputBuffer
+ OutputBufferSize
, SIZE_1MB
);
367 DEBUG ((EFI_D_VERBOSE
, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
368 "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__
, OutputBuffer
,
369 OutputBufferSize
, ScratchBuffer
, ScratchBufferSize
,
370 PcdGet32 (PcdOvmfDecompressionScratchEnd
)));
371 ASSERT ((UINTN
)ScratchBuffer
+ ScratchBufferSize
==
372 PcdGet32 (PcdOvmfDecompressionScratchEnd
));
374 Status
= ExtractGuidedSectionDecode (
378 &AuthenticationStatus
380 if (EFI_ERROR (Status
)) {
381 DEBUG ((EFI_D_ERROR
, "Error during GUID section decode\n"));
385 Status
= FindFfsSectionInstance (
388 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
392 if (EFI_ERROR (Status
)) {
393 DEBUG ((EFI_D_ERROR
, "Unable to find PEI FV section\n"));
397 ASSERT (SECTION_SIZE (FvSection
) ==
398 (PcdGet32 (PcdOvmfPeiMemFvSize
) + sizeof (*FvSection
)));
399 ASSERT (FvSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
);
401 PeiMemFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
) PcdGet32 (PcdOvmfPeiMemFvBase
);
402 CopyMem (PeiMemFv
, (VOID
*) (FvSection
+ 1), PcdGet32 (PcdOvmfPeiMemFvSize
));
404 if (PeiMemFv
->Signature
!= EFI_FVH_SIGNATURE
) {
405 DEBUG ((EFI_D_ERROR
, "Extracted FV at %p does not have FV header signature\n", PeiMemFv
));
407 return EFI_VOLUME_CORRUPTED
;
410 Status
= FindFfsSectionInstance (
413 EFI_SECTION_FIRMWARE_VOLUME_IMAGE
,
417 if (EFI_ERROR (Status
)) {
418 DEBUG ((EFI_D_ERROR
, "Unable to find DXE FV section\n"));
422 ASSERT (FvSection
->Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
);
423 ASSERT (SECTION_SIZE (FvSection
) ==
424 (PcdGet32 (PcdOvmfDxeMemFvSize
) + sizeof (*FvSection
)));
426 DxeMemFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
) PcdGet32 (PcdOvmfDxeMemFvBase
);
427 CopyMem (DxeMemFv
, (VOID
*) (FvSection
+ 1), PcdGet32 (PcdOvmfDxeMemFvSize
));
429 if (DxeMemFv
->Signature
!= EFI_FVH_SIGNATURE
) {
430 DEBUG ((EFI_D_ERROR
, "Extracted FV at %p does not have FV header signature\n", DxeMemFv
));
432 return EFI_VOLUME_CORRUPTED
;
440 Locates the PEI Core entry point address
442 @param[in] Fv The firmware volume to search
443 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
445 @retval EFI_SUCCESS The file and section was found
446 @retval EFI_NOT_FOUND The file and section was not found
447 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
451 FindPeiCoreImageBaseInFv (
452 IN EFI_FIRMWARE_VOLUME_HEADER
*Fv
,
453 OUT EFI_PHYSICAL_ADDRESS
*PeiCoreImageBase
457 EFI_COMMON_SECTION_HEADER
*Section
;
459 Status
= FindFfsFileAndSection (
461 EFI_FV_FILETYPE_PEI_CORE
,
465 if (EFI_ERROR (Status
)) {
466 Status
= FindFfsFileAndSection (
468 EFI_FV_FILETYPE_PEI_CORE
,
472 if (EFI_ERROR (Status
)) {
473 DEBUG ((EFI_D_ERROR
, "Unable to find PEI Core image\n"));
478 *PeiCoreImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(Section
+ 1);
484 Reads 8-bits of CMOS data.
486 Reads the 8-bits of CMOS data at the location specified by Index.
487 The 8-bit read value is returned.
489 @param Index The CMOS location to read.
491 @return The value read.
500 IoWrite8 (0x70, (UINT8
) Index
);
501 return IoRead8 (0x71);
511 return (CmosRead8 (0xF) == 0xFE);
518 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**PeiFv
521 *PeiFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)(UINTN
) PcdGet32 (PcdOvmfPeiMemFvBase
);
527 Locates the PEI Core entry point address
529 @param[in,out] Fv The firmware volume to search
530 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
532 @retval EFI_SUCCESS The file and section was found
533 @retval EFI_NOT_FOUND The file and section was not found
534 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
538 FindPeiCoreImageBase (
539 IN OUT EFI_FIRMWARE_VOLUME_HEADER
**BootFv
,
540 OUT EFI_PHYSICAL_ADDRESS
*PeiCoreImageBase
545 *PeiCoreImageBase
= 0;
547 S3Resume
= IsS3Resume ();
548 if (S3Resume
&& !FeaturePcdGet (PcdSmmSmramRequire
)) {
550 // A malicious runtime OS may have injected something into our previously
551 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
553 DEBUG ((EFI_D_VERBOSE
, "SEC: S3 resume\n"));
554 GetS3ResumePeiFv (BootFv
);
557 // We're either not resuming, or resuming "securely" -- we'll decompress
558 // both PEI FV and DXE FV from pristine flash.
560 DEBUG ((EFI_D_VERBOSE
, "SEC: %a\n",
561 S3Resume
? "S3 resume (with PEI decompression)" : "Normal boot"));
564 DecompressMemFvs (BootFv
);
567 FindPeiCoreImageBaseInFv (*BootFv
, PeiCoreImageBase
);
571 Find core image base.
576 IN EFI_FIRMWARE_VOLUME_HEADER
*BootFirmwareVolumePtr
,
577 OUT EFI_PHYSICAL_ADDRESS
*SecCoreImageBase
580 EFI_PHYSICAL_ADDRESS CurrentAddress
;
581 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume
;
582 EFI_FFS_FILE_HEADER
*File
;
584 EFI_PHYSICAL_ADDRESS EndOfFile
;
585 EFI_COMMON_SECTION_HEADER
*Section
;
586 EFI_PHYSICAL_ADDRESS EndOfSection
;
588 *SecCoreImageBase
= 0;
590 CurrentAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) BootFirmwareVolumePtr
;
591 EndOfFirmwareVolume
= CurrentAddress
+ BootFirmwareVolumePtr
->FvLength
;
594 // Loop through the FFS files in the Boot Firmware Volume
596 for (EndOfFile
= CurrentAddress
+ BootFirmwareVolumePtr
->HeaderLength
; ; ) {
598 CurrentAddress
= (EndOfFile
+ 7) & 0xfffffffffffffff8ULL
;
599 if (CurrentAddress
> EndOfFirmwareVolume
) {
600 return EFI_NOT_FOUND
;
603 File
= (EFI_FFS_FILE_HEADER
*)(UINTN
) CurrentAddress
;
604 Size
= *(UINT32
*) File
->Size
& 0xffffff;
605 if (Size
< sizeof (*File
)) {
606 return EFI_NOT_FOUND
;
609 EndOfFile
= CurrentAddress
+ Size
;
610 if (EndOfFile
> EndOfFirmwareVolume
) {
611 return EFI_NOT_FOUND
;
617 if (File
->Type
!= EFI_FV_FILETYPE_SECURITY_CORE
) {
622 // Loop through the FFS file sections within the FFS file
624 EndOfSection
= (EFI_PHYSICAL_ADDRESS
)(UINTN
) (File
+ 1);
626 CurrentAddress
= (EndOfSection
+ 3) & 0xfffffffffffffffcULL
;
627 Section
= (EFI_COMMON_SECTION_HEADER
*)(UINTN
) CurrentAddress
;
629 Size
= *(UINT32
*) Section
->Size
& 0xffffff;
630 if (Size
< sizeof (*Section
)) {
631 return EFI_NOT_FOUND
;
634 EndOfSection
= CurrentAddress
+ Size
;
635 if (EndOfSection
> EndOfFile
) {
636 return EFI_NOT_FOUND
;
640 // Look for executable sections
642 if (Section
->Type
== EFI_SECTION_PE32
|| Section
->Type
== EFI_SECTION_TE
) {
643 if (File
->Type
== EFI_FV_FILETYPE_SECURITY_CORE
) {
644 *SecCoreImageBase
= (PHYSICAL_ADDRESS
) (UINTN
) (Section
+ 1);
651 // SEC Core image found
653 if (*SecCoreImageBase
!= 0) {
660 Find and return Pei Core entry point.
662 It also find SEC and PEI Core file debug inforamtion. It will report them if
663 remote debug is enabled.
667 FindAndReportEntryPoints (
668 IN EFI_FIRMWARE_VOLUME_HEADER
**BootFirmwareVolumePtr
,
669 OUT EFI_PEI_CORE_ENTRY_POINT
*PeiCoreEntryPoint
673 EFI_PHYSICAL_ADDRESS SecCoreImageBase
;
674 EFI_PHYSICAL_ADDRESS PeiCoreImageBase
;
675 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
678 // Find SEC Core and PEI Core image base
680 Status
= FindImageBase (*BootFirmwareVolumePtr
, &SecCoreImageBase
);
681 ASSERT_EFI_ERROR (Status
);
683 FindPeiCoreImageBase (BootFirmwareVolumePtr
, &PeiCoreImageBase
);
685 ZeroMem ((VOID
*) &ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
687 // Report SEC Core debug information when remote debug is enabled
689 ImageContext
.ImageAddress
= SecCoreImageBase
;
690 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
691 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
694 // Report PEI Core debug information when remote debug is enabled
696 ImageContext
.ImageAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PeiCoreImageBase
;
697 ImageContext
.PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageContext
.ImageAddress
);
698 PeCoffLoaderRelocateImageExtraAction (&ImageContext
);
701 // Find PEI Core entry point
703 Status
= PeCoffLoaderGetEntryPoint ((VOID
*) (UINTN
) PeiCoreImageBase
, (VOID
**) PeiCoreEntryPoint
);
704 if (EFI_ERROR (Status
)) {
705 *PeiCoreEntryPoint
= 0;
713 SecCoreStartupWithStack (
714 IN EFI_FIRMWARE_VOLUME_HEADER
*BootFv
,
715 IN VOID
*TopOfCurrentStack
718 EFI_SEC_PEI_HAND_OFF SecCoreData
;
719 SEC_IDT_TABLE IdtTableInStack
;
720 IA32_DESCRIPTOR IdtDescriptor
;
722 volatile UINT8
*Table
;
725 // To ensure SMM can't be compromised on S3 resume, we must force re-init of
726 // the BaseExtractGuidedSectionLib. Since this is before library contructors
727 // are called, we must use a loop rather than SetMem.
729 Table
= (UINT8
*)(UINTN
)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress
);
731 Index
< FixedPcdGet32 (PcdGuidedExtractHandlerTableSize
);
736 ProcessLibraryConstructorList (NULL
, NULL
);
739 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
740 (UINT32
)(UINTN
)BootFv
,
741 (UINT32
)(UINTN
)TopOfCurrentStack
745 // Initialize floating point operating environment
746 // to be compliant with UEFI spec.
748 InitializeFloatingPointUnits ();
753 IdtTableInStack
.PeiService
= NULL
;
754 for (Index
= 0; Index
< SEC_IDT_ENTRY_COUNT
; Index
++) {
755 CopyMem (&IdtTableInStack
.IdtTable
[Index
], &mIdtEntryTemplate
, sizeof (mIdtEntryTemplate
));
758 IdtDescriptor
.Base
= (UINTN
)&IdtTableInStack
.IdtTable
;
759 IdtDescriptor
.Limit
= (UINT16
)(sizeof (IdtTableInStack
.IdtTable
) - 1);
761 AsmWriteIdtr (&IdtDescriptor
);
763 #if defined (MDE_CPU_X64)
765 // ASSERT that the Page Tables were set by the reset vector code to
766 // the address we expect.
768 ASSERT (AsmReadCr3 () == (UINTN
) PcdGet32 (PcdOvmfSecPageTablesBase
));
772 // |-------------| <-- TopOfCurrentStack
776 // |-------------| <-- SecCoreData.TemporaryRamBase
779 ASSERT ((UINTN
) (PcdGet32 (PcdOvmfSecPeiTempRamBase
) +
780 PcdGet32 (PcdOvmfSecPeiTempRamSize
)) ==
781 (UINTN
) TopOfCurrentStack
);
784 // Initialize SEC hand-off state
786 SecCoreData
.DataSize
= sizeof(EFI_SEC_PEI_HAND_OFF
);
788 SecCoreData
.TemporaryRamSize
= (UINTN
) PcdGet32 (PcdOvmfSecPeiTempRamSize
);
789 SecCoreData
.TemporaryRamBase
= (VOID
*)((UINT8
*)TopOfCurrentStack
- SecCoreData
.TemporaryRamSize
);
791 SecCoreData
.PeiTemporaryRamBase
= SecCoreData
.TemporaryRamBase
;
792 SecCoreData
.PeiTemporaryRamSize
= SecCoreData
.TemporaryRamSize
>> 1;
794 SecCoreData
.StackBase
= (UINT8
*)SecCoreData
.TemporaryRamBase
+ SecCoreData
.PeiTemporaryRamSize
;
795 SecCoreData
.StackSize
= SecCoreData
.TemporaryRamSize
>> 1;
797 SecCoreData
.BootFirmwareVolumeBase
= BootFv
;
798 SecCoreData
.BootFirmwareVolumeSize
= (UINTN
) BootFv
->FvLength
;
801 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
803 IoWrite8 (0x21, 0xff);
804 IoWrite8 (0xA1, 0xff);
807 // Initialize Local APIC Timer hardware and disable Local APIC Timer
808 // interrupts before initializing the Debug Agent and the debug timer is
811 InitializeApicTimer (0, MAX_UINT32
, TRUE
, 5);
812 DisableApicTimerInterrupt ();
815 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
817 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC
, &SecCoreData
, SecStartupPhase2
);
821 Caller provided function to be invoked at the end of InitializeDebugAgent().
823 Entry point to the C language phase of SEC. After the SEC assembly
824 code has initialized some temporary memory and set up the stack,
825 the control is transferred to this function.
827 @param[in] Context The first input parameter of InitializeDebugAgent().
836 EFI_SEC_PEI_HAND_OFF
*SecCoreData
;
837 EFI_FIRMWARE_VOLUME_HEADER
*BootFv
;
838 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint
;
840 SecCoreData
= (EFI_SEC_PEI_HAND_OFF
*) Context
;
843 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
846 BootFv
= (EFI_FIRMWARE_VOLUME_HEADER
*)SecCoreData
->BootFirmwareVolumeBase
;
847 FindAndReportEntryPoints (&BootFv
, &PeiCoreEntryPoint
);
848 SecCoreData
->BootFirmwareVolumeBase
= BootFv
;
849 SecCoreData
->BootFirmwareVolumeSize
= (UINTN
) BootFv
->FvLength
;
852 // Transfer the control to the PEI core
854 (*PeiCoreEntryPoint
) (SecCoreData
, (EFI_PEI_PPI_DESCRIPTOR
*)&mPrivateDispatchTable
);
857 // If we get here then the PEI Core returned, which is not recoverable.
865 TemporaryRamMigration (
866 IN CONST EFI_PEI_SERVICES
**PeiServices
,
867 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase
,
868 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase
,
872 IA32_DESCRIPTOR IdtDescriptor
;
877 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext
;
879 BASE_LIBRARY_JUMP_BUFFER JumpBuffer
;
882 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
888 OldHeap
= (VOID
*)(UINTN
)TemporaryMemoryBase
;
889 NewHeap
= (VOID
*)((UINTN
)PermanentMemoryBase
+ (CopySize
>> 1));
891 OldStack
= (VOID
*)((UINTN
)TemporaryMemoryBase
+ (CopySize
>> 1));
892 NewStack
= (VOID
*)(UINTN
)PermanentMemoryBase
;
894 DebugAgentContext
.HeapMigrateOffset
= (UINTN
)NewHeap
- (UINTN
)OldHeap
;
895 DebugAgentContext
.StackMigrateOffset
= (UINTN
)NewStack
- (UINTN
)OldStack
;
897 OldStatus
= SaveAndSetDebugTimerInterrupt (FALSE
);
898 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC
, (VOID
*) &DebugAgentContext
, NULL
);
903 CopyMem (NewHeap
, OldHeap
, CopySize
>> 1);
908 CopyMem (NewStack
, OldStack
, CopySize
>> 1);
911 // Rebase IDT table in permanent memory
913 AsmReadIdtr (&IdtDescriptor
);
914 IdtDescriptor
.Base
= IdtDescriptor
.Base
- (UINTN
)OldStack
+ (UINTN
)NewStack
;
916 AsmWriteIdtr (&IdtDescriptor
);
919 // Use SetJump()/LongJump() to switch to a new stack.
921 if (SetJump (&JumpBuffer
) == 0) {
922 #if defined (MDE_CPU_IA32)
923 JumpBuffer
.Esp
= JumpBuffer
.Esp
+ DebugAgentContext
.StackMigrateOffset
;
925 #if defined (MDE_CPU_X64)
926 JumpBuffer
.Rsp
= JumpBuffer
.Rsp
+ DebugAgentContext
.StackMigrateOffset
;
928 LongJump (&JumpBuffer
, (UINTN
)-1);
931 SaveAndSetDebugTimerInterrupt (OldStatus
);