From 70d1481b559c2964eafe3938f1d728a09691d7cb Mon Sep 17 00:00:00 2001 From: Min M Xu Date: Tue, 17 Jan 2023 07:31:58 +0800 Subject: OvmfPkg/PeilessStartupLib: Find NCCFV in non-td guest BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4152 As described in BZ#4152, NCCFV includes the DXE phase drivers for non-cc guest. PeilessStartupLib is updated to find NCCFV for non-cc guest. Cc: Gerd Hoffmann Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Tom Lendacky Signed-off-by: Min Xu Acked-by: Gerd Hoffmann Reviewed-by: Jiewen Yao --- OvmfPkg/Library/PeilessStartupLib/DxeLoad.c | 134 ++++++++++++++++++++- .../PeilessStartupLib/PeilessStartupInternal.h | 6 + .../PeilessStartupLib/PeilessStartupLib.inf | 1 + 3 files changed, 140 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c b/OvmfPkg/Library/PeilessStartupLib/DxeLoad.c index 6e79c30846..4b1fefd452 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,133 @@ FindDxeCore ( return Status; } +/** + * This is a FFS_CHECK_SECTION_HOOK which is defined by caller to check + * if the section is an EFI_SECTION_FIRMWARE_VOLUME_IMAGE and if it is + * a NonCc FV. + * + * @param Section The section in which we're checking for the NonCc FV. + * @return EFI_STATUS The section is the NonCc FV. + */ +EFI_STATUS +EFIAPI +CheckSectionHookForDxeNonCc ( + IN EFI_COMMON_SECTION_HEADER *Section + ) +{ + VOID *Buffer; + EFI_STATUS Status; + EFI_FV_INFO FvImageInfo; + + if (Section->Type != EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { + return EFI_INVALID_PARAMETER; + } + + 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; +} + +/** + * Find the NonCc FV. + * + * @param FvInstance The FvInstance number. + * @return EFI_STATUS Successfuly find the NonCc FV. + */ +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 +296,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 09cac3e26c..f56bc3578e 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 def50b4b01..5c6eb1597b 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartupLib.inf @@ -67,6 +67,7 @@ gEfiMemoryTypeInformationGuid gPcdDataBaseHobGuid gCcEventEntryHobGuid + gEfiNonCcFvGuid [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdCfvBase -- cgit v1.2.3