From c59e401bb6fba74d40caccedc3b4b1223c7effc6 Mon Sep 17 00:00:00 2001 From: Min M Xu Date: Wed, 26 Oct 2022 18:10:52 +0800 Subject: [PATCH] OvmfPkg/PeilessStartupLib: Find DxeNonCcFv in non-td guest Signed-off-by: Min Xu --- OvmfPkg/Library/PeilessStartupLib/DxeLoad.c | 118 +++++++++++++++++- .../PeilessStartupInternal.h | 6 + .../PeilessStartupLib/PeilessStartupLib.inf | 1 + 3 files changed, 124 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c b/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c index 6e79c308467..a3c80d5e5b4 100644 --- a/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c +++ b/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c @@ -22,6 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #define STACK_SIZE 0x20000 +extern EFI_GUID gEfiNonCcFvGuid; /** Transfers control to DxeCore. @@ -136,6 +137,117 @@ FindDxeCore ( return Status; } +EFI_STATUS +EFIAPI +CheckSectionHookForDxeNonCc ( + IN EFI_COMMON_SECTION_HEADER *Section + ) +{ + VOID *Buffer; + EFI_STATUS Status; + EFI_FV_INFO FvImageInfo; + + ASSERT (Section->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE); + + if (IS_SECTION2 (Section)) { + Buffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER2)); + } else { + Buffer = (VOID *)((UINT8 *)Section + sizeof (EFI_COMMON_SECTION_HEADER)); + } + + ZeroMem (&FvImageInfo, sizeof (FvImageInfo)); + Status = FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE)(UINTN)Buffer, &FvImageInfo); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Cannot get volume info! %r\n", Status)); + return Status; + } + + return CompareGuid (&FvImageInfo.FvName, &gEfiNonCcFvGuid) ? EFI_SUCCESS : EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +FindDxeNonCc ( + IN INTN FvInstance + ) +{ + EFI_STATUS Status; + EFI_PEI_FV_HANDLE VolumeHandle; + EFI_PEI_FILE_HANDLE FileHandle; + EFI_PEI_FV_HANDLE FvImageHandle; + EFI_FV_INFO FvImageInfo; + UINT32 FvAlignment; + VOID *FvBuffer; + + FileHandle = NULL; + + // + // Caller passed in a specific FV to try, so only try that one + // + Status = FfsFindNextVolume (FvInstance, &VolumeHandle); + ASSERT (Status == EFI_SUCCESS); + + Status = FfsFindNextFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, VolumeHandle, &FileHandle); + ASSERT (FileHandle != NULL); + + // + // Find FvImage in FvFile + // + Status = FfsFindSectionData (EFI_SECTION_FIRMWARE_VOLUME_IMAGE, CheckSectionHookForDxeNonCc, FileHandle, (VOID **)&FvImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Collect FvImage Info. + // + ZeroMem (&FvImageInfo, sizeof (FvImageInfo)); + Status = FfsGetVolumeInfo (FvImageHandle, &FvImageInfo); + ASSERT_EFI_ERROR (Status); + + // + // FvAlignment must be more than 8 bytes required by FvHeader structure. + // + FvAlignment = 1 << ((FvImageInfo.FvAttributes & EFI_FVB2_ALIGNMENT) >> 16); + if (FvAlignment < 8) { + FvAlignment = 8; + } + + // + // Check FvImage + // + if ((UINTN)FvImageInfo.FvStart % FvAlignment != 0) { + FvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32)FvImageInfo.FvSize), FvAlignment); + if (FvBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (FvBuffer, FvImageInfo.FvStart, (UINTN)FvImageInfo.FvSize); + // + // Update FvImageInfo after reload FvImage to new aligned memory + // + FfsGetVolumeInfo ((EFI_PEI_FV_HANDLE)FvBuffer, &FvImageInfo); + } + + // + // Inform HOB consumer phase, i.e. DXE core, the existence of this FV + // + BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN)FvImageInfo.FvStart, FvImageInfo.FvSize); + + // + // Makes the encapsulated volume show up in DXE phase to skip processing of + // encapsulated file again. + // + BuildFv2Hob ( + (EFI_PHYSICAL_ADDRESS)(UINTN)FvImageInfo.FvStart, + FvImageInfo.FvSize, + &FvImageInfo.FvName, + &(((EFI_FFS_FILE_HEADER *)FileHandle)->Name) + ); + + return Status; +} + /** This function finds DXE Core in the firmware volume and transfer the control to DXE core. @@ -168,10 +280,14 @@ DxeLoadCore ( return Status; } + if (!TdIsEnabled ()) { + FindDxeNonCc (FvInstance); + } + // // Load the DXE Core from a Firmware Volume. // - Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage); + Status = FfsFindSectionData (EFI_SECTION_PE32, NULL, FileHandle, &PeCoffImage); if (EFI_ERROR (Status)) { return Status; } diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h index 09cac3e26c6..f56bc3578e5 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupInternal.h @@ -21,6 +21,12 @@ DxeLoadCore ( IN INTN FvInstance ); +EFI_STATUS +EFIAPI +FindDxeNonCc ( + IN INTN FvInstance + ); + VOID EFIAPI TransferHobList ( diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf index b8dafe3ddd1..ac9c5ff2bcd 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf @@ -67,6 +67,7 @@ gEfiMemoryTypeInformationGuid gPcdDataBaseHobGuid gCcEventEntryHobGuid + gEfiNonCcFvGuid [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase