X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FSec%2FSecMain.c;h=f7fec3d8c03b93d73042e480e4400be41f22ce32;hp=ece1c9b517e5bef07942bb3a74aba3de0b0b3336;hb=89796c69d9fdaa9bd13d37b6b1687df5e0104ed5;hpb=b382ede3864e17e8827dbc90c7d4f1540b94ff3f
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index ece1c9b517..f7fec3d8c0 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -1,7 +1,8 @@
/** @file
Main SEC phase code. Transitions to PEI.
- Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
@@ -28,6 +29,7 @@
#include
#include
#include
+#include
#include
@@ -128,9 +130,13 @@ FindMainFv (
Locates a section within a series of sections
with the specified section type.
+ The Instance parameter indicates which instance of the section
+ type to return. (0 is first instance, 1 is second...)
+
@param[in] Sections The sections to search
@param[in] SizeOfSections Total size of all sections
@param[in] SectionType The section type to locate
+ @param[in] Instance The section instance number
@param[out] FoundSection The FFS section if found
@retval EFI_SUCCESS The file and section was found
@@ -139,10 +145,11 @@ FindMainFv (
**/
EFI_STATUS
-FindFfsSectionInSections (
+FindFfsSectionInstance (
IN VOID *Sections,
IN UINTN SizeOfSections,
IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
OUT EFI_COMMON_SECTION_HEADER **FoundSection
)
{
@@ -167,7 +174,6 @@ FindFfsSectionInSections (
}
Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
- DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type));
Size = SECTION_SIZE (Section);
if (Size < sizeof (*Section)) {
@@ -183,15 +189,49 @@ FindFfsSectionInSections (
// Look for the requested section type
//
if (Section->Type == SectionType) {
- *FoundSection = Section;
- return EFI_SUCCESS;
+ if (Instance == 0) {
+ *FoundSection = Section;
+ return EFI_SUCCESS;
+ } else {
+ Instance--;
+ }
}
- DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));
}
return EFI_NOT_FOUND;
}
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInSections (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ return FindFfsSectionInstance (
+ Sections,
+ SizeOfSections,
+ SectionType,
+ 0,
+ FoundSection
+ );
+}
+
/**
Locates a FFS file with the specified file type and a section
within that file with the specified section type.
@@ -207,7 +247,6 @@ FindFfsSectionInSections (
**/
EFI_STATUS
-EFIAPI
FindFfsFileAndSection (
IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
IN EFI_FV_FILETYPE FileType,
@@ -223,7 +262,7 @@ FindFfsFileAndSection (
EFI_PHYSICAL_ADDRESS EndOfFile;
if (Fv->Signature != EFI_FVH_SIGNATURE) {
- DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv));
+ DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));
return EFI_VOLUME_CORRUPTED;
}
@@ -245,7 +284,6 @@ FindFfsFileAndSection (
if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
return EFI_VOLUME_CORRUPTED;
}
- DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type));
EndOfFile = CurrentAddress + Size;
if (EndOfFile > EndOfFirmwareVolume) {
@@ -256,7 +294,6 @@ FindFfsFileAndSection (
// Look for the request file type
//
if (File->Type != FileType) {
- DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));
continue;
}
@@ -276,7 +313,7 @@ FindFfsFileAndSection (
Locates the compressed main firmware volume and decompresses it.
@param[in,out] Fv On input, the firmware volume to search
- On output, the decompressed main FV
+ On output, the decompressed BOOT/PEI FV
@retval EFI_SUCCESS The file and section was found
@retval EFI_NOT_FOUND The file and section was not found
@@ -284,8 +321,7 @@ FindFfsFileAndSection (
**/
EFI_STATUS
-EFIAPI
-DecompressGuidedFv (
+DecompressMemFvs (
IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv
)
{
@@ -297,10 +333,13 @@ DecompressGuidedFv (
UINT32 AuthenticationStatus;
VOID *OutputBuffer;
VOID *ScratchBuffer;
- EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;
- EFI_FIRMWARE_VOLUME_HEADER *NewFv;
+ EFI_COMMON_SECTION_HEADER *FvSection;
+ EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;
+ UINT32 FvHeaderSize;
+ UINT32 FvSectionSize;
- NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;
+ FvSection = (EFI_COMMON_SECTION_HEADER*) NULL;
Status = FindFfsFileAndSection (
*Fv,
@@ -324,9 +363,16 @@ DecompressGuidedFv (
return Status;
}
- //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)
- OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);
+ OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);
ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);
+
+ DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
+ "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer,
+ OutputBufferSize, ScratchBuffer, ScratchBufferSize,
+ PcdGet32 (PcdOvmfDecompressionScratchEnd)));
+ ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize ==
+ PcdGet32 (PcdOvmfDecompressionScratchEnd));
+
Status = ExtractGuidedSectionDecode (
Section,
&OutputBuffer,
@@ -338,27 +384,65 @@ DecompressGuidedFv (
return Status;
}
- Status = FindFfsSectionInSections (
+ Status = FindFfsSectionInstance (
OutputBuffer,
OutputBufferSize,
EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
- (EFI_COMMON_SECTION_HEADER**) &NewFvSection
+ 0,
+ &FvSection
);
if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));
+ DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));
return Status;
}
- NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);
- CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));
+ ASSERT (SECTION_SIZE (FvSection) ==
+ (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection)));
+ ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+ PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);
+ CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));
- if (NewFv->Signature != EFI_FVH_SIGNATURE) {
- DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));
+ if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));
CpuDeadLoop ();
return EFI_VOLUME_CORRUPTED;
}
- *Fv = NewFv;
+ Status = FindFfsSectionInstance (
+ OutputBuffer,
+ OutputBufferSize,
+ EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+ 1,
+ &FvSection
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));
+ return Status;
+ }
+
+ ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+ if (IS_SECTION2 (FvSection)) {
+ FvSectionSize = SECTION2_SIZE (FvSection);
+ FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+ } else {
+ FvSectionSize = SECTION_SIZE (FvSection);
+ FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
+ }
+
+ ASSERT (FvSectionSize == (PcdGet32 (PcdOvmfDxeMemFvSize) + FvHeaderSize));
+
+ DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase);
+ CopyMem (DxeMemFv, (VOID*) ((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdOvmfDxeMemFvSize));
+
+ if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));
+ CpuDeadLoop ();
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ *Fv = PeiMemFv;
return EFI_SUCCESS;
}
@@ -374,7 +458,6 @@ DecompressGuidedFv (
**/
EFI_STATUS
-EFIAPI
FindPeiCoreImageBaseInFv (
IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
@@ -406,6 +489,50 @@ FindPeiCoreImageBaseInFv (
return EFI_SUCCESS;
}
+
+/**
+ Reads 8-bits of CMOS data.
+
+ Reads the 8-bits of CMOS data at the location specified by Index.
+ The 8-bit read value is returned.
+
+ @param Index The CMOS location to read.
+
+ @return The value read.
+
+**/
+STATIC
+UINT8
+CmosRead8 (
+ IN UINTN Index
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ return IoRead8 (0x71);
+}
+
+
+STATIC
+BOOLEAN
+IsS3Resume (
+ VOID
+ )
+{
+ return (CmosRead8 (0xF) == 0xFE);
+}
+
+
+STATIC
+EFI_STATUS
+GetS3ResumePeiFv (
+ IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv
+ )
+{
+ *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);
+ return EFI_SUCCESS;
+}
+
+
/**
Locates the PEI Core entry point address
@@ -418,17 +545,34 @@ FindPeiCoreImageBaseInFv (
**/
VOID
-EFIAPI
FindPeiCoreImageBase (
IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
)
{
+ BOOLEAN S3Resume;
+
*PeiCoreImageBase = 0;
- FindMainFv (BootFv);
+ S3Resume = IsS3Resume ();
+ if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // A malicious runtime OS may have injected something into our previously
+ // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
+ //
+ DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));
+ GetS3ResumePeiFv (BootFv);
+ } else {
+ //
+ // We're either not resuming, or resuming "securely" -- we'll decompress
+ // both PEI FV and DXE FV from pristine flash.
+ //
+ DEBUG ((EFI_D_VERBOSE, "SEC: %a\n",
+ S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"));
+ FindMainFv (BootFv);
- DecompressGuidedFv (BootFv);
+ DecompressMemFvs (BootFv);
+ }
FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
}
@@ -438,7 +582,6 @@ FindPeiCoreImageBase (
**/
EFI_STATUS
-EFIAPI
FindImageBase (
IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
@@ -526,12 +669,11 @@ FindImageBase (
/*
Find and return Pei Core entry point.
- It also find SEC and PEI Core file debug inforamtion. It will report them if
+ It also find SEC and PEI Core file debug information. It will report them if
remote debug is enabled.
**/
VOID
-EFIAPI
FindAndReportEntryPoints (
IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
@@ -587,10 +729,23 @@ SecCoreStartupWithStack (
SEC_IDT_TABLE IdtTableInStack;
IA32_DESCRIPTOR IdtDescriptor;
UINT32 Index;
+ volatile UINT8 *Table;
+
+ //
+ // To ensure SMM can't be compromised on S3 resume, we must force re-init of
+ // the BaseExtractGuidedSectionLib. Since this is before library contructors
+ // are called, we must use a loop rather than SetMem.
+ //
+ Table = (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
+ for (Index = 0;
+ Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
+ ++Index) {
+ Table[Index] = 0;
+ }
ProcessLibraryConstructorList (NULL, NULL);
- DEBUG ((EFI_D_ERROR,
+ DEBUG ((EFI_D_INFO,
"SecCoreStartupWithStack(0x%x, 0x%x)\n",
(UINT32)(UINTN)BootFv,
(UINT32)(UINTN)TopOfCurrentStack
@@ -631,12 +786,16 @@ SecCoreStartupWithStack (
// |-------------| <-- SecCoreData.TemporaryRamBase
//
+ ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +
+ PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
+ (UINTN) TopOfCurrentStack);
+
//
// Initialize SEC hand-off state
//
SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);
- SecCoreData.TemporaryRamSize = SIZE_64KB;
+ SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);
SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
@@ -653,6 +812,14 @@ SecCoreStartupWithStack (
//
IoWrite8 (0x21, 0xff);
IoWrite8 (0xA1, 0xff);
+
+ //
+ // Initialize Local APIC Timer hardware and disable Local APIC Timer
+ // interrupts before initializing the Debug Agent and the debug timer is
+ // enabled.
+ //
+ InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
+ DisableApicTimerInterrupt ();
//
// Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
@@ -721,7 +888,12 @@ TemporaryRamMigration (
BOOLEAN OldStatus;
BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
- DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize));
+ DEBUG ((EFI_D_INFO,
+ "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
+ TemporaryMemoryBase,
+ PermanentMemoryBase,
+ (UINT64)CopySize
+ ));
OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
@@ -759,9 +931,11 @@ TemporaryRamMigration (
if (SetJump (&JumpBuffer) == 0) {
#if defined (MDE_CPU_IA32)
JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
+ JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset;
#endif
#if defined (MDE_CPU_X64)
JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
+ JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset;
#endif
LongJump (&JumpBuffer, (UINTN)-1);
}