summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChasel Chiu <chasel.chiu@intel.com>2023-02-04 00:04:14 +0300
committerChasel Chiu <chasel.chiu@intel.com>2023-02-09 01:15:26 +0300
commite9730dfa998a9bf3996c10ede6773afd49a9b268 (patch)
tree4e7eec3d7fe38232c49b2454c75686f69104795c
parent615afc82db9f3ff348dacf8a94d9bb588783964b (diff)
downloadedk2-platforms-spifvb_fix.tar.xz
IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.spifvb_fix
When invalid VariableStore FV header detected, current SpiFvbService will erase both FV and VariableStore headers from flash, however, it will only rewrite FV header back and cause invalid VariableStore header. This patch adding the support for rewriting both FV header and VariableStore header when VariableStore corruption happened. The Corrupted variable content should be taken care by FaultTolerantWrite driver later. Platform has to set PcdFlashVariableStoreType to inform SpiFvbService which VariableStoreType should be rewritten. Cc: Ashraf Ali S <ashraf.ali.s@intel.com> Cc: Isaac Oram <isaac.w.oram@intel.com> Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Michael Kubacki <michael.kubacki@microsoft.com> Signed-off-by: Chasel Chiu <chasel.chiu@intel.com>
-rw-r--r--Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c69
-rw-r--r--Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf3
-rw-r--r--Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec8
3 files changed, 75 insertions, 5 deletions
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
index 6b4bcdcfe3..052be97872 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
@@ -12,6 +12,7 @@
#include <Library/MmServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Protocol/SmmFirmwareVolumeBlock.h>
+#include <Guid/VariableFormat.h>
/**
The function installs EFI_FIRMWARE_VOLUME_BLOCK protocol
@@ -113,7 +114,12 @@ FvbInitialize (
UINT32 MaxLbaSize;
UINT32 BytesWritten;
UINTN BytesErased;
+ EFI_PHYSICAL_ADDRESS NvStorageBaseAddress;
UINT64 NvStorageFvSize;
+ UINT32 ExpectedBytesWritten;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINT8 VariableStoreType;
+ UINT8 *NvStoreBuffer;
Status = GetVariableFlashNvStorageInfo (&BaseAddress, &NvStorageFvSize);
if (EFI_ERROR (Status)) {
@@ -124,12 +130,14 @@ FvbInitialize (
// Stay within the current UINT32 size assumptions in the variable stack.
Status = SafeUint64ToUint32 (BaseAddress, &mPlatformFvBaseAddress[0].FvBase);
+ NvStorageBaseAddress = mPlatformFvBaseAddress[0].FvBase;
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_ERROR, "[%a] - 64-bit variable storage base address not supported.\n", __FUNCTION__));
return;
}
Status = SafeUint64ToUint32 (NvStorageFvSize, &mPlatformFvBaseAddress[0].FvSize);
+ NvStorageFvSize = mPlatformFvBaseAddress[0].FvSize;
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
DEBUG ((DEBUG_ERROR, "[%a] - 64-bit variable storage size not supported.\n", __FUNCTION__));
@@ -186,8 +194,59 @@ FvbInitialize (
}
continue;
}
- BytesWritten = FvHeader->HeaderLength;
- Status = SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, (UINT8*)FvHeader);
+
+ BytesWritten = FvHeader->HeaderLength;
+ ExpectedBytesWritten = BytesWritten;
+ if (BaseAddress != NvStorageBaseAddress) {
+ Status = SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, (UINT8 *)FvHeader);
+ } else {
+ //
+ // This is Variable Store, rewrite both EFI_FIRMWARE_VOLUME_HEADER and VARIABLE_STORE_HEADER.
+ // The corrupted Variable content should be taken care by FaultTolerantWrite driver later.
+ //
+ NvStoreBuffer = NULL;
+ NvStoreBuffer = AllocateZeroPool (sizeof (VARIABLE_STORE_HEADER) + FvHeader->HeaderLength);
+ if (NvStoreBuffer != NULL) {
+ //
+ // Combine FV header and VariableStore header into the buffer.
+ //
+ CopyMem (NvStoreBuffer, FvHeader, FvHeader->HeaderLength);
+ VariableStoreHeader = (VARIABLE_STORE_HEADER *)(NvStoreBuffer + FvHeader->HeaderLength);
+ VariableStoreType = PcdGet8 (PcdFlashVariableStoreType);
+ switch (VariableStoreType) {
+ case 0:
+ DEBUG ((DEBUG_ERROR, "Type: gEfiVariableGuid\n"));
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
+ break;
+ case 1:
+ DEBUG ((DEBUG_ERROR, "Type: gEfiAuthenticatedVariableGuid\n"));
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
+ break;
+ default:
+ break;
+ }
+
+ //
+ // Initialize common VariableStore header fields
+ //
+ VariableStoreHeader->Size = (UINT32) (NvStorageFvSize - FvHeader->HeaderLength);
+ VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
+ VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
+ VariableStoreHeader->Reserved = 0;
+ VariableStoreHeader->Reserved1 = 0;
+
+ //
+ // Write buffer to flash
+ //
+ BytesWritten = FvHeader->HeaderLength + sizeof (VARIABLE_STORE_HEADER);
+ ExpectedBytesWritten = BytesWritten;
+ Status = SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, NvStoreBuffer);
+ FreePool (NvStoreBuffer);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "ERROR - SpiFlashWrite Error %r\n", Status));
if (FvHeader != NULL) {
@@ -195,9 +254,9 @@ FvbInitialize (
}
continue;
}
- if (BytesWritten != FvHeader->HeaderLength) {
- DEBUG ((DEBUG_WARN, "ERROR - BytesWritten != HeaderLength\n"));
- DEBUG ((DEBUG_INFO, " BytesWritten = 0x%X\n HeaderLength = 0x%X\n", BytesWritten, FvHeader->HeaderLength));
+ if (BytesWritten != ExpectedBytesWritten) {
+ DEBUG ((DEBUG_WARN, "ERROR - BytesWritten != ExpectedBytesWritten\n"));
+ DEBUG ((DEBUG_INFO, " BytesWritten = 0x%X\n ExpectedBytesWritten = 0x%X\n", BytesWritten, ExpectedBytesWritten));
if (FvHeader != NULL) {
FreePool (FvHeader);
}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
index 0cfa3f909b..73049eceb2 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
@@ -45,6 +45,7 @@
[Pcd]
gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase ## CONSUMES
gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize ## CONSUMES
+ gIntelSiliconPkgTokenSpaceGuid.PcdFlashVariableStoreType ## SOMETIMES_CONSUMES
[Sources]
FvbInfo.c
@@ -61,6 +62,8 @@
[Guids]
gEfiFirmwareFileSystem2Guid ## CONSUMES
gEfiSystemNvDataFvGuid ## CONSUMES
+ gEfiVariableGuid ## SOMETIMES_CONSUMES
+ gEfiAuthenticatedVariableGuid ## SOMETIMES_CONSUMES
[Depex]
TRUE
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index 485cb3e80a..63dae756ad 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -186,3 +186,11 @@
# @Prompt VTd abort DMA mode support.
gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN|0x0000000C
+ ## Define Flash Variable Store type.<BR><BR>
+ # When Flash Variable Store corruption happened, the SpiFvbService will recreate Variable Store
+ # with valid header information provided by this PCD value.<BR>
+ # 0: Variable Store is gEfiVariableGuid type.<BR>
+ # 1: Variable Store is gEfiAuthenticatedVariableGuid type.<BR>
+ # Other value: reserved for future use.<BR>
+ # @Prompt Flash Variable Store type.
+ gIntelSiliconPkgTokenSpaceGuid.PcdFlashVariableStoreType|0x00|UINT8|0x0000000E