diff options
Diffstat (limited to 'OvmfPkg/Library')
-rw-r--r-- | OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c | 32 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c | 176 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c | 262 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c | 58 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf | 5 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c | 43 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h | 107 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c | 9 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c | 76 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf | 6 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c | 93 | ||||
-rw-r--r-- | OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf | 13 |
12 files changed, 854 insertions, 26 deletions
diff --git a/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c b/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c index 42db1a6..170860f 100644 --- a/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c +++ b/OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c @@ -7,6 +7,9 @@ **/
#include <PiPei.h>
+#include <Base.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Library/HobLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -47,6 +50,10 @@ InitializePlatform ( DEBUG ((DEBUG_INFO, "InitializePlatform in Pei-less boot\n"));
PlatformDebugDumpCmos ();
+ if (RETURN_ERROR (QemuFwCfgInitCache (PlatformInfoHob))) {
+ DEBUG ((DEBUG_ERROR, "QemuFwCfgInitCache failed !\n"));
+ }
+
PlatformInfoHob->DefaultMaxCpuNumber = 64;
PlatformInfoHob->PcdPciMmio64Size = 0x800000000;
@@ -116,6 +123,21 @@ InitializePlatform ( return EFI_SUCCESS;
}
+STATIC
+EFI_HOB_PLATFORM_INFO *
+BuildPlatformInfoHob (
+ VOID
+ )
+{
+ EFI_HOB_PLATFORM_INFO PlatformInfoHob;
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ ZeroMem (&PlatformInfoHob, sizeof PlatformInfoHob);
+ BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &PlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO));
+ GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
+ return (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob);
+}
+
/**
* This function brings up the Tdx guest from SEC phase to DXE phase.
* PEI phase is skipped because most of the components in PEI phase
@@ -134,7 +156,7 @@ PeilessStartup ( EFI_SEC_PEI_HAND_OFF *SecCoreData;
EFI_FIRMWARE_VOLUME_HEADER *BootFv;
EFI_STATUS Status;
- EFI_HOB_PLATFORM_INFO PlatformInfoHob;
+ EFI_HOB_PLATFORM_INFO *PlatformInfoHob;
UINT32 DxeCodeBase;
UINT32 DxeCodeSize;
TD_RETURN_DATA TdReturnData;
@@ -145,8 +167,6 @@ PeilessStartup ( VmmHobList = NULL;
SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;
- ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob));
-
if (TdIsEnabled ()) {
VmmHobList = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);
Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
@@ -184,17 +204,17 @@ PeilessStartup ( }
}
+ PlatformInfoHob = BuildPlatformInfoHob ();
+
//
// Initialize the Platform
//
- Status = InitializePlatform (&PlatformInfoHob);
+ Status = InitializePlatform (PlatformInfoHob);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
CpuDeadLoop ();
}
- BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &PlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO));
-
//
// SecFV
//
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c new file mode 100644 index 0000000..6cb302a --- /dev/null +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c @@ -0,0 +1,176 @@ +/** @file
+ QemuFwCfg cached feature related functions.
+ Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include "QemuFwCfgLibInternal.h"
+
+/**
+ Get the pointer to the cached fw_cfg item.
+ @param[in] Item The fw_cfg item to be retrieved.
+ @retval FW_CFG_CACHED_ITEM Pointer to the cached fw_cfg item.
+ @retval NULL The fw_cfg item is not cached.
+**/
+FW_CFG_CACHED_ITEM *
+InternalQemuFwCfgItemCached (
+ IN FIRMWARE_CONFIG_ITEM Item
+ )
+{
+ BOOLEAN Cached;
+ FW_CFG_CACHED_ITEM *CachedItem;
+ UINT16 SelectItem;
+ EFI_PEI_HOB_POINTERS Hob;
+ FW_CFG_CACHED_ITEM *FwCfgCachedItem;
+
+ #ifdef TDX_PEI_LESS_BOOT
+ if (InternalQemuFwCfgCheckOvmfWorkArea () == FALSE) {
+ return NULL;
+ }
+
+ #endif
+
+ SelectItem = (UINT16)(UINTN)Item;
+
+ Hob.Raw = GetFirstGuidHob (&gOvmfFwCfgInfoHobGuid);
+ Cached = FALSE;
+ CachedItem = NULL;
+
+ while (Hob.Raw != NULL) {
+ FwCfgCachedItem = GET_GUID_HOB_DATA (Hob);
+ if ((SelectItem == FwCfgCachedItem->FwCfgItem) && (FwCfgCachedItem->DataSize != 0)) {
+ Cached = TRUE;
+ CachedItem = FwCfgCachedItem;
+ break;
+ }
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gOvmfFwCfgInfoHobGuid, Hob.Raw);
+ }
+
+ return Cached ? CachedItem : NULL;
+}
+
+/**
+ Clear the QEMU_FW_CFG_WORK_AREA.
+**/
+VOID
+InternalQemuFwCfgCacheResetWorkArea (
+ VOID
+ )
+{
+ QEMU_FW_CFG_WORK_AREA *QemuFwCfgWorkArea;
+
+ QemuFwCfgWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgWorkArea != NULL) {
+ QemuFwCfgWorkArea->FwCfgItem = 0;
+ QemuFwCfgWorkArea->Offset = 0;
+ QemuFwCfgWorkArea->Reading = FALSE;
+ }
+}
+
+/**
+ Check if reading from FwCfgCache is ongoing.
+ @retval TRUE Reading from FwCfgCache is ongoing.
+ @retval FALSE Reading from FwCfgCache is not ongoing.
+**/
+BOOLEAN
+InternalQemuFwCfgCacheReading (
+ VOID
+ )
+{
+ BOOLEAN Reading;
+ QEMU_FW_CFG_WORK_AREA *QemuFwCfgWorkArea;
+
+ Reading = FALSE;
+ QemuFwCfgWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgWorkArea != NULL) {
+ Reading = QemuFwCfgWorkArea->Reading;
+ }
+
+ return Reading;
+}
+
+BOOLEAN
+InternalQemuFwCfgCacheSelectItem (
+ IN FIRMWARE_CONFIG_ITEM Item
+ )
+{
+ QEMU_FW_CFG_WORK_AREA *QemuFwCfgWorkArea;
+
+ // Walk thru cached fw_items to see if Item is cached.
+ if (InternalQemuFwCfgItemCached (Item) == NULL) {
+ return FALSE;
+ }
+
+ QemuFwCfgWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgWorkArea == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FwCfg Cache Work Area\n", __func__));
+ return FALSE;
+ }
+
+ QemuFwCfgWorkArea->FwCfgItem = (UINT16)Item;
+ QemuFwCfgWorkArea->Offset = 0;
+ QemuFwCfgWorkArea->Reading = TRUE;
+
+ return TRUE;
+}
+
+/**
+ Read the fw_cfg data from Cache.
+ @param[in] Size Data size to be read
+ @param[in] Buffer Pointer to the buffer to which data is written
+ @retval EFI_SUCCESS - Successfully
+ @retval Others - As the error code indicates
+**/
+EFI_STATUS
+InternalQemuFwCfgCacheReadBytes (
+ IN UINTN Size,
+ IN OUT VOID *Buffer
+ )
+{
+ QEMU_FW_CFG_WORK_AREA *QemuFwCfgWorkArea;
+ FW_CFG_CACHED_ITEM *CachedItem;
+ UINTN ReadSize;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ QemuFwCfgWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgWorkArea == NULL) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (!QemuFwCfgWorkArea->Reading) {
+ return RETURN_NOT_READY;
+ }
+
+ CachedItem = InternalQemuFwCfgItemCached (QemuFwCfgWorkArea->FwCfgItem);
+ if (CachedItem == NULL) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (QemuFwCfgWorkArea->Offset >= CachedItem->DataSize) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid Item Offset(0x%x) in FwCfg Cache\n", __func__, QemuFwCfgWorkArea->Offset));
+ ASSERT (FALSE);
+ return RETURN_ABORTED;
+ }
+
+ if (CachedItem->DataSize - QemuFwCfgWorkArea->Offset > Size) {
+ ReadSize = Size;
+ } else {
+ ReadSize = CachedItem->DataSize - QemuFwCfgWorkArea->Offset;
+ }
+
+ CopyMem (Buffer, (UINT8 *)CachedItem + sizeof (FW_CFG_CACHED_ITEM) + QemuFwCfgWorkArea->Offset, ReadSize);
+ QemuFwCfgWorkArea->Offset += (UINT32)ReadSize;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: found Item 0x%x in FwCfg Cache\n", __func__, QemuFwCfgWorkArea->FwCfgItem));
+ return RETURN_SUCCESS;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c new file mode 100644 index 0000000..d3220c8 --- /dev/null +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c @@ -0,0 +1,262 @@ +/** @file
+ QemuFwCfg cached feature related functions.
+ Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include "QemuFwCfgLibInternal.h"
+#include <Library/TdxHelperLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+#define EV_POSTCODE_INFO_QEMU_FW_CFG_DATA "QEMU FW CFG"
+#define QEMU_FW_CFG_SIZE sizeof (EV_POSTCODE_INFO_QEMU_FW_CFG_DATA)
+
+#pragma pack(1)
+typedef struct {
+ CHAR8 FileName[QEMU_FW_CFG_FNAME_SIZE];
+ BOOLEAN NeedMeasure;
+ UINT16 FwCfgItem;
+ UINT32 FwCfgSize;
+} CACHE_FW_CFG_STRCUT;
+
+typedef struct {
+ UINT8 FwCfg[QEMU_FW_CFG_SIZE];
+ UINT8 FwCfgFileName[QEMU_FW_CFG_FNAME_SIZE];
+} FW_CFG_EVENT;
+
+#pragma pack()
+
+#define QEMU_FW_CFG_SIGNATURE \
+ "QemuFwCfgSignature"
+
+#define QEMU_FW_CFG_SIGNATURE_SIZE sizeof (UINT32)
+
+#define QEMU_FW_CFG_INTERFACE_VERSION \
+ "QemuFwCfgInterfaceVersion"
+
+#define QEMU_FW_CFG_INTERFACE_VERSION_SIZE sizeof (UINT32)
+
+#define QEMU_FW_CFG_FILE_DIR \
+ "QemuFwCfgFileDri"
+
+#define E820_FWCFG_FILE \
+ "etc/e820"
+
+#define SYSTEM_STATES_FWCFG_FILE \
+ "etc/system-states"
+
+#define EXTRA_PCI_ROOTS_FWCFG_FILE \
+ "etc/extra-pci-roots"
+
+#define EXTRA_PCI_ROOTS_FWCFG_SIZE sizeof (UINT64)
+
+#define BOOT_MENU_FWCFG_NAME "BootMenu"
+
+#define BOOT_MENU_FWCFG_SIZE sizeof (UINT16)
+
+#define BOOT_MENU_WAIT_TIME_FWCFG_FILE \
+ "etc/boot-menu-wait"
+
+#define BOOT_MENU_WAIT_TIME_FWCFG_SIZE sizeof (UINT16)
+
+#define RESERVED_MEMORY_END_FWCFG_FILE \
+ "etc/reserved-memory-end"
+
+#define RESERVED_MEMORY_END_FWCFG_SIZE sizeof (UINT64)
+
+#define PCI_MMIO64_FWCFG_FILE \
+ "opt/ovmf/X-PciMmio64Mb"
+
+#define BOOTORDER_FWCFG_FILE \
+ "bootorder"
+
+#define INVALID_FW_CFG_ITEM 0xFFFF
+
+STATIC CONST CACHE_FW_CFG_STRCUT mCacheFwCfgList[] = {
+ { QEMU_FW_CFG_SIGNATURE, FALSE, QemuFwCfgItemSignature, QEMU_FW_CFG_SIGNATURE_SIZE },
+ { QEMU_FW_CFG_INTERFACE_VERSION, FALSE, QemuFwCfgItemInterfaceVersion, QEMU_FW_CFG_INTERFACE_VERSION_SIZE },
+ { QEMU_FW_CFG_FILE_DIR, FALSE, QemuFwCfgItemFileDir, 0 },
+ { E820_FWCFG_FILE, FALSE, INVALID_FW_CFG_ITEM, 0 },
+ { SYSTEM_STATES_FWCFG_FILE, FALSE, INVALID_FW_CFG_ITEM, 0 },
+ { EXTRA_PCI_ROOTS_FWCFG_FILE, TRUE, INVALID_FW_CFG_ITEM, EXTRA_PCI_ROOTS_FWCFG_SIZE },
+ { BOOT_MENU_FWCFG_NAME, TRUE, QemuFwCfgItemBootMenu, BOOT_MENU_FWCFG_SIZE },
+ { BOOT_MENU_WAIT_TIME_FWCFG_FILE, TRUE, INVALID_FW_CFG_ITEM, BOOT_MENU_WAIT_TIME_FWCFG_SIZE },
+ { RESERVED_MEMORY_END_FWCFG_FILE, TRUE, INVALID_FW_CFG_ITEM, RESERVED_MEMORY_END_FWCFG_SIZE },
+ { PCI_MMIO64_FWCFG_FILE, TRUE, INVALID_FW_CFG_ITEM, 0 },
+ { BOOTORDER_FWCFG_FILE, TRUE, INVALID_FW_CFG_ITEM, 0 },
+};
+
+#define CACHE_FW_CFG_COUNT sizeof (mCacheFwCfgList)/sizeof (mCacheFwCfgList[0])
+
+STATIC
+UINT32
+CalcuateQemuFwCfgFileDirSize (
+ IN FIRMWARE_CONFIG_ITEM FwCfgItem
+ )
+{
+ UINT32 FileCount;
+ UINT32 FileDirSize;
+
+ QemuFwCfgSelectItem (FwCfgItem);
+ FileCount = SwapBytes32 (QemuFwCfgRead32 ());
+ FileDirSize = FileCount * sizeof (FWCFG_FILE) + sizeof (UINT32);
+ return FileDirSize;
+}
+
+STATIC
+EFI_STATUS
+ConstructCacheFwCfgList (
+ IN OUT CACHE_FW_CFG_STRCUT *CacheFwCfgList
+ )
+{
+ UINT32 Index;
+ UINT32 Count;
+ UINTN FwCfgSize;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+
+ if (CacheFwCfgList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (CacheFwCfgList, mCacheFwCfgList, sizeof (mCacheFwCfgList));
+ Count = CACHE_FW_CFG_COUNT;
+
+ for (Index = 0; Index < Count; Index++) {
+ if (CacheFwCfgList[Index].FwCfgItem == QemuFwCfgItemFileDir) {
+ CacheFwCfgList[Index].FwCfgSize = CalcuateQemuFwCfgFileDirSize (QemuFwCfgItemFileDir);
+ continue;
+ }
+
+ if (CacheFwCfgList[Index].FwCfgItem != INVALID_FW_CFG_ITEM) {
+ continue;
+ }
+
+ if (EFI_ERROR (QemuFwCfgFindFile (CacheFwCfgList[Index].FileName, &FwCfgItem, &FwCfgSize))) {
+ continue;
+ }
+
+ if (FwCfgSize == 0) {
+ continue;
+ }
+
+ if ((CacheFwCfgList[Index].FwCfgSize != 0) && (FwCfgSize != CacheFwCfgList[Index].FwCfgSize)) {
+ continue;
+ }
+
+ CacheFwCfgList[Index].FwCfgItem = (UINT16)FwCfgItem;
+ CacheFwCfgList[Index].FwCfgSize = (UINT32)FwCfgSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+CacheFwCfgInfoWithOptionalMeasurment (
+ IN CACHE_FW_CFG_STRCUT *CacheFwCfgList
+ )
+{
+ UINT32 Index;
+ UINT32 Count;
+ UINT8 *FwCfginfoHobData;
+ FW_CFG_CACHED_ITEM *CachedItem;
+ UINT8 *ItemData;
+ UINT32 FwCfgItemHobSize;
+
+ Count = CACHE_FW_CFG_COUNT;
+
+ for (Index = 0; Index < Count; Index++) {
+ if ((CacheFwCfgList[Index].FwCfgItem == INVALID_FW_CFG_ITEM) || (CacheFwCfgList[Index].FwCfgSize == 0)) {
+ continue;
+ }
+
+ FwCfginfoHobData = NULL;
+ FwCfgItemHobSize = sizeof (FW_CFG_CACHED_ITEM) + CacheFwCfgList[Index].FwCfgSize;
+ FwCfginfoHobData = BuildGuidHob (&gOvmfFwCfgInfoHobGuid, FwCfgItemHobSize);
+ if (FwCfginfoHobData == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: BuildGuidHob Failed with FwCfgItemHobSize(0x%x)\n", __func__, FwCfgItemHobSize));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (FwCfginfoHobData, FwCfgItemHobSize);
+ CachedItem = (FW_CFG_CACHED_ITEM *)FwCfginfoHobData;
+ ItemData = (UINT8 *)CachedItem + sizeof (FW_CFG_CACHED_ITEM);
+
+ QemuFwCfgSelectItem (CacheFwCfgList[Index].FwCfgItem);
+ QemuFwCfgReadBytes (CacheFwCfgList[Index].FwCfgSize, ItemData);
+
+ CachedItem->FwCfgItem = CacheFwCfgList[Index].FwCfgItem;
+ CachedItem->DataSize = CacheFwCfgList[Index].FwCfgSize;
+ DEBUG ((
+ DEBUG_INFO,
+ "Cache FwCfg Name: %a Item:0x%x Size: 0x%x \n",
+ CacheFwCfgList[Index].FileName,
+ CachedItem->FwCfgItem,
+ CachedItem->DataSize
+ ));
+
+ if (CacheFwCfgList[Index].NeedMeasure == FALSE) {
+ continue;
+ }
+
+ if (TdIsEnabled ()) {
+ FW_CFG_EVENT FwCfgEvent;
+ EFI_STATUS Status;
+
+ ZeroMem (&FwCfgEvent, sizeof (FW_CFG_EVENT));
+ CopyMem (&FwCfgEvent.FwCfg, EV_POSTCODE_INFO_QEMU_FW_CFG_DATA, sizeof (EV_POSTCODE_INFO_QEMU_FW_CFG_DATA));
+ CopyMem (&FwCfgEvent.FwCfgFileName, CacheFwCfgList[Index].FileName, QEMU_FW_CFG_FNAME_SIZE);
+
+ Status = TpmMeasureAndLogData (
+ 1,
+ EV_PLATFORM_CONFIG_FLAGS,
+ (VOID *)&FwCfgEvent,
+ sizeof (FwCfgEvent),
+ (VOID *)ItemData,
+ CacheFwCfgList[Index].FwCfgSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "TpmMeasureAndLogData failed with %r\n", Status));
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InternalQemuFwCfgInitCache (
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ if (PlatformInfoHob == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PlatformInfoHob->QemuFwCfgWorkArea.FwCfgItem = INVALID_FW_CFG_ITEM;
+ PlatformInfoHob->QemuFwCfgWorkArea.Offset = 0;
+ PlatformInfoHob->QemuFwCfgWorkArea.Reading = FALSE;
+
+ if (!QemuFwCfgIsAvailable ()) {
+ return EFI_UNSUPPORTED;
+ }
+
+ CACHE_FW_CFG_STRCUT CacheFwCfgList[CACHE_FW_CFG_COUNT];
+
+ if (EFI_ERROR (ConstructCacheFwCfgList (CacheFwCfgList))) {
+ return EFI_ABORTED;
+ }
+
+ if (EFI_ERROR (CacheFwCfgInfoWithOptionalMeasurment (CacheFwCfgList))) {
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c index c86f591..e8b2caf 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c @@ -24,11 +24,10 @@ #include "QemuFwCfgLibInternal.h"
-STATIC BOOLEAN mQemuFwCfgSupported = FALSE;
-STATIC BOOLEAN mQemuFwCfgDmaSupported;
-
STATIC EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
+STATIC QEMU_FW_CFG_WORK_AREA mQemuFwCfgWorkArea = { 0 };
+
/**
Returns a boolean indicating if the firmware configuration interface
is available or not.
@@ -62,8 +61,8 @@ QemuFwCfgInitialize ( // Enable the access routines while probing to see if it is supported.
// For probing we always use the IO Port (IoReadFifo8()) access method.
//
- mQemuFwCfgSupported = TRUE;
- mQemuFwCfgDmaSupported = FALSE;
+ mQemuFwCfgWorkArea.QemuFwCfgSupported = TRUE;
+ mQemuFwCfgWorkArea.QemuFwCfgDmaSupported = FALSE;
QemuFwCfgSelectItem (QemuFwCfgItemSignature);
Signature = QemuFwCfgRead32 ();
@@ -76,20 +75,20 @@ QemuFwCfgInitialize ( )
{
DEBUG ((DEBUG_INFO, "QemuFwCfg interface not supported.\n"));
- mQemuFwCfgSupported = FALSE;
+ mQemuFwCfgWorkArea.QemuFwCfgSupported = FALSE;
return RETURN_SUCCESS;
}
if ((Revision & FW_CFG_F_DMA) == 0) {
DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n"));
} else {
- mQemuFwCfgDmaSupported = TRUE;
+ mQemuFwCfgWorkArea.QemuFwCfgDmaSupported = TRUE;
DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
}
CcGuestAttr = PcdGet64 (PcdConfidentialComputingGuestAttr);
- if (mQemuFwCfgDmaSupported && (CC_GUEST_IS_SEV (CcGuestAttr) ||
- CC_GUEST_IS_TDX (CcGuestAttr)))
+ if (mQemuFwCfgWorkArea.QemuFwCfgDmaSupported && (CC_GUEST_IS_SEV (CcGuestAttr) ||
+ CC_GUEST_IS_TDX (CcGuestAttr)))
{
EFI_STATUS Status;
@@ -131,7 +130,7 @@ InternalQemuFwCfgIsAvailable ( VOID
)
{
- return mQemuFwCfgSupported;
+ return mQemuFwCfgWorkArea.QemuFwCfgSupported;
}
/**
@@ -146,7 +145,7 @@ InternalQemuFwCfgDmaIsAvailable ( VOID
)
{
- return mQemuFwCfgDmaSupported;
+ return mQemuFwCfgWorkArea.QemuFwCfgDmaSupported;
}
/**
@@ -496,3 +495,40 @@ InternalQemuFwCfgDmaBytes ( UnmapFwCfgDmaDataBuffer (DataMapping);
}
}
+
+/**
+ Check if the Ovmf work area is built as HobList before invoking Hob services.
+
+ @retval TRUE Ovmf work area is not NULL and it is built as HobList.
+ @retval FALSE Ovmf work area is NULL or it is not built as HobList.
+**/
+BOOLEAN
+InternalQemuFwCfgCheckOvmfWorkArea (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+/**
+ Get the pointer to the QEMU_FW_CFG_WORK_AREA. This data is used as the
+ workarea to record the ongoing fw_cfg item and offset.
+ @retval QEMU_FW_CFG_WORK_AREA Pointer to the QEMU_FW_CFG_WORK_AREA
+ @retval NULL QEMU_FW_CFG_WORK_AREA doesn't exist
+**/
+QEMU_FW_CFG_WORK_AREA *
+InternalQemuFwCfgCacheGetWorkArea (
+ VOID
+ )
+{
+ return &mQemuFwCfgWorkArea;
+}
+
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitCache (
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ return RETURN_UNSUPPORTED;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf index 11fbcda..5132680 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf @@ -30,6 +30,7 @@ QemuFwCfgLibInternal.h
QemuFwCfgLib.c
QemuFwCfgDxe.c
+ QemuFwCfgCache.c
[Packages]
MdePkg/MdePkg.dec
@@ -42,6 +43,7 @@ DebugLib
IoLib
MemoryAllocationLib
+ HobLib
[Protocols]
gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
@@ -49,5 +51,8 @@ [Pcd]
gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
+[Guids]
+ gOvmfFwCfgInfoHobGuid
+
[Depex]
gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c index 8e8f54b..9e896fb 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c @@ -35,6 +35,13 @@ QemuFwCfgSelectItem ( )
{
DEBUG ((DEBUG_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN)QemuFwCfgItem));
+
+ if (InternalQemuFwCfgCacheSelectItem (QemuFwCfgItem)) {
+ return;
+ } else {
+ InternalQemuFwCfgCacheResetWorkArea ();
+ }
+
IoWrite16 (FW_CFG_IO_SELECTOR, (UINT16)(UINTN)QemuFwCfgItem);
}
@@ -52,6 +59,11 @@ InternalQemuFwCfgReadBytes ( IN VOID *Buffer OPTIONAL
)
{
+ if ( InternalQemuFwCfgCacheReading ()) {
+ InternalQemuFwCfgCacheReadBytes (Size, Buffer);
+ return;
+ }
+
if (InternalQemuFwCfgDmaIsAvailable () && (Size <= MAX_UINT32)) {
InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FW_CFG_DMA_CTL_READ);
return;
@@ -114,6 +126,32 @@ QemuFwCfgWriteBytes ( }
/**
+ Skip bytes in FwCfg cache info Hob.
+ @param[in] Size Number of bytes to skip.
+**/
+STATIC
+VOID
+InternalQemuFwCfgCacheSkipBytes (
+ IN UINT32 Size
+ )
+{
+ QEMU_FW_CFG_WORK_AREA *QemuFwCfgWorkArea;
+
+ if (Size == 0) {
+ return;
+ }
+
+ QemuFwCfgWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if ((QemuFwCfgWorkArea->Offset + Size) > MAX_UINT32) {
+ DEBUG ((DEBUG_ERROR, "%a: Integer overflow with invalid offset size\n", __func__));
+ ASSERT (FALSE);
+ QemuFwCfgWorkArea->Offset = MAX_UINT32;
+ } else {
+ QemuFwCfgWorkArea->Offset += Size;
+ }
+}
+
+/**
Skip bytes in the firmware configuration item.
Increase the offset of the firmware configuration item without transferring
@@ -135,6 +173,11 @@ QemuFwCfgSkipBytes ( return;
}
+ if ( InternalQemuFwCfgCacheReading () && (Size <= MAX_UINT32)) {
+ InternalQemuFwCfgCacheSkipBytes ((UINT32)Size);
+ return;
+ }
+
if (InternalQemuFwCfgDmaIsAvailable () && (Size <= MAX_UINT32)) {
InternalQemuFwCfgDmaBytes ((UINT32)Size, NULL, FW_CFG_DMA_CTL_SKIP);
return;
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h index 6f7beb6..a33caff 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h @@ -11,6 +11,31 @@ #ifndef __QEMU_FW_CFG_LIB_INTERNAL_H__
#define __QEMU_FW_CFG_LIB_INTERNAL_H__
+#include <Base.h>
+#include <Uefi/UefiMultiPhase.h>
+#include <Uefi/UefiBaseType.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+#include <Library/HobLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#pragma pack(1)
+typedef struct {
+ UINT16 FwCfgItem;
+ UINT32 DataSize;
+ // UINT8 *data
+} FW_CFG_CACHED_ITEM;
+
+// Refer to https://www.qemu.org/docs/master/specs/fw_cfg.html
+// The FwCfg File item struct in QemuFwCfgItemFileDir
+typedef struct {
+ UINT32 Size; /* size of referenced fw_cfg item, big-endian */
+ UINT16 Select; /* selector key of fw_cfg item, big-endian */
+ UINT16 Reserved;
+ UINT8 Name[QEMU_FW_CFG_FNAME_SIZE];
+} FWCFG_FILE;
+#pragma pack()
+
/**
Returns a boolean indicating if the firmware configuration interface is
available for library-internal purposes.
@@ -70,4 +95,86 @@ QemuFwCfgIsTdxGuest ( VOID
);
+/**
+ Check if the Ovmf work area is built as HobList before invoking Hob services.
+
+ @retval TRUE Ovmf work area is not NULL and it is built as HobList.
+ @retval FALSE Ovmf work area is NULL or it is not built as HobList.
+**/
+BOOLEAN
+InternalQemuFwCfgCheckOvmfWorkArea (
+ VOID
+ );
+
+/**
+ Read the fw_cfg data from Cache.
+ @retval EFI_SUCCESS - Successfully
+ @retval Others - As the error code indicates
+**/
+EFI_STATUS
+InternalQemuFwCfgCacheReadBytes (
+ IN UINTN Size,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Select the fw_cfg item for reading from cache. If the fw_cfg item
+ is not cached, then it returns FALSE.
+ @param[in] Item The fw_cfg item to be selected
+ @retval TRUE The fw_cfg item is selected.
+ @retval FALSE The fw_cfg item is not selected.
+**/
+BOOLEAN
+InternalQemuFwCfgCacheSelectItem (
+ IN FIRMWARE_CONFIG_ITEM Item
+ );
+
+/**
+ Get the pointer to the QEMU_FW_CFG_WORK_AREA. This data is used as the
+ workarea to record the ongoing fw_cfg item and offset.
+ @retval QEMU_FW_CFG_WORK_AREA Pointer to the QEMU_FW_CFG_WORK_AREA
+ @retval NULL QEMU_FW_CFG_WORK_AREA doesn't exist
+**/
+QEMU_FW_CFG_WORK_AREA *
+InternalQemuFwCfgCacheGetWorkArea (
+ VOID
+ );
+
+/**
+ Clear the QEMU_FW_CFG_WORK_AREA.
+**/
+VOID
+InternalQemuFwCfgCacheResetWorkArea (
+ VOID
+ );
+
+/**
+ Get the pointer to the cached fw_cfg item.
+ @param[in] Item The fw_cfg item to be retrieved.
+ @retval FW_CFG_CACHED_ITEM Pointer to the cached fw_cfg item.
+ @retval NULL The fw_cfg item is not cached.
+**/
+FW_CFG_CACHED_ITEM *
+InternalQemuFwCfgItemCached (
+ IN FIRMWARE_CONFIG_ITEM Item
+ );
+
+/**
+ Check if reading from FwCfgCache is ongoing.
+ @retval TRUE Reading from FwCfgCache is ongoing.
+ @retval FALSE Reading from FwCfgCache is not ongoing.
+**/
+BOOLEAN
+InternalQemuFwCfgCacheReading (
+ VOID
+ );
+
+/**
+ init the fw_cfg info hob with optional measurement
+**/
+EFI_STATUS
+InternalQemuFwCfgInitCache (
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ );
+
#endif
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c index 6a85ed6..dc99d91 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c @@ -197,3 +197,12 @@ QemuFwCfgFindFile ( {
return RETURN_UNSUPPORTED;
}
+
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitCache (
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ return RETURN_UNSUPPORTED;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c index da86a3c..9c69f52 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c @@ -14,7 +14,6 @@ #include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/IoLib.h>
-#include <Library/PlatformInitLib.h>
#include <Library/QemuFwCfgLib.h>
#include <WorkArea.h>
@@ -69,10 +68,20 @@ QemuFwCfgProbe ( BOOLEAN CcGuest;
// Use direct Io* calls for probing to avoid recursion.
- IoWrite16 (FW_CFG_IO_SELECTOR, (UINT16)QemuFwCfgItemSignature);
- IoReadFifo8 (FW_CFG_IO_DATA, sizeof Signature, &Signature);
- IoWrite16 (FW_CFG_IO_SELECTOR, (UINT16)QemuFwCfgItemInterfaceVersion);
- IoReadFifo8 (FW_CFG_IO_DATA, sizeof Revision, &Revision);
+ QemuFwCfgSelectItem (QemuFwCfgItemSignature);
+ if ( InternalQemuFwCfgCacheReading ()) {
+ InternalQemuFwCfgCacheReadBytes (sizeof Signature, &Signature);
+ } else {
+ IoReadFifo8 (FW_CFG_IO_DATA, sizeof Signature, &Signature);
+ }
+
+ QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
+ if ( InternalQemuFwCfgCacheReading ()) {
+ InternalQemuFwCfgCacheReadBytes (sizeof Revision, &Revision);
+ } else {
+ IoReadFifo8 (FW_CFG_IO_DATA, sizeof Revision, &Revision);
+ }
+
CcGuest = QemuFwCfgIsCcGuest ();
*Supported = FALSE;
@@ -111,8 +120,8 @@ QemuFwCfgGetPlatformInfo ( if (!PlatformInfoHob->QemuFwCfgChecked) {
QemuFwCfgProbe (
- &PlatformInfoHob->QemuFwCfgSupported,
- &PlatformInfoHob->QemuFwCfgDmaSupported
+ &PlatformInfoHob->QemuFwCfgWorkArea.QemuFwCfgSupported,
+ &PlatformInfoHob->QemuFwCfgWorkArea.QemuFwCfgDmaSupported
);
PlatformInfoHob->QemuFwCfgChecked = TRUE;
}
@@ -145,7 +154,7 @@ InternalQemuFwCfgIsAvailable ( {
EFI_HOB_PLATFORM_INFO *PlatformInfoHob = QemuFwCfgGetPlatformInfo ();
- return PlatformInfoHob->QemuFwCfgSupported;
+ return PlatformInfoHob->QemuFwCfgWorkArea.QemuFwCfgSupported;
}
/**
@@ -162,7 +171,7 @@ InternalQemuFwCfgDmaIsAvailable ( {
EFI_HOB_PLATFORM_INFO *PlatformInfoHob = QemuFwCfgGetPlatformInfo ();
- return PlatformInfoHob->QemuFwCfgDmaSupported;
+ return PlatformInfoHob->QemuFwCfgWorkArea.QemuFwCfgDmaSupported;
}
/**
@@ -242,3 +251,52 @@ InternalQemuFwCfgDmaBytes ( //
MemoryFence ();
}
+
+/**
+ Get the pointer to the QEMU_FW_CFG_WORK_AREA. This data is used as the
+ workarea to record the onging fw_cfg item and offset.
+ @retval QEMU_FW_CFG_WORK_AREA Pointer to the QEMU_FW_CFG_WORK_AREA
+ @retval NULL QEMU_FW_CFG_WORK_AREA doesn't exist
+**/
+QEMU_FW_CFG_WORK_AREA *
+InternalQemuFwCfgCacheGetWorkArea (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_HOB_PLATFORM_INFO *PlatformHobinfo;
+
+ GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
+ if (GuidHob == NULL) {
+ return NULL;
+ }
+
+ PlatformHobinfo = (EFI_HOB_PLATFORM_INFO *)(VOID *)GET_GUID_HOB_DATA (GuidHob);
+ return &(PlatformHobinfo->QemuFwCfgWorkArea);
+}
+
+/**
+ OVMF reads configuration data from QEMU via fw_cfg.
+ For Td-Guest VMM is out of TCB and the configuration data is untrusted.
+ From the security perpective the configuration data shall be measured
+ before it is consumed.
+ This function reads the fw_cfg items and cached them. In the meanwhile these
+ fw_cfg items are measured as well. This is to avoid changing the order when
+ reading the fw_cfg process, which depends on multiple factors(depex, order in
+ the Firmware volume).
+ @retval RETURN_SUCCESS - Successfully cache with measurement
+ @retval Others - As the error code indicates
+ */
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitCache (
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ if (EFI_ERROR (InternalQemuFwCfgInitCache (PlatformInfoHob))) {
+ return RETURN_ABORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "QemuFwCfgInitCache Pass!!!\n"));
+ return RETURN_SUCCESS;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf index b1f548f..7ecfa48 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf @@ -30,10 +30,14 @@ QemuFwCfgLibInternal.h
QemuFwCfgLib.c
QemuFwCfgPei.c
+ QemuFwCfgCache.c
+ QemuFwCfgCacheInit.c
[Packages]
MdePkg/MdePkg.dec
OvmfPkg/OvmfPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
[LibraryClasses]
BaseLib
@@ -42,9 +46,11 @@ HobLib
IoLib
MemoryAllocationLib
+ TpmMeasurementLib
[Guids]
gUefiOvmfPkgPlatformInfoGuid
+ gOvmfFwCfgInfoHobGuid
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c index 63cfee9..31bafa9 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c @@ -13,7 +13,10 @@ #include <Library/BaseLib.h>
#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
#include <Library/QemuFwCfgLib.h>
+#include <PiPei.h>
+#include <WorkArea.h>
#include "QemuFwCfgLibInternal.h"
@@ -119,3 +122,93 @@ InternalQemuFwCfgDmaBytes ( ASSERT (FALSE);
CpuDeadLoop ();
}
+
+#ifdef TDX_PEI_LESS_BOOT
+
+/**
+ Check if the Ovmf work area is built as HobList before invoking Hob services.
+
+ @retval TRUE Ovmf work area is not NULL and it is built as HobList.
+ @retval FALSE Ovmf work area is NULL or it is not built as HobList.
+**/
+BOOLEAN
+InternalQemuFwCfgCheckOvmfWorkArea (
+ VOID
+ )
+{
+ TDX_WORK_AREA *TdxWorkArea;
+
+ // QemuFwCfgLib might be called in a very early stage
+ // (at that moment HobList may not be set). So an additional check
+ // to the HobList is needed.
+ TdxWorkArea = (TDX_WORK_AREA *)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase);
+ if ((TdxWorkArea == NULL) || (TdxWorkArea->SecTdxWorkArea.HobList == 0)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Get the pointer to the QEMU_FW_CFG_WORK_AREA. This data is used as the
+ workarea to record the ongoing fw_cfg item and offset.
+ @retval QEMU_FW_CFG_WORK_AREA Pointer to the QEMU_FW_CFG_WORK_AREA
+ @retval NULL QEMU_FW_CFG_WORK_AREA doesn't exist
+**/
+QEMU_FW_CFG_WORK_AREA *
+InternalQemuFwCfgCacheGetWorkArea (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_HOB_PLATFORM_INFO *PlatformHobinfo;
+
+ if (InternalQemuFwCfgCheckOvmfWorkArea () == FALSE) {
+ return NULL;
+ }
+
+ GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
+ if (GuidHob == NULL) {
+ return NULL;
+ }
+
+ PlatformHobinfo = (EFI_HOB_PLATFORM_INFO *)(VOID *)GET_GUID_HOB_DATA (GuidHob);
+ return &(PlatformHobinfo->QemuFwCfgWorkArea);
+}
+
+/**
+ OVMF reads configuration data from QEMU via fw_cfg.
+ For Td-Guest VMM is out of TCB and the configuration data is untrusted.
+ From the security perpective the configuration data shall be measured
+ before it is consumed.
+ This function reads the fw_cfg items and cached them. In the meanwhile these
+ fw_cfg items are measured as well. This is to avoid changing the order when
+ reading the fw_cfg process, which depends on multiple factors(depex, order in
+ the Firmware volume).
+ @retval RETURN_SUCCESS - Successfully cache with measurement
+ @retval Others - As the error code indicates
+ */
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitCache (
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
+ )
+{
+ if (!QemuFwCfgIsAvailable ()) {
+ DEBUG ((DEBUG_ERROR, "%a: Qemu Fw_Cfg is not Available! \n", __func__));
+ return RETURN_UNSUPPORTED;
+ }
+
+ if (InternalQemuFwCfgCheckOvmfWorkArea () == FALSE) {
+ return RETURN_ABORTED;
+ }
+
+ if (EFI_ERROR (InternalQemuFwCfgInitCache (PlatformInfoHob))) {
+ return RETURN_ABORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "QemuFwCfgInitCache Pass!!!\n"));
+ return RETURN_SUCCESS;
+}
+
+#endif
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf index d34edd6..587fe3e 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf @@ -28,10 +28,14 @@ QemuFwCfgLibInternal.h
QemuFwCfgLib.c
QemuFwCfgSec.c
+ QemuFwCfgCache.c
+ QemuFwCfgCacheInit.c
[Packages]
MdePkg/MdePkg.dec
OvmfPkg/OvmfPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
[LibraryClasses]
BaseLib
@@ -39,4 +43,13 @@ DebugLib
IoLib
MemoryAllocationLib
+ HobLib
+ TpmMeasurementLib
+
+[Guids]
+ gOvmfFwCfgInfoHobGuid
+ gUefiOvmfPkgPlatformInfoGuid
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
|