MdeModulePkg FaultTolerantWriteDxe: Remove assumptions below in FTW driver.

1. Work space and spare block must be in a FVB with FV header.
Updated to work space and spare block could be in independent FVBs that are without FV header.
2. NV region, work space and spare block must have same BlockSize.
Updated to NV region, work space and spare block could have different BlockSize.
3. Works space size must be <= one block size.
Update to work space size could be <= one block size (not span blocks) or > one block size (block size aligned).

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@16201 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Star Zeng
2014-10-10 02:27:14 +00:00
committed by lzeng14
parent d2a867217d
commit 0d3edd9d26
6 changed files with 502 additions and 204 deletions

View File

@@ -125,6 +125,132 @@ InitWorkSpaceHeader (
return EFI_SUCCESS;
}
/**
Read work space data from work block or spare block.
@param FtwDevice The private data of FTW driver.
@param FvBlock FVB Protocol interface to access the block.
@param BlockSize The size of the block.
@param Lba Lba of the block.
@param Offset The offset within the block.
@param Length The number of bytes to read from the block.
@param Buffer The data is read.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_ABORTED The function could not complete successfully.
**/
EFI_STATUS
ReadWorkSpaceData (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
IN UINTN BlockSize,
IN EFI_LBA Lba,
IN UINTN Offset,
IN UINTN Length,
OUT UINT8 *Buffer
)
{
EFI_STATUS Status;
UINT8 *Ptr;
UINTN MyLength;
//
// Calculate the real Offset and Lba to write.
//
while (Offset >= BlockSize) {
Offset -= BlockSize;
Lba++;
}
Ptr = Buffer;
while (Length > 0) {
if ((Offset + Length) > BlockSize) {
MyLength = BlockSize - Offset;
} else {
MyLength = Length;
}
Status = FvBlock->Read (
FvBlock,
Lba,
Offset,
&MyLength,
Ptr
);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
Offset = 0;
Length -= MyLength;
Ptr += MyLength;
Lba++;
}
return EFI_SUCCESS;
}
/**
Write work space data to work block.
@param FvBlock FVB Protocol interface to access the block.
@param BlockSize The size of the block.
@param Lba Lba of the block.
@param Offset The offset within the block to place the data.
@param Length The number of bytes to write to the block.
@param Buffer The data to write.
@retval EFI_SUCCESS The function completed successfully.
@retval EFI_ABORTED The function could not complete successfully.
**/
EFI_STATUS
WriteWorkSpaceData (
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
IN UINTN BlockSize,
IN EFI_LBA Lba,
IN UINTN Offset,
IN UINTN Length,
IN UINT8 *Buffer
)
{
EFI_STATUS Status;
UINT8 *Ptr;
UINTN MyLength;
//
// Calculate the real Offset and Lba to write.
//
while (Offset >= BlockSize) {
Offset -= BlockSize;
Lba++;
}
Ptr = Buffer;
while (Length > 0) {
if ((Offset + Length) > BlockSize) {
MyLength = BlockSize - Offset;
} else {
MyLength = Length;
}
Status = FvBlock->Write (
FvBlock,
Lba,
Offset,
&MyLength,
Ptr
);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
Offset = 0;
Length -= MyLength;
Ptr += MyLength;
Lba++;
}
return EFI_SUCCESS;
}
/**
Read from working block to refresh the work space in memory.
@@ -140,7 +266,6 @@ WorkSpaceRefresh (
)
{
EFI_STATUS Status;
UINTN Length;
UINTN RemainingSpaceSize;
//
@@ -155,14 +280,14 @@ WorkSpaceRefresh (
//
// Read from working block
//
Length = FtwDevice->FtwWorkSpaceSize;
Status = FtwDevice->FtwFvBlock->Read (
FtwDevice->FtwFvBlock,
FtwDevice->FtwWorkSpaceLba,
FtwDevice->FtwWorkSpaceBase,
&Length,
FtwDevice->FtwWorkSpace
);
Status = ReadWorkSpaceData (
FtwDevice->FtwFvBlock,
FtwDevice->WorkBlockSize,
FtwDevice->FtwWorkSpaceLba,
FtwDevice->FtwWorkSpaceBase,
FtwDevice->FtwWorkSpaceSize,
FtwDevice->FtwWorkSpace
);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
@@ -194,14 +319,14 @@ WorkSpaceRefresh (
//
// Read from working block again
//
Length = FtwDevice->FtwWorkSpaceSize;
Status = FtwDevice->FtwFvBlock->Read (
FtwDevice->FtwFvBlock,
FtwDevice->FtwWorkSpaceLba,
FtwDevice->FtwWorkSpaceBase,
&Length,
FtwDevice->FtwWorkSpace
);
Status = ReadWorkSpaceData (
FtwDevice->FtwFvBlock,
FtwDevice->WorkBlockSize,
FtwDevice->FtwWorkSpaceLba,
FtwDevice->FtwWorkSpaceBase,
FtwDevice->FtwWorkSpaceSize,
FtwDevice->FtwWorkSpace
);
if (EFI_ERROR (Status)) {
return EFI_ABORTED;
}
@@ -265,15 +390,15 @@ FtwReclaimWorkSpace (
//
// Read all original data from working block to a memory buffer
//
TempBufferSize = FtwDevice->SpareAreaLength;
TempBufferSize = FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize;
TempBuffer = AllocateZeroPool (TempBufferSize);
if (TempBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ptr = TempBuffer;
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
Length = FtwDevice->BlockSize;
for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {
Length = FtwDevice->WorkBlockSize;
Status = FtwDevice->FtwFvBlock->Read (
FtwDevice->FtwFvBlock,
FtwDevice->FtwWorkBlockLba + Index,
@@ -292,7 +417,7 @@ FtwReclaimWorkSpace (
// Clean up the workspace, remove all the completed records.
//
Ptr = TempBuffer +
(UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize +
(UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +
FtwDevice->FtwWorkSpaceBase;
//
@@ -348,7 +473,7 @@ FtwReclaimWorkSpace (
// Set the WorkingBlockValid and WorkingBlockInvalid as INVALID
//
WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (TempBuffer +
(UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize +
(UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +
FtwDevice->FtwWorkSpaceBase);
WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE;
WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
@@ -366,7 +491,7 @@ FtwReclaimWorkSpace (
Ptr = SpareBuffer;
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
Length = FtwDevice->BlockSize;
Length = FtwDevice->SpareBlockSize;
Status = FtwDevice->FtwBackupFvb->Read (
FtwDevice->FtwBackupFvb,
FtwDevice->FtwSpareLba + Index,
@@ -387,8 +512,12 @@ FtwReclaimWorkSpace (
//
Status = FtwEraseSpareBlock (FtwDevice);
Ptr = TempBuffer;
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
Length = FtwDevice->BlockSize;
for (Index = 0; TempBufferSize > 0; Index += 1) {
if (TempBufferSize > FtwDevice->SpareBlockSize) {
Length = FtwDevice->SpareBlockSize;
} else {
Length = TempBufferSize;
}
Status = FtwDevice->FtwBackupFvb->Write (
FtwDevice->FtwBackupFvb,
FtwDevice->FtwSpareLba + Index,
@@ -403,6 +532,7 @@ FtwReclaimWorkSpace (
}
Ptr += Length;
TempBufferSize -= Length;
}
//
// Free TempBuffer
@@ -414,8 +544,9 @@ FtwReclaimWorkSpace (
//
Status = FtwUpdateFvState (
FtwDevice->FtwBackupFvb,
FtwDevice->FtwSpareLba + WorkSpaceLbaOffset,
FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
FtwDevice->SpareBlockSize,
FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
FtwDevice->FtwWorkSpaceBaseInSpare + sizeof (EFI_GUID) + sizeof (UINT32),
WORKING_BLOCK_VALID
);
if (EFI_ERROR (Status)) {
@@ -430,6 +561,7 @@ FtwReclaimWorkSpace (
//
Status = FtwUpdateFvState (
FtwDevice->FtwFvBlock,
FtwDevice->WorkBlockSize,
FtwDevice->FtwWorkSpaceLba,
FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
WORKING_BLOCK_INVALID
@@ -455,7 +587,7 @@ FtwReclaimWorkSpace (
Status = FtwEraseSpareBlock (FtwDevice);
Ptr = SpareBuffer;
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
Length = FtwDevice->BlockSize;
Length = FtwDevice->SpareBlockSize;
Status = FtwDevice->FtwBackupFvb->Write (
FtwDevice->FtwBackupFvb,
FtwDevice->FtwSpareLba + Index,