Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache measure fwcfg.v3 #6399

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions OvmfPkg/AmdSev/AmdSevX64.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@
OvmfPkg/PlatformPei/PlatformPei.inf {
<LibraryClasses>
NULL|OvmfPkg/IntelTdx/TdxHelperLib/TdxHelperLibNull.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
}
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
UefiCpuPkg/CpuMpPei/CpuMpPei.inf
Expand Down
1 change: 1 addition & 0 deletions OvmfPkg/CloudHv/CloudHvX64.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@
OvmfPkg/PlatformPei/PlatformPei.inf {
<LibraryClasses>
NULL|OvmfPkg/IntelTdx/TdxHelperLib/TdxHelperLibNull.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
}
UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf {
<LibraryClasses>
Expand Down
10 changes: 10 additions & 0 deletions OvmfPkg/Include/Dsc/OvmfTpmLibs.dsc.inc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
!endif

!if $(TPM2_ENABLE) == TRUE || $(CC_MEASUREMENT_ENABLE) == TRUE
#
# TpmMeasurementLib supports measurement functions for both TPM and Confidential Computing.
# It should be controlled by TPM2_ENABLE and CC_MEASUREMENT_ENABLE.
#
TpmMeasurementLib|SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf
!else
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
!endif

[LibraryClasses.common.DXE_DRIVER]
!if $(TPM2_ENABLE) == TRUE
!if $(TPM1_ENABLE) == TRUE
Expand Down
19 changes: 19 additions & 0 deletions OvmfPkg/Include/Library/QemuFwCfgLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,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 (
VOID
);

#endif
1 change: 1 addition & 0 deletions OvmfPkg/IntelTdx/IntelTdxX64.dsc
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@
NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
NULL|OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelperLib.inf
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SecCryptLib.inf
TpmMeasurementLib|SecurityPkg/Library/SecTpmMeasurementLib/SecTpmMeasurementLib.inf
}

#
Expand Down
6 changes: 6 additions & 0 deletions OvmfPkg/Library/PeilessStartupLib/PeilessStartup.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <ConfidentialComputingGuestAttr.h>
#include <Guid/MemoryTypeInformation.h>
#include <OvmfPlatforms.h>
#include <Base.h>
#include <Library/QemuFwCfgLib.h>
#include "PeilessStartupInternal.h"

