Skip to content

Commit 4f173db

Browse files
mxu9mergify[bot]
authored andcommitted
OvmfPkg/PlatformInitLib: Add functions for EmuVariableNvStore
There are 3 functions added for EmuVariableNvStore: - PlatformReserveEmuVariableNvStore - PlatformInitEmuVariableNvStore - PlatformValidateNvVarStore PlatformReserveEmuVariableNvStore allocate storage for NV variables early on so it will be at a consistent address. PlatformInitEmuVariableNvStore copies the content in PcdOvmfFlashNvStorageVariableBase to the storage allocated by PlatformReserveEmuVariableNvStore. This is used in the case that OVMF is launched with -bios parameter. Because in that situation UEFI variables will be partially emulated, and non-volatile variables may lose their contents after a reboot. This makes the secure boot feature not working. PlatformValidateNvVarStore is renamed from TdxValidateCfv and it is used to validate the integrity of FlashNvVarStore (PcdOvmfFlashNvStorageVariableBase). It should be called before PlatformInitEmuVariableNvStore is called to copy over the content. Cc: Erdem Aktas <erdemaktas@google.com> Cc: James Bottomley <jejb@linux.ibm.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Min Xu <min.m.xu@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
1 parent 0e72e87 commit 4f173db

File tree

3 files changed

+292
-0
lines changed

3 files changed

+292
-0
lines changed

OvmfPkg/Include/Library/PlatformInitLib.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,55 @@ PlatformTdxPublishRamRegions (
234234
VOID
235235
);
236236

237+
/**
238+
Check the integrity of NvVarStore.
239+
240+
@param[in] NvVarStoreBase - A pointer to NvVarStore header
241+
@param[in] NvVarStoreSize - NvVarStore size
242+
243+
@retval TRUE - The NvVarStore is valid.
244+
@retval FALSE - The NvVarStore is invalid.
245+
246+
**/
247+
BOOLEAN
248+
EFIAPI
249+
PlatformValidateNvVarStore (
250+
IN UINT8 *NvVarStoreBase,
251+
IN UINT32 NvVarStoreSize
252+
);
253+
254+
/**
255+
Allocate storage for NV variables early on so it will be
256+
at a consistent address. Since VM memory is preserved
257+
across reboots, this allows the NV variable storage to survive
258+
a VM reboot.
259+
260+
*
261+
* @retval VOID* The pointer to the storage for NV Variables
262+
*/
263+
VOID *
264+
EFIAPI
265+
PlatformReserveEmuVariableNvStore (
266+
VOID
267+
);
268+
269+
/**
270+
When OVMF is lauched with -bios parameter, UEFI variables will be
271+
partially emulated, and non-volatile variables may lose their contents
272+
after a reboot. This makes the secure boot feature not working.
273+
274+
This function is used to initialize the EmuVariableNvStore
275+
with the conent in PcdOvmfFlashNvStorageVariableBase.
276+
277+
@param[in] EmuVariableNvStore - A pointer to EmuVariableNvStore
278+
279+
@retval EFI_SUCCESS - Successfully init the EmuVariableNvStore
280+
@retval Others - As the error code indicates
281+
*/
282+
EFI_STATUS
283+
EFIAPI
284+
PlatformInitEmuVariableNvStore (
285+
IN VOID *EmuVariableNvStore
286+
);
287+
237288
#endif // PLATFORM_INIT_LIB_H_

OvmfPkg/Library/PlatformInitLib/Platform.c

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525
#include <IndustryStandard/Pci22.h>
2626
#include <IndustryStandard/Q35MchIch9.h>
2727
#include <IndustryStandard/QemuCpuHotplug.h>
28+
#include <Library/MemoryAllocationLib.h>
2829
#include <Library/QemuFwCfgLib.h>
2930
#include <Library/QemuFwCfgS3Lib.h>
3031
#include <Library/QemuFwCfgSimpleParserLib.h>
3132
#include <Library/PciLib.h>
33+
#include <Guid/SystemNvDataGuid.h>
34+
#include <Guid/VariableFormat.h>
3235
#include <OvmfPlatforms.h>
3336

