[edk2-platforms: PATCH v4] IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.


Chiu, Chasel
 

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@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Ray Ni <ray.ni@...>
Cc: Michael Kubacki <michael.kubacki@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.=
c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-=
----
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm=
.inf | 3 +++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec =
| 8 ++++++++
3 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiF=
vbServiceMm.c b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/S=
piFvbServiceMm.c
index 6b4bcdcfe3..052be97872 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServi=
ceMm.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServi=
ceMm.c
@@ -12,6 +12,7 @@
#include <Library/MmServicesTableLib.h>=0D
#include <Library/UefiDriverEntryPoint.h>=0D
#include <Protocol/SmmFirmwareVolumeBlock.h>=0D
+#include <Guid/VariableFormat.h>=0D
=0D
/**=0D
The function installs EFI_FIRMWARE_VOLUME_BLOCK protocol=0D
@@ -113,7 +114,12 @@ FvbInitialize (
UINT32 MaxLbaSize;=0D
UINT32 BytesWritten;=0D
UINTN BytesErased;=0D
+ EFI_PHYSICAL_ADDRESS NvStorageBaseAddress;=0D
UINT64 NvStorageFvSize;=0D
+ UINT32 ExpectedBytesWritten;=0D
+ VARIABLE_STORE_HEADER *VariableStoreHeader;=0D
+ UINT8 VariableStoreType;=0D
+ UINT8 *NvStoreBuffer;=0D
=0D
Status =3D GetVariableFlashNvStorageInfo (&BaseAddress, &NvStorageFvSize=
);=0D
if (EFI_ERROR (Status)) {=0D
@@ -124,12 +130,14 @@ FvbInitialize (
=0D
// Stay within the current UINT32 size assumptions in the variable stack=
.=0D
Status =3D SafeUint64ToUint32 (BaseAddress, &mPlatformFvBaseAddress[0].F=
vBase);=0D
+ NvStorageBaseAddress =3D mPlatformFvBaseAddress[0].FvBase;=0D
if (EFI_ERROR (Status)) {=0D
ASSERT_EFI_ERROR (Status);=0D
DEBUG ((DEBUG_ERROR, "[%a] - 64-bit variable storage base address not =
supported.\n", __FUNCTION__));=0D
return;=0D
}=0D
Status =3D SafeUint64ToUint32 (NvStorageFvSize, &mPlatformFvBaseAddress[=
0].FvSize);=0D
+ NvStorageFvSize =3D mPlatformFvBaseAddress[0].FvSize;=0D
if (EFI_ERROR (Status)) {=0D
ASSERT_EFI_ERROR (Status);=0D
DEBUG ((DEBUG_ERROR, "[%a] - 64-bit variable storage size not supporte=
d.\n", __FUNCTION__));=0D
@@ -186,8 +194,59 @@ FvbInitialize (
}=0D
continue;=0D
}=0D
- BytesWritten =3D FvHeader->HeaderLength;=0D
- Status =3D SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, (UINT=
8*)FvHeader);=0D
+=0D
+ BytesWritten =3D FvHeader->HeaderLength;=0D
+ ExpectedBytesWritten =3D BytesWritten;=0D
+ if (BaseAddress !=3D NvStorageBaseAddress) {=0D
+ Status =3D SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, (UI=
NT8 *)FvHeader);=0D
+ } else {=0D
+ //=0D
+ // This is Variable Store, rewrite both EFI_FIRMWARE_VOLUME_HEAD=
ER and VARIABLE_STORE_HEADER.=0D
+ // The corrupted Variable content should be taken care by FaultT=
olerantWrite driver later.=0D
+ //=0D
+ NvStoreBuffer =3D NULL;=0D
+ NvStoreBuffer =3D AllocateZeroPool (sizeof (VARIABLE_STORE_HEADE=
R) + FvHeader->HeaderLength);=0D
+ if (NvStoreBuffer !=3D NULL) {=0D
+ //=0D
+ // Combine FV header and VariableStore header into the buffer.=
=0D
+ //=0D
+ CopyMem (NvStoreBuffer, FvHeader, FvHeader->HeaderLength);=0D
+ VariableStoreHeader =3D (VARIABLE_STORE_HEADER *)(NvStoreBuffe=
r + FvHeader->HeaderLength);=0D
+ VariableStoreType =3D PcdGet8 (PcdFlashVariableStoreType);=0D
+ switch (VariableStoreType) {=0D
+ case 0:=0D
+ DEBUG ((DEBUG_ERROR, "Type: gEfiVariableGuid\n"));=0D
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGu=
id);=0D
+ break;=0D
+ case 1:=0D
+ DEBUG ((DEBUG_ERROR, "Type: gEfiAuthenticatedVariableGuid\=
n"));=0D
+ CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthentica=
tedVariableGuid);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize common VariableStore header fields=0D
+ //=0D
+ VariableStoreHeader->Size =3D (UINT32) (NvStorageFvSize -=
FvHeader->HeaderLength);=0D
+ VariableStoreHeader->Format =3D VARIABLE_STORE_FORMATTED;=0D
+ VariableStoreHeader->State =3D VARIABLE_STORE_HEALTHY;=0D
+ VariableStoreHeader->Reserved =3D 0;=0D
+ VariableStoreHeader->Reserved1 =3D 0;=0D
+=0D
+ //=0D
+ // Write buffer to flash=0D
+ //=0D
+ BytesWritten =3D FvHeader->HeaderLength + sizeof (VARI=
ABLE_STORE_HEADER);=0D
+ ExpectedBytesWritten =3D BytesWritten;=0D
+ Status =3D SpiFlashWrite ((UINTN)BaseAddress, &B=
ytesWritten, NvStoreBuffer);=0D
+ FreePool (NvStoreBuffer);=0D
+ } else {=0D
+ Status =3D EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
if (EFI_ERROR (Status)) {=0D
DEBUG ((DEBUG_WARN, "ERROR - SpiFlashWrite Error %r\n", Status)=
);=0D
if (FvHeader !=3D NULL) {=0D
@@ -195,9 +254,9 @@ FvbInitialize (
}=0D
continue;=0D
}=0D
- if (BytesWritten !=3D FvHeader->HeaderLength) {=0D
- DEBUG ((DEBUG_WARN, "ERROR - BytesWritten !=3D HeaderLength\n"))=
;=0D
- DEBUG ((DEBUG_INFO, " BytesWritten =3D 0x%X\n HeaderLength =3D 0=
x%X\n", BytesWritten, FvHeader->HeaderLength));=0D
+ if (BytesWritten !=3D ExpectedBytesWritten) {=0D
+ DEBUG ((DEBUG_WARN, "ERROR - BytesWritten !=3D ExpectedBytesWrit=
ten\n"));=0D
+ DEBUG ((DEBUG_INFO, " BytesWritten =3D 0x%X\n ExpectedBytesWritt=
en =3D 0x%X\n", BytesWritten, ExpectedBytesWritten));=0D
if (FvHeader !=3D NULL) {=0D
FreePool (FvHeader);=0D
}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiF=
vbServiceSmm.inf b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbServic=
e/SpiFvbServiceSmm.inf
index 0cfa3f909b..73049eceb2 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServi=
ceSmm.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServi=
ceSmm.inf
@@ -45,6 +45,7 @@
[Pcd]=0D
gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase ## CONSUM=
ES=0D
gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize ## CONSUM=
ES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdFlashVariableStoreType ## SOMETI=
MES_CONSUMES=0D
=0D
[Sources]=0D
FvbInfo.c=0D
@@ -61,6 +62,8 @@
[Guids]=0D
gEfiFirmwareFileSystem2Guid ## CONSUMES=0D
gEfiSystemNvDataFvGuid ## CONSUMES=0D
+ gEfiVariableGuid ## SOMETIMES_CONSUMES=0D
+ gEfiAuthenticatedVariableGuid ## SOMETIMES_CONSUMES=0D
=0D
[Depex]=0D
TRUE=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/In=
tel/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.=0D
gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN|0=
x0000000C=0D
=0D
+ ## Define Flash Variable Store type.<BR><BR>=0D
+ # When Flash Variable Store corruption happened, the SpiFvbService will=
recreate Variable Store=0D
+ # with valid header information provided by this PCD value.<BR>=0D
+ # 0: Variable Store is gEfiVariableGuid type.<BR>=0D
+ # 1: Variable Store is gEfiAuthenticatedVariableGuid type.<BR>=0D
+ # Other value: reserved for future use.<BR>=0D
+ # @Prompt Flash Variable Store type.=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdFlashVariableStoreType|0x00|UINT8|0x00=
00000E=0D
--=20
2.35.0.windows.1


Michael Kubacki
 

Reviewed-by: Michael Kubacki <michael.kubacki@...>

On the following lines, I recommend moving the assignment until after the if block. It seems unnecessary to assign a potentially invalid value to a local variable before checking the validation result.

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;
}

---

(similar for NvStorageFvSize)

Thanks,
Michael

On 2/8/2023 5:17 PM, Chiu, Chasel wrote:
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@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Ray Ni <ray.ni@...>
Cc: Michael Kubacki <michael.kubacki@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf | 3 +++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 8 ++++++++
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


Chiu, Chasel
 

Thanks Michael! I will apply the change during merging!

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael
Kubacki
Sent: Wednesday, February 8, 2023 4:41 PM
To: devel@edk2.groups.io; Chiu, Chasel <chasel.chiu@...>
Cc: S, Ashraf Ali <ashraf.ali.s@...>; Oram, Isaac W
<isaac.w.oram@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Ni, Ray <ray.ni@...>; Kubacki,
Michael <michael.kubacki@...>
Subject: Re: [edk2-devel] [edk2-platforms: PATCH v4]
IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.

Reviewed-by: Michael Kubacki <michael.kubacki@...>

On the following lines, I recommend moving the assignment until after the if
block. It seems unnecessary to assign a potentially invalid value to a local
variable before checking the validation result.

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;
}

---

(similar for NvStorageFvSize)

Thanks,
Michael

On 2/8/2023 5:17 PM, Chiu, Chasel wrote:
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@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Ray Ni <ray.ni@...>
Cc: Michael Kubacki <michael.kubacki@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
| 69
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
| 3 +++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 8 ++++++++
3 files changed, 75 insertions(+), 5 deletions(-)

diff --git
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
index 6b4bcdcfe3..052be97872 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvb
+++ ServiceMm.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/SpiFvbServ
iceSmm.inf
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceSmm.inf
index 0cfa3f909b..73049eceb2 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceSmm.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvb
+++ ServiceSmm.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|BOOLE
AN
|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



Isaac Oram
 

Reviewed-by: Isaac Oram <isaac.w.oram@...>

At some point, we should work to comment the related flows better so that code is clear on the different responsibilities for the different paths through first boots, normal scenarios, reclaims, and error remediation. For now though, this is fine.

Regards,
Isaac

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael Kubacki
Sent: Wednesday, February 8, 2023 4:41 PM
To: devel@edk2.groups.io; Chiu, Chasel <chasel.chiu@...>
Cc: S, Ashraf Ali <ashraf.ali.s@...>; Oram, Isaac W <isaac.w.oram@...>; Chaganty, Rangasai V <rangasai.v.chaganty@...>; Ni, Ray <ray.ni@...>; Kubacki, Michael <michael.kubacki@...>
Subject: Re: [edk2-devel] [edk2-platforms: PATCH v4] IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.

Reviewed-by: Michael Kubacki <michael.kubacki@...>

On the following lines, I recommend moving the assignment until after the if block. It seems unnecessary to assign a potentially invalid value to a local variable before checking the validation result.

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;
}

---

(similar for NvStorageFvSize)

Thanks,
Michael

On 2/8/2023 5:17 PM, Chiu, Chasel wrote:
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@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Ray Ni <ray.ni@...>
Cc: Michael Kubacki <michael.kubacki@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf | 3 +++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 8 ++++++++
3 files changed, 75 insertions(+), 5 deletions(-)

diff --git
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
index 6b4bcdcfe3..052be97872 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvb
+++ ServiceMm.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/SpiFvbServ
iceSmm.inf
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceSmm.inf
index 0cfa3f909b..73049eceb2 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceSmm.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvb
+++ ServiceSmm.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


Chiu, Chasel
 

Thanks Isaac!

-----Original Message-----
From: Oram, Isaac W <isaac.w.oram@...>
Sent: Wednesday, February 8, 2023 5:39 PM
To: devel@edk2.groups.io; mikuback@...; Chiu, Chasel
<chasel.chiu@...>
Cc: S, Ashraf Ali <ashraf.ali.s@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Ni, Ray <ray.ni@...>; Kubacki,
Michael <michael.kubacki@...>
Subject: RE: [edk2-devel] [edk2-platforms: PATCH v4]
IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.

Reviewed-by: Isaac Oram <isaac.w.oram@...>

At some point, we should work to comment the related flows better so that
code is clear on the different responsibilities for the different paths through first
boots, normal scenarios, reclaims, and error remediation. For now though, this
is fine.

Regards,
Isaac

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Michael
Kubacki
Sent: Wednesday, February 8, 2023 4:41 PM
To: devel@edk2.groups.io; Chiu, Chasel <chasel.chiu@...>
Cc: S, Ashraf Ali <ashraf.ali.s@...>; Oram, Isaac W
<isaac.w.oram@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Ni, Ray <ray.ni@...>; Kubacki,
Michael <michael.kubacki@...>
Subject: Re: [edk2-devel] [edk2-platforms: PATCH v4]
IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.

Reviewed-by: Michael Kubacki <michael.kubacki@...>

On the following lines, I recommend moving the assignment until after the if
block. It seems unnecessary to assign a potentially invalid value to a local
variable before checking the validation result.

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;
}

---

(similar for NvStorageFvSize)

Thanks,
Michael

On 2/8/2023 5:17 PM, Chiu, Chasel wrote:
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@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Ray Ni <ray.ni@...>
Cc: Michael Kubacki <michael.kubacki@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
| 69
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
| 3 +++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 8 ++++++++
3 files changed, 75 insertions(+), 5 deletions(-)

diff --git
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
index 6b4bcdcfe3..052be97872 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceMm.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvb
+++ ServiceMm.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/SpiFvbServ
iceSmm.inf
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceSmm.inf
index 0cfa3f909b..73049eceb2 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServ
iceSmm.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvb
+++ ServiceSmm.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|BOOLE
AN
|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



Chiu, Chasel
 

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Chiu, Chasel
Sent: Wednesday, February 8, 2023 2:17 PM
To: devel@edk2.groups.io
Cc: Chiu, Chasel <chasel.chiu@...>; S, Ashraf Ali <ashraf.ali.s@...>;
Oram, Isaac W <isaac.w.oram@...>; Chaganty, Rangasai V
<rangasai.v.chaganty@...>; Ni, Ray <ray.ni@...>; Kubacki,
Michael <michael.kubacki@...>
Subject: [edk2-devel] [edk2-platforms: PATCH v4]
IntelSiliconPkg/SpiFvbServiceSmm: Rewrite VariableStore header.

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@...>
Cc: Isaac Oram <isaac.w.oram@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Ray Ni <ray.ni@...>
Cc: Michael Kubacki <michael.kubacki@...>
Signed-off-by: Chasel Chiu <chasel.chiu@...>
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c |
69
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
---
Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
| 3 +++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 8 ++++++++
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/SpiFvbSe
+++ rviceMm.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.in
f
b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.in
f
index 0cfa3f909b..73049eceb2 100644
---
a/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.in
f
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbSe
+++ rviceSmm.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] TRUEdiff --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|BOOLE
AN|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|0x000
0000E--
2.35.0.windows.1



-=-=-=-=-=-=
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#99818): https://edk2.groups.io/g/devel/message/99818
Mute This Topic: https://groups.io/mt/96841486/1777047
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [chasel.chiu@...] -=-
=-=-=-=-=