X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FSec%2FSecMain.c;h=3ca0dcdfd3ddd513f85566be0692fea2aa5825b3;hp=b7df549f31007afbe3a0cb72e04b5dfaf639632e;hb=ff36b2550f94dc5fac838cf298ae5a23cfddf204;hpb=6394c35a7db3d7a7cc68f491179a45fe430a335a diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c index b7df549f31..3ca0dcdfd3 100644 --- a/OvmfPkg/Sec/SecMain.c +++ b/OvmfPkg/Sec/SecMain.c @@ -1,15 +1,11 @@ /** @file Main SEC phase code. Transitions to PEI. - Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.
- This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -21,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -28,44 +25,67 @@ #include #include #include - +#include +#include #include +#include +#include +#include +#include "AmdSev.h" #define SEC_IDT_ENTRY_COUNT 34 typedef struct _SEC_IDT_TABLE { - EFI_PEI_SERVICES *PeiService; - IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; + EFI_PEI_SERVICES *PeiService; + IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; } SEC_IDT_TABLE; VOID EFIAPI SecStartupPhase2 ( - IN VOID *Context + IN VOID *Context ); EFI_STATUS EFIAPI TemporaryRamMigration ( - IN CONST EFI_PEI_SERVICES **PeiServices, - IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, - IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, - IN UINTN CopySize + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize ); // // -// -EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { +// +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { TemporaryRamMigration }; -EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { +EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTableMp[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI), + &gEfiTemporaryRamSupportPpiGuid, + &mTemporaryRamSupportPpi + }, { (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMpInitLibMpDepPpiGuid, + NULL + }, +}; + +EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTableUp[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI), &gEfiTemporaryRamSupportPpiGuid, &mTemporaryRamSupportPpi }, + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMpInitLibUpDepPpiGuid, + NULL + }, }; // @@ -78,7 +98,7 @@ IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = { 0x0, // Reserved_0 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType 0xffff // OffsetHigh - } + } }; /** @@ -93,18 +113,18 @@ IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = { **/ EFI_STATUS FindMainFv ( - IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv ) { EFI_FIRMWARE_VOLUME_HEADER *Fv; UINTN Distance; - ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0); + ASSERT (((UINTN)*BootFv & EFI_PAGE_MASK) == 0); - Fv = *BootFv; - Distance = (UINTN) (*BootFv)->FvLength; + Fv = *BootFv; + Distance = (UINTN)(*BootFv)->FvLength; do { - Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE); + Fv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)Fv - EFI_PAGE_SIZE); Distance += EFI_PAGE_SIZE; if (Distance > SIZE_32MB) { return EFI_NOT_FOUND; @@ -114,13 +134,12 @@ FindMainFv ( continue; } - if ((UINTN) Fv->FvLength > Distance) { + if ((UINTN)Fv->FvLength > Distance) { continue; } *BootFv = Fv; return EFI_SUCCESS; - } while (TRUE); } @@ -144,34 +163,35 @@ FindMainFv ( **/ EFI_STATUS FindFfsSectionInstance ( - IN VOID *Sections, - IN UINTN SizeOfSections, - IN EFI_SECTION_TYPE SectionType, - IN UINTN Instance, - OUT EFI_COMMON_SECTION_HEADER **FoundSection + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_COMMON_SECTION_HEADER **FoundSection ) { - EFI_PHYSICAL_ADDRESS CurrentAddress; - UINT32 Size; - EFI_PHYSICAL_ADDRESS EndOfSections; - EFI_COMMON_SECTION_HEADER *Section; - EFI_PHYSICAL_ADDRESS EndOfSection; + EFI_PHYSICAL_ADDRESS CurrentAddress; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfSections; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; // // Loop through the FFS file sections within the PEI Core FFS file // - EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections; + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections; EndOfSections = EndOfSection + SizeOfSections; - for (;;) { + for ( ; ;) { if (EndOfSection == EndOfSections) { break; } + CurrentAddress = (EndOfSection + 3) & ~(3ULL); if (CurrentAddress >= EndOfSections) { return EFI_VOLUME_CORRUPTED; } - Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress; Size = SECTION_SIZE (Section); if (Size < sizeof (*Section)) { @@ -215,10 +235,10 @@ FindFfsSectionInstance ( **/ EFI_STATUS FindFfsSectionInSections ( - IN VOID *Sections, - IN UINTN SizeOfSections, - IN EFI_SECTION_TYPE SectionType, - OUT EFI_COMMON_SECTION_HEADER **FoundSection + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection ) { return FindFfsSectionInstance ( @@ -246,39 +266,38 @@ FindFfsSectionInSections ( **/ EFI_STATUS FindFfsFileAndSection ( - IN EFI_FIRMWARE_VOLUME_HEADER *Fv, - IN EFI_FV_FILETYPE FileType, - IN EFI_SECTION_TYPE SectionType, - OUT EFI_COMMON_SECTION_HEADER **FoundSection + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + IN EFI_FV_FILETYPE FileType, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection ) { - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS CurrentAddress; - EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; - EFI_FFS_FILE_HEADER *File; - UINT32 Size; - EFI_PHYSICAL_ADDRESS EndOfFile; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; if (Fv->Signature != EFI_FVH_SIGNATURE) { - DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv)); + DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv)); return EFI_VOLUME_CORRUPTED; } - CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv; + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv; EndOfFirmwareVolume = CurrentAddress + Fv->FvLength; // // Loop through the FFS files in the Boot Firmware Volume // for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) { - CurrentAddress = (EndOfFile + 7) & ~(7ULL); if (CurrentAddress > EndOfFirmwareVolume) { return EFI_VOLUME_CORRUPTED; } - File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; - Size = *(UINT32*) File->Size & 0xffffff; + File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress; + Size = FFS_FILE_SIZE (File); if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { return EFI_VOLUME_CORRUPTED; } @@ -296,8 +315,8 @@ FindFfsFileAndSection ( } Status = FindFfsSectionInSections ( - (VOID*) (File + 1), - (UINTN) EndOfFile - (UINTN) (File + 1), + (VOID *)(File + 1), + (UINTN)EndOfFile - (UINTN)(File + 1), SectionType, FoundSection ); @@ -320,31 +339,33 @@ FindFfsFileAndSection ( **/ EFI_STATUS DecompressMemFvs ( - IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv + IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv ) { - EFI_STATUS Status; - EFI_GUID_DEFINED_SECTION *Section; - UINT32 OutputBufferSize; - UINT32 ScratchBufferSize; - UINT16 SectionAttribute; - UINT32 AuthenticationStatus; - VOID *OutputBuffer; - VOID *ScratchBuffer; - EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FvSection; - EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv; - EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv; - - FvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL; + EFI_STATUS Status; + EFI_GUID_DEFINED_SECTION *Section; + UINT32 OutputBufferSize; + UINT32 ScratchBufferSize; + UINT16 SectionAttribute; + UINT32 AuthenticationStatus; + VOID *OutputBuffer; + VOID *ScratchBuffer; + EFI_COMMON_SECTION_HEADER *FvSection; + EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv; + EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv; + UINT32 FvHeaderSize; + UINT32 FvSectionSize; + + FvSection = (EFI_COMMON_SECTION_HEADER *)NULL; Status = FindFfsFileAndSection ( *Fv, EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_GUID_DEFINED, - (EFI_COMMON_SECTION_HEADER**) &Section + (EFI_COMMON_SECTION_HEADER **)&Section ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n")); + DEBUG ((DEBUG_ERROR, "Unable to find GUID defined section\n")); return Status; } @@ -355,12 +376,29 @@ DecompressMemFvs ( &SectionAttribute ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n")); + DEBUG ((DEBUG_ERROR, "Unable to GetInfo for GUIDed section\n")); return Status; } - OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB); - ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB); + OutputBuffer = (VOID *)((UINT8 *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB); + ScratchBuffer = ALIGN_POINTER ((UINT8 *)OutputBuffer + OutputBufferSize, SIZE_1MB); + + DEBUG (( + DEBUG_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, @@ -368,7 +406,7 @@ DecompressMemFvs ( &AuthenticationStatus ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n")); + DEBUG ((DEBUG_ERROR, "Error during GUID section decode\n")); return Status; } @@ -377,22 +415,24 @@ DecompressMemFvs ( OutputBufferSize, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, 0, - (EFI_COMMON_SECTION_HEADER**) &FvSection + &FvSection ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n")); + DEBUG ((DEBUG_ERROR, "Unable to find PEI FV section\n")); return Status; } - ASSERT (SECTION_SIZE (FvSection) == - (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection))); + 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)); + PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase); + CopyMem (PeiMemFv, (VOID *)(FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize)); if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) { - DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv)); + DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv)); CpuDeadLoop (); return EFI_VOLUME_CORRUPTED; } @@ -402,22 +442,30 @@ DecompressMemFvs ( OutputBufferSize, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, 1, - (EFI_COMMON_SECTION_HEADER**) &FvSection + &FvSection ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n")); + DEBUG ((DEBUG_ERROR, "Unable to find DXE FV section\n")); return Status; } ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE); - ASSERT (SECTION_SIZE (FvSection) == - (PcdGet32 (PcdOvmfDxeMemFvSize) + sizeof (*FvSection))); - DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase); - CopyMem (DxeMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfDxeMemFvSize)); + 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)); + DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv)); CpuDeadLoop (); return EFI_VOLUME_CORRUPTED; } @@ -439,12 +487,12 @@ DecompressMemFvs ( **/ EFI_STATUS FindPeiCoreImageBaseInFv ( - IN EFI_FIRMWARE_VOLUME_HEADER *Fv, - OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase ) { - EFI_STATUS Status; - EFI_COMMON_SECTION_HEADER *Section; + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; Status = FindFfsFileAndSection ( Fv, @@ -460,7 +508,7 @@ FindPeiCoreImageBaseInFv ( &Section ); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n")); + DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n")); return Status; } } @@ -469,7 +517,6 @@ FindPeiCoreImageBaseInFv ( return EFI_SUCCESS; } - /** Reads 8-bits of CMOS data. @@ -484,14 +531,13 @@ FindPeiCoreImageBaseInFv ( STATIC UINT8 CmosRead8 ( - IN UINTN Index + IN UINTN Index ) { - IoWrite8 (0x70, (UINT8) Index); + IoWrite8 (0x70, (UINT8)Index); return IoRead8 (0x71); } - STATIC BOOLEAN IsS3Resume ( @@ -501,18 +547,16 @@ IsS3Resume ( return (CmosRead8 (0xF) == 0xFE); } - STATIC EFI_STATUS GetS3ResumePeiFv ( - IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv + IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv ) { - *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase); + *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase); return EFI_SUCCESS; } - /** Locates the PEI Core entry point address @@ -526,17 +570,32 @@ GetS3ResumePeiFv ( **/ VOID FindPeiCoreImageBase ( - IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv, - OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase ) { + BOOLEAN S3Resume; + *PeiCoreImageBase = 0; - if (IsS3Resume ()) { - DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n")); + 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 ((DEBUG_VERBOSE, "SEC: S3 resume\n")); GetS3ResumePeiFv (BootFv); } else { - DEBUG ((EFI_D_VERBOSE, "SEC: Normal boot\n")); + // + // We're either not resuming, or resuming "securely" -- we'll decompress + // both PEI FV and DXE FV from pristine flash. + // + DEBUG (( + DEBUG_VERBOSE, + "SEC: %a\n", + S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot" + )); FindMainFv (BootFv); DecompressMemFvs (BootFv); @@ -551,35 +610,34 @@ FindPeiCoreImageBase ( **/ EFI_STATUS FindImageBase ( - IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, - OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase ) { - EFI_PHYSICAL_ADDRESS CurrentAddress; - EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; - EFI_FFS_FILE_HEADER *File; - UINT32 Size; - EFI_PHYSICAL_ADDRESS EndOfFile; - EFI_COMMON_SECTION_HEADER *Section; - EFI_PHYSICAL_ADDRESS EndOfSection; + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; *SecCoreImageBase = 0; - CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr; EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; // // Loop through the FFS files in the Boot Firmware Volume // for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { - CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; if (CurrentAddress > EndOfFirmwareVolume) { return EFI_NOT_FOUND; } - File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; - Size = *(UINT32*) File->Size & 0xffffff; + File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress; + Size = FFS_FILE_SIZE (File); if (Size < sizeof (*File)) { return EFI_NOT_FOUND; } @@ -599,12 +657,12 @@ FindImageBase ( // // Loop through the FFS file sections within the FFS file // - EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1); - for (;;) { + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)(File + 1); + for ( ; ;) { CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; - Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress; - Size = *(UINT32*) Section->Size & 0xffffff; + Size = SECTION_SIZE (Section); if (Size < sizeof (*Section)) { return EFI_NOT_FOUND; } @@ -617,10 +675,11 @@ FindImageBase ( // // Look for executable sections // - if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) { + if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) { if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) { - *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1); + *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1); } + break; } } @@ -637,48 +696,48 @@ 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 FindAndReportEntryPoints ( - IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, - OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint ) { - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS SecCoreImageBase; - EFI_PHYSICAL_ADDRESS PeiCoreImageBase; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS SecCoreImageBase; + EFI_PHYSICAL_ADDRESS PeiCoreImageBase; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; // // Find SEC Core and PEI Core image base - // + // Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase); ASSERT_EFI_ERROR (Status); FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase); - - ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + + ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); // // Report SEC Core debug information when remote debug is enabled // ImageContext.ImageAddress = SecCoreImageBase; - ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress); PeCoffLoaderRelocateImageExtraAction (&ImageContext); // // Report PEI Core debug information when remote debug is enabled // ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase; - ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress); PeCoffLoaderRelocateImageExtraAction (&ImageContext); // // Find PEI Core entry point // - Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint); + Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint); if (EFI_ERROR (Status)) { *PeiCoreEntryPoint = 0; } @@ -689,18 +748,119 @@ FindAndReportEntryPoints ( VOID EFIAPI SecCoreStartupWithStack ( - IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, - IN VOID *TopOfCurrentStack + IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, + IN VOID *TopOfCurrentStack ) { - EFI_SEC_PEI_HAND_OFF SecCoreData; - SEC_IDT_TABLE IdtTableInStack; - IA32_DESCRIPTOR IdtDescriptor; - UINT32 Index; + EFI_SEC_PEI_HAND_OFF SecCoreData; + SEC_IDT_TABLE IdtTableInStack; + IA32_DESCRIPTOR IdtDescriptor; + UINT32 Index; + volatile UINT8 *Table; + + #if defined (TDX_GUEST_SUPPORTED) + if (CcProbe () == CcGuestTypeIntelTdx) { + // + // For Td guests, the memory map info is in TdHobLib. It should be processed + // first so that the memory is accepted. Otherwise access to the unaccepted + // memory will trigger tripple fault. + // + if (ProcessTdxHobList () != EFI_SUCCESS) { + CpuDeadLoop (); + } + } + + #endif + + // + // 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; + } + + // + // Initialize IDT - Since this is before library constructors are called, + // we use a loop rather than CopyMem. + // + IdtTableInStack.PeiService = NULL; + + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) { + // + // Declare the local variables that actually move the data elements as + // volatile to prevent the optimizer from replacing this function with + // the intrinsic memcpy() + // + CONST UINT8 *Src; + volatile UINT8 *Dst; + UINTN Byte; + + Src = (CONST UINT8 *)&mIdtEntryTemplate; + Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index]; + for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) { + Dst[Byte] = Src[Byte]; + } + } + + IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + if (SevEsIsEnabled ()) { + SevEsProtocolCheck (); + + // + // For SEV-ES guests, the exception handler is needed before calling + // ProcessLibraryConstructorList() because some of the library constructors + // perform some functions that result in #VC exceptions being generated. + // + // Due to this code executing before library constructors, *all* library + // API calls are theoretically interface contract violations. However, + // because this is SEC (executing in flash), those constructors cannot + // write variables with static storage duration anyway. Furthermore, only + // a small, restricted set of APIs, such as AsmWriteIdtr() and + // InitializeCpuExceptionHandlers(), are called, where we require that the + // underlying library not require constructors to have been invoked and + // that the library instance not trigger any #VC exceptions. + // + AsmWriteIdtr (&IdtDescriptor); + InitializeCpuExceptionHandlers (NULL); + } ProcessLibraryConstructorList (NULL, NULL); - DEBUG ((EFI_D_INFO, + if (!SevEsIsEnabled ()) { + // + // For non SEV-ES guests, just load the IDTR. + // + AsmWriteIdtr (&IdtDescriptor); + } else { + // + // Under SEV-ES, the hypervisor can't modify CR0 and so can't enable + // caching in order to speed up the boot. Enable caching early for + // an SEV-ES guest. + // + AsmEnableCache (); + } + + #if defined (TDX_GUEST_SUPPORTED) + if (CcProbe () == CcGuestTypeIntelTdx) { + // + // InitializeCpuExceptionHandlers () should be called in Td guests so that + // #VE exceptions can be handled correctly. + // + InitializeCpuExceptionHandlers (NULL); + } + + #endif + + DEBUG (( + DEBUG_INFO, "SecCoreStartupWithStack(0x%x, 0x%x)\n", (UINT32)(UINTN)BootFv, (UINT32)(UINTN)TopOfCurrentStack @@ -712,26 +872,13 @@ SecCoreStartupWithStack ( // InitializeFloatingPointUnits (); - // - // Initialize IDT - // - IdtTableInStack.PeiService = NULL; - for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { - CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate)); - } - - IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; - IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); - - AsmWriteIdtr (&IdtDescriptor); - -#if defined (MDE_CPU_X64) + #if defined (MDE_CPU_X64) // // ASSERT that the Page Tables were set by the reset vector code to // the address we expect. // - ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase)); -#endif + ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase)); + #endif // // |-------------| <-- TopOfCurrentStack @@ -741,39 +888,54 @@ SecCoreStartupWithStack ( // |-------------| <-- SecCoreData.TemporaryRamBase // - ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) + - PcdGet32 (PcdOvmfSecPeiTempRamSize)) == - (UINTN) TopOfCurrentStack); + ASSERT ( + (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) + + PcdGet32 (PcdOvmfSecPeiTempRamSize)) == + (UINTN)TopOfCurrentStack + ); // // Initialize SEC hand-off state // - SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); + SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF); - SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize); - SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize); + SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize); + SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize); - SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; - SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; - SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; - SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; + SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; + SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; SecCoreData.BootFirmwareVolumeBase = BootFv; - SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; + SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength; + + // + // Validate the System RAM used in the SEC Phase + // + SecValidateSystemRam (); // // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled // 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. // InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2); } - + /** Caller provided function to be invoked at the end of InitializeDebugAgent(). @@ -786,16 +948,17 @@ SecCoreStartupWithStack ( **/ VOID EFIAPI -SecStartupPhase2( - IN VOID *Context +SecStartupPhase2 ( + IN VOID *Context ) { EFI_SEC_PEI_HAND_OFF *SecCoreData; EFI_FIRMWARE_VOLUME_HEADER *BootFv; EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; - - SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; - + EFI_PEI_PPI_DESCRIPTOR *EfiPeiPpiDescriptor; + + SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context; + // // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug // is enabled. @@ -803,13 +966,23 @@ SecStartupPhase2( BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint); SecCoreData->BootFirmwareVolumeBase = BootFv; - SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; + SecCoreData->BootFirmwareVolumeSize = (UINTN)BootFv->FvLength; + + // + // Td guest is required to use the MpInitLibUp (unique-processor version). + // Other guests use the MpInitLib (multi-processor version). + // + if (CcProbe () == CcGuestTypeIntelTdx) { + EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableUp; + } else { + EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableMp; + } // // Transfer the control to the PEI core // - (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable); - + (*PeiCoreEntryPoint)(SecCoreData, EfiPeiPpiDescriptor); + // // If we get here then the PEI Core returned, which is not recoverable. // @@ -820,10 +993,10 @@ SecStartupPhase2( EFI_STATUS EFIAPI TemporaryRamMigration ( - IN CONST EFI_PEI_SERVICES **PeiServices, - IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, - IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, - IN UINTN CopySize + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize ) { IA32_DESCRIPTOR IdtDescriptor; @@ -834,25 +1007,26 @@ TemporaryRamMigration ( DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext; BOOLEAN OldStatus; BASE_LIBRARY_JUMP_BUFFER JumpBuffer; - - DEBUG ((EFI_D_INFO, + + DEBUG (( + DEBUG_INFO, "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n", TemporaryMemoryBase, PermanentMemoryBase, (UINT64)CopySize )); - - OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; - NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1)); - - OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1)); - NewStack = (VOID*)(UINTN)PermanentMemoryBase; - - DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap; + + OldHeap = (VOID *)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1)); + + OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1)); + NewStack = (VOID *)(UINTN)PermanentMemoryBase; + + DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap; DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack; - + OldStatus = SaveAndSetDebugTimerInterrupt (FALSE); - InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL); + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *)&DebugAgentContext, NULL); // // Migrate Heap @@ -863,7 +1037,7 @@ TemporaryRamMigration ( // Migrate Stack // CopyMem (NewStack, OldStack, CopySize >> 1); - + // // Rebase IDT table in permanent memory // @@ -874,14 +1048,20 @@ TemporaryRamMigration ( // // Use SetJump()/LongJump() to switch to a new stack. - // + // if (SetJump (&JumpBuffer) == 0) { -#if defined (MDE_CPU_IA32) + #if defined (MDE_CPU_IA32) JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset; -#endif -#if defined (MDE_CPU_X64) + #ifndef OMIT_FRAME_POINTER + JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset; + #endif + #endif + #if defined (MDE_CPU_X64) JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset; -#endif + #ifndef OMIT_FRAME_POINTER + JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset; + #endif + #endif LongJump (&JumpBuffer, (UINTN)-1); } @@ -889,4 +1069,3 @@ TemporaryRamMigration ( return EFI_SUCCESS; } -