#define GET_GPAW_INIT_STATE(INFO) ((UINT8) ((INFO) & 0x3f))
Expand All @@ -47,6 +49,10 @@ InitializePlatform (
DEBUG ((DEBUG_INFO, "InitializePlatform in Pei-less boot\n"));
PlatformDebugDumpCmos ();

if (RETURN_ERROR (QemuFwCfgInitCache ())) {
DEBUG ((DEBUG_ERROR, "QemuFwCfgInitCache failed !\n"));
}

PlatformInfoHob->DefaultMaxCpuNumber = 64;
PlatformInfoHob->PcdPciMmio64Size = 0x800000000;

Expand Down
242 changes: 242 additions & 0 deletions OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgCache.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
/** @file
QemuFwCfg cached feature related functions.
Copyright (c) 2024, 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
)
{
UINT16 HobSize;
UINT16 Offset;
BOOLEAN Cached;
FW_CFG_CACHED_ITEM *CachedItem;
EFI_HOB_GUID_TYPE *GuidHob;
UINTN CachedItemSize;
UINT16 SelectItem;

if (!InternalQemuFwCfgCacheEnable ()) {
return NULL;
}

SelectItem = (UINT16)Item;
GuidHob = GetFirstGuidHob (&gOvmfFwCfgInfoHobGuid);

HobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
Offset = sizeof (EFI_HOB_GUID_TYPE) + sizeof (FW_CFG_CACHE_WORK_AREA);
if (Offset > HobSize) {
return NULL;
}

CachedItem = InternalQemuFwCfgCacheFirstItem ();

Cached = FALSE;
while (Offset < HobSize) {
if (CachedItem->FwCfgItem == SelectItem) {
Cached = TRUE;
break;
}

CachedItemSize = CachedItem->DataSize + sizeof (FW_CFG_CACHED_ITEM);
Offset += (UINT16)CachedItemSize;
CachedItem = (FW_CFG_CACHED_ITEM *)((UINT8 *)CachedItem + CachedItemSize);
}

return Cached ? CachedItem : NULL;
}

/**
Clear the FW_CFG_CACHE_WORK_AREA.
**/
VOID
InternalQemuFwCfgCacheResetWorkArea (
VOID
)
{
FW_CFG_CACHE_WORK_AREA *FwCfgCacheWorkArea;

FwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
if (FwCfgCacheWorkArea != NULL) {
FwCfgCacheWorkArea->FwCfgItem = 0;
FwCfgCacheWorkArea->Offset = 0;
FwCfgCacheWorkArea->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;
FW_CFG_CACHE_WORK_AREA *FwCfgCacheWorkArea;

Reading = FALSE;
FwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
if (FwCfgCacheWorkArea != NULL) {
Reading = FwCfgCacheWorkArea->Reading;
}

return Reading;
}

BOOLEAN
InternalQemuFwCfgCacheSelectItem (
IN FIRMWARE_CONFIG_ITEM Item
)
{
FW_CFG_CACHE_WORK_AREA *FwCfgCacheWorkArea;

// Walk thru cached fw_items to see if Item is cached.
if (InternalQemuFwCfgItemCached (Item) == NULL) {
return FALSE;
}

FwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
if (FwCfgCacheWorkArea == NULL) {
DEBUG ((DEBUG_ERROR, "%a: Invalid FwCfg Cache Work Area\n", __func__));
return FALSE;
}

FwCfgCacheWorkArea->FwCfgItem = (UINT16)Item;
FwCfgCacheWorkArea->Offset = 0;
FwCfgCacheWorkArea->Reading = TRUE;

return TRUE;
}

/**
Get the first cached item.
@retval FW_CFG_CACHED_ITEM The first cached item.
@retval NULL There is no cached item.
**/
FW_CFG_CACHED_ITEM *
InternalQemuFwCfgCacheFirstItem (
VOID
)
{
EFI_HOB_GUID_TYPE *GuidHob;
UINT16 Offset;

if (!InternalQemuFwCfgCacheEnable ()) {
return NULL;
}

GuidHob = GetFirstGuidHob (&gOvmfFwCfgInfoHobGuid);

Offset = sizeof (FW_CFG_CACHE_WORK_AREA);

return (FW_CFG_CACHED_ITEM *)((UINT8 *)GET_GUID_HOB_DATA (GuidHob) + Offset);
}

/**
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
)
{
FW_CFG_CACHE_WORK_AREA *FwCfgCacheWorkArea;
FW_CFG_CACHED_ITEM *CachedItem;
UINTN ReadSize;

if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}

FwCfgCacheWorkArea = InternalQemuFwCfgCacheGetWorkArea ();
if (FwCfgCacheWorkArea == NULL) {
return RETURN_NOT_FOUND;
}

if (!FwCfgCacheWorkArea->Reading) {
return RETURN_NOT_READY;
}

CachedItem = InternalQemuFwCfgItemCached (FwCfgCacheWorkArea->FwCfgItem);
if (CachedItem == NULL) {
return RETURN_NOT_FOUND;
}

if (CachedItem->DataSize - FwCfgCacheWorkArea->Offset > Size) {
ReadSize = Size;
} else {
ReadSize = CachedItem->DataSize - FwCfgCacheWorkArea->Offset;
}

CopyMem (Buffer, (UINT8 *)CachedItem + sizeof (FW_CFG_CACHED_ITEM) + FwCfgCacheWorkArea->Offset, ReadSize);
FwCfgCacheWorkArea->Offset += (UINT32)ReadSize;

DEBUG ((DEBUG_INFO, "%a: found Item 0x%x in FwCfg Cache\n", __func__, FwCfgCacheWorkArea->FwCfgItem));
return RETURN_SUCCESS;
}

RETURN_STATUS
InternalQemuFwCfgItemInCacheList (
IN CONST CHAR8 *Name,
OUT FIRMWARE_CONFIG_ITEM *Item,
OUT UINTN *Size
)
{
UINT16 HobSize;
UINT16 Offset;
FW_CFG_CACHED_ITEM *CachedItem;
EFI_HOB_GUID_TYPE *GuidHob;
UINTN CachedItemSize;

CachedItem = InternalQemuFwCfgCacheFirstItem ();
if (CachedItem == NULL) {
return RETURN_NOT_FOUND;
}

GuidHob = GetFirstGuidHob (&gOvmfFwCfgInfoHobGuid);
if (GuidHob == NULL) {
return RETURN_NOT_FOUND;
}

HobSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
Offset = sizeof (EFI_HOB_GUID_TYPE) + sizeof (FW_CFG_CACHE_WORK_AREA);
if (Offset > HobSize) {
return RETURN_NOT_FOUND;
}

while (Offset < HobSize) {
if (AsciiStrCmp (Name, CachedItem->FileName) == 0) {
*Item = CachedItem->FwCfgItem;
*Size = CachedItem->DataSize;
return RETURN_SUCCESS;
}

CachedItemSize = CachedItem->DataSize + sizeof (FW_CFG_CACHED_ITEM);
Offset += (UINT16)CachedItemSize;
CachedItem = (FW_CFG_CACHED_ITEM *)((UINT8 *)CachedItem + CachedItemSize);
}

return RETURN_NOT_FOUND;
}
Loading
Loading