Add EBC, FTW, Crc32SectionExtract, NullMemoryTest modules.
CrcSectionExtract cannot build for now for some missing definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2813 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -0,0 +1,931 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2007, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
FtwLite.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This is a simple fault tolerant write driver, based on PlatformFd library.
|
||||
And it only supports write BufferSize <= SpareAreaLength.
|
||||
|
||||
This boot service only protocol provides fault tolerant write capability for
|
||||
block devices. The protocol has internal non-volatile intermediate storage
|
||||
of the data and private information. It should be able to recover
|
||||
automatically from a critical fault, such as power failure.
|
||||
|
||||
Notes:
|
||||
|
||||
The implementation uses an FTW Lite (Fault Tolerant Write) Work Space.
|
||||
This work space is a memory copy of the work space on the Woring Block,
|
||||
the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
|
||||
|
||||
--*/
|
||||
|
||||
#include <FtwLite.h>
|
||||
|
||||
//
|
||||
// In write function, we should check the target range to prevent the user
|
||||
// from writing Spare block and Working space directly.
|
||||
//
|
||||
//
|
||||
// Fault Tolerant Write Protocol API
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FtwLiteWrite (
|
||||
IN EFI_FTW_LITE_PROTOCOL *This,
|
||||
IN EFI_HANDLE FvbHandle,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN OUT UINTN *NumBytes,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Starts a target block update. This function will record data about write
|
||||
in fault tolerant storage and will complete the write in a recoverable
|
||||
manner, ensuring at all times that either the original contents or
|
||||
the modified contents are available.
|
||||
|
||||
Arguments:
|
||||
This - Calling context
|
||||
FvbHandle - The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
Lba - The logical block address of the target block.
|
||||
Offset - The offset within the target block to place the data.
|
||||
NumBytes - The number of bytes to write to the target block.
|
||||
Buffer - The data to write.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_BAD_BUFFER_SIZE - The write would span a target block, which is not
|
||||
a valid action.
|
||||
EFI_ACCESS_DENIED - No writes have been allocated.
|
||||
EFI_NOT_FOUND - Cannot find FVB by handle.
|
||||
EFI_OUT_OF_RESOURCES - Cannot allocate memory.
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice;
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
EFI_PHYSICAL_ADDRESS FvbPhysicalAddress;
|
||||
UINTN MyLength;
|
||||
UINTN MyOffset;
|
||||
UINTN MyBufferSize;
|
||||
UINT8 *MyBuffer;
|
||||
UINTN SpareBufferSize;
|
||||
UINT8 *SpareBuffer;
|
||||
UINTN Index;
|
||||
UINT8 *Ptr;
|
||||
EFI_DEV_PATH_PTR DevPtr;
|
||||
|
||||
//
|
||||
// Refresh work space and get last record
|
||||
//
|
||||
FtwLiteDevice = FTW_LITE_CONTEXT_FROM_THIS (This);
|
||||
Status = WorkSpaceRefresh (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Record = FtwLiteDevice->FtwLastRecord;
|
||||
|
||||
//
|
||||
// Check the flags of last write record
|
||||
//
|
||||
if ((Record->WriteAllocated == FTW_VALID_STATE) || (Record->SpareCompleted == FTW_VALID_STATE)) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
//
|
||||
// IF former record has completed, THEN use next record
|
||||
//
|
||||
if (Record->WriteCompleted == FTW_VALID_STATE) {
|
||||
Record++;
|
||||
FtwLiteDevice->FtwLastRecord = Record;
|
||||
}
|
||||
|
||||
MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
|
||||
|
||||
//
|
||||
// Check if the input data can fit within the target block
|
||||
//
|
||||
if ((Offset +*NumBytes) > FtwLiteDevice->SpareAreaLength) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
//
|
||||
// Check if there is enough free space for allocate a record
|
||||
//
|
||||
if ((MyOffset + WRITE_TOTAL_SIZE) > FtwLiteDevice->FtwWorkSpaceSize) {
|
||||
Status = FtwReclaimWorkSpace (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Reclaim work space - %r", Status));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Get the FVB protocol by handle
|
||||
//
|
||||
Status = FtwGetFvbByHandle (FvbHandle, &Fvb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Allocate a write record in workspace.
|
||||
// Update Header->WriteAllocated as VALID
|
||||
//
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + MyOffset,
|
||||
WRITE_ALLOCATED
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Allocate record - %r\n", Status));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Record->WriteAllocated = FTW_VALID_STATE;
|
||||
|
||||
//
|
||||
// Prepare data of write record, filling DevPath with memory mapped address.
|
||||
//
|
||||
DevPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath;
|
||||
DevPtr.MemMap->Header.Type = HARDWARE_DEVICE_PATH;
|
||||
DevPtr.MemMap->Header.SubType = HW_MEMMAP_DP;
|
||||
SetDevicePathNodeLength (&DevPtr.MemMap->Header, sizeof (MEMMAP_DEVICE_PATH));
|
||||
|
||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Get FVB physical address - %r\n", Status));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
DevPtr.MemMap->MemoryType = EfiMemoryMappedIO;
|
||||
DevPtr.MemMap->StartingAddress = FvbPhysicalAddress;
|
||||
DevPtr.MemMap->EndingAddress = FvbPhysicalAddress +*NumBytes;
|
||||
//
|
||||
// ignored!
|
||||
//
|
||||
Record->Lba = Lba;
|
||||
Record->Offset = Offset;
|
||||
Record->NumBytes = *NumBytes;
|
||||
|
||||
//
|
||||
// Write the record to the work space.
|
||||
//
|
||||
MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
|
||||
MyLength = FTW_LITE_RECORD_SIZE;
|
||||
|
||||
Status = FtwLiteDevice->FtwFvBlock->Write (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + MyOffset,
|
||||
&MyLength,
|
||||
(UINT8 *) Record
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Record has been written to working block, then write data.
|
||||
//
|
||||
//
|
||||
// Allocate a memory buffer
|
||||
//
|
||||
MyBufferSize = FtwLiteDevice->SpareAreaLength;
|
||||
MyBuffer = AllocatePool (MyBufferSize);
|
||||
if (MyBuffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
//
|
||||
// Starting at Lba, if the number of the rest blocks on Fvb is less
|
||||
// than NumberOfSpareBlock.
|
||||
//
|
||||
//
|
||||
// Read all original data from target block to memory buffer
|
||||
//
|
||||
if (IsInWorkingBlock (FtwLiteDevice, Fvb, Lba)) {
|
||||
//
|
||||
// If target block falls into working block, we must follow the process of
|
||||
// updating working block.
|
||||
//
|
||||
Ptr = MyBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
MyLength = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwFvBlock->Read (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkBlockLba + Index,
|
||||
0,
|
||||
&MyLength,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (MyBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += MyLength;
|
||||
}
|
||||
//
|
||||
// Update Offset by adding the offset from the start LBA of working block to
|
||||
// the target LBA. The target block can not span working block!
|
||||
//
|
||||
Offset = (((UINTN) (Lba - FtwLiteDevice->FtwWorkBlockLba)) * FtwLiteDevice->SizeOfSpareBlock + Offset);
|
||||
ASSERT ((Offset +*NumBytes) <= FtwLiteDevice->SpareAreaLength);
|
||||
|
||||
} else {
|
||||
|
||||
Ptr = MyBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
MyLength = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (MyBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += MyLength;
|
||||
}
|
||||
}
|
||||
//
|
||||
// Overwrite the updating range data with
|
||||
// the input buffer content
|
||||
//
|
||||
CopyMem (MyBuffer + Offset, Buffer, *NumBytes);
|
||||
|
||||
//
|
||||
// Try to keep the content of spare block
|
||||
// Save spare block into a spare backup memory buffer (Sparebuffer)
|
||||
//
|
||||
SpareBufferSize = FtwLiteDevice->SpareAreaLength;
|
||||
SpareBuffer = AllocatePool (SpareBufferSize);
|
||||
if (SpareBuffer == NULL) {
|
||||
FreePool (MyBuffer);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ptr = SpareBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
MyLength = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Read (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&MyLength,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (MyBuffer);
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += MyLength;
|
||||
}
|
||||
//
|
||||
// Write the memory buffer to spare block
|
||||
// Don't forget to erase Flash first.
|
||||
//
|
||||
Status = FtwEraseSpareBlock (FtwLiteDevice);
|
||||
Ptr = MyBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
MyLength = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Write (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&MyLength,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (MyBuffer);
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += MyLength;
|
||||
}
|
||||
//
|
||||
// Free MyBuffer
|
||||
//
|
||||
FreePool (MyBuffer);
|
||||
|
||||
//
|
||||
// Set the SpareCompleteD in the FTW record,
|
||||
//
|
||||
MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + MyOffset,
|
||||
SPARE_COMPLETED
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Record->SpareCompleted = FTW_VALID_STATE;
|
||||
|
||||
//
|
||||
// Since the content has already backuped in spare block, the write is
|
||||
// guaranteed to be completed with fault tolerant manner.
|
||||
//
|
||||
Status = FtwWriteRecord (FtwLiteDevice, Fvb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Record++;
|
||||
FtwLiteDevice->FtwLastRecord = Record;
|
||||
|
||||
//
|
||||
// Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
|
||||
//
|
||||
Status = FtwEraseSpareBlock (FtwLiteDevice);
|
||||
Ptr = SpareBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
MyLength = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Write (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&MyLength,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += MyLength;
|
||||
}
|
||||
//
|
||||
// All success.
|
||||
//
|
||||
FreePool (SpareBuffer);
|
||||
|
||||
DEBUG (
|
||||
(EFI_D_FTW_LITE,
|
||||
"FtwLite: Write() success, (Lba:Offset)=(%lx:0x%x), NumBytes: 0x%x\n",
|
||||
Lba,
|
||||
Offset,
|
||||
*NumBytes)
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
FtwWriteRecord (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Write a record with fault tolerant mannaer.
|
||||
Since the content has already backuped in spare block, the write is
|
||||
guaranteed to be completed with fault tolerant manner.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
Fvb - The FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
EFI_LBA WorkSpaceLbaOffset;
|
||||
UINTN Offset;
|
||||
|
||||
//
|
||||
// Spare Complete but Destination not complete,
|
||||
// Recover the targt block with the spare block.
|
||||
//
|
||||
Record = FtwLiteDevice->FtwLastRecord;
|
||||
|
||||
//
|
||||
// IF target block is working block, THEN Flush Spare Block To Working Block;
|
||||
// ELSE IF target block is boot block, THEN Flush Spare Block To boot Block;
|
||||
// ELSE flush spare block to normal target block.ENDIF
|
||||
//
|
||||
if (IsInWorkingBlock (FtwLiteDevice, Fvb, Record->Lba)) {
|
||||
//
|
||||
// If target block is working block, Attention:
|
||||
// it's required to set SPARE_COMPLETED to spare block.
|
||||
//
|
||||
WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba;
|
||||
Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + Offset,
|
||||
SPARE_COMPLETED
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
|
||||
} else if (IsBootBlock (FtwLiteDevice, Fvb, Record->Lba)) {
|
||||
//
|
||||
// Update boot block
|
||||
//
|
||||
Status = FlushSpareBlockToBootBlock (FtwLiteDevice);
|
||||
} else {
|
||||
//
|
||||
// Update blocks other than working block or boot block
|
||||
//
|
||||
Status = FlushSpareBlockToTargetBlock (FtwLiteDevice, Fvb, Record->Lba);
|
||||
}
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Set WriteCompleted flag in record
|
||||
//
|
||||
Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + Offset,
|
||||
WRITE_COMPLETED
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Record->WriteCompleted = FTW_VALID_STATE;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
FtwRestart (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Restarts a previously interrupted write. The caller must provide the
|
||||
block protocol needed to complete the interrupted write.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
FvbHandle - The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ACCESS_DENIED - No pending writes exist
|
||||
EFI_NOT_FOUND - FVB protocol not found by the handle
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
EFI_DEV_PATH_PTR DevPathPtr;
|
||||
|
||||
//
|
||||
// Spare Completed but Destination not complete,
|
||||
// Recover the targt block with the spare block.
|
||||
//
|
||||
Record = FtwLiteDevice->FtwLastRecord;
|
||||
|
||||
//
|
||||
// Only support memory mapped FVB device path by now.
|
||||
//
|
||||
DevPathPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath;
|
||||
if (!((DevPathPtr.MemMap->Header.Type == HARDWARE_DEVICE_PATH) && (DevPathPtr.MemMap->Header.SubType == HW_MEMMAP_DP))
|
||||
) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Device Path is not memory mapped\n"));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Status = GetFvbByAddress (DevPathPtr.MemMap->StartingAddress, &Fvb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Since the content has already backuped in spare block, the write is
|
||||
// guaranteed to be completed with fault tolerant manner.
|
||||
//
|
||||
Status = FtwWriteRecord (FtwLiteDevice, Fvb);
|
||||
DEBUG ((EFI_D_FTW_INFO, "FtwLite: Restart() - %r\n", Status));
|
||||
|
||||
Record++;
|
||||
FtwLiteDevice->FtwLastRecord = Record;
|
||||
|
||||
//
|
||||
// Erase Spare block
|
||||
// This is restart, no need to keep spareblock content.
|
||||
//
|
||||
FtwEraseSpareBlock (FtwLiteDevice);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
FtwAbort (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Aborts all previous allocated writes.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
EFI_NOT_FOUND - No allocated writes exist.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Offset;
|
||||
|
||||
if (FtwLiteDevice->FtwLastRecord->WriteCompleted == FTW_VALID_STATE) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Update the complete state of the header as VALID and abort.
|
||||
//
|
||||
Offset = (UINT8 *) FtwLiteDevice->FtwLastRecord - FtwLiteDevice->FtwWorkSpace;
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + Offset,
|
||||
WRITE_COMPLETED
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
FtwLiteDevice->FtwLastRecord->WriteCompleted = FTW_VALID_STATE;
|
||||
|
||||
Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);
|
||||
|
||||
//
|
||||
// Erase the spare block
|
||||
//
|
||||
Status = FtwEraseSpareBlock (FtwLiteDevice);
|
||||
|
||||
DEBUG ((EFI_D_FTW_INFO, "FtwLite: Abort() success \n"));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeFtwLite (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
Routine Description:
|
||||
This function is the entry point of the Fault Tolerant Write driver.
|
||||
|
||||
Arguments:
|
||||
ImageHandle - EFI_HANDLE: A handle for the image that is initializing
|
||||
this driver
|
||||
SystemTable - EFI_SYSTEM_TABLE: A pointer to the EFI system table
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - FTW has finished the initialization
|
||||
EFI_ABORTED - FTW initialization error
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
UINTN Index;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN HandleCount;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice;
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
UINTN Length;
|
||||
EFI_STATUS Status;
|
||||
UINTN Offset;
|
||||
EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
|
||||
UINT32 LbaIndex;
|
||||
|
||||
//
|
||||
// Allocate Private data of this driver,
|
||||
// INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE].
|
||||
//
|
||||
FtwLiteDevice = NULL;
|
||||
FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + FTW_WORK_SPACE_SIZE);
|
||||
if (FtwLiteDevice != NULL) {
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
ZeroMem (FtwLiteDevice, sizeof (EFI_FTW_LITE_DEVICE));
|
||||
FtwLiteDevice->Signature = FTW_LITE_DEVICE_SIGNATURE;
|
||||
|
||||
//
|
||||
// Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
|
||||
//
|
||||
FtwLiteDevice->FtwWorkSpace = (UINT8 *) (FtwLiteDevice + 1);
|
||||
FtwLiteDevice->FtwWorkSpaceSize = FTW_WORK_SPACE_SIZE;
|
||||
SetMem (
|
||||
FtwLiteDevice->FtwWorkSpace,
|
||||
FtwLiteDevice->FtwWorkSpaceSize,
|
||||
FTW_ERASED_BYTE
|
||||
);
|
||||
FtwLiteDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwLiteDevice->FtwWorkSpace;
|
||||
|
||||
FtwLiteDevice->FtwLastRecord = NULL;
|
||||
|
||||
FtwLiteDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
|
||||
FtwLiteDevice->WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
|
||||
|
||||
FtwLiteDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
|
||||
FtwLiteDevice->SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
|
||||
|
||||
ASSERT ((FtwLiteDevice->WorkSpaceLength != 0) && (FtwLiteDevice->SpareAreaLength != 0));
|
||||
|
||||
//
|
||||
// Locate FVB protocol
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
ASSERT (HandleCount > 0);
|
||||
|
||||
FtwLiteDevice->FtwFvBlock = NULL;
|
||||
FtwLiteDevice->FtwBackupFvb = NULL;
|
||||
FtwLiteDevice->FtwWorkSpaceLba = (EFI_LBA) (-1);
|
||||
FtwLiteDevice->FtwSpareLba = (EFI_LBA) (-1);
|
||||
for (Index = 0; Index < HandleCount; Index += 1) {
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) &Fvb
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress);
|
||||
|
||||
if ((FtwLiteDevice->WorkSpaceAddress >= BaseAddress) &&
|
||||
(FtwLiteDevice->WorkSpaceAddress <= (BaseAddress + FwVolHeader->FvLength))
|
||||
) {
|
||||
FtwLiteDevice->FtwFvBlock = Fvb;
|
||||
//
|
||||
// To get the LBA of work space
|
||||
//
|
||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||
//
|
||||
// FV may have multiple types of BlockLength
|
||||
//
|
||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||
while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->Length == 0))) {
|
||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||
if (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex)) {
|
||||
FtwLiteDevice->FtwWorkSpaceLba = LbaIndex - 1;
|
||||
//
|
||||
// Get the Work space size and Base(Offset)
|
||||
//
|
||||
FtwLiteDevice->FtwWorkSpaceSize = FtwLiteDevice->WorkSpaceLength;
|
||||
FtwLiteDevice->FtwWorkSpaceBase = (UINTN) (FtwLiteDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
//
|
||||
// end for
|
||||
//
|
||||
FvbMapEntry++;
|
||||
}
|
||||
//
|
||||
// end while
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
if ((FtwLiteDevice->SpareAreaAddress >= BaseAddress) &&
|
||||
(FtwLiteDevice->SpareAreaAddress <= (BaseAddress + FwVolHeader->FvLength))
|
||||
) {
|
||||
FtwLiteDevice->FtwBackupFvb = Fvb;
|
||||
//
|
||||
// To get the LBA of spare
|
||||
//
|
||||
if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
|
||||
//
|
||||
// FV may have multiple types of BlockLength
|
||||
//
|
||||
FvbMapEntry = &FwVolHeader->BlockMap[0];
|
||||
while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->Length == 0))) {
|
||||
for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
|
||||
if (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex)) {
|
||||
//
|
||||
// Get the NumberOfSpareBlock and SizeOfSpareBlock
|
||||
//
|
||||
FtwLiteDevice->FtwSpareLba = LbaIndex - 1;
|
||||
FtwLiteDevice->SizeOfSpareBlock = FvbMapEntry->Length;
|
||||
FtwLiteDevice->NumberOfSpareBlock = FtwLiteDevice->SpareAreaLength / FtwLiteDevice->SizeOfSpareBlock;
|
||||
//
|
||||
// Check the range of spare area to make sure that it's in FV range
|
||||
//
|
||||
ASSERT ((FtwLiteDevice->FtwSpareLba + FtwLiteDevice->NumberOfSpareBlock) <= FvbMapEntry->NumBlocks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FvbMapEntry++;
|
||||
}
|
||||
//
|
||||
// end while
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Calculate the start LBA of working block. Working block is an area which
|
||||
// contains working space in its last block and has the same size as spare
|
||||
// block, unless there are not enough blocks before the block that contains
|
||||
// working space.
|
||||
//
|
||||
FtwLiteDevice->FtwWorkBlockLba = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->NumberOfSpareBlock + 1;
|
||||
if ((INT64) (FtwLiteDevice->FtwWorkBlockLba) < 0) {
|
||||
FtwLiteDevice->FtwWorkBlockLba = 0;
|
||||
}
|
||||
|
||||
if ((FtwLiteDevice->FtwFvBlock == NULL) ||
|
||||
(FtwLiteDevice->FtwBackupFvb == NULL) ||
|
||||
(FtwLiteDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) ||
|
||||
(FtwLiteDevice->FtwSpareLba == (EFI_LBA) (-1))
|
||||
) {
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Working or spare FVB not ready\n"));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
//
|
||||
// Refresh workspace data from working block
|
||||
//
|
||||
Status = WorkSpaceRefresh (FtwLiteDevice);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// If the working block workspace is not valid, try the spare block
|
||||
//
|
||||
if (!IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace invalid, read from backup\n"));
|
||||
//
|
||||
// Read from spare block
|
||||
//
|
||||
Length = FtwLiteDevice->FtwWorkSpaceSize;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Read (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase,
|
||||
&Length,
|
||||
FtwLiteDevice->FtwWorkSpace
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// If spare block is valid, then replace working block content.
|
||||
//
|
||||
if (IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) {
|
||||
Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart working block in Init() - %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
FtwAbort (FtwLiteDevice);
|
||||
//
|
||||
// Refresh work space.
|
||||
//
|
||||
Status = WorkSpaceRefresh (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
} else {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Both are invalid, init workspace\n"));
|
||||
//
|
||||
// If both are invalid, then initialize work space.
|
||||
//
|
||||
SetMem (
|
||||
FtwLiteDevice->FtwWorkSpace,
|
||||
FtwLiteDevice->FtwWorkSpaceSize,
|
||||
FTW_ERASED_BYTE
|
||||
);
|
||||
InitWorkSpaceHeader (FtwLiteDevice->FtwWorkSpaceHeader);
|
||||
//
|
||||
// Write to work space on the working block
|
||||
//
|
||||
Length = FtwLiteDevice->FtwWorkSpaceSize;
|
||||
Status = FtwLiteDevice->FtwFvBlock->Write (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase,
|
||||
&Length,
|
||||
FtwLiteDevice->FtwWorkSpace
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Hook the protocol API
|
||||
//
|
||||
FtwLiteDevice->FtwLiteInstance.Write = FtwLiteWrite;
|
||||
|
||||
//
|
||||
// Install protocol interface
|
||||
//
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&FtwLiteDevice->Handle,
|
||||
&gEfiFaultTolerantWriteLiteProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&FtwLiteDevice->FtwLiteInstance
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// If (!SpareCompleted) THEN Abort to rollback.
|
||||
//
|
||||
if ((FtwLiteDevice->FtwLastRecord->WriteAllocated == FTW_VALID_STATE) &&
|
||||
(FtwLiteDevice->FtwLastRecord->SpareCompleted != FTW_VALID_STATE)
|
||||
) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Init.. record not SpareCompleted, abort()\n"));
|
||||
FtwAbort (FtwLiteDevice);
|
||||
}
|
||||
//
|
||||
// if (SpareCompleted) THEN Restart to fault tolerant write.
|
||||
//
|
||||
if ((FtwLiteDevice->FtwLastRecord->SpareCompleted == FTW_VALID_STATE) &&
|
||||
(FtwLiteDevice->FtwLastRecord->WriteCompleted != FTW_VALID_STATE)
|
||||
) {
|
||||
|
||||
Status = FtwRestart (FtwLiteDevice);
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart last write - %r\n", Status));
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
//
|
||||
// To check the workspace buffer behind last records is EMPTY or not.
|
||||
// If it's not EMPTY, FTW_LITE also need to call reclaim().
|
||||
//
|
||||
Record = FtwLiteDevice->FtwLastRecord;
|
||||
Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;
|
||||
if (FtwLiteDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
|
||||
Offset += WRITE_TOTAL_SIZE;
|
||||
}
|
||||
|
||||
if (!IsErasedFlashBuffer (
|
||||
FTW_ERASE_POLARITY,
|
||||
FtwLiteDevice->FtwWorkSpace + Offset,
|
||||
FtwLiteDevice->FtwWorkSpaceSize - Offset
|
||||
)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace is dirty, call reclaim...\n"));
|
||||
Status = FtwReclaimWorkSpace (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace reclaim - %r\n", Status));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
FtwLite.dxs
|
||||
|
||||
Abstract:
|
||||
|
||||
Dependency expression source file.
|
||||
|
||||
--*/
|
||||
#include <DxeDepex.h>
|
||||
|
||||
|
||||
DEPENDENCY_START
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID AND EFI_ALTERNATE_FV_BLOCK_GUID
|
||||
DEPENDENCY_END
|
@ -0,0 +1,695 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
FtwLite.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This is a simple fault tolerant write driver, based on PlatformFd library.
|
||||
And it only supports write BufferSize <= SpareAreaLength.
|
||||
|
||||
This boot service only protocol provides fault tolerant write capability for
|
||||
block devices. The protocol has internal non-volatile intermediate storage
|
||||
of the data and private information. It should be able to recover
|
||||
automatically from a critical fault, such as power failure.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _EFI_FAULT_TOLERANT_WRITE_LITE_H_
|
||||
#define _EFI_FAULT_TOLERANT_WRITE_LITE_H_
|
||||
|
||||
//
|
||||
// The package level header files this module uses
|
||||
//
|
||||
#include <PiDxe.h>
|
||||
//
|
||||
// The protocols, PPI and GUID defintions for this module
|
||||
//
|
||||
#include <Protocol/PciRootBridgeIo.h>
|
||||
#include <Guid/SystemNvDataGuid.h>
|
||||
#include <Protocol/FaultTolerantWriteLite.h>
|
||||
#include <Protocol/FirmwareVolumeBlock.h>
|
||||
//
|
||||
// The Library classes this module consumes
|
||||
//
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#include <Common/WorkingBlockHeader.h>
|
||||
|
||||
#define EFI_D_FTW_LITE EFI_D_ERROR
|
||||
#define EFI_D_FTW_INFO EFI_D_INFO
|
||||
|
||||
//
|
||||
// Flash erase polarity is 1
|
||||
//
|
||||
#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))
|
||||
|
||||
typedef struct {
|
||||
UINT8 WriteAllocated : 1;
|
||||
UINT8 SpareCompleted : 1;
|
||||
UINT8 WriteCompleted : 1;
|
||||
UINT8 Reserved : 5;
|
||||
#define WRITE_ALLOCATED 0x1
|
||||
#define SPARE_COMPLETED 0x2
|
||||
#define WRITE_COMPLETED 0x4
|
||||
|
||||
EFI_DEV_PATH DevPath;
|
||||
EFI_LBA Lba;
|
||||
UINTN Offset;
|
||||
UINTN NumBytes;
|
||||
//
|
||||
// UINTN SpareAreaOffset;
|
||||
//
|
||||
} EFI_FTW_LITE_RECORD;
|
||||
|
||||
#define FTW_LITE_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('F', 'T', 'W', 'L')
|
||||
|
||||
//
|
||||
// MACRO for Block size.
|
||||
// Flash Erasing will do in block granularity.
|
||||
//
|
||||
#ifdef FV_BLOCK_SIZE
|
||||
#define FTW_BLOCK_SIZE FV_BLOCK_SIZE
|
||||
#else
|
||||
#define FV_BLOCK_SIZE 0x10000
|
||||
#define FTW_BLOCK_SIZE FV_BLOCK_SIZE
|
||||
#endif
|
||||
//
|
||||
// MACRO for FTW WORK SPACE Base & Size
|
||||
//
|
||||
#ifdef EFI_FTW_WORKING_OFFSET
|
||||
#define FTW_WORK_SPACE_BASE EFI_FTW_WORKING_OFFSET
|
||||
#else
|
||||
#define FTW_WORK_SPACE_BASE 0x00E000
|
||||
#endif
|
||||
|
||||
#ifdef EFI_FTW_WORKING_LENGTH
|
||||
#define FTW_WORK_SPACE_SIZE EFI_FTW_WORKING_LENGTH
|
||||
#else
|
||||
#define FTW_WORK_SPACE_SIZE 0x002000
|
||||
#endif
|
||||
//
|
||||
// MACRO for FTW header and record
|
||||
//
|
||||
#define FTW_WORKING_QUEUE_SIZE (FTW_WORK_SPACE_SIZE - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER))
|
||||
#define FTW_LITE_RECORD_SIZE (sizeof (EFI_FTW_LITE_RECORD))
|
||||
#define WRITE_TOTAL_SIZE FTW_LITE_RECORD_SIZE
|
||||
|
||||
//
|
||||
// EFI Fault tolerant protocol private data structure
|
||||
//
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_FTW_LITE_PROTOCOL FtwLiteInstance;
|
||||
EFI_PHYSICAL_ADDRESS WorkSpaceAddress;
|
||||
UINTN WorkSpaceLength;
|
||||
EFI_PHYSICAL_ADDRESS SpareAreaAddress;
|
||||
UINTN SpareAreaLength;
|
||||
UINTN NumberOfSpareBlock; // Number of the blocks in spare block
|
||||
UINTN SizeOfSpareBlock; // Block size in bytes of the blocks in spare block
|
||||
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader;
|
||||
EFI_FTW_LITE_RECORD *FtwLastRecord;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwFvBlock; // FVB of working block
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwBackupFvb; // FVB of spare block
|
||||
EFI_LBA FtwSpareLba;
|
||||
EFI_LBA FtwWorkBlockLba; // Start LBA of working block
|
||||
EFI_LBA FtwWorkSpaceLba; // Start LBA of working space
|
||||
UINTN FtwWorkSpaceBase; // Offset from LBA start addr
|
||||
UINTN FtwWorkSpaceSize;
|
||||
UINT8 *FtwWorkSpace;
|
||||
//
|
||||
// Following a buffer of FtwWorkSpace[FTW_WORK_SPACE_SIZE],
|
||||
// Allocated with EFI_FTW_LITE_DEVICE.
|
||||
//
|
||||
} EFI_FTW_LITE_DEVICE;
|
||||
|
||||
#define FTW_LITE_CONTEXT_FROM_THIS(a) CR (a, EFI_FTW_LITE_DEVICE, FtwLiteInstance, FTW_LITE_DEVICE_SIGNATURE)
|
||||
|
||||
//
|
||||
// Driver entry point
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeFtwLite (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
This function is the entry point of the Fault Tolerant Write driver.
|
||||
|
||||
Arguments:
|
||||
ImageHandle - EFI_HANDLE: A handle for the image that is initializing
|
||||
this driver
|
||||
SystemTable - EFI_SYSTEM_TABLE: A pointer to the EFI system table
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - FTW has finished the initialization
|
||||
EFI_ABORTED - FTW initialization error
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
//
|
||||
// Fault Tolerant Write Protocol API
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
FtwLiteWrite (
|
||||
IN EFI_FTW_LITE_PROTOCOL *This,
|
||||
IN EFI_HANDLE FvbHandle,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN UINTN *NumBytes,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Starts a target block update. This function will record data about write
|
||||
in fault tolerant storage and will complete the write in a recoverable
|
||||
manner, ensuring at all times that either the original contents or
|
||||
the modified contents are available.
|
||||
|
||||
Arguments:
|
||||
This - Calling context
|
||||
FvbHandle - The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
Lba - The logical block address of the target block.
|
||||
Offset - The offset within the target block to place the data.
|
||||
NumBytes - The number of bytes to write to the target block.
|
||||
Buffer - The data to write.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_BAD_BUFFER_SIZE - The write would span a target block, which is not
|
||||
a valid action.
|
||||
EFI_ACCESS_DENIED - No writes have been allocated.
|
||||
EFI_NOT_FOUND - Cannot find FVB by handle.
|
||||
EFI_OUT_OF_RESOURCES - Cannot allocate memory.
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
//
|
||||
// Internal functions
|
||||
//
|
||||
EFI_STATUS
|
||||
FtwRestart (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Restarts a previously interrupted write. The caller must provide the
|
||||
block protocol needed to complete the interrupted write.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
FvbHandle - The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ACCESS_DENIED - No pending writes exist
|
||||
EFI_NOT_FOUND - FVB protocol not found by the handle
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwAbort (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Aborts all previous allocated writes.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
EFI_NOT_FOUND - No allocated writes exist.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
|
||||
EFI_STATUS
|
||||
FtwWriteRecord (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Write a record with fault tolerant mannaer.
|
||||
Since the content has already backuped in spare block, the write is
|
||||
guaranteed to be completed with fault tolerant manner.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
Fvb - The FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwEraseBlock (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
To Erase one block. The size is FTW_BLOCK_SIZE
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - FVB Protocol interface
|
||||
Lba - Lba of the firmware block
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Block LBA is Erased successfully
|
||||
Others - Error occurs
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwEraseSpareBlock (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Erase spare block.
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
|
||||
Returns:
|
||||
|
||||
Status code
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwGetFvbByHandle (
|
||||
IN EFI_HANDLE FvBlockHandle,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrive the proper FVB protocol interface by HANDLE.
|
||||
|
||||
Arguments:
|
||||
FvBlockHandle - The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
FvBlock - The interface of FVB protocol
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
GetFvbByAddress (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get firmware block by address.
|
||||
|
||||
Arguments:
|
||||
|
||||
Address - Address specified the block
|
||||
FvBlock - The block caller wanted
|
||||
|
||||
Returns:
|
||||
|
||||
Status code
|
||||
|
||||
EFI_NOT_FOUND - Block not found
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
BOOLEAN
|
||||
IsInWorkingBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Is it in working block?
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - Fvb protocol instance
|
||||
Lba - The block specified
|
||||
|
||||
Returns:
|
||||
|
||||
In working block or not
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
BOOLEAN
|
||||
IsBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Check whether the block is a boot block.
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - Fvb protocol instance
|
||||
Lba - Lba value
|
||||
|
||||
Returns:
|
||||
|
||||
Is a boot block or not
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToTargetBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Target block is accessed by FvBlock protocol interface. LBA is Lba.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
FvBlock - FVB Protocol interface to access target block
|
||||
Lba - Lba of the target block
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to target block
|
||||
EFI_INVALID_PARAMETER - Input parameter error
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToWorkingBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Working block is accessed by FTW working FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwWorkBlockLba.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to target block
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
Notes:
|
||||
Since the working block header is important when FTW initializes, the
|
||||
state of the operation should be handled carefully. The Crc value is
|
||||
calculated without STATE element.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Boot block is accessed by BootFvb protocol interface. LBA is 0.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to boot block
|
||||
EFI_INVALID_PARAMETER - Input parameter error
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwUpdateFvState (
|
||||
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN UINT8 NewBit
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Update a bit of state on a block device. The location of the bit is
|
||||
calculated by the (Lba, Offset, bit). Here bit is determined by the
|
||||
the name of a certain bit.
|
||||
|
||||
Arguments:
|
||||
FvBlock - FVB Protocol interface to access SrcBlock and DestBlock
|
||||
Lba - Lba of a block
|
||||
Offset - Offset on the Lba
|
||||
NewBit - New value that will override the old value if it can be change
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - A state bit has been updated successfully
|
||||
Others - Access block device error.
|
||||
|
||||
Notes:
|
||||
Assume all bits of State are inside the same BYTE.
|
||||
|
||||
EFI_ABORTED - Read block fail
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwGetLastRecord (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
OUT EFI_FTW_LITE_RECORD **FtwLastRecord
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Get the last Write record pointer.
|
||||
The last record is the record whose 'complete' state hasn't been set.
|
||||
After all, this header may be a EMPTY header entry for next Allocate.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Private data of this driver
|
||||
FtwLastRecord - Pointer to retrieve the last write record
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Get the last write record successfully
|
||||
EFI_ABORTED - The FTW work space is damaged
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
BOOLEAN
|
||||
IsErasedFlashBuffer (
|
||||
IN BOOLEAN Polarity,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Check whether a flash buffer is erased.
|
||||
|
||||
Arguments:
|
||||
|
||||
Polarity - All 1 or all 0
|
||||
Buffer - Buffer to check
|
||||
BufferSize - Size of the buffer
|
||||
|
||||
Returns:
|
||||
|
||||
Erased or not.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
InitWorkSpaceHeader (
|
||||
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Initialize a work space when there is no work space.
|
||||
|
||||
Arguments:
|
||||
WorkingHeader - Pointer of working block header
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
WorkSpaceRefresh (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Read from working block to refresh the work space in memory.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Point to private data of FTW driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
BOOLEAN
|
||||
IsValidWorkSpace (
|
||||
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Check to see if it is a valid work space.
|
||||
|
||||
Arguments:
|
||||
WorkingHeader - Pointer of working block header
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
CleanupWorkSpace (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN OUT UINT8 *BlockBuffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Reclaim the work space. Get rid of all the completed write records
|
||||
and write records in the Fault Tolerant work space.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Point to private data of FTW driver
|
||||
FtwSpaceBuffer - Buffer to contain the reclaimed clean data
|
||||
BufferSize - Size of the FtwSpaceBuffer
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_BUFFER_TOO_SMALL - The FtwSpaceBuffer is too small
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
EFI_STATUS
|
||||
FtwReclaimWorkSpace (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Reclaim the work space on the working block.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Point to private data of FTW driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
;
|
||||
|
||||
#endif
|
@ -0,0 +1,133 @@
|
||||
#/** @file
|
||||
# Component description file for FtwLite module.
|
||||
#
|
||||
# This driver provides fault tolerant write capability for block devices.
|
||||
# Copyright (c) 2006 - 2007, Intel Corporation
|
||||
#
|
||||
# All rights reserved. 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
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Defines Section - statements that will be processed to create a Makefile.
|
||||
#
|
||||
################################################################################
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = FtwLite
|
||||
FILE_GUID = 4C862FC6-0E54-4e36-8C8F-FF6F3167951F
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
EDK_RELEASE_VERSION = 0x00020000
|
||||
EFI_SPECIFICATION_VERSION = 0x00020000
|
||||
|
||||
ENTRY_POINT = InitializeFtwLite
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Sources Section - list of files that are required for the build to succeed.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
[Sources.common]
|
||||
FtwLite.dxs
|
||||
FtwWorkSpace.c
|
||||
FtwMisc.c
|
||||
FtwLite.c
|
||||
FtwLite.h
|
||||
|
||||
[Sources.Ia32]
|
||||
Ia32/Ia32FtwMisc.c
|
||||
|
||||
[Sources.X64]
|
||||
x64/x64FtwMisc.c
|
||||
|
||||
[Sources.IPF]
|
||||
Ipf/IpfFtwMisc.c
|
||||
|
||||
[Sources.EBC]
|
||||
Ia32/Ia32FtwMisc.c
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Package Dependency Section - list of Package files that are required for
|
||||
# this module.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Library Class Section - list of Library Classes that are required for
|
||||
# this module.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
[LibraryClasses]
|
||||
UefiBootServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
PcdLib
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Guid C Name Section - list of Guids that this module uses or produces.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
[Guids]
|
||||
gEfiSystemNvDataFvGuid # ALWAYS_CONSUMED
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Protocol C Name Section - list of Protocol and Protocol Notify C Names
|
||||
# that this module uses or produces.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
[Protocols]
|
||||
gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
gEfiFaultTolerantWriteLiteProtocolGuid # PROTOCOL ALWAYS_PRODUCED
|
||||
|
||||
[Protocols.IA32]
|
||||
gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
||||
[Protocols.EBC]
|
||||
gEfiPciRootBridgeIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
|
||||
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Pcd DYNAMIC - list of PCDs that this module is coded for.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
[PcdsDynamic.common]
|
||||
PcdFlashNvStorageFtwWorkingSize|gEfiGenericPlatformTokenSpaceGuid
|
||||
PcdFlashNvStorageFtwWorkingBase|gEfiGenericPlatformTokenSpaceGuid
|
||||
PcdFlashNvStorageFtwSpareSize|gEfiGenericPlatformTokenSpaceGuid
|
||||
PcdFlashNvStorageFtwSpareBase|gEfiGenericPlatformTokenSpaceGuid
|
||||
|
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<MsaHeader>
|
||||
<ModuleName>FtwLite</ModuleName>
|
||||
<ModuleType>DXE_DRIVER</ModuleType>
|
||||
<GuidValue>4C862FC6-0E54-4e36-8C8F-FF6F3167951F</GuidValue>
|
||||
<Version>1.0</Version>
|
||||
<Abstract>Component description file for FtwLite module.</Abstract>
|
||||
<Description>This driver provides fault tolerant write capability for block devices.</Description>
|
||||
<Copyright>Copyright (c) 2006 - 2007, Intel Corporation</Copyright>
|
||||
<License>All rights reserved. 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
|
||||
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.</License>
|
||||
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
|
||||
</MsaHeader>
|
||||
<ModuleDefinitions>
|
||||
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
|
||||
<BinaryModule>false</BinaryModule>
|
||||
<OutputFileBasename>FtwLite</OutputFileBasename>
|
||||
</ModuleDefinitions>
|
||||
<LibraryClassDefinitions>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>PcdLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>DebugLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiDriverEntryPoint</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>BaseMemoryLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>MemoryAllocationLib</Keyword>
|
||||
</LibraryClass>
|
||||
<LibraryClass Usage="ALWAYS_CONSUMED">
|
||||
<Keyword>UefiBootServicesTableLib</Keyword>
|
||||
</LibraryClass>
|
||||
</LibraryClassDefinitions>
|
||||
<SourceFiles>
|
||||
<Filename>FtwLite.h</Filename>
|
||||
<Filename>FtwLite.c</Filename>
|
||||
<Filename>FtwMisc.c</Filename>
|
||||
<Filename>FtwWorkSpace.c</Filename>
|
||||
<Filename>FtwLite.dxs</Filename>
|
||||
<Filename SupArchList="IA32 EBC">Ia32/Ia32FtwMisc.c</Filename>
|
||||
<Filename SupArchList="X64">x64/x64FtwMisc.c</Filename>
|
||||
<Filename SupArchList="IPF">Ipf/IpfFtwMisc.c</Filename>
|
||||
</SourceFiles>
|
||||
<PackageDependencies>
|
||||
<Package PackageGuid="1E73767F-8F52-4603-AEB4-F29B510B6766"/>
|
||||
<Package PackageGuid="BA0D78D6-2CAF-414b-BD4D-B6762A894288"/>
|
||||
</PackageDependencies>
|
||||
<Protocols>
|
||||
<Protocol Usage="ALWAYS_PRODUCED">
|
||||
<ProtocolCName>gEfiFaultTolerantWriteLiteProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED" SupArchList="IA32 EBC">
|
||||
<ProtocolCName>gEfiPciRootBridgeIoProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
<Protocol Usage="ALWAYS_CONSUMED">
|
||||
<ProtocolCName>gEfiFirmwareVolumeBlockProtocolGuid</ProtocolCName>
|
||||
</Protocol>
|
||||
</Protocols>
|
||||
<Guids>
|
||||
<GuidCNames Usage="ALWAYS_CONSUMED">
|
||||
<GuidCName>gEfiSystemNvDataFvGuid</GuidCName>
|
||||
</GuidCNames>
|
||||
</Guids>
|
||||
<Externs>
|
||||
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
|
||||
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
|
||||
<Extern>
|
||||
<ModuleEntryPoint>InitializeFtwLite</ModuleEntryPoint>
|
||||
</Extern>
|
||||
</Externs>
|
||||
<PcdCoded>
|
||||
<PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
|
||||
<C_Name>PcdFlashNvStorageFtwSpareBase</C_Name>
|
||||
<TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
|
||||
<HelpText>To get base address of the FTW spare block section in NV firmware volume.</HelpText>
|
||||
</PcdEntry>
|
||||
<PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
|
||||
<C_Name>PcdFlashNvStorageFtwSpareSize</C_Name>
|
||||
<TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
|
||||
<HelpText>To get size of the FTW spare block section in NV firmware volume.</HelpText>
|
||||
</PcdEntry>
|
||||
<PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
|
||||
<C_Name>PcdFlashNvStorageFtwWorkingBase</C_Name>
|
||||
<TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
|
||||
<HelpText>To get base address of the FTW working block section in NV firmware volume.</HelpText>
|
||||
</PcdEntry>
|
||||
<PcdEntry PcdItemType="DYNAMIC" Usage="ALWAYS_CONSUMED">
|
||||
<C_Name>PcdFlashNvStorageFtwWorkingSize</C_Name>
|
||||
<TokenSpaceGuidCName>gEfiGenericPlatformTokenSpaceGuid</TokenSpaceGuidCName>
|
||||
<HelpText>To get size of the FTW working block section in NV firmware volume.</HelpText>
|
||||
</PcdEntry>
|
||||
</PcdCoded>
|
||||
</ModuleSurfaceArea>
|
@ -0,0 +1,530 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2007, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
Module Name:
|
||||
|
||||
FtwMisc.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Internal functions to support fault tolerant write.
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
#include <FtwLite.h>
|
||||
|
||||
BOOLEAN
|
||||
IsErasedFlashBuffer (
|
||||
IN BOOLEAN Polarity,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Check whether a flash buffer is erased.
|
||||
|
||||
Arguments:
|
||||
|
||||
Polarity - All 1 or all 0
|
||||
Buffer - Buffer to check
|
||||
BufferSize - Size of the buffer
|
||||
|
||||
Returns:
|
||||
|
||||
Erased or not.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT8 ErasedValue;
|
||||
UINT8 *Ptr;
|
||||
|
||||
if (Polarity) {
|
||||
ErasedValue = 0xFF;
|
||||
} else {
|
||||
ErasedValue = 0;
|
||||
}
|
||||
|
||||
Ptr = Buffer;
|
||||
while (BufferSize--) {
|
||||
if (*Ptr++ != ErasedValue) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FtwEraseBlock (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
To Erase one block. The size is FTW_BLOCK_SIZE
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - FVB Protocol interface
|
||||
Lba - Lba of the firmware block
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Block LBA is Erased successfully
|
||||
Others - Error occurs
|
||||
|
||||
--*/
|
||||
{
|
||||
return FvBlock->EraseBlocks (
|
||||
FvBlock,
|
||||
Lba,
|
||||
FtwLiteDevice->NumberOfSpareBlock,
|
||||
EFI_LBA_LIST_TERMINATOR
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FtwEraseSpareBlock (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Erase spare block.
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
|
||||
Returns:
|
||||
|
||||
Status code
|
||||
|
||||
--*/
|
||||
{
|
||||
return FtwLiteDevice->FtwBackupFvb->EraseBlocks (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba,
|
||||
FtwLiteDevice->NumberOfSpareBlock,
|
||||
EFI_LBA_LIST_TERMINATOR
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FtwGetFvbByHandle (
|
||||
IN EFI_HANDLE FvBlockHandle,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrive the proper FVB protocol interface by HANDLE.
|
||||
|
||||
Arguments:
|
||||
FvBlockHandle - The handle of FVB protocol that provides services for
|
||||
reading, writing, and erasing the target block.
|
||||
FvBlock - The interface of FVB protocol
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// To get the FVB protocol interface on the handle
|
||||
//
|
||||
return gBS->HandleProtocol (
|
||||
FvBlockHandle,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) FvBlock
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
GetFvbByAddress (
|
||||
IN EFI_PHYSICAL_ADDRESS Address,
|
||||
OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get firmware block by address.
|
||||
|
||||
Arguments:
|
||||
|
||||
Address - Address specified the block
|
||||
FvBlock - The block caller wanted
|
||||
|
||||
Returns:
|
||||
|
||||
Status code
|
||||
|
||||
EFI_NOT_FOUND - Block not found
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN HandleCount;
|
||||
UINTN Index;
|
||||
EFI_PHYSICAL_ADDRESS FvbBaseAddress;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
|
||||
EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
|
||||
|
||||
*FvBlock = NULL;
|
||||
//
|
||||
// Locate all handles of Fvb protocol
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
NULL,
|
||||
&HandleCount,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
//
|
||||
// Search all FVB until find the right one
|
||||
//
|
||||
for (Index = 0; Index < HandleCount; Index += 1) {
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiFirmwareVolumeBlockProtocolGuid,
|
||||
(VOID **) &Fvb
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
//
|
||||
// Compare the address and select the right one
|
||||
//
|
||||
Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
|
||||
if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + (FwVolHeader->FvLength - 1)))) {
|
||||
*FvBlock = Fvb;
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (HandleBuffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsInWorkingBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Is it in working block?
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - Fvb protocol instance
|
||||
Lba - The block specified
|
||||
|
||||
Returns:
|
||||
|
||||
In working block or not
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// If matching the following condition, the target block is in working block.
|
||||
// 1. Target block is on the FV of working block (Using the same FVB protocol instance).
|
||||
// 2. Lba falls into the range of working block.
|
||||
//
|
||||
return (BOOLEAN)
|
||||
(
|
||||
(FvBlock == FtwLiteDevice->FtwFvBlock) &&
|
||||
(Lba >= FtwLiteDevice->FtwWorkBlockLba) &&
|
||||
(Lba <= FtwLiteDevice->FtwWorkSpaceLba)
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToTargetBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Target block is accessed by FvBlock protocol interface. LBA is Lba.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
FvBlock - FVB Protocol interface to access target block
|
||||
Lba - Lba of the target block
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to target block
|
||||
EFI_INVALID_PARAMETER - Input parameter error
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Length;
|
||||
UINT8 *Buffer;
|
||||
UINTN Count;
|
||||
UINT8 *Ptr;
|
||||
UINTN Index;
|
||||
|
||||
if ((FtwLiteDevice == NULL) || (FvBlock == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
//
|
||||
// Allocate a memory buffer
|
||||
//
|
||||
Length = FtwLiteDevice->SpareAreaLength;
|
||||
Buffer = AllocatePool (Length);
|
||||
if (Buffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
//
|
||||
// Read all content of spare block to memory buffer
|
||||
//
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Read (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&Count,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
//
|
||||
// Erase the target block
|
||||
//
|
||||
Status = FtwEraseBlock (FtwLiteDevice, FvBlock, Lba);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Write memory buffer to block, using the FvbBlock protocol interface
|
||||
//
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write block - %r\n", Status));
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
|
||||
FreePool (Buffer);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToWorkingBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Working block is accessed by FTW working FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwWorkBlockLba.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to target block
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
Notes:
|
||||
Since the working block header is important when FTW initializes, the
|
||||
state of the operation should be handled carefully. The Crc value is
|
||||
calculated without STATE element.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Length;
|
||||
UINT8 *Buffer;
|
||||
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
|
||||
EFI_LBA WorkSpaceLbaOffset;
|
||||
UINTN Count;
|
||||
UINT8 *Ptr;
|
||||
UINTN Index;
|
||||
|
||||
//
|
||||
// Allocate a memory buffer
|
||||
//
|
||||
Length = FtwLiteDevice->SpareAreaLength;
|
||||
Buffer = AllocatePool (Length);
|
||||
if (Buffer == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
//
|
||||
// To guarantee that the WorkingBlockValid is set on spare block
|
||||
//
|
||||
WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba;
|
||||
FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
|
||||
WORKING_BLOCK_VALID
|
||||
);
|
||||
//
|
||||
// Read from spare block to memory buffer
|
||||
//
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Read (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&Count,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
//
|
||||
// Clear the CRC and STATE, copy data from spare to working block.
|
||||
//
|
||||
WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (Buffer + (UINTN) WorkSpaceLbaOffset * FtwLiteDevice->SizeOfSpareBlock + FtwLiteDevice->FtwWorkSpaceBase);
|
||||
InitWorkSpaceHeader (WorkingBlockHeader);
|
||||
WorkingBlockHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
|
||||
WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
|
||||
|
||||
//
|
||||
// target block is working block, then
|
||||
// Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
|
||||
// before erase the working block.
|
||||
//
|
||||
// Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
|
||||
// WorkingBlockInvalid);
|
||||
// To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
|
||||
//
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
|
||||
WORKING_BLOCK_INVALID
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
|
||||
|
||||
//
|
||||
// Erase the working block
|
||||
//
|
||||
Status = FtwEraseBlock (
|
||||
FtwLiteDevice,
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkBlockLba
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Write memory buffer to working block, using the FvbBlock protocol interface
|
||||
//
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwFvBlock->Write (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkBlockLba + Index,
|
||||
0,
|
||||
&Count,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write block - %r\n", Status));
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
//
|
||||
// Since the memory buffer will not be used, free memory Buffer.
|
||||
//
|
||||
FreePool (Buffer);
|
||||
|
||||
//
|
||||
// Update the VALID of the working block
|
||||
//
|
||||
// Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
|
||||
// WorkingBlockValid);
|
||||
// Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc
|
||||
//
|
||||
Status = FtwUpdateFvState (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
|
||||
WORKING_BLOCK_VALID
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -0,0 +1,561 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2007, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
Module Name:
|
||||
|
||||
FtwWorkSpace.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include <FtwLite.h>
|
||||
|
||||
BOOLEAN
|
||||
IsValidWorkSpace (
|
||||
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Check to see if it is a valid work space.
|
||||
|
||||
Arguments:
|
||||
WorkingHeader - Pointer of working block header
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER WorkingBlockHeader;
|
||||
|
||||
ASSERT (WorkingHeader != NULL);
|
||||
if (WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) {
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// Check signature with gEfiSystemNvDataFvGuid
|
||||
//
|
||||
if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) {
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// Check the CRC of header
|
||||
//
|
||||
CopyMem (
|
||||
&WorkingBlockHeader,
|
||||
WorkingHeader,
|
||||
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
|
||||
);
|
||||
|
||||
//
|
||||
// Filter out the Crc and State fields
|
||||
//
|
||||
SetMem (
|
||||
&WorkingBlockHeader.Crc,
|
||||
sizeof (UINT32),
|
||||
FTW_ERASED_BYTE
|
||||
);
|
||||
WorkingBlockHeader.WorkingBlockValid = FTW_ERASE_POLARITY;
|
||||
WorkingBlockHeader.WorkingBlockInvalid = FTW_ERASE_POLARITY;
|
||||
|
||||
//
|
||||
// Calculate the Crc of woking block header
|
||||
//
|
||||
Status = gBS->CalculateCrc32 (
|
||||
(UINT8 *) &WorkingBlockHeader,
|
||||
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
|
||||
&WorkingBlockHeader.Crc
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
if (WorkingBlockHeader.Crc != WorkingHeader->Crc) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Work block header CRC check error\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
InitWorkSpaceHeader (
|
||||
IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Initialize a work space when there is no work space.
|
||||
|
||||
Arguments:
|
||||
WorkingHeader - Pointer of working block header
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT (WorkingHeader != NULL);
|
||||
|
||||
//
|
||||
// Here using gEfiSystemNvDataFvGuid as the signature.
|
||||
//
|
||||
CopyMem (
|
||||
&WorkingHeader->Signature,
|
||||
&gEfiSystemNvDataFvGuid,
|
||||
sizeof (EFI_GUID)
|
||||
);
|
||||
WorkingHeader->WriteQueueSize = FTW_WORKING_QUEUE_SIZE;
|
||||
|
||||
//
|
||||
// Crc is calculated with all the fields except Crc and STATE
|
||||
//
|
||||
WorkingHeader->WorkingBlockValid = FTW_ERASE_POLARITY;
|
||||
WorkingHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;
|
||||
SetMem (&WorkingHeader->Crc, sizeof (UINT32), FTW_ERASED_BYTE);
|
||||
|
||||
//
|
||||
// Calculate the CRC value
|
||||
//
|
||||
Status = gBS->CalculateCrc32 (
|
||||
(UINT8 *) WorkingHeader,
|
||||
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
|
||||
&WorkingHeader->Crc
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Restore the WorkingBlockValid flag to VALID state
|
||||
//
|
||||
WorkingHeader->WorkingBlockValid = FTW_VALID_STATE;
|
||||
WorkingHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FtwUpdateFvState (
|
||||
IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN Offset,
|
||||
IN UINT8 NewBit
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Update a bit of state on a block device. The location of the bit is
|
||||
calculated by the (Lba, Offset, bit). Here bit is determined by the
|
||||
the name of a certain bit.
|
||||
|
||||
Arguments:
|
||||
FvBlock - FVB Protocol interface to access SrcBlock and DestBlock
|
||||
Lba - Lba of a block
|
||||
Offset - Offset on the Lba
|
||||
NewBit - New value that will override the old value if it can be change
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - A state bit has been updated successfully
|
||||
Others - Access block device error.
|
||||
|
||||
Notes:
|
||||
Assume all bits of State are inside the same BYTE.
|
||||
|
||||
EFI_ABORTED - Read block fail
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 State;
|
||||
UINTN Length;
|
||||
|
||||
//
|
||||
// Read state from device, assume State is only one byte.
|
||||
//
|
||||
Length = sizeof (UINT8);
|
||||
Status = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
State ^= FTW_POLARITY_REVERT;
|
||||
State = (UINT8) (State | NewBit);
|
||||
State ^= FTW_POLARITY_REVERT;
|
||||
|
||||
//
|
||||
// Write state back to device
|
||||
//
|
||||
Length = sizeof (UINT8);
|
||||
Status = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FtwGetLastRecord (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
OUT EFI_FTW_LITE_RECORD **FtwLastRecord
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Get the last Write record pointer.
|
||||
The last record is the record whose 'complete' state hasn't been set.
|
||||
After all, this header may be a EMPTY header entry for next Allocate.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Private data of this driver
|
||||
FtwLastRecord - Pointer to retrieve the last write record
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Get the last write record successfully
|
||||
EFI_ABORTED - The FTW work space is damaged
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
|
||||
Record = (EFI_FTW_LITE_RECORD *) (FtwLiteDevice->FtwWorkSpaceHeader + 1);
|
||||
while (Record->WriteCompleted == FTW_VALID_STATE) {
|
||||
//
|
||||
// If Offset exceed the FTW work space boudary, return error.
|
||||
//
|
||||
if ((UINTN) ((UINT8 *) Record - FtwLiteDevice->FtwWorkSpace) > FtwLiteDevice->FtwWorkSpaceSize) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Record++;
|
||||
}
|
||||
//
|
||||
// Last write record is found
|
||||
//
|
||||
*FtwLastRecord = Record;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
WorkSpaceRefresh (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Read from working block to refresh the work space in memory.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Point to private data of FTW driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Length;
|
||||
UINTN Offset;
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
|
||||
//
|
||||
// Initialize WorkSpace as FTW_ERASED_BYTE
|
||||
//
|
||||
SetMem (
|
||||
FtwLiteDevice->FtwWorkSpace,
|
||||
FtwLiteDevice->FtwWorkSpaceSize,
|
||||
FTW_ERASED_BYTE
|
||||
);
|
||||
|
||||
//
|
||||
// Read from working block
|
||||
//
|
||||
Length = FtwLiteDevice->FtwWorkSpaceSize;
|
||||
Status = FtwLiteDevice->FtwFvBlock->Read (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->FtwWorkSpaceLba,
|
||||
FtwLiteDevice->FtwWorkSpaceBase,
|
||||
&Length,
|
||||
FtwLiteDevice->FtwWorkSpace
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Refresh the FtwLastRecord
|
||||
//
|
||||
Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);
|
||||
|
||||
Record = FtwLiteDevice->FtwLastRecord;
|
||||
Offset = (UINTN) (UINT8 *) Record - (UINTN) FtwLiteDevice->FtwWorkSpace;
|
||||
|
||||
//
|
||||
// IF work space has error or Record is out of the workspace limit, THEN
|
||||
// call reclaim.
|
||||
//
|
||||
if (EFI_ERROR (Status) || (Offset + WRITE_TOTAL_SIZE >= FtwLiteDevice->FtwWorkSpaceSize)) {
|
||||
//
|
||||
// reclaim work space in working block.
|
||||
//
|
||||
Status = FtwReclaimWorkSpace (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: Reclaim workspace - %r\n", Status));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
CleanupWorkSpace (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN OUT UINT8 *FtwSpaceBuffer,
|
||||
IN UINTN BufferSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Reclaim the work space. Get rid of all the completed write records
|
||||
and write records in the Fault Tolerant work space.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Point to private data of FTW driver
|
||||
FtwSpaceBuffer - Buffer to contain the reclaimed clean data
|
||||
BufferSize - Size of the FtwSpaceBuffer
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_BUFFER_TOO_SMALL - The FtwSpaceBuffer is too small
|
||||
EFI_ABORTED - The function could not complete successfully.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINTN Length;
|
||||
EFI_FTW_LITE_RECORD *Record;
|
||||
|
||||
//
|
||||
// To check if the buffer is large enough
|
||||
//
|
||||
Length = FtwLiteDevice->FtwWorkSpaceSize;
|
||||
if (BufferSize < Length) {
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
//
|
||||
// Clear the content of buffer that will save the new work space data
|
||||
//
|
||||
SetMem (FtwSpaceBuffer, Length, FTW_ERASED_BYTE);
|
||||
|
||||
//
|
||||
// Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer
|
||||
//
|
||||
CopyMem (
|
||||
FtwSpaceBuffer,
|
||||
FtwLiteDevice->FtwWorkSpaceHeader,
|
||||
sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
|
||||
);
|
||||
|
||||
//
|
||||
// Get the last record
|
||||
//
|
||||
Record = FtwLiteDevice->FtwLastRecord;
|
||||
if ((Record != NULL) && (Record->WriteAllocated == FTW_VALID_STATE) && (Record->WriteCompleted != FTW_VALID_STATE)) {
|
||||
CopyMem (
|
||||
(UINT8 *) FtwSpaceBuffer + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
|
||||
Record,
|
||||
WRITE_TOTAL_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FtwReclaimWorkSpace (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Reclaim the work space on the working block.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Point to private data of FTW driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *TempBuffer;
|
||||
UINTN TempBufferSize;
|
||||
UINT8 *Ptr;
|
||||
UINTN Length;
|
||||
UINTN Index;
|
||||
UINTN SpareBufferSize;
|
||||
UINT8 *SpareBuffer;
|
||||
EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
|
||||
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: start to reclaim work space\n"));
|
||||
|
||||
//
|
||||
// Read all original data from working block to a memory buffer
|
||||
//
|
||||
TempBufferSize = FtwLiteDevice->SpareAreaLength;
|
||||
TempBuffer = AllocateZeroPool (TempBufferSize);
|
||||
if (TempBuffer != NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ptr = TempBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Length = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwFvBlock->Read (
|
||||
FtwLiteDevice->FtwFvBlock,
|
||||
FtwLiteDevice->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 +
|
||||
((UINTN) (FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba)) *
|
||||
FtwLiteDevice->SizeOfSpareBlock + FtwLiteDevice->FtwWorkSpaceBase;
|
||||
|
||||
Status = CleanupWorkSpace (
|
||||
FtwLiteDevice,
|
||||
Ptr,
|
||||
FtwLiteDevice->FtwWorkSpaceSize
|
||||
);
|
||||
|
||||
CopyMem (
|
||||
FtwLiteDevice->FtwWorkSpace,
|
||||
Ptr,
|
||||
FtwLiteDevice->FtwWorkSpaceSize
|
||||
);
|
||||
|
||||
Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);
|
||||
|
||||
//
|
||||
// Set the WorkingBlockValid and WorkingBlockInvalid as INVALID
|
||||
//
|
||||
WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) Ptr;
|
||||
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 = FtwLiteDevice->SpareAreaLength;
|
||||
SpareBuffer = AllocatePool (SpareBufferSize);
|
||||
if (SpareBuffer == NULL) {
|
||||
FreePool (TempBuffer);
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Ptr = SpareBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Length = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Read (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->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 (FtwLiteDevice);
|
||||
Ptr = TempBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Length = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Write (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&Length,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (TempBuffer);
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += Length;
|
||||
}
|
||||
//
|
||||
// Free TempBuffer
|
||||
//
|
||||
FreePool (TempBuffer);
|
||||
|
||||
//
|
||||
// Write the spare block to working block
|
||||
//
|
||||
Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (SpareBuffer);
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
|
||||
//
|
||||
Status = FtwEraseSpareBlock (FtwLiteDevice);
|
||||
Ptr = SpareBuffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Length = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Write (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&Length,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (SpareBuffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
Ptr += Length;
|
||||
}
|
||||
|
||||
FreePool (SpareBuffer);
|
||||
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: reclaim work space success\n"));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -0,0 +1,403 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006 - 2007, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
Module Name:
|
||||
|
||||
Ia32FtwMisc.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Ia32 platform related code to support FtwLite..
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include <FtwLite.h>
|
||||
|
||||
//
|
||||
// MACROs for boot block update
|
||||
//
|
||||
#define BOOT_BLOCK_BASE 0xFFFF0000
|
||||
|
||||
//
|
||||
// (LPC -- D31:F0)
|
||||
//
|
||||
#define LPC_BUS_NUMBER 0x00
|
||||
#define LPC_DEVICE_NUMBER 0x1F
|
||||
#define LPC_IF 0xF0
|
||||
//
|
||||
// Top swap
|
||||
//
|
||||
#define GEN_STATUS 0xD4
|
||||
#define TOP_SWAP_BIT (1 << 13)
|
||||
|
||||
STATIC
|
||||
UINT32
|
||||
ReadPciRegister (
|
||||
IN UINT32 Offset
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Read PCI register value.
|
||||
|
||||
Arguments:
|
||||
|
||||
Offset - Offset of the register
|
||||
|
||||
Returns:
|
||||
|
||||
The value.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Value;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
||||
|
||||
Value = 0;
|
||||
Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status));
|
||||
return 0;
|
||||
}
|
||||
|
||||
Status = PciRootBridgeIo->Pci.Read (
|
||||
PciRootBridgeIo,
|
||||
EfiPciWidthUint32,
|
||||
EFI_PCI_ADDRESS (
|
||||
LPC_BUS_NUMBER,
|
||||
LPC_DEVICE_NUMBER,
|
||||
LPC_IF,
|
||||
Offset
|
||||
),
|
||||
1,
|
||||
&Value
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
GetSwapState (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
OUT BOOLEAN *SwapState
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get swap state
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
SwapState - Swap state
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - State successfully got
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Top swap status is 13 bit
|
||||
//
|
||||
*SwapState = (BOOLEAN) ((ReadPciRegister (GEN_STATUS) & TOP_SWAP_BIT) != 0);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SetSwapState (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN BOOLEAN TopSwap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Set swap state.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Indicates a pointer to the calling context.
|
||||
TopSwap - New swap state
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
|
||||
Note:
|
||||
the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
|
||||
software will not be able to clear the Top-Swap bit until the system is
|
||||
rebooted without GNT[A]# being pulled down.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT32 GenStatus;
|
||||
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Top-Swap bit (bit 13, D31: F0, Offset D4h)
|
||||
//
|
||||
GenStatus = ReadPciRegister (GEN_STATUS);
|
||||
|
||||
//
|
||||
// Set 13 bit, according to input NewSwapState
|
||||
//
|
||||
if (TopSwap) {
|
||||
GenStatus |= TOP_SWAP_BIT;
|
||||
} else {
|
||||
GenStatus &= ~TOP_SWAP_BIT;
|
||||
}
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status));
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Write back the GenStatus register
|
||||
//
|
||||
Status = PciRootBridgeIo->Pci.Write (
|
||||
PciRootBridgeIo,
|
||||
EfiPciWidthUint32,
|
||||
EFI_PCI_ADDRESS (
|
||||
LPC_BUS_NUMBER,
|
||||
LPC_DEVICE_NUMBER,
|
||||
LPC_IF,
|
||||
GEN_STATUS
|
||||
),
|
||||
1,
|
||||
&GenStatus
|
||||
);
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
if (TopSwap) {
|
||||
DEBUG ((EFI_D_ERROR, "SAR: Set top swap\n"));
|
||||
} else {
|
||||
DEBUG ((EFI_D_ERROR, "SAR: Clear top swap\n"));
|
||||
}
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Check whether the block is a boot block.
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - Fvb protocol instance
|
||||
Lba - Lba value
|
||||
|
||||
Returns:
|
||||
|
||||
Is a boot block or not
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
|
||||
|
||||
Status = GetFvbByAddress (BOOT_BLOCK_BASE, &BootFvb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// Compare the Fvb
|
||||
//
|
||||
return (BOOLEAN) (FvBlock == BootFvb);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Boot block is accessed by BootFvb protocol interface. LBA is 0.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to boot block
|
||||
EFI_INVALID_PARAMETER - Input parameter error
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
Notes:
|
||||
FTW will do extra work on boot block update.
|
||||
FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,
|
||||
which is produced by a chipset driver.
|
||||
|
||||
FTW updating boot block steps:
|
||||
1. Erase top swap block (0xFFFE-0xFFFEFFFF) and write data to it ready
|
||||
2. Read data from top swap block to memory buffer
|
||||
3. SetSwapState(EFI_SWAPPED)
|
||||
4. Erasing boot block (0xFFFF-0xFFFFFFFF)
|
||||
5. Programming boot block until the boot block is ok.
|
||||
6. SetSwapState(UNSWAPPED)
|
||||
|
||||
Notes:
|
||||
1. Since the SwapState bit is saved in CMOS, FTW can restore and continue
|
||||
even in the scenario of power failure.
|
||||
2. FTW shall not allow to update boot block when battery state is error.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Length;
|
||||
UINT8 *Buffer;
|
||||
UINTN Count;
|
||||
UINT8 *Ptr;
|
||||
UINTN Index;
|
||||
BOOLEAN TopSwap;
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
|
||||
EFI_LBA BootLba;
|
||||
|
||||
//
|
||||
// Allocate a memory buffer
|
||||
//
|
||||
Length = FtwLiteDevice->SpareAreaLength;
|
||||
Buffer = AllocatePool (Length);
|
||||
if (Buffer == NULL) {
|
||||
}
|
||||
//
|
||||
// Get TopSwap bit state
|
||||
//
|
||||
Status = GetSwapState (FtwLiteDevice, &TopSwap);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Get Top Swapped status - %r\n", Status));
|
||||
FreePool (Buffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
if (TopSwap) {
|
||||
//
|
||||
// Get FVB of current boot block
|
||||
//
|
||||
Status = GetFvbByAddress (FtwLiteDevice->SpareAreaAddress + FTW_BLOCK_SIZE, &BootFvb);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Read data from current boot block
|
||||
//
|
||||
BootLba = 0;
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = BootFvb->Read (
|
||||
BootFvb,
|
||||
BootLba + Index,
|
||||
0,
|
||||
&Count,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// Read data from spare block
|
||||
//
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Read (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&Count,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
//
|
||||
// Set TopSwap bit
|
||||
//
|
||||
Status = SetSwapState (FtwLiteDevice, TRUE);
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Set Swap State - %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
//
|
||||
// Erase boot block. After setting TopSwap bit, it's spare block now!
|
||||
//
|
||||
Status = FtwEraseSpareBlock (FtwLiteDevice);
|
||||
if (EFI_ERROR (Status)) {
|
||||
FreePool (Buffer);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
//
|
||||
// Write memory buffer to currenet spare block
|
||||
//
|
||||
Ptr = Buffer;
|
||||
for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {
|
||||
Count = FtwLiteDevice->SizeOfSpareBlock;
|
||||
Status = FtwLiteDevice->FtwBackupFvb->Write (
|
||||
FtwLiteDevice->FtwBackupFvb,
|
||||
FtwLiteDevice->FtwSpareLba + Index,
|
||||
0,
|
||||
&Count,
|
||||
Ptr
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write boot block - %r\n", Status));
|
||||
FreePool (Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Ptr += Count;
|
||||
}
|
||||
|
||||
FreePool (Buffer);
|
||||
|
||||
//
|
||||
// Clear TopSwap bit
|
||||
//
|
||||
Status = SetSwapState (FtwLiteDevice, FALSE);
|
||||
DEBUG ((EFI_D_ERROR, "FtwLite: Clear Swap State - %r\n", Status));
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
Module Name:
|
||||
|
||||
IpfFtwMisc.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Ipf platform related code to support FtwLite..
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include <FtwLite.h>
|
||||
|
||||
//
|
||||
// MACROs for boot block update
|
||||
//
|
||||
#define BOOT_BLOCK_BASE
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
GetSwapState (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
OUT BOOLEAN *SwapState
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get swap state
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
SwapState - Swap state
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - State successfully got
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SetSwapState (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN BOOLEAN TopSwap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Set swap state.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Indicates a pointer to the calling context.
|
||||
TopSwap - New swap state
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
|
||||
Note:
|
||||
the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
|
||||
software will not be able to clear the Top-Swap bit until the system is
|
||||
rebooted without GNT[A]# being pulled down.
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Check whether the block is a boot block.
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - Fvb protocol instance
|
||||
Lba - Lba value
|
||||
|
||||
Returns:
|
||||
|
||||
Is a boot block or not
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// IPF doesn't support safe bootblock update
|
||||
// so treat bootblock as normal block
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Boot block is accessed by BootFvb protocol interface. LBA is 0.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to boot block
|
||||
EFI_INVALID_PARAMETER - Input parameter error
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
@ -0,0 +1,140 @@
|
||||
|
||||
/*++
|
||||
|
||||
Copyright (c) 2006, Intel Corporation
|
||||
All rights reserved. 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
|
||||
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.
|
||||
|
||||
Module Name:
|
||||
|
||||
x64FtwMisc.c
|
||||
|
||||
Abstract:
|
||||
|
||||
X64 platform related code to support FtwLite..
|
||||
|
||||
Revision History
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include <FtwLite.h>
|
||||
|
||||
//
|
||||
// MACROs for boot block update
|
||||
//
|
||||
#define BOOT_BLOCK_BASE
|
||||
|
||||
// STATIC
|
||||
EFI_STATUS
|
||||
GetSwapState (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
OUT BOOLEAN *SwapState
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get swap state
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
SwapState - Swap state
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS - State successfully got
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// STATIC
|
||||
EFI_STATUS
|
||||
SetSwapState (
|
||||
IN EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
IN BOOLEAN TopSwap
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Set swap state.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - Indicates a pointer to the calling context.
|
||||
TopSwap - New swap state
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - The function completed successfully
|
||||
|
||||
Note:
|
||||
the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that
|
||||
software will not be able to clear the Top-Swap bit until the system is
|
||||
rebooted without GNT[A]# being pulled down.
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice,
|
||||
EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
|
||||
EFI_LBA Lba
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Check whether the block is a boot block.
|
||||
|
||||
Arguments:
|
||||
|
||||
FtwLiteDevice - Calling context
|
||||
FvBlock - Fvb protocol instance
|
||||
Lba - Lba value
|
||||
|
||||
Returns:
|
||||
|
||||
Is a boot block or not
|
||||
|
||||
--*/
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
FlushSpareBlockToBootBlock (
|
||||
EFI_FTW_LITE_DEVICE *FtwLiteDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
|
||||
Spare block is accessed by FTW backup FVB protocol interface. LBA is
|
||||
FtwLiteDevice->FtwSpareLba.
|
||||
Boot block is accessed by BootFvb protocol interface. LBA is 0.
|
||||
|
||||
Arguments:
|
||||
FtwLiteDevice - The private data of FTW_LITE driver
|
||||
|
||||
Returns:
|
||||
EFI_SUCCESS - Spare block content is copied to boot block
|
||||
EFI_INVALID_PARAMETER - Input parameter error
|
||||
EFI_OUT_OF_RESOURCES - Allocate memory error
|
||||
EFI_ABORTED - The function could not complete successfully
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
{
|
||||
return EFI_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user