2009-03-04 02:05:31 +01:00
|
|
|
/** @file
|
|
|
|
|
|
|
|
Internal functions to operate Working Block Space.
|
|
|
|
|
2013-07-03 11:08:40 +02:00
|
|
|
Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
|
2010-04-24 11:33:45 +02:00
|
|
|
This program and the accompanying materials
|
2009-03-04 02:05:31 +01:00
|
|
|
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
|
|
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
|
|
#include "FaultTolerantWrite.h"
|
|
|
|
|
2012-12-21 01:52:57 +01:00
|
|
|
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER mWorkingBlockHeader = {ZERO_GUID, 0, 0, 0, 0, {0, 0, 0}, 0};
|
2009-03-04 02:05:31 +01:00
|
|
|
|
2012-12-21 01:52:57 +01:00
|
|
|
/**
|
|
|
|
Initialize a local work space header.
|
2009-03-04 02:05:31 +01:00
|
|
|
|
2012-12-21 01:52:57 +01:00
|
|
|
Since Signature and WriteQueueSize have been known, Crc can be calculated out,
|
|
|
|
then the work space header will be fixed.
|
2009-03-04 02:05:31 +01:00
|
|
|
**/
|
2012-12-21 01:52:57 +01:00
|
|
|
VOID
|
|
|
|
InitializeLocalWorkSpaceHeader (
|
|
|
|
VOID
|
2009-03-04 02:05:31 +01:00
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
|
|
|
|
//
|
2013-07-03 11:08:40 +02:00
|
|
|
// Check signature with gEdkiiWorkingBlockSignatureGuid.
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
2013-07-03 11:08:40 +02:00
|
|
|
if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) {
|
2012-12-21 01:52:57 +01:00
|
|
|
//
|
|
|
|
// The local work space header has been initialized.
|
|
|
|
//
|
|
|
|
return;
|
2009-03-04 02:05:31 +01:00
|
|
|
}
|
2012-12-21 01:52:57 +01:00
|
|
|
|
|
|
|
SetMem (
|
|
|
|
&mWorkingBlockHeader,
|
|
|
|
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
|
|
|
|
FTW_ERASED_BYTE
|
|
|
|
);
|
|
|
|
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
2013-07-03 11:08:40 +02:00
|
|
|
// Here using gEdkiiWorkingBlockSignatureGuid as the signature.
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
|
|
|
CopyMem (
|
2012-12-21 01:52:57 +01:00
|
|
|
&mWorkingBlockHeader.Signature,
|
2013-07-03 11:08:40 +02:00
|
|
|
&gEdkiiWorkingBlockSignatureGuid,
|
2012-12-21 01:52:57 +01:00
|
|
|
sizeof (EFI_GUID)
|
2009-03-04 02:05:31 +01:00
|
|
|
);
|
2012-12-21 01:52:57 +01:00
|
|
|
mWorkingBlockHeader.WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
|
2009-03-04 02:05:31 +01:00
|
|
|
|
|
|
|
//
|
2012-12-21 01:52:57 +01:00
|
|
|
// Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// Calculate the Crc of woking block header
|
|
|
|
//
|
|
|
|
Status = gBS->CalculateCrc32 (
|
2012-12-21 01:52:57 +01:00
|
|
|
&mWorkingBlockHeader,
|
2009-03-04 02:05:31 +01:00
|
|
|
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
|
2012-12-21 01:52:57 +01:00
|
|
|
&mWorkingBlockHeader.Crc
|
2009-03-04 02:05:31 +01:00
|
|
|
);
|
2012-12-21 01:52:57 +01:00
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
|
|
mWorkingBlockHeader.WorkingBlockValid = FTW_VALID_STATE;
|
|
|
|
mWorkingBlockHeader.WorkingBlockInvalid = FTW_INVALID_STATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Check to see if it is a valid work space.
|
|
|
|
|
|
|
|
|
|
|
|
@param WorkingHeader Pointer of working block header
|
|
|
|
|
|
|
|
@retval TRUE The work space is valid.
|
|
|
|
@retval FALSE The work space is invalid.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
IsValidWorkSpace (
|
|
|
|
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (WorkingHeader == NULL) {
|
2009-03-04 02:05:31 +01:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-12-21 01:52:57 +01:00
|
|
|
if (CompareMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) == 0) {
|
|
|
|
return TRUE;
|
2009-03-04 02:05:31 +01:00
|
|
|
}
|
|
|
|
|
2012-12-21 01:52:57 +01:00
|
|
|
DEBUG ((EFI_D_ERROR, "Ftw: Work block header check error\n"));
|
|
|
|
return FALSE;
|
2009-03-04 02:05:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Initialize a work space when there is no work space.
|
|
|
|
|
|
|
|
@param WorkingHeader Pointer of working block header
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
|
|
@retval EFI_ABORTED The function could not complete successfully.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
InitWorkSpaceHeader (
|
|
|
|
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (WorkingHeader == NULL) {
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
2012-12-21 01:52:57 +01:00
|
|
|
CopyMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
|
2009-03-04 02:05:31 +01:00
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Read from working block to refresh the work space in memory.
|
|
|
|
|
|
|
|
@param FtwDevice Point to private data of FTW driver
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
|
|
@retval EFI_ABORTED The function could not complete successfully.
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
WorkSpaceRefresh (
|
|
|
|
IN EFI_FTW_DEVICE *FtwDevice
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINTN Length;
|
2012-12-17 04:18:16 +01:00
|
|
|
UINTN RemainingSpaceSize;
|
2009-03-04 02:05:31 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Initialize WorkSpace as FTW_ERASED_BYTE
|
|
|
|
//
|
|
|
|
SetMem (
|
|
|
|
FtwDevice->FtwWorkSpace,
|
|
|
|
FtwDevice->FtwWorkSpaceSize,
|
|
|
|
FTW_ERASED_BYTE
|
|
|
|
);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read from working block
|
|
|
|
//
|
|
|
|
Length = FtwDevice->FtwWorkSpaceSize;
|
|
|
|
Status = FtwDevice->FtwFvBlock->Read (
|
|
|
|
FtwDevice->FtwFvBlock,
|
|
|
|
FtwDevice->FtwWorkSpaceLba,
|
|
|
|
FtwDevice->FtwWorkSpaceBase,
|
|
|
|
&Length,
|
|
|
|
FtwDevice->FtwWorkSpace
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Refresh the FtwLastWriteHeader
|
|
|
|
//
|
|
|
|
Status = FtwGetLastWriteHeader (
|
|
|
|
FtwDevice->FtwWorkSpaceHeader,
|
|
|
|
FtwDevice->FtwWorkSpaceSize,
|
|
|
|
&FtwDevice->FtwLastWriteHeader
|
|
|
|
);
|
2012-12-17 04:18:16 +01:00
|
|
|
RemainingSpaceSize = FtwDevice->FtwWorkSpaceSize - ((UINTN) FtwDevice->FtwLastWriteHeader - (UINTN) FtwDevice->FtwWorkSpace);
|
|
|
|
DEBUG ((EFI_D_INFO, "Ftw: Remaining work space size - %x\n", RemainingSpaceSize));
|
|
|
|
//
|
|
|
|
// If FtwGetLastWriteHeader() returns error, or the remaining space size is even not enough to contain
|
|
|
|
// one EFI_FAULT_TOLERANT_WRITE_HEADER + one EFI_FAULT_TOLERANT_WRITE_RECORD(It will cause that the header
|
|
|
|
// pointed by FtwDevice->FtwLastWriteHeader or record pointed by FtwDevice->FtwLastWriteRecord may contain invalid data),
|
|
|
|
// it needs to reclaim work space.
|
|
|
|
//
|
|
|
|
if (EFI_ERROR (Status) || RemainingSpaceSize < sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD)) {
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
|
|
|
// reclaim work space in working block.
|
|
|
|
//
|
|
|
|
Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
DEBUG ((EFI_D_ERROR, "Ftw: Reclaim workspace - %r\n", Status));
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Read from working block again
|
|
|
|
//
|
|
|
|
Length = FtwDevice->FtwWorkSpaceSize;
|
|
|
|
Status = FtwDevice->FtwFvBlock->Read (
|
|
|
|
FtwDevice->FtwFvBlock,
|
|
|
|
FtwDevice->FtwWorkSpaceLba,
|
|
|
|
FtwDevice->FtwWorkSpaceBase,
|
|
|
|
&Length,
|
|
|
|
FtwDevice->FtwWorkSpace
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = FtwGetLastWriteHeader (
|
|
|
|
FtwDevice->FtwWorkSpaceHeader,
|
|
|
|
FtwDevice->FtwWorkSpaceSize,
|
|
|
|
&FtwDevice->FtwLastWriteHeader
|
|
|
|
);
|
2012-09-14 08:54:35 +02:00
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
2009-03-04 02:05:31 +01:00
|
|
|
}
|
|
|
|
//
|
|
|
|
// Refresh the FtwLastWriteRecord
|
|
|
|
//
|
|
|
|
Status = FtwGetLastWriteRecord (
|
|
|
|
FtwDevice->FtwLastWriteHeader,
|
|
|
|
&FtwDevice->FtwLastWriteRecord
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Reclaim the work space on the working block.
|
|
|
|
|
|
|
|
@param FtwDevice Point to private data of FTW driver
|
|
|
|
@param PreserveRecord Whether to preserve the working record is needed
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Allocate memory error
|
|
|
|
@retval EFI_ABORTED The function could not complete successfully
|
|
|
|
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
FtwReclaimWorkSpace (
|
|
|
|
IN EFI_FTW_DEVICE *FtwDevice,
|
|
|
|
IN BOOLEAN PreserveRecord
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINTN Length;
|
|
|
|
EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
|
|
|
|
UINT8 *TempBuffer;
|
|
|
|
UINTN TempBufferSize;
|
|
|
|
UINTN SpareBufferSize;
|
|
|
|
UINT8 *SpareBuffer;
|
|
|
|
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
|
|
|
|
UINTN Index;
|
|
|
|
UINT8 *Ptr;
|
2012-09-14 08:54:35 +02:00
|
|
|
EFI_LBA WorkSpaceLbaOffset;
|
2009-03-04 02:05:31 +01:00
|
|
|
|
2013-10-08 11:31:48 +02:00
|
|
|
DEBUG ((EFI_D_INFO, "Ftw: start to reclaim work space\n"));
|
2009-03-04 02:05:31 +01:00
|
|
|
|
2012-09-14 08:54:35 +02:00
|
|
|
WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
|
|
|
|
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
|
|
|
// Read all original data from working block to a memory buffer
|
|
|
|
//
|
|
|
|
TempBufferSize = FtwDevice->SpareAreaLength;
|
|
|
|
TempBuffer = AllocateZeroPool (TempBufferSize);
|
|
|
|
if (TempBuffer == NULL) {
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr = TempBuffer;
|
|
|
|
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
|
|
|
|
Length = FtwDevice->BlockSize;
|
|
|
|
Status = FtwDevice->FtwFvBlock->Read (
|
|
|
|
FtwDevice->FtwFvBlock,
|
|
|
|
FtwDevice->FtwWorkBlockLba + Index,
|
|
|
|
0,
|
|
|
|
&Length,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (TempBuffer);
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr += Length;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Clean up the workspace, remove all the completed records.
|
|
|
|
//
|
|
|
|
Ptr = TempBuffer +
|
2012-09-14 08:54:35 +02:00
|
|
|
(UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize +
|
2009-03-04 02:05:31 +01:00
|
|
|
FtwDevice->FtwWorkSpaceBase;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Clear the content of buffer that will save the new work space data
|
|
|
|
//
|
|
|
|
SetMem (Ptr, FtwDevice->FtwWorkSpaceSize, FTW_ERASED_BYTE);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer
|
|
|
|
//
|
|
|
|
CopyMem (
|
|
|
|
Ptr,
|
|
|
|
FtwDevice->FtwWorkSpaceHeader,
|
|
|
|
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
|
|
|
|
);
|
|
|
|
if (PreserveRecord) {
|
|
|
|
//
|
|
|
|
// Get the last record following the header,
|
|
|
|
//
|
|
|
|
Status = FtwGetLastWriteHeader (
|
|
|
|
FtwDevice->FtwWorkSpaceHeader,
|
|
|
|
FtwDevice->FtwWorkSpaceSize,
|
|
|
|
&FtwDevice->FtwLastWriteHeader
|
|
|
|
);
|
|
|
|
Header = FtwDevice->FtwLastWriteHeader;
|
2011-02-16 06:31:53 +01:00
|
|
|
if (!EFI_ERROR (Status) && (Header != NULL) && (Header->Complete != FTW_VALID_STATE) && (Header->HeaderAllocated == FTW_VALID_STATE)) {
|
2009-03-04 02:05:31 +01:00
|
|
|
CopyMem (
|
|
|
|
Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
|
|
|
|
FtwDevice->FtwLastWriteHeader,
|
2013-07-03 11:08:40 +02:00
|
|
|
FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
|
2009-03-04 02:05:31 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem (
|
|
|
|
FtwDevice->FtwWorkSpace,
|
|
|
|
Ptr,
|
|
|
|
FtwDevice->FtwWorkSpaceSize
|
|
|
|
);
|
|
|
|
|
|
|
|
FtwGetLastWriteHeader (
|
|
|
|
FtwDevice->FtwWorkSpaceHeader,
|
|
|
|
FtwDevice->FtwWorkSpaceSize,
|
|
|
|
&FtwDevice->FtwLastWriteHeader
|
|
|
|
);
|
|
|
|
|
2012-09-14 08:54:35 +02:00
|
|
|
FtwGetLastWriteRecord (
|
|
|
|
FtwDevice->FtwLastWriteHeader,
|
|
|
|
&FtwDevice->FtwLastWriteRecord
|
|
|
|
);
|
|
|
|
|
2009-03-04 02:05:31 +01:00
|
|
|
//
|
|
|
|
// Set the WorkingBlockValid and WorkingBlockInvalid as INVALID
|
|
|
|
//
|
2012-09-14 08:54:35 +02:00
|
|
|
WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (TempBuffer +
|
|
|
|
(UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize +
|
|
|
|
FtwDevice->FtwWorkSpaceBase);
|
2009-03-04 02:05:31 +01:00
|
|
|
WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE;
|
|
|
|
WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Try to keep the content of spare block
|
|
|
|
// Save spare block into a spare backup memory buffer (Sparebuffer)
|
|
|
|
//
|
|
|
|
SpareBufferSize = FtwDevice->SpareAreaLength;
|
|
|
|
SpareBuffer = AllocatePool (SpareBufferSize);
|
|
|
|
if (SpareBuffer == NULL) {
|
|
|
|
FreePool (TempBuffer);
|
|
|
|
return EFI_OUT_OF_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr = SpareBuffer;
|
|
|
|
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
|
|
|
|
Length = FtwDevice->BlockSize;
|
|
|
|
Status = FtwDevice->FtwBackupFvb->Read (
|
|
|
|
FtwDevice->FtwBackupFvb,
|
|
|
|
FtwDevice->FtwSpareLba + Index,
|
|
|
|
0,
|
|
|
|
&Length,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (TempBuffer);
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr += Length;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Write the memory buffer to spare block
|
|
|
|
//
|
|
|
|
Status = FtwEraseSpareBlock (FtwDevice);
|
|
|
|
Ptr = TempBuffer;
|
|
|
|
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
|
|
|
|
Length = FtwDevice->BlockSize;
|
|
|
|
Status = FtwDevice->FtwBackupFvb->Write (
|
|
|
|
FtwDevice->FtwBackupFvb,
|
|
|
|
FtwDevice->FtwSpareLba + Index,
|
|
|
|
0,
|
|
|
|
&Length,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (TempBuffer);
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr += Length;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Free TempBuffer
|
|
|
|
//
|
|
|
|
FreePool (TempBuffer);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set the WorkingBlockValid in spare block
|
|
|
|
//
|
|
|
|
Status = FtwUpdateFvState (
|
|
|
|
FtwDevice->FtwBackupFvb,
|
2012-09-14 08:54:35 +02:00
|
|
|
FtwDevice->FtwSpareLba + WorkSpaceLbaOffset,
|
2009-03-04 02:05:31 +01:00
|
|
|
FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
|
|
|
|
WORKING_BLOCK_VALID
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Before erase the working block, set WorkingBlockInvalid in working block.
|
|
|
|
//
|
|
|
|
// Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
|
|
|
|
// WorkingBlockInvalid);
|
|
|
|
//
|
|
|
|
Status = FtwUpdateFvState (
|
|
|
|
FtwDevice->FtwFvBlock,
|
|
|
|
FtwDevice->FtwWorkSpaceLba,
|
|
|
|
FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
|
|
|
|
WORKING_BLOCK_INVALID
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Write the spare block to working block
|
|
|
|
//
|
|
|
|
Status = FlushSpareBlockToWorkingBlock (FtwDevice);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
|
|
|
|
//
|
|
|
|
Status = FtwEraseSpareBlock (FtwDevice);
|
|
|
|
Ptr = SpareBuffer;
|
|
|
|
for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
|
|
|
|
Length = FtwDevice->BlockSize;
|
|
|
|
Status = FtwDevice->FtwBackupFvb->Write (
|
|
|
|
FtwDevice->FtwBackupFvb,
|
|
|
|
FtwDevice->FtwSpareLba + Index,
|
|
|
|
0,
|
|
|
|
&Length,
|
|
|
|
Ptr
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
return EFI_ABORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ptr += Length;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreePool (SpareBuffer);
|
|
|
|
|
2013-10-08 11:31:48 +02:00
|
|
|
DEBUG ((EFI_D_INFO, "Ftw: reclaim work space successfully\n"));
|
2009-03-04 02:05:31 +01:00
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|