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:
qhuang8
2007-06-27 14:52:40 +00:00
parent eb5f1a7fc7
commit d7dec593ea
40 changed files with 14183 additions and 3 deletions

View File

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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

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

View File

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

View File

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

View File

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

View File

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