blob: d3220c8f0392439fe26a67e730cf2c4a9b9977e0 [file] [log] [blame]
/** @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;
}