3437
#include <Library/PlatformInitLib.h>
@@ -576,3 +579,238 @@ PlatformMaxCpuCountInitialization (
576579
PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber = MaxCpuCount;
577580
PlatformInfoHob->PcdCpuBootLogicalProcessorNumber = BootCpuCount;
578581
}
582+
583+
/**
584+
Check padding data all bit should be 1.
585+
586+
@param[in] Buffer - A pointer to buffer header
587+
@param[in] BufferSize - Buffer size
588+
589+
@retval TRUE - The padding data is valid.
590+
@retval TRUE - The padding data is invalid.
591+
592+
**/
593+
BOOLEAN
594+
CheckPaddingData (
595+
IN UINT8 *Buffer,
596+
IN UINT32 BufferSize
597+
)
598+
{
599+
UINT32 index;
600+
601+
for (index = 0; index < BufferSize; index++) {
602+
if (Buffer[index] != 0xFF) {
603+
return FALSE;
604+
}
605+
}
606+
607+
return TRUE;
608+
}
609+
610+
/**
611+
Check the integrity of NvVarStore.
612+
613+
@param[in] NvVarStoreBase - A pointer to NvVarStore header
614+
@param[in] NvVarStoreSize - NvVarStore size
615+
616+
@retval TRUE - The NvVarStore is valid.
617+
@retval FALSE - The NvVarStore is invalid.
618+
619+
**/
620+
BOOLEAN
621+
EFIAPI
622+
PlatformValidateNvVarStore (
623+
IN UINT8 *NvVarStoreBase,
624+
IN UINT32 NvVarStoreSize
625+
)
626+
{
627+
UINT16 Checksum;
628+
UINTN VariableBase;
629+
UINT32 VariableOffset;
630+
UINT32 VariableOffsetBeforeAlign;
631+
EFI_FIRMWARE_VOLUME_HEADER *NvVarStoreFvHeader;
632+
VARIABLE_STORE_HEADER *NvVarStoreHeader;
633+
AUTHENTICATED_VARIABLE_HEADER *VariableHeader;
634+
635+
static EFI_GUID FvHdrGUID = EFI_SYSTEM_NV_DATA_FV_GUID;
636+
static EFI_GUID VarStoreHdrGUID = EFI_AUTHENTICATED_VARIABLE_GUID;
637+
638+
VariableOffset = 0;
639+
640+
if (NvVarStoreBase == NULL) {
641+
DEBUG ((DEBUG_ERROR, "NvVarStore pointer is NULL.\n"));
642+
return FALSE;
643+
}
644+
645+
//
646+
// Verify the header zerovetor, filesystemguid,
647+
// revision, signature, attributes, fvlength, checksum
648+
// HeaderLength cannot be an odd number
649+
//
650+
NvVarStoreFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NvVarStoreBase;
651+
652+
if ((!IsZeroBuffer (NvVarStoreFvHeader->ZeroVector, 16)) ||
653+
(!CompareGuid (&FvHdrGUID, &NvVarStoreFvHeader->FileSystemGuid)) ||
654+
(NvVarStoreFvHeader->Signature != EFI_FVH_SIGNATURE) ||
655+
(NvVarStoreFvHeader->Attributes != 0x4feff) ||
656+
(NvVarStoreFvHeader->Revision != EFI_FVH_REVISION) ||
657+
(NvVarStoreFvHeader->FvLength != NvVarStoreSize)
658+
)
659+
{
660+
DEBUG ((DEBUG_ERROR, "NvVarStore FV headers were invalid.\n"));
661+
return FALSE;
662+
}
663+
664+
//
665+
// Verify the header checksum
666+
//
667+
Checksum = CalculateSum16 ((VOID *)NvVarStoreFvHeader, NvVarStoreFvHeader->HeaderLength);
668+
669+
if (Checksum != 0) {
670+
DEBUG ((DEBUG_ERROR, "NvVarStore FV checksum was invalid.\n"));
671+
return FALSE;
672+
}
673+
674+
//
675+
// Verify the header signature, size, format, state
676+
//
677+
NvVarStoreHeader = (VARIABLE_STORE_HEADER *)(NvVarStoreBase + NvVarStoreFvHeader->HeaderLength);
678+
if ((!CompareGuid (&VarStoreHdrGUID, &NvVarStoreHeader->Signature)) ||
679+
(NvVarStoreHeader->Format != VARIABLE_STORE_FORMATTED) ||
680+
(NvVarStoreHeader->State != VARIABLE_STORE_HEALTHY) ||
681+
(NvVarStoreHeader->Size > (NvVarStoreFvHeader->FvLength - NvVarStoreFvHeader->HeaderLength)) ||
682+
(NvVarStoreHeader->Size < sizeof (VARIABLE_STORE_HEADER))
683+
)
684+
{
685+
DEBUG ((DEBUG_ERROR, "NvVarStore header signature/size/format/state were invalid.\n"));
686+
return FALSE;
687+
}
688+
689+
//
690+
// Verify the header startId, state
691+
// Verify data to the end
692+
//
693+
VariableBase = (UINTN)NvVarStoreBase + NvVarStoreFvHeader->HeaderLength + sizeof (VARIABLE_STORE_HEADER);
694+
while (VariableOffset < (NvVarStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {
695+
VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)(VariableBase + VariableOffset);
696+
if (VariableHeader->StartId != VARIABLE_DATA) {
697+
if (!CheckPaddingData ((UINT8 *)VariableHeader, NvVarStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - VariableOffset)) {
698+
DEBUG ((DEBUG_ERROR, "NvVarStore variable header StartId was invalid.\n"));
699+
return FALSE;
700+
}
701+
702+
VariableOffset = NvVarStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER);
703+
} else {
704+
if (!((VariableHeader->State == VAR_IN_DELETED_TRANSITION) ||
705+
(VariableHeader->State == VAR_DELETED) ||
706+
(VariableHeader->State == VAR_HEADER_VALID_ONLY) ||
707+
(VariableHeader->State == VAR_ADDED)))
708+
{
709+
DEBUG ((DEBUG_ERROR, "NvVarStore Variable header State was invalid.\n"));
710+
return FALSE;
711+
}
712+
713+
VariableOffset += sizeof (AUTHENTICATED_VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize;
714+
// Verify VariableOffset should be less than or equal NvVarStoreHeader->Size - sizeof(VARIABLE_STORE_HEADER)
715+
if (VariableOffset > (NvVarStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER))) {
716+
DEBUG ((DEBUG_ERROR, "NvVarStore Variable header VariableOffset was invalid.\n"));
717+
return FALSE;
718+
}
719+
720+
VariableOffsetBeforeAlign = VariableOffset;
721+
// 4 byte align
722+
VariableOffset = (VariableOffset + 3) & (UINTN)(~3);
723+
724+
if (!CheckPaddingData ((UINT8 *)(VariableBase + VariableOffsetBeforeAlign), VariableOffset - VariableOffsetBeforeAlign)) {
725+
DEBUG ((DEBUG_ERROR, "NvVarStore Variable header PaddingData was invalid.\n"));
726+
return FALSE;
727+
}
728+
}
729+
}
730+
731+
return TRUE;
732+
}
733+
734+
/**
735+
Allocate storage for NV variables early on so it will be
736+
at a consistent address. Since VM memory is preserved
737+
across reboots, this allows the NV variable storage to survive
738+
a VM reboot.
739+
740+
*
741+
* @retval VOID* The pointer to the storage for NV Variables
742+
*/
743+
VOID *
744+
EFIAPI
745+
PlatformReserveEmuVariableNvStore (
746+
VOID
747+
)
748+
{
749+
VOID *VariableStore;
750+
UINT32 VarStoreSize;
751+
752+
VarStoreSize = 2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize);
753+
//
754+
// Allocate storage for NV variables early on so it will be
755+
// at a consistent address. Since VM memory is preserved
756+
// across reboots, this allows the NV variable storage to survive
757+
// a VM reboot.
758+
//
759+
VariableStore =
760+
AllocateRuntimePages (
761+
EFI_SIZE_TO_PAGES (VarStoreSize)
762+
);
763+
DEBUG ((
764+
DEBUG_INFO,
765+
"Reserved variable store memory: 0x%p; size: %dkb\n",
766+
VariableStore,
767+
VarStoreSize / 1024
768+
));
769+
770+
return VariableStore;
771+
}
772+
773+
/**
774+
When OVMF is lauched with -bios parameter, UEFI variables will be
775+
partially emulated, and non-volatile variables may lose their contents
776+
after a reboot. This makes the secure boot feature not working.
777+
778+
This function is used to initialize the EmuVariableNvStore
779+
with the conent in PcdOvmfFlashNvStorageVariableBase.
780+
781+
@param[in] EmuVariableNvStore - A pointer to EmuVariableNvStore
782+
783+
@retval EFI_SUCCESS - Successfully init the EmuVariableNvStore
784+
@retval Others - As the error code indicates
785+
*/
786+
EFI_STATUS
787+
EFIAPI
788+
PlatformInitEmuVariableNvStore (
789+
IN VOID *EmuVariableNvStore
790+
)
791+
{
792+
UINT8 *Base;
793+
UINT32 Size;
794+
UINT32 EmuVariableNvStoreSize;
795+
796+
EmuVariableNvStoreSize = 2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize);
797+
if ((EmuVariableNvStore == NULL) || (EmuVariableNvStoreSize == 0)) {
798+
DEBUG ((DEBUG_ERROR, "Invalid EmuVariableNvStore parameter.\n"));
799+
return EFI_INVALID_PARAMETER;
800+
}
801+
802+
Base = (UINT8 *)(UINTN)PcdGet32 (PcdOvmfFlashNvStorageVariableBase);
803+
Size = (UINT32)PcdGet32 (PcdFlashNvStorageVariableSize);
804+
ASSERT (Size < EmuVariableNvStoreSize);
805+
806+
if (!PlatformValidateNvVarStore (Base, PcdGet32 (PcdCfvRawDataSize))) {
807+
ASSERT (FALSE);
808+
return EFI_INVALID_PARAMETER;
809+
}
810+
811+
DEBUG ((DEBUG_INFO, "Init EmuVariableNvStore with the content in FlashNvStorage\n"));
812+
813+
CopyMem (EmuVariableNvStore, Base, Size);
814+
815+
return EFI_SUCCESS;
816+
}

OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
HobLib
4848
QemuFwCfgLib
4949
QemuFwCfgSimpleParserLib
50+
MemoryAllocationLib
5051
MtrrLib
5152
PcdLib
5253
PciLib
@@ -96,6 +97,8 @@
9697
gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
9798

9899
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
100+
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase
101+
gUefiOvmfPkgTokenSpaceGuid.PcdCfvRawDataSize
99102

100103
[FeaturePcd]
101104
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode

0 commit comments

Comments
 (0)