summaryrefslogtreecommitdiff
path: root/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c')
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCacheInit.c262
1 files changed, 262 insertions, 0 deletions
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;
+}