summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCeping Sun <cepingx.sun@intel.com>2024-09-27 13:50:26 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-03-20 02:37:31 +0000
commitbe529ef3c9d617209fb6b17206e35b656edc68cf (patch)
tree453ebe1cc80077e361e1672b5bdf31d3def95bc4
parent63408b289565c719b2ae759dc815e147820a8d3e (diff)
downloadedk2-be529ef3c9d617209fb6b17206e35b656edc68cf.tar.gz
edk2-be529ef3c9d617209fb6b17206e35b656edc68cf.tar.bz2
edk2-be529ef3c9d617209fb6b17206e35b656edc68cf.zip
OvmfPkg/QemuFwCfgLib: Add FwCfg cache interface
Since TDVF needs to cache and measure FwCfg, it is required to add an API to support cache with optional measurement and add some internal interfaces to support cache in QemuFwCfgLib. The new API is listed below: QemuFwCfgInitCache() The new Internal interfaces are listed below: InternalQemuFwCfgCacheReadBytes() InternalQemuFwCfgCacheSelectItem() InternalQemuFwCfgCacheGetWorkArea() InternalQemuFwCfgCacheResetWorkArea() InternalQemuFwCfgItemCached() InternalQemuFwCfgCacheReading() InternalQemuFwCfgInitCache() InternalQemuFwCfgCheckOvmfWorkArea() Cc: Erdem Aktas <erdemaktas@google.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Min Xu <min.m.xu@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Min Xu <min.m.xu@intel.com> Signed-off-by: Ceping Sun <cepingx.sun@intel.com>
-rw-r--r--OvmfPkg/Include/Library/QemuFwCfgLib.h20
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c176
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c262
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h107
4 files changed, 565 insertions, 0 deletions
diff --git a/OvmfPkg/Include/Library/QemuFwCfgLib.h b/OvmfPkg/Include/Library/QemuFwCfgLib.h
index 2ad96c0297..73f4503263 100644
--- a/OvmfPkg/Include/Library/QemuFwCfgLib.h
+++ b/OvmfPkg/Include/Library/QemuFwCfgLib.h
@@ -12,6 +12,7 @@
#define __FW_CFG_LIB__
#include <IndustryStandard/QemuFwCfg.h>
+#include <Library/PlatformInitLib.h>
/**
Returns a boolean indicating if the firmware configuration interface
@@ -164,4 +165,23 @@ QemuFwCfgFindFile (
OUT UINTN *Size
);
+/**
+ 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
+ );
+
#endif
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c
new file mode 100644
index 0000000000..f15ae7a6ec
--- /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_CACHE_WORK_AREA.
+**/
+VOID
+InternalQemuFwCfgCacheResetWorkArea (
+ VOID
+ )
+{
+ QEMU_FW_CFG_CACHE_WORK_AREA *QemuFwCfgCacheWorkArea;
+
+ QemuFwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgCacheWorkArea != NULL) {
+ QemuFwCfgCacheWorkArea->FwCfgItem = 0;
+ QemuFwCfgCacheWorkArea->Offset = 0;
+ QemuFwCfgCacheWorkArea->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_CACHE_WORK_AREA *QemuFwCfgCacheWorkArea;
+
+ Reading = FALSE;
+ QemuFwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgCacheWorkArea != NULL) {
+ Reading = QemuFwCfgCacheWorkArea->Reading;
+ }
+
+ return Reading;
+}
+
+BOOLEAN
+InternalQemuFwCfgCacheSelectItem (
+ IN FIRMWARE_CONFIG_ITEM Item
+ )
+{
+ QEMU_FW_CFG_CACHE_WORK_AREA *QemuFwCfgCacheWorkArea;
+
+ // Walk thru cached fw_items to see if Item is cached.
+ if (InternalQemuFwCfgItemCached (Item) == NULL) {
+ return FALSE;
+ }
+
+ QemuFwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgCacheWorkArea == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FwCfg Cache Work Area\n", __func__));
+ return FALSE;
+ }
+
+ QemuFwCfgCacheWorkArea->FwCfgItem = (UINT16)Item;
+ QemuFwCfgCacheWorkArea->Offset = 0;
+ QemuFwCfgCacheWorkArea->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_CACHE_WORK_AREA *QemuFwCfgCacheWorkArea;
+ FW_CFG_CACHED_ITEM *CachedItem;
+ UINTN ReadSize;
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ QemuFwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
+ if (QemuFwCfgCacheWorkArea == NULL) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (!QemuFwCfgCacheWorkArea->Reading) {
+ return RETURN_NOT_READY;
+ }
+
+ CachedItem = InternalQemuFwCfgItemCached (QemuFwCfgCacheWorkArea->FwCfgItem);
+ if (CachedItem == NULL) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (QemuFwCfgCacheWorkArea->Offset >= CachedItem->DataSize) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid Item Offset(0x%x) in FwCfg Cache\n", __func__, QemuFwCfgCacheWorkArea->Offset));
+ ASSERT (FALSE);
+ return RETURN_ABORTED;
+ }
+
+ if (CachedItem->DataSize - QemuFwCfgCacheWorkArea->Offset > Size) {
+ ReadSize = Size;
+ } else {
+ ReadSize = CachedItem->DataSize - QemuFwCfgCacheWorkArea->Offset;
+ }
+
+ CopyMem (Buffer, (UINT8 *)CachedItem + sizeof (FW_CFG_CACHED_ITEM) + QemuFwCfgCacheWorkArea->Offset, ReadSize);
+ QemuFwCfgCacheWorkArea->Offset += (UINT32)ReadSize;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: found Item 0x%x in FwCfg Cache\n", __func__, QemuFwCfgCacheWorkArea->FwCfgItem));
+ return RETURN_SUCCESS;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c
new file mode 100644
index 0000000000..25fd1f10d7
--- /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->QemuFwCfgCacheWorkArea.FwCfgItem = INVALID_FW_CFG_ITEM;
+ PlatformInfoHob->QemuFwCfgCacheWorkArea.Offset = 0;
+ PlatformInfoHob->QemuFwCfgCacheWorkArea.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/QemuFwCfgLibInternal.h b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
index 6f7beb6ac1..acbaf0017d 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_CACHE_WORK_AREA. This data is used as the
+ workarea to record the ongoing fw_cfg item and offset.
+ @retval QEMU_FW_CFG_CACHE_WORK_AREA Pointer to the QEMU_FW_CFG_CACHE_WORK_AREA
+ @retval NULL QEMU_FW_CFG_CACHE_WORK_AREA doesn't exist
+**/
+QEMU_FW_CFG_CACHE_WORK_AREA *
+InternalQemuFwCfgCacheGetWorkArea (
+ VOID
+ );
+
+/**
+ Clear the QEMU_FW_CFG_CACHE_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