diff options
author | Star Zeng <star.zeng@intel.com> | 2013-07-03 09:08:40 +0000 |
---|---|---|
committer | lzeng14 <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524> | 2013-07-03 09:08:40 +0000 |
commit | 3e02ebb2bbe0fd4da880511b1f35951e1c4b8404 (patch) | |
tree | 95fc155e9d76e163cd295db373734cc276f4abc6 /MdeModulePkg/Universal/FaultTolerantWriteDxe | |
parent | 70066a82a54bd5136556dff3ea76dff035a3aca3 (diff) | |
download | edk2-platforms-3e02ebb2bbe0fd4da880511b1f35951e1c4b8404.tar.xz |
MdeModulePkg: Variable drivers robustly handle crashes during Reclaim().
PEI variable implementation checks only the variable header signature for validity. This does not seem robust if system crash occurred during previous Reclaim() operation. If the crash occurred while FTW was rewriting the variable FV, the signature could be valid even though the rest of the FV isn't valid.
Solution: Add a FaultTolerantWritePei driver to check and provide the FTW last write status, then PEI variable and early phase(before FTW protocol ready) of DXE variable can check the status and determine if all or partial variable data has been backed up in spare block, and then use the backed up data.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14454 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/FaultTolerantWriteDxe')
6 files changed, 33 insertions, 70 deletions
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c index 2f110167d7..3d1d29dfd9 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c @@ -3,7 +3,7 @@ These are the common Fault Tolerant Write (FTW) functions that are shared
by DXE FTW driver and SMM FTW driver.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -95,7 +95,7 @@ FtwAllocate ( //
// Check if there is enough space for the coming allocation
//
- if (WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceHeader->WriteQueueSize) {
+ if (FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceHeader->WriteQueueSize) {
DEBUG ((EFI_D_ERROR, "Ftw: Allocate() request exceed Workspace, Caller: %g\n", CallerId));
return EFI_BUFFER_TOO_SMALL;
}
@@ -115,7 +115,7 @@ FtwAllocate ( // If workspace is not enough, then reclaim workspace
//
Offset = (UINT8 *) FtwHeader - (UINT8 *) FtwDevice->FtwWorkSpace;
- if (Offset + WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
+ if (Offset + FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
@@ -365,7 +365,7 @@ FtwWrite ( //
// If Record is out of the range of Header, return access denied.
//
- if (((UINTN)((UINT8 *) Record - (UINT8 *) Header)) > WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
+ if (((UINTN)((UINT8 *) Record - (UINT8 *) Header)) > FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
return EFI_ACCESS_DENIED;
}
@@ -415,13 +415,13 @@ FtwWrite ( Record->Lba = Lba;
Record->Offset = Offset;
Record->Length = Length;
- Record->FvBaseAddress = FvbPhysicalAddress;
+ Record->RelativeOffset = (INT64) (FvbPhysicalAddress + (UINTN) Lba * FtwDevice->BlockSize) - (INT64) FtwDevice->SpareAreaAddress;
if (PrivateData != NULL) {
- CopyMem ((Record + 1), PrivateData, Header->PrivateDataSize);
+ CopyMem ((Record + 1), PrivateData, (UINTN) Header->PrivateDataSize);
}
MyOffset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
- MyLength = RECORD_SIZE (Header->PrivateDataSize);
+ MyLength = FTW_RECORD_SIZE (Header->PrivateDataSize);
Status = FtwDevice->FtwFvBlock->Write (
FtwDevice->FtwFvBlock,
@@ -693,6 +693,10 @@ FtwAbort ( return EFI_ABORTED;
}
+ if (FtwDevice->FtwLastWriteHeader->HeaderAllocated != FTW_VALID_STATE) {
+ return EFI_NOT_FOUND;
+ }
+
if (FtwDevice->FtwLastWriteHeader->Complete == FTW_VALID_STATE) {
return EFI_NOT_FOUND;
}
@@ -809,16 +813,16 @@ FtwGetLastWrite ( //
CopyMem (CallerId, &Header->CallerId, sizeof (EFI_GUID));
*Lba = Record->Lba;
- *Offset = Record->Offset;
- *Length = Record->Length;
+ *Offset = (UINTN) Record->Offset;
+ *Length = (UINTN) Record->Length;
*Complete = (BOOLEAN) (Record->DestinationComplete == FTW_VALID_STATE);
if (*PrivateDataSize < Header->PrivateDataSize) {
- *PrivateDataSize = Header->PrivateDataSize;
+ *PrivateDataSize = (UINTN) Header->PrivateDataSize;
PrivateData = NULL;
Status = EFI_BUFFER_TOO_SMALL;
} else {
- *PrivateDataSize = Header->PrivateDataSize;
+ *PrivateDataSize = (UINTN) Header->PrivateDataSize;
CopyMem (PrivateData, Record + 1, *PrivateDataSize);
Status = EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h index 8deae8851a..78c65f2af6 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h @@ -3,7 +3,7 @@ The internal header file includes the common header files, defines
internal structure and functions used by FtwLite module.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -38,59 +38,17 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. //
#define FTW_ERASE_POLARITY 1
-#define FTW_VALID_STATE 0
-#define FTW_INVALID_STATE 1
-
#define FTW_ERASED_BYTE ((UINT8) (255))
#define FTW_POLARITY_REVERT ((UINT8) (255))
-//
-// EFI Fault tolerant block update write queue entry
-//
-typedef struct {
- UINT8 HeaderAllocated : 1;
- UINT8 WritesAllocated : 1;
- UINT8 Complete : 1;
#define HEADER_ALLOCATED 0x1
#define WRITES_ALLOCATED 0x2
#define WRITES_COMPLETED 0x4
- UINT8 Reserved : 5;
- EFI_GUID CallerId;
- UINTN NumberOfWrites;
- UINTN PrivateDataSize;
-} EFI_FAULT_TOLERANT_WRITE_HEADER;
-//
-// EFI Fault tolerant block update write queue record
-//
-typedef struct {
- UINT8 BootBlockUpdate : 1;
- UINT8 SpareComplete : 1;
- UINT8 DestinationComplete : 1;
#define BOOT_BLOCK_UPDATE 0x1
#define SPARE_COMPLETED 0x2
#define DEST_COMPLETED 0x4
- UINT8 Reserved : 5;
- EFI_LBA Lba;
- UINTN Offset;
- UINTN Length;
- EFI_PHYSICAL_ADDRESS FvBaseAddress;
- //
- // UINT8 PrivateData[PrivateDataSize]
- //
-} EFI_FAULT_TOLERANT_WRITE_RECORD;
-
-
-#define RECORD_SIZE(PrivateDataSize) (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + PrivateDataSize)
-
-#define RECORD_TOTAL_SIZE(NumberOfWrites, PrivateDataSize) \
- ((NumberOfWrites) * (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + PrivateDataSize))
-#define WRITE_TOTAL_SIZE(NumberOfWrites, PrivateDataSize) \
- ( \
- sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + (NumberOfWrites) * \
- (sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD) + PrivateDataSize) \
- )
#define FTW_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'T', 'W', 'D')
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf index f60ab287e5..3d4b9123a1 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf @@ -3,7 +3,7 @@ # which provides fault tolerant write capability for block devices.
# Its implementation depends on the full functionality FVB protocol that support read, write/erase flash access.
#
-# Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
@@ -49,7 +49,7 @@ PcdLib
[Guids]
- gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
+ gEdkiiWorkingBlockSignatureGuid ## CONSUMES ## FV Signature of Working Space Header
[Protocols]
gEfiSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf index c39f84ca3c..a5c8a58f22 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf @@ -52,7 +52,7 @@ PcdLib
[Guids]
- gEfiSystemNvDataFvGuid ## CONSUMES ## FV Signature of Working Space Header
+ gEdkiiWorkingBlockSignatureGuid ## CONSUMES ## FV Signature of Working Space Header
[Protocols]
gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c index 2e4052c1ea..fdd9dfa0c1 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c @@ -689,6 +689,7 @@ FlushSpareBlockToWorkingBlock ( return EFI_ABORTED;
}
+ FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
return EFI_SUCCESS;
@@ -775,7 +776,7 @@ FtwGetLastWriteHeader ( Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
while (FtwHeader->Complete == FTW_VALID_STATE) {
- Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
//
// If Offset exceed the FTW work space boudary, return error.
//
@@ -834,7 +835,7 @@ FtwGetLastWriteRecord ( FtwRecord++;
if (FtwWriteHeader->PrivateDataSize != 0) {
- FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + FtwWriteHeader->PrivateDataSize);
+ FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + (UINTN) FtwWriteHeader->PrivateDataSize);
}
}
//
@@ -844,7 +845,7 @@ FtwGetLastWriteRecord ( // also return the last record.
//
if (Index == FtwWriteHeader->NumberOfWrites) {
- *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
+ *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
return EFI_SUCCESS;
}
@@ -901,7 +902,7 @@ IsLastRecordOfWrites ( Head = (UINT8 *) FtwHeader;
Ptr = (UINT8 *) FtwRecord;
- Head += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
+ Head += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
return (BOOLEAN) (Head == Ptr);
}
@@ -929,7 +930,7 @@ GetPreviousRecordOfWrites ( }
Ptr = (UINT8 *) (*FtwRecord);
- Ptr -= RECORD_SIZE (FtwHeader->PrivateDataSize);
+ Ptr -= FTW_RECORD_SIZE (FtwHeader->PrivateDataSize);
*FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
return EFI_SUCCESS;
}
@@ -1259,7 +1260,7 @@ InitFtwProtocol ( FtwHeader = FtwDevice->FtwLastWriteHeader;
Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;
if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
- Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
+ Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
}
if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
@@ -1283,7 +1284,7 @@ InitFtwProtocol ( // if (SpareCompleted) THEN Restart to fault tolerant write.
//
FvbHandle = NULL;
- FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb);
+ FvbHandle = GetFvbByAddress ((EFI_PHYSICAL_ADDRESS) (UINTN) ((INT64) FtwDevice->SpareAreaAddress + FtwDevice->FtwLastWriteRecord->RelativeOffset), &Fvb);
if (FvbHandle != NULL) {
Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c index bd8285d00e..4c658b2977 100644 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c +++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c @@ -2,7 +2,7 @@ Internal functions to operate Working Block Space.
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -32,9 +32,9 @@ InitializeLocalWorkSpaceHeader ( EFI_STATUS Status;
//
- // Check signature with gEfiSystemNvDataFvGuid.
+ // Check signature with gEdkiiWorkingBlockSignatureGuid.
//
- if (CompareGuid (&gEfiSystemNvDataFvGuid, &mWorkingBlockHeader.Signature)) {
+ if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) {
//
// The local work space header has been initialized.
//
@@ -48,11 +48,11 @@ InitializeLocalWorkSpaceHeader ( );
//
- // Here using gEfiSystemNvDataFvGuid as the signature.
+ // Here using gEdkiiWorkingBlockSignatureGuid as the signature.
//
CopyMem (
&mWorkingBlockHeader.Signature,
- &gEfiSystemNvDataFvGuid,
+ &gEdkiiWorkingBlockSignatureGuid,
sizeof (EFI_GUID)
);
mWorkingBlockHeader.WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
@@ -322,7 +322,7 @@ FtwReclaimWorkSpace ( CopyMem (
Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
FtwDevice->FtwLastWriteHeader,
- WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
+ FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
);
}
}
|