diff options
Diffstat (limited to 'MdeModulePkg/Universal/FaultTolerantWriteDxe')
18 files changed, 0 insertions, 5662 deletions
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c deleted file mode 100644 index 7a6c377854..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c +++ /dev/null @@ -1,893 +0,0 @@ -/** @file
-
- These are the common Fault Tolerant Write (FTW) functions that are shared
- by DXE FTW driver and SMM FTW driver.
-
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "FaultTolerantWrite.h"
-
-//
-// Fault Tolerant Write Protocol API
-//
-/**
- Query the largest block that may be updated in a fault tolerant manner.
-
-
- @param This The pointer to this protocol instance.
- @param BlockSize A pointer to a caller allocated UINTN that is updated to
- indicate the size of the largest block that can be updated.
-
- @return EFI_SUCCESS The function completed successfully
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetMaxBlockSize (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT UINTN *BlockSize
- )
-{
- EFI_FTW_DEVICE *FtwDevice;
-
- if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {
- return EFI_UNSUPPORTED;
- }
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- *BlockSize = FtwDevice->SpareAreaLength;
-
- return EFI_SUCCESS;
-}
-
-/**
- Allocates space for the protocol to maintain information about writes.
- Since writes must be completed in a fault tolerant manner and multiple
- updates will require more resources to be successful, this function
- enables the protocol to ensure that enough space exists to track
- information about the upcoming writes.
-
- All writes must be completed or aborted before another fault tolerant write can occur.
-
- @param This The pointer to this protocol instance.
- @param CallerId The GUID identifying the write.
- @param PrivateDataSize The size of the caller's private data
- that must be recorded for each write.
- @param NumberOfWrites The number of fault tolerant block writes
- that will need to occur.
-
- @return EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_ACCESS_DENIED All allocated writes have not been completed.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAllocate (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_GUID *CallerId,
- IN UINTN PrivateDataSize,
- IN UINTN NumberOfWrites
- )
-{
- EFI_STATUS Status;
- UINTN Offset;
- EFI_FTW_DEVICE *FtwDevice;
- EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- Status = WorkSpaceRefresh (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- //
- // Check if there is enough space for the coming allocation
- //
- if (FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceHeader->WriteQueueSize) {
- DEBUG ((EFI_D_ERROR, "Ftw: Allocate() request exceed Workspace, Caller: %g\n", CallerId));
- return EFI_BUFFER_TOO_SMALL;
- }
- //
- // Find the last write header and record.
- // If the FtwHeader is complete, skip the completed last write header/records
- //
- FtwHeader = FtwDevice->FtwLastWriteHeader;
-
- //
- // Previous write has not completed, access denied.
- //
- if ((FtwHeader->HeaderAllocated == FTW_VALID_STATE) || (FtwHeader->WritesAllocated == FTW_VALID_STATE)) {
- return EFI_ACCESS_DENIED;
- }
- //
- // If workspace is not enough, then reclaim workspace
- //
- Offset = (UINT8 *) FtwHeader - (UINT8 *) FtwDevice->FtwWorkSpace;
- if (Offset + FTW_WRITE_TOTAL_SIZE (NumberOfWrites, PrivateDataSize) > FtwDevice->FtwWorkSpaceSize) {
- Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- FtwHeader = FtwDevice->FtwLastWriteHeader;
- }
- //
- // Prepare FTW write header,
- // overwrite the buffer and write to workspace.
- //
- FtwHeader->WritesAllocated = FTW_INVALID_STATE;
- FtwHeader->Complete = FTW_INVALID_STATE;
- CopyMem (&FtwHeader->CallerId, CallerId, sizeof (EFI_GUID));
- FtwHeader->NumberOfWrites = NumberOfWrites;
- FtwHeader->PrivateDataSize = PrivateDataSize;
- FtwHeader->HeaderAllocated = FTW_VALID_STATE;
-
- Status = WriteWorkSpaceData (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + Offset,
- sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER),
- (UINT8 *) FtwHeader
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- //
- // Update Header->WriteAllocated as VALID
- //
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + Offset,
- WRITES_ALLOCATED
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- DEBUG (
- (EFI_D_INFO,
- "Ftw: Allocate() success, Caller:%g, # %d\n",
- CallerId,
- NumberOfWrites)
- );
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Write a record with fault tolerant manner.
- Since the content has already backuped in spare block, the write is
- guaranteed to be completed with fault tolerant manner.
-
- @param This The pointer to this protocol instance.
- @param Fvb The FVB protocol that provides services for
- reading, writing, and erasing the target block.
- @param BlockSize The size of the block.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FtwWriteRecord (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb,
- IN UINTN BlockSize
- )
-{
- EFI_STATUS Status;
- EFI_FTW_DEVICE *FtwDevice;
- EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
- EFI_FAULT_TOLERANT_WRITE_RECORD *Record;
- UINTN Offset;
- UINTN NumberOfWriteBlocks;
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- //
- // Spare Complete but Destination not complete,
- // Recover the target block with the spare block.
- //
- Header = FtwDevice->FtwLastWriteHeader;
- Record = FtwDevice->FtwLastWriteRecord;
-
- //
- // IF target block is working block, THEN Flush Spare Block To Working Block;
- // ELSE flush spare block to target block, which may be boot block after all.
- //
- if (IsWorkingBlock (FtwDevice, Fvb, Record->Lba)) {
- //
- // If target block is working block,
- // it also need to set SPARE_COMPLETED to spare block.
- //
- Offset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
- Status = FtwUpdateFvState (
- FtwDevice->FtwBackupFvb,
- FtwDevice->SpareBlockSize,
- FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
- FtwDevice->FtwWorkSpaceBaseInSpare + Offset,
- SPARE_COMPLETED
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- Status = FlushSpareBlockToWorkingBlock (FtwDevice);
- } else if (IsBootBlock (FtwDevice, Fvb)) {
- //
- // Update boot block
- //
- Status = FlushSpareBlockToBootBlock (FtwDevice);
- } else {
- //
- // Update blocks other than working block or boot block
- //
- NumberOfWriteBlocks = FTW_BLOCKS ((UINTN) (Record->Offset + Record->Length), BlockSize);
- Status = FlushSpareBlockToTargetBlock (FtwDevice, Fvb, Record->Lba, BlockSize, NumberOfWriteBlocks);
- }
-
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- //
- // Record the DestionationComplete in record
- //
- Offset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + Offset,
- DEST_COMPLETED
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- Record->DestinationComplete = FTW_VALID_STATE;
-
- //
- // If this is the last Write in these write sequence,
- // set the complete flag of write header.
- //
- if (IsLastRecordOfWrites (Header, Record)) {
- Offset = (UINT8 *) Header - FtwDevice->FtwWorkSpace;
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + Offset,
- WRITES_COMPLETED
- );
- Header->Complete = FTW_VALID_STATE;
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- 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.
-
- @param This The pointer to this protocol instance.
- @param Lba The logical block address of the target block.
- @param Offset The offset within the target block to place the data.
- @param Length The number of bytes to write to the target block.
- @param PrivateData A pointer to private data that the caller requires to
- complete any pending writes in the event of a fault.
- @param FvBlockHandle The handle of FVB protocol that provides services for
- reading, writing, and erasing the target block.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_BAD_BUFFER_SIZE The input data can't fit within the spare block.
- Offset + *NumBytes > SpareAreaLength.
- @retval EFI_ACCESS_DENIED No writes have been allocated.
- @retval EFI_OUT_OF_RESOURCES Cannot allocate enough memory resource.
- @retval EFI_NOT_FOUND Cannot find FVB protocol by handle.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- IN VOID *PrivateData,
- IN EFI_HANDLE FvBlockHandle,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- EFI_FTW_DEVICE *FtwDevice;
- EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
- EFI_FAULT_TOLERANT_WRITE_RECORD *Record;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
- UINTN MyLength;
- UINTN MyOffset;
- UINTN MyBufferSize;
- UINT8 *MyBuffer;
- UINTN SpareBufferSize;
- UINT8 *SpareBuffer;
- UINTN Index;
- UINT8 *Ptr;
- EFI_PHYSICAL_ADDRESS FvbPhysicalAddress;
- UINTN BlockSize;
- UINTN NumberOfBlocks;
- UINTN NumberOfWriteBlocks;
- UINTN WriteLength;
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- Status = WorkSpaceRefresh (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- Header = FtwDevice->FtwLastWriteHeader;
- Record = FtwDevice->FtwLastWriteRecord;
-
- if (IsErasedFlashBuffer ((UINT8 *) Header, sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER))) {
- if (PrivateData == NULL) {
- //
- // Ftw Write Header is not allocated.
- // No additional private data, the private data size is zero. Number of record can be set to 1.
- //
- Status = FtwAllocate (This, &gEfiCallerIdGuid, 0, 1);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- } else {
- //
- // Ftw Write Header is not allocated
- // Additional private data is not NULL, the private data size can't be determined.
- //
- DEBUG ((EFI_D_ERROR, "Ftw: no allocates space for write record!\n"));
- DEBUG ((EFI_D_ERROR, "Ftw: Allocate service should be called before Write service!\n"));
- return EFI_NOT_READY;
- }
- }
-
- //
- // If Record is out of the range of Header, return access denied.
- //
- if (((UINTN)((UINT8 *) Record - (UINT8 *) Header)) > FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites - 1, Header->PrivateDataSize)) {
- return EFI_ACCESS_DENIED;
- }
-
- //
- // Check the COMPLETE flag of last write header
- //
- if (Header->Complete == FTW_VALID_STATE) {
- return EFI_ACCESS_DENIED;
- }
-
- if (Record->DestinationComplete == FTW_VALID_STATE) {
- return EFI_ACCESS_DENIED;
- }
-
- if ((Record->SpareComplete == FTW_VALID_STATE) && (Record->DestinationComplete != FTW_VALID_STATE)) {
- return EFI_NOT_READY;
- }
-
- //
- // Get the FVB protocol by handle
- //
- Status = FtwGetFvbByHandle (FvBlockHandle, &Fvb);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Write(), Get FVB physical address - %r\n", Status));
- return EFI_ABORTED;
- }
-
- //
- // Now, one FVB has one type of BlockSize.
- //
- Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Write(), Get block size - %r\n", Status));
- return EFI_ABORTED;
- }
-
- NumberOfWriteBlocks = FTW_BLOCKS (Offset + Length, BlockSize);
- DEBUG ((EFI_D_INFO, "Ftw: Write(), BlockSize - 0x%x, NumberOfWriteBlock - 0x%x\n", BlockSize, NumberOfWriteBlocks));
- WriteLength = NumberOfWriteBlocks * BlockSize;
-
- //
- // Check if the input data can fit within the spare block.
- //
- if (WriteLength > FtwDevice->SpareAreaLength) {
- return EFI_BAD_BUFFER_SIZE;
- }
-
- //
- // Set BootBlockUpdate FLAG if it's updating boot block.
- //
- if (IsBootBlock (FtwDevice, Fvb)) {
- Record->BootBlockUpdate = FTW_VALID_STATE;
- //
- // Boot Block and Spare Block should have same block size and block numbers.
- //
- ASSERT ((BlockSize == FtwDevice->SpareBlockSize) && (NumberOfWriteBlocks == FtwDevice->NumberOfSpareBlock));
- }
- //
- // Write the record to the work space.
- //
- Record->Lba = Lba;
- Record->Offset = Offset;
- Record->Length = Length;
- Record->RelativeOffset = (INT64) (FvbPhysicalAddress + (UINTN) Lba * BlockSize) - (INT64) FtwDevice->SpareAreaAddress;
- if (PrivateData != NULL) {
- CopyMem ((Record + 1), PrivateData, (UINTN) Header->PrivateDataSize);
- }
-
- MyOffset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
- MyLength = FTW_RECORD_SIZE (Header->PrivateDataSize);
-
- Status = WriteWorkSpaceData (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + MyOffset,
- MyLength,
- (UINT8 *) Record
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- //
- // Record has written to working block, then do the data.
- //
- //
- // Allocate a memory buffer
- //
- MyBufferSize = WriteLength;
- MyBuffer = AllocatePool (MyBufferSize);
- if (MyBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Read all original data from target block to memory buffer
- //
- Ptr = MyBuffer;
- for (Index = 0; Index < NumberOfWriteBlocks; Index += 1) {
- MyLength = BlockSize;
- 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, Length);
-
- //
- // Try to keep the content of spare block
- // Save spare block into a spare backup memory buffer (Sparebuffer)
- //
- SpareBufferSize = FtwDevice->SpareAreaLength;
- SpareBuffer = AllocatePool (SpareBufferSize);
- if (SpareBuffer == NULL) {
- FreePool (MyBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
-
- Ptr = SpareBuffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- MyLength = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Read (
- FtwDevice->FtwBackupFvb,
- FtwDevice->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
- // Do not assume Spare Block and Target Block have same block size
- //
- Status = FtwEraseSpareBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- FreePool (MyBuffer);
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
- Ptr = MyBuffer;
- for (Index = 0; MyBufferSize > 0; Index += 1) {
- if (MyBufferSize > FtwDevice->SpareBlockSize) {
- MyLength = FtwDevice->SpareBlockSize;
- } else {
- MyLength = MyBufferSize;
- }
- Status = FtwDevice->FtwBackupFvb->Write (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &MyLength,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (MyBuffer);
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- Ptr += MyLength;
- MyBufferSize -= MyLength;
- }
- //
- // Free MyBuffer
- //
- FreePool (MyBuffer);
-
- //
- // Set the SpareComplete in the FTW record,
- //
- MyOffset = (UINT8 *) Record - FtwDevice->FtwWorkSpace;
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + MyOffset,
- SPARE_COMPLETED
- );
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- Record->SpareComplete = 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 (This, Fvb, BlockSize);
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
- //
- // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
- //
- Status = FtwEraseSpareBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
- Ptr = SpareBuffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- MyLength = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Write (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &MyLength,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- Ptr += MyLength;
- }
- //
- // All success.
- //
- FreePool (SpareBuffer);
-
- DEBUG (
- (EFI_D_INFO,
- "Ftw: Write() success, (Lba:Offset)=(%lx:0x%x), Length: 0x%x\n",
- Lba,
- Offset,
- Length)
- );
-
- return EFI_SUCCESS;
-}
-
-/**
- Restarts a previously interrupted write. The caller must provide the
- block protocol needed to complete the interrupted write.
-
- @param This The pointer to this protocol instance.
- @param FvBlockHandle The handle of FVB protocol that provides services for
- reading, writing, and erasing the target block.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ACCESS_DENIED No pending writes exist
- @retval EFI_NOT_FOUND FVB protocol not found by the handle
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-EFIAPI
-FtwRestart (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_HANDLE FvBlockHandle
- )
-{
- EFI_STATUS Status;
- EFI_FTW_DEVICE *FtwDevice;
- EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
- EFI_FAULT_TOLERANT_WRITE_RECORD *Record;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
- UINTN BlockSize;
- UINTN NumberOfBlocks;
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- Status = WorkSpaceRefresh (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- Header = FtwDevice->FtwLastWriteHeader;
- Record = FtwDevice->FtwLastWriteRecord;
-
- //
- // Spare Complete but Destination not complete,
- // Recover the targt block with the spare block.
- //
- Status = FtwGetFvbByHandle (FvBlockHandle, &Fvb);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Now, one FVB has one type of BlockSize
- //
- Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Restart(), Get block size - %r\n", Status));
- return EFI_ABORTED;
- }
-
- //
- // Check the COMPLETE flag of last write header
- //
- if (Header->Complete == FTW_VALID_STATE) {
- return EFI_ACCESS_DENIED;
- }
-
- //
- // Check the flags of last write record
- //
- if (Record->DestinationComplete == FTW_VALID_STATE) {
- return EFI_ACCESS_DENIED;
- }
-
- if ((Record->SpareComplete != FTW_VALID_STATE)) {
- return EFI_ABORTED;
- }
-
- //
- // Since the content has already backuped in spare block, the write is
- // guaranteed to be completed with fault tolerant manner.
- //
- Status = FtwWriteRecord (This, Fvb, BlockSize);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- //
- // Erase Spare block
- // This is restart, no need to keep spareblock content.
- //
- Status = FtwEraseSpareBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- DEBUG ((EFI_D_ERROR, "Ftw: Restart() success \n"));
- return EFI_SUCCESS;
-}
-
-/**
- Aborts all previous allocated writes.
-
- @param This The pointer to this protocol instance.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_NOT_FOUND No allocated writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAbort (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- UINTN Offset;
- EFI_FTW_DEVICE *FtwDevice;
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- Status = WorkSpaceRefresh (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- if (FtwDevice->FtwLastWriteHeader->HeaderAllocated != FTW_VALID_STATE) {
- return EFI_NOT_FOUND;
- }
-
- if (FtwDevice->FtwLastWriteHeader->Complete == FTW_VALID_STATE) {
- return EFI_NOT_FOUND;
- }
- //
- // Update the complete state of the header as VALID and abort.
- //
- Offset = (UINT8 *) FtwDevice->FtwLastWriteHeader - FtwDevice->FtwWorkSpace;
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + Offset,
- WRITES_COMPLETED
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- FtwDevice->FtwLastWriteHeader->Complete = FTW_VALID_STATE;
-
- DEBUG ((EFI_D_ERROR, "Ftw: Abort() success \n"));
- return EFI_SUCCESS;
-}
-
-/**
- Starts a target block update. This records information about the 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.
-
- @param This The pointer to this protocol instance.
- @param CallerId The GUID identifying the last write.
- @param Lba The logical block address of the last write.
- @param Offset The offset within the block of the last write.
- @param Length The length of the last write.
- @param PrivateDataSize bytes from the private data
- stored for this write.
- @param PrivateData A pointer to a buffer. The function will copy
- @param Complete A Boolean value with TRUE indicating
- that the write was completed.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully
- @retval EFI_NOT_FOUND No allocated writes exist
- @retval EFI_BUFFER_TOO_SMALL Input buffer is not larget enough
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetLastWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT EFI_GUID *CallerId,
- OUT EFI_LBA *Lba,
- OUT UINTN *Offset,
- OUT UINTN *Length,
- IN OUT UINTN *PrivateDataSize,
- OUT VOID *PrivateData,
- OUT BOOLEAN *Complete
- )
-{
- EFI_STATUS Status;
- EFI_FTW_DEVICE *FtwDevice;
- EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
- EFI_FAULT_TOLERANT_WRITE_RECORD *Record;
-
- if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {
- return EFI_UNSUPPORTED;
- }
-
- FtwDevice = FTW_CONTEXT_FROM_THIS (This);
-
- Status = WorkSpaceRefresh (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- Header = FtwDevice->FtwLastWriteHeader;
- Record = FtwDevice->FtwLastWriteRecord;
-
- //
- // If Header is incompleted and the last record has completed, then
- // call Abort() to set the Header->Complete FLAG.
- //
- if ((Header->Complete != FTW_VALID_STATE) &&
- (Record->DestinationComplete == FTW_VALID_STATE) &&
- IsLastRecordOfWrites (Header, Record)
- ) {
-
- Status = FtwAbort (This);
- *Complete = TRUE;
- return EFI_NOT_FOUND;
- }
- //
- // If there is no write header/record, return not found.
- //
- if (Header->HeaderAllocated != FTW_VALID_STATE) {
- *Complete = TRUE;
- return EFI_NOT_FOUND;
- }
- //
- // If this record SpareComplete has not set, then it can not restart.
- //
- if (Record->SpareComplete != FTW_VALID_STATE) {
- Status = GetPreviousRecordOfWrites (Header, &Record);
- if (EFI_ERROR (Status)) {
- FtwAbort (This);
- *Complete = TRUE;
- return EFI_NOT_FOUND;
- }
- ASSERT (Record != NULL);
- }
-
- //
- // Fill all the requested values
- //
- CopyMem (CallerId, &Header->CallerId, sizeof (EFI_GUID));
- *Lba = Record->Lba;
- *Offset = (UINTN) Record->Offset;
- *Length = (UINTN) Record->Length;
- *Complete = (BOOLEAN) (Record->DestinationComplete == FTW_VALID_STATE);
-
- if (*PrivateDataSize < Header->PrivateDataSize) {
- *PrivateDataSize = (UINTN) Header->PrivateDataSize;
- PrivateData = NULL;
- Status = EFI_BUFFER_TOO_SMALL;
- } else {
- *PrivateDataSize = (UINTN) Header->PrivateDataSize;
- CopyMem (PrivateData, Record + 1, *PrivateDataSize);
- Status = EFI_SUCCESS;
- }
-
- DEBUG ((EFI_D_ERROR, "Ftw: GetLasetWrite() success\n"));
-
- return Status;
-}
-
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h deleted file mode 100644 index 849d1f4233..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.h +++ /dev/null @@ -1,769 +0,0 @@ -/** @file
-
- The internal header file includes the common header files, defines
- internal structure and functions used by Ftw module.
-
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-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.
-
-**/
-
-#ifndef _EFI_FAULT_TOLERANT_WRITE_H_
-#define _EFI_FAULT_TOLERANT_WRITE_H_
-
-#include <PiDxe.h>
-
-#include <Guid/SystemNvDataGuid.h>
-#include <Guid/ZeroGuid.h>
-#include <Protocol/FaultTolerantWrite.h>
-#include <Protocol/FirmwareVolumeBlock.h>
-#include <Protocol/SwapAddressRange.h>
-
-#include <Library/PcdLib.h>
-#include <Library/DebugLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/ReportStatusCodeLib.h>
-
-//
-// Flash erase polarity is 1
-//
-#define FTW_ERASE_POLARITY 1
-
-#define FTW_ERASED_BYTE ((UINT8) (255))
-#define FTW_POLARITY_REVERT ((UINT8) (255))
-
-#define HEADER_ALLOCATED 0x1
-#define WRITES_ALLOCATED 0x2
-#define WRITES_COMPLETED 0x4
-
-#define BOOT_BLOCK_UPDATE 0x1
-#define SPARE_COMPLETED 0x2
-#define DEST_COMPLETED 0x4
-
-#define FTW_BLOCKS(Length, BlockSize) ((UINTN) ((Length) / (BlockSize) + (((Length) & ((BlockSize) - 1)) ? 1 : 0)))
-
-#define FTW_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'T', 'W', 'D')
-
-//
-// EFI Fault tolerant protocol private data structure
-//
-typedef struct {
- UINTN Signature;
- EFI_HANDLE Handle;
- EFI_FAULT_TOLERANT_WRITE_PROTOCOL FtwInstance;
- EFI_PHYSICAL_ADDRESS WorkSpaceAddress; // Base address of working space range in flash.
- EFI_PHYSICAL_ADDRESS SpareAreaAddress; // Base address of spare range in flash.
- UINTN WorkSpaceLength; // Size of working space range in flash.
- UINTN NumberOfWorkSpaceBlock; // Number of the blocks in work block for work space.
- UINTN WorkBlockSize; // Block size in bytes of the work blocks in flash
- UINTN SpareAreaLength; // Size of spare range in flash.
- UINTN NumberOfSpareBlock; // Number of the blocks in spare block.
- UINTN SpareBlockSize; // Block size in bytes of the spare blocks in flash
- EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader;// Pointer to Working Space Header in memory buffer
- EFI_FAULT_TOLERANT_WRITE_HEADER *FtwLastWriteHeader;// Pointer to last record header in memory buffer
- EFI_FAULT_TOLERANT_WRITE_RECORD *FtwLastWriteRecord;// Pointer to last record in memory buffer
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwFvBlock; // FVB of working block
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwBackupFvb; // FVB of spare block
- EFI_LBA FtwSpareLba; // Start LBA of spare block
- EFI_LBA FtwWorkBlockLba; // Start LBA of working block that contains working space in its last block.
- UINTN NumberOfWorkBlock; // Number of the blocks in work block.
- EFI_LBA FtwWorkSpaceLba; // Start LBA of working space
- UINTN FtwWorkSpaceBase; // Offset into the FtwWorkSpaceLba block.
- UINTN FtwWorkSpaceSize; // Size of working space range that stores write record.
- EFI_LBA FtwWorkSpaceLbaInSpare; // Start LBA of working space in spare block.
- UINTN FtwWorkSpaceBaseInSpare;// Offset into the FtwWorkSpaceLbaInSpare block.
- UINT8 *FtwWorkSpace; // Point to Work Space in memory buffer
- //
- // Following a buffer of FtwWorkSpace[FTW_WORK_SPACE_SIZE],
- // Allocated with EFI_FTW_DEVICE.
- //
-} EFI_FTW_DEVICE;
-
-#define FTW_CONTEXT_FROM_THIS(a) CR (a, EFI_FTW_DEVICE, FtwInstance, FTW_DEVICE_SIGNATURE)
-
-//
-// Driver entry point
-//
-/**
- This function is the entry point of the Fault Tolerant Write driver.
-
- @param ImageHandle A handle for the image that is initializing this driver
- @param SystemTable A pointer to the EFI system table
-
- @return EFI_SUCCESS FTW has finished the initialization
- @retval EFI_NOT_FOUND Locate FVB protocol error
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_VOLUME_CORRUPTED Firmware volume is error
- @retval EFI_ABORTED FTW initialization error
-
-**/
-EFI_STATUS
-EFIAPI
-InitializeFaultTolerantWrite (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- );
-
-//
-// Fault Tolerant Write Protocol API
-//
-
-/**
- Query the largest block that may be updated in a fault tolerant manner.
-
-
- @param This Indicates a pointer to the calling context.
- @param BlockSize A pointer to a caller allocated UINTN that is updated to
- indicate the size of the largest block that can be updated.
-
- @return EFI_SUCCESS The function completed successfully
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetMaxBlockSize (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT UINTN *BlockSize
- );
-
-/**
- Allocates space for the protocol to maintain information about writes.
- Since writes must be completed in a fault tolerant manner and multiple
- updates will require more resources to be successful, this function
- enables the protocol to ensure that enough space exists to track
- information about the upcoming writes.
-
- All writes must be completed or aborted before another fault tolerant write can occur.
-
- @param This Indicates a pointer to the calling context.
- @param CallerId The GUID identifying the write.
- @param PrivateDataSize The size of the caller's private data
- that must be recorded for each write.
- @param NumberOfWrites The number of fault tolerant block writes
- that will need to occur.
-
- @return EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_ACCESS_DENIED All allocated writes have not been completed.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAllocate (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_GUID *CallerId,
- IN UINTN PrivateDataSize,
- IN UINTN NumberOfWrites
- );
-
-/**
- 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.
-
-
- @param This Calling context
- @param Lba The logical block address of the target block.
- @param Offset The offset within the target block to place the data.
- @param Length The number of bytes to write to the target block.
- @param PrivateData A pointer to private data that the caller requires to
- complete any pending writes in the event of a fault.
- @param FvBlockHandle The handle of FVB protocol that provides services for
- reading, writing, and erasing the target block.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_BAD_BUFFER_SIZE The input data can't fit within the spare block.
- Offset + *NumBytes > SpareAreaLength.
- @retval EFI_ACCESS_DENIED No writes have been allocated.
- @retval EFI_OUT_OF_RESOURCES Cannot allocate enough memory resource.
- @retval EFI_NOT_FOUND Cannot find FVB protocol by handle.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- IN VOID *PrivateData,
- IN EFI_HANDLE FvBlockHandle,
- IN VOID *Buffer
- );
-
-/**
- Restarts a previously interrupted write. The caller must provide the
- block protocol needed to complete the interrupted write.
-
- @param This Calling context.
- @param FvBlockHandle The handle of FVB protocol that provides services for
- reading, writing, and erasing the target block.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ACCESS_DENIED No pending writes exist
- @retval EFI_NOT_FOUND FVB protocol not found by the handle
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-EFIAPI
-FtwRestart (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_HANDLE FvBlockHandle
- );
-
-/**
- Aborts all previous allocated writes.
-
- @param This Calling context
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_NOT_FOUND No allocated writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAbort (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This
- );
-
-/**
- Starts a target block update. This records information about the 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.
-
- @param This Indicates a pointer to the calling context.
- @param CallerId The GUID identifying the last write.
- @param Lba The logical block address of the last write.
- @param Offset The offset within the block of the last write.
- @param Length The length of the last write.
- @param PrivateDataSize bytes from the private data
- stored for this write.
- @param PrivateData A pointer to a buffer. The function will copy
- @param Complete A Boolean value with TRUE indicating
- that the write was completed.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully
- @retval EFI_NOT_FOUND No allocated writes exist
- @retval EFI_BUFFER_TOO_SMALL Input buffer is not larget enough
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetLastWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT EFI_GUID *CallerId,
- OUT EFI_LBA *Lba,
- OUT UINTN *Offset,
- OUT UINTN *Length,
- IN OUT UINTN *PrivateDataSize,
- OUT VOID *PrivateData,
- OUT BOOLEAN *Complete
- );
-
-/**
- Erase spare block.
-
- @param FtwDevice The private data of FTW driver
-
- @retval EFI_SUCCESS The erase request was successfully completed.
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
- @retval EFI_DEVICE_ERROR The block device is not functioning
- correctly and could not be written.
- The firmware device may have been
- partially erased.
- @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
- in the variable argument list do
- not exist in the firmware volume.
-
-
-**/
-EFI_STATUS
-FtwEraseSpareBlock (
- IN EFI_FTW_DEVICE *FtwDevice
- );
-
-/**
- Retrive the proper FVB protocol interface by HANDLE.
-
-
- @param FvBlockHandle The handle of FVB protocol that provides services for
- reading, writing, and erasing the target block.
- @param FvBlock The interface of FVB protocol
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FtwGetFvbByHandle (
- IN EFI_HANDLE FvBlockHandle,
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
- );
-
-/**
-
- Is it in working block?
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock Fvb protocol instance
- @param Lba The block specified
-
- @return A BOOLEAN value indicating in working block or not.
-
-**/
-BOOLEAN
-IsWorkingBlock (
- EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- EFI_LBA Lba
- );
-
-/**
-
- Is it in boot block?
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock Fvb protocol instance
-
- @return A BOOLEAN value indicating in boot block or not.
-
-**/
-BOOLEAN
-IsBootBlock (
- EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock
- );
-
-/**
- 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.
- Target block is accessed by FvBlock protocol interface.
-
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock FVB Protocol interface to access target block
- @param Lba Lba of the target block
- @param BlockSize The size of the block
- @param NumberOfBlocks The number of consecutive blocks starting with Lba
-
- @retval EFI_SUCCESS Spare block content is copied to target block
- @retval EFI_INVALID_PARAMETER Input parameter error
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FlushSpareBlockToTargetBlock (
- EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- EFI_LBA Lba,
- UINTN BlockSize,
- UINTN NumberOfBlocks
- );
-
-/**
- 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
- FtwDevice->FtwSpareLba.
- Working block is accessed by FTW working FVB protocol interface. LBA is
- FtwDevice->FtwWorkBlockLba.
-
- 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.
-
- @param FtwDevice The private data of FTW driver
-
- @retval EFI_SUCCESS Spare block content is copied to target block
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FlushSpareBlockToWorkingBlock (
- EFI_FTW_DEVICE *FtwDevice
- );
-
-/**
- Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
- Spare block is accessed by FTW working FVB protocol interface.
- Target block is accessed by FvBlock protocol interface.
-
- 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 may be:
- 1. GetRangeLocation(), if the Range is inside the boot block, FTW know
- that boot block will be update. It shall add a FLAG in the working block.
- 2. When spare block is ready,
- 3. SetSwapState(SWAPPED)
- 4. erasing boot block,
- 5. programming boot block until the boot block is ok.
- 6. SetSwapState(UNSWAPPED)
- FTW shall not allow to update boot block when battery state is error.
-
- @param FtwDevice The private data of FTW driver
-
- @retval EFI_SUCCESS Spare block content is copied to boot block
- @retval EFI_INVALID_PARAMETER Input parameter error
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FlushSpareBlockToBootBlock (
- EFI_FTW_DEVICE *FtwDevice
- );
-
-/**
- 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.
-
-
- @param FvBlock FVB Protocol interface to access SrcBlock and DestBlock
- @param BlockSize The size of the block
- @param Lba Lba of a block
- @param Offset Offset on the Lba
- @param NewBit New value that will override the old value if it can be change
-
- @retval EFI_SUCCESS A state bit has been updated successfully
- @retval Others Access block device error.
- Notes:
- Assume all bits of State are inside the same BYTE.
- @retval EFI_ABORTED Read block fail
-
-**/
-EFI_STATUS
-FtwUpdateFvState (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- IN UINTN BlockSize,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINT8 NewBit
- );
-
-/**
- Get the last Write Header pointer.
- The last write header is the header whose 'complete' state hasn't been set.
- After all, this header may be a EMPTY header entry for next Allocate.
-
-
- @param FtwWorkSpaceHeader Pointer of the working block header
- @param FtwWorkSpaceSize Size of the work space
- @param FtwWriteHeader Pointer to retrieve the last write header
-
- @retval EFI_SUCCESS Get the last write record successfully
- @retval EFI_ABORTED The FTW work space is damaged
-
-**/
-EFI_STATUS
-FtwGetLastWriteHeader (
- IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader,
- IN UINTN FtwWorkSpaceSize,
- OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader
- );
-
-/**
- Get the last Write Record pointer. The last write Record is the Record
- whose DestinationCompleted state hasn't been set. After all, this Record
- may be a EMPTY record entry for next write.
-
-
- @param FtwWriteHeader Pointer to the write record header
- @param FtwWriteRecord Pointer to retrieve the last write record
-
- @retval EFI_SUCCESS Get the last write record successfully
- @retval EFI_ABORTED The FTW work space is damaged
-
-**/
-EFI_STATUS
-FtwGetLastWriteRecord (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader,
- OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord
- );
-
-/**
- To check if FtwRecord is the first record of FtwHeader.
-
- @param FtwHeader Pointer to the write record header
- @param FtwRecord Pointer to the write record
-
- @retval TRUE FtwRecord is the first Record of the FtwHeader
- @retval FALSE FtwRecord is not the first Record of the FtwHeader
-
-**/
-BOOLEAN
-IsFirstRecordOfWrites (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
- IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord
- );
-
-/**
- To check if FtwRecord is the last record of FtwHeader. Because the
- FtwHeader has NumberOfWrites & PrivateDataSize, the FtwRecord can be
- determined if it is the last record of FtwHeader.
-
- @param FtwHeader Pointer to the write record header
- @param FtwRecord Pointer to the write record
-
- @retval TRUE FtwRecord is the last Record of the FtwHeader
- @retval FALSE FtwRecord is not the last Record of the FtwHeader
-
-**/
-BOOLEAN
-IsLastRecordOfWrites (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
- IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord
- );
-
-/**
- To check if FtwRecord is the first record of FtwHeader.
-
- @param FtwHeader Pointer to the write record header
- @param FtwRecord Pointer to retrieve the previous write record
-
- @retval EFI_ACCESS_DENIED Input record is the first record, no previous record is return.
- @retval EFI_SUCCESS The previous write record is found.
-
-**/
-EFI_STATUS
-GetPreviousRecordOfWrites (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
- IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwRecord
- );
-
-/**
-
- Check whether a flash buffer is erased.
-
- @param Buffer Buffer to check
- @param BufferSize Size of the buffer
-
- @return A BOOLEAN value indicating erased or not.
-
-**/
-BOOLEAN
-IsErasedFlashBuffer (
- IN UINT8 *Buffer,
- IN UINTN BufferSize
- );
-/**
- Initialize a work space when there is no work space.
-
- @param WorkingHeader Pointer of working block header
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-InitWorkSpaceHeader (
- IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
- );
-/**
- Read from working block to refresh the work space in memory.
-
- @param FtwDevice Point to private data of FTW driver
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-WorkSpaceRefresh (
- IN EFI_FTW_DEVICE *FtwDevice
- );
-/**
- Check to see if it is a valid work space.
-
-
- @param WorkingHeader Pointer of working block header
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-BOOLEAN
-IsValidWorkSpace (
- IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
- );
-/**
- Reclaim the work space on the working block.
-
- @param FtwDevice Point to private data of FTW driver
- @param PreserveRecord Whether to preserve the working record is needed
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FtwReclaimWorkSpace (
- IN EFI_FTW_DEVICE *FtwDevice,
- IN BOOLEAN PreserveRecord
- );
-
-/**
-
- Get firmware volume block by address.
-
-
- @param Address Address specified the block
- @param FvBlock The block caller wanted
-
- @retval EFI_SUCCESS The protocol instance if found.
- @retval EFI_NOT_FOUND Block not found
-
-**/
-EFI_HANDLE
-GetFvbByAddress (
- IN EFI_PHYSICAL_ADDRESS Address,
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
- );
-
-/**
- Retrive the proper Swap Address Range protocol interface.
-
- @param[out] SarProtocol The interface of SAR protocol
-
- @retval EFI_SUCCESS The SAR protocol instance was found and returned in SarProtocol.
- @retval EFI_NOT_FOUND The SAR protocol instance was not found.
- @retval EFI_INVALID_PARAMETER SarProtocol is NULL.
-
-**/
-EFI_STATUS
-FtwGetSarProtocol (
- OUT VOID **SarProtocol
- );
-
-/**
- Function returns an array of handles that support the FVB protocol
- in a buffer allocated from pool.
-
- @param[out] NumberHandles The number of handles returned in Buffer.
- @param[out] Buffer A pointer to the buffer to return the requested
- array of handles that support FVB protocol.
-
- @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
- handles in Buffer was returned in NumberHandles.
- @retval EFI_NOT_FOUND No FVB handle was found.
- @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
- @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
-
-**/
-EFI_STATUS
-GetFvbCountAndBuffer (
- OUT UINTN *NumberHandles,
- OUT EFI_HANDLE **Buffer
- );
-
-
-/**
- Allocate private data for FTW driver and initialize it.
-
- @param[out] FtwData Pointer to the FTW device structure
-
- @retval EFI_SUCCESS Initialize the FTW device successfully.
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
-
-**/
-EFI_STATUS
-InitFtwDevice (
- OUT EFI_FTW_DEVICE **FtwData
- );
-
-
-/**
- Initialization for Fault Tolerant Write is done in this handler.
-
- @param[in, out] FtwDevice Pointer to the FTW device structure
-
- @retval EFI_SUCCESS Initialize the FTW protocol successfully.
- @retval EFI_NOT_FOUND No proper FVB protocol was found.
-
-**/
-EFI_STATUS
-InitFtwProtocol (
- IN OUT EFI_FTW_DEVICE *FtwDevice
- );
-
-/**
- Initialize a local work space header.
-
- Since Signature and WriteQueueSize have been known, Crc can be calculated out,
- then the work space header will be fixed.
-**/
-VOID
-InitializeLocalWorkSpaceHeader (
- VOID
- );
-
-/**
- Read work space data from work block or spare block.
-
- @param FvBlock FVB Protocol interface to access the block.
- @param BlockSize The size of the block.
- @param Lba Lba of the block.
- @param Offset The offset within the block.
- @param Length The number of bytes to read from the block.
- @param Buffer The data is read.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-ReadWorkSpaceData (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- IN UINTN BlockSize,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- OUT UINT8 *Buffer
- );
-
-/**
- Write data to work block.
-
- @param FvBlock FVB Protocol interface to access the block.
- @param BlockSize The size of the block.
- @param Lba Lba of the block.
- @param Offset The offset within the block to place the data.
- @param Length The number of bytes to write to the block.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-WriteWorkSpaceData (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- IN UINTN BlockSize,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- IN UINT8 *Buffer
- );
-
-#endif
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.c deleted file mode 100644 index f570729273..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.c +++ /dev/null @@ -1,252 +0,0 @@ -/** @file
-
- This is a simple fault tolerant write driver.
-
- This boot service protocol only 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.
-
- The implementation uses an FTW (Fault Tolerant Write) Work Space.
- This work space is a memory copy of the work space on the Working Block,
- the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
-
- The work space stores each write record as EFI_FTW_RECORD structure.
- The spare block stores the write buffer before write to the target block.
-
- The write record has three states to specify the different phase of write operation.
- 1) WRITE_ALLOCATED is that the record is allocated in write space.
- The information of write operation is stored in write record structure.
- 2) SPARE_COMPLETED is that the data from write buffer is writed into the spare block as the backup.
- 3) WRITE_COMPLETED is that the data is copied from the spare block to the target block.
-
- This driver operates the data as the whole size of spare block.
- It first read the SpareAreaLength data from the target block into the spare memory buffer.
- Then copy the write buffer data into the spare memory buffer.
- Then write the spare memory buffer into the spare block.
- Final copy the data from the spare block to the target block.
-
- To make this drive work well, the following conditions must be satisfied:
- 1. The write NumBytes data must be fit within Spare area.
- Offset + NumBytes <= SpareAreaLength
- 2. The whole flash range has the same block size.
- 3. Working block is an area which contains working space in its last block and has the same size as spare block.
- 4. Working Block area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
- 5. Spare area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
- 6. Any write data area (SpareAreaLength Area) which the data will be written into must be
- in the single one Firmware Volume Block range which FVB protocol is produced on.
- 7. If write data area (such as Variable range) is enlarged, the spare area range must be enlarged.
- The spare area must be enough large to store the write data before write them into the target range.
- If one of them is not satisfied, FtwWrite may fail.
- Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.
-
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "FaultTolerantWrite.h"
-EFI_EVENT mFvbRegistration = NULL;
-
-
-/**
- Retrive the FVB protocol interface by HANDLE.
-
- @param[in] FvBlockHandle The handle of FVB protocol that provides services for
- reading, writing, and erasing the target block.
- @param[out] FvBlock The interface of FVB protocol
-
- @retval EFI_SUCCESS The interface information for the specified protocol was returned.
- @retval EFI_UNSUPPORTED The device does not support the FVB protocol.
- @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
-
-**/
-EFI_STATUS
-FtwGetFvbByHandle (
- IN EFI_HANDLE FvBlockHandle,
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
- )
-{
- //
- // To get the FVB protocol interface on the handle
- //
- return gBS->HandleProtocol (
- FvBlockHandle,
- &gEfiFirmwareVolumeBlockProtocolGuid,
- (VOID **) FvBlock
- );
-}
-
-/**
- Retrive the Swap Address Range protocol interface.
-
- @param[out] SarProtocol The interface of SAR protocol
-
- @retval EFI_SUCCESS The SAR protocol instance was found and returned in SarProtocol.
- @retval EFI_NOT_FOUND The SAR protocol instance was not found.
- @retval EFI_INVALID_PARAMETER SarProtocol is NULL.
-
-**/
-EFI_STATUS
-FtwGetSarProtocol (
- OUT VOID **SarProtocol
- )
-{
- EFI_STATUS Status;
-
- //
- // Locate Swap Address Range protocol
- //
- Status = gBS->LocateProtocol (
- &gEfiSwapAddressRangeProtocolGuid,
- NULL,
- SarProtocol
- );
- return Status;
-}
-
-/**
- Function returns an array of handles that support the FVB protocol
- in a buffer allocated from pool.
-
- @param[out] NumberHandles The number of handles returned in Buffer.
- @param[out] Buffer A pointer to the buffer to return the requested
- array of handles that support FVB protocol.
-
- @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
- handles in Buffer was returned in NumberHandles.
- @retval EFI_NOT_FOUND No FVB handle was found.
- @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
- @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
-
-**/
-EFI_STATUS
-GetFvbCountAndBuffer (
- OUT UINTN *NumberHandles,
- OUT EFI_HANDLE **Buffer
- )
-{
- EFI_STATUS Status;
-
- //
- // Locate all handles of Fvb protocol
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiFirmwareVolumeBlockProtocolGuid,
- NULL,
- NumberHandles,
- Buffer
- );
- return Status;
-}
-
-
-/**
- Firmware Volume Block Protocol notification event handler.
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context Pointer to the notification function's context.
-
-**/
-VOID
-EFIAPI
-FvbNotificationEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
- EFI_FTW_DEVICE *FtwDevice;
-
- //
- // Just return to avoid installing FaultTolerantWriteProtocol again
- // if Fault Tolerant Write protocol has been installed.
- //
- Status = gBS->LocateProtocol (
- &gEfiFaultTolerantWriteProtocolGuid,
- NULL,
- (VOID **) &FtwProtocol
- );
- if (!EFI_ERROR (Status)) {
- return ;
- }
-
- //
- // Found proper FVB protocol and initialize FtwDevice for protocol installation
- //
- FtwDevice = (EFI_FTW_DEVICE *)Context;
- Status = InitFtwProtocol (FtwDevice);
- if (EFI_ERROR(Status)) {
- return ;
- }
-
- //
- // Install protocol interface
- //
- Status = gBS->InstallProtocolInterface (
- &FtwDevice->Handle,
- &gEfiFaultTolerantWriteProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &FtwDevice->FtwInstance
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->CloseEvent (Event);
- ASSERT_EFI_ERROR (Status);
-
- return;
-}
-
-
-/**
- This function is the entry point of the Fault Tolerant Write driver.
-
- @param[in] ImageHandle A handle for the image that is initializing this driver
- @param[in] SystemTable A pointer to the EFI system table
-
- @retval EFI_SUCCESS The initialization finished successfully.
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
-
-**/
-EFI_STATUS
-EFIAPI
-FaultTolerantWriteInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- EFI_FTW_DEVICE *FtwDevice;
-
- FtwDevice = NULL;
-
- //
- // Allocate private data structure for FTW protocol and do some initialization
- //
- Status = InitFtwDevice (&FtwDevice);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- //
- // Register FvbNotificationEvent () notify function.
- //
- EfiCreateProtocolNotifyEvent (
- &gEfiFirmwareVolumeBlockProtocolGuid,
- TPL_CALLBACK,
- FvbNotificationEvent,
- (VOID *)FtwDevice,
- &mFvbRegistration
- );
-
- return EFI_SUCCESS;
-}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf deleted file mode 100644 index 5649241f71..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +++ /dev/null @@ -1,91 +0,0 @@ -## @file
-# Fault Tolerant Write Dxe Driver.
-#
-# This driver installs Fault Tolerant Write (FTW) protocol,
-# which provides fault tolerant write capability for block devices.
-# Its implementation depends on the full functionality FVB protocol that support read, write/erase flash access.
-#
-# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-#
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# 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]
- INF_VERSION = 0x00010005
- BASE_NAME = FaultTolerantWriteDxe
- MODULE_UNI_FILE = FaultTolerantWriteDxe.uni
- FILE_GUID = FE5CEA76-4F72-49e8-986F-2CD899DFFE5D
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = FaultTolerantWriteInitialize
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64 IPF EBC
-#
-
-[Sources]
- FtwMisc.c
- UpdateWorkingBlock.c
- FaultTolerantWrite.c
- FaultTolerantWriteDxe.c
- FaultTolerantWrite.h
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- UefiBootServicesTableLib
- MemoryAllocationLib
- BaseMemoryLib
- UefiDriverEntryPoint
- DebugLib
- UefiLib
- PcdLib
- ReportStatusCodeLib
-
-[Guids]
- #
- # Signature in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
- #
- ## CONSUMES ## GUID
- ## PRODUCES ## GUID
- gEdkiiWorkingBlockSignatureGuid
-
-[Protocols]
- gEfiSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## SOMETIMES_CONSUMES
- ## NOTIFY
- ## CONSUMES
- gEfiFirmwareVolumeBlockProtocolGuid
- gEfiFaultTolerantWriteProtocolGuid ## PRODUCES
-
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES
-
-#
-# gBS->CalculateCrc32() is consumed in EntryPoint.
-# PI spec said: When the DXE Foundation is notified that the EFI_RUNTIME_ARCH_PROTOCOL
-# has been installed, then the Boot Service CalculateCrc32() is available.
-# So add gEfiRuntimeArchProtocolGuid Depex here.
-#
-[Depex]
- gEfiFirmwareVolumeBlockProtocolGuid AND gEfiRuntimeArchProtocolGuid
-
-[UserExtensions.TianoCore."ExtraFiles"]
- FaultTolerantWriteDxeExtra.uni
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.uni b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.uni Binary files differdeleted file mode 100644 index 694784ba57..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.uni +++ /dev/null diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxeExtra.uni b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxeExtra.uni Binary files differdeleted file mode 100644 index d4135ffab3..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxeExtra.uni +++ /dev/null diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c deleted file mode 100644 index bc5e6177c3..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.c +++ /dev/null @@ -1,650 +0,0 @@ -/** @file
-
- This is a simple fault tolerant write driver that is intended to use in the SMM environment.
-
- This boot service protocol only 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.
-
- The implementation uses an FTW (Fault Tolerant Write) Work Space.
- This work space is a memory copy of the work space on the Working Block,
- the size of the work space is the FTW_WORK_SPACE_SIZE bytes.
-
- The work space stores each write record as EFI_FTW_RECORD structure.
- The spare block stores the write buffer before write to the target block.
-
- The write record has three states to specify the different phase of write operation.
- 1) WRITE_ALLOCATED is that the record is allocated in write space.
- The information of write operation is stored in write record structure.
- 2) SPARE_COMPLETED is that the data from write buffer is writed into the spare block as the backup.
- 3) WRITE_COMPLETED is that the data is copied from the spare block to the target block.
-
- This driver operates the data as the whole size of spare block.
- It first read the SpareAreaLength data from the target block into the spare memory buffer.
- Then copy the write buffer data into the spare memory buffer.
- Then write the spare memory buffer into the spare block.
- Final copy the data from the spare block to the target block.
-
- To make this drive work well, the following conditions must be satisfied:
- 1. The write NumBytes data must be fit within Spare area.
- Offset + NumBytes <= SpareAreaLength
- 2. The whole flash range has the same block size.
- 3. Working block is an area which contains working space in its last block and has the same size as spare block.
- 4. Working Block area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
- 5. Spare area must be in the single one Firmware Volume Block range which FVB protocol is produced on.
- 6. Any write data area (SpareAreaLength Area) which the data will be written into must be
- in the single one Firmware Volume Block range which FVB protocol is produced on.
- 7. If write data area (such as Variable range) is enlarged, the spare area range must be enlarged.
- The spare area must be enough large to store the write data before write them into the target range.
- If one of them is not satisfied, FtwWrite may fail.
- Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.
-
- Caution: This module requires additional review when modified.
- This driver need to make sure the CommBuffer is not in the SMRAM range.
-
-Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include <PiSmm.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Library/SmmMemLib.h>
-#include <Protocol/SmmSwapAddressRange.h>
-#include "FaultTolerantWrite.h"
-#include "FaultTolerantWriteSmmCommon.h"
-#include <Protocol/SmmEndOfDxe.h>
-
-EFI_EVENT mFvbRegistration = NULL;
-EFI_FTW_DEVICE *mFtwDevice = NULL;
-
-///
-/// The flag to indicate whether the platform has left the DXE phase of execution.
-///
-BOOLEAN mEndOfDxe = FALSE;
-
-/**
- Retrive the SMM FVB protocol interface by HANDLE.
-
- @param[in] FvBlockHandle The handle of SMM FVB protocol that provides services for
- reading, writing, and erasing the target block.
- @param[out] FvBlock The interface of SMM FVB protocol
-
- @retval EFI_SUCCESS The interface information for the specified protocol was returned.
- @retval EFI_UNSUPPORTED The device does not support the SMM FVB protocol.
- @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
-
-**/
-EFI_STATUS
-FtwGetFvbByHandle (
- IN EFI_HANDLE FvBlockHandle,
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
- )
-{
- //
- // To get the SMM FVB protocol interface on the handle
- //
- return gSmst->SmmHandleProtocol (
- FvBlockHandle,
- &gEfiSmmFirmwareVolumeBlockProtocolGuid,
- (VOID **) FvBlock
- );
-}
-
-/**
- Retrive the SMM Swap Address Range protocol interface.
-
- @param[out] SarProtocol The interface of SMM SAR protocol
-
- @retval EFI_SUCCESS The SMM SAR protocol instance was found and returned in SarProtocol.
- @retval EFI_NOT_FOUND The SMM SAR protocol instance was not found.
- @retval EFI_INVALID_PARAMETER SarProtocol is NULL.
-
-**/
-EFI_STATUS
-FtwGetSarProtocol (
- OUT VOID **SarProtocol
- )
-{
- EFI_STATUS Status;
-
- //
- // Locate Smm Swap Address Range protocol
- //
- Status = gSmst->SmmLocateProtocol (
- &gEfiSmmSwapAddressRangeProtocolGuid,
- NULL,
- SarProtocol
- );
- return Status;
-}
-
-/**
- Function returns an array of handles that support the SMM FVB protocol
- in a buffer allocated from pool.
-
- @param[out] NumberHandles The number of handles returned in Buffer.
- @param[out] Buffer A pointer to the buffer to return the requested
- array of handles that support SMM FVB protocol.
-
- @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of
- handles in Buffer was returned in NumberHandles.
- @retval EFI_NOT_FOUND No SMM FVB handle was found.
- @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.
- @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
-
-**/
-EFI_STATUS
-GetFvbCountAndBuffer (
- OUT UINTN *NumberHandles,
- OUT EFI_HANDLE **Buffer
- )
-{
- EFI_STATUS Status;
- UINTN BufferSize;
-
- if ((NumberHandles == NULL) || (Buffer == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- BufferSize = 0;
- *NumberHandles = 0;
- *Buffer = NULL;
- Status = gSmst->SmmLocateHandle (
- ByProtocol,
- &gEfiSmmFirmwareVolumeBlockProtocolGuid,
- NULL,
- &BufferSize,
- *Buffer
- );
- if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
- return EFI_NOT_FOUND;
- }
-
- *Buffer = AllocatePool (BufferSize);
- if (*Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Status = gSmst->SmmLocateHandle (
- ByProtocol,
- &gEfiSmmFirmwareVolumeBlockProtocolGuid,
- NULL,
- &BufferSize,
- *Buffer
- );
-
- *NumberHandles = BufferSize / sizeof(EFI_HANDLE);
- if (EFI_ERROR(Status)) {
- *NumberHandles = 0;
- FreePool (*Buffer);
- *Buffer = NULL;
- }
-
- return Status;
-}
-
-
-/**
- Get the handle of the SMM FVB protocol by the FVB base address and attributes.
-
- @param[in] Address The base address of SMM FVB protocol.
- @param[in] Attributes The attributes of the SMM FVB protocol.
- @param[out] SmmFvbHandle The handle of the SMM FVB protocol.
-
- @retval EFI_SUCCESS The FVB handle is found.
- @retval EFI_ABORTED The FVB protocol is not found.
-
-**/
-EFI_STATUS
-GetFvbByAddressAndAttribute (
- IN EFI_PHYSICAL_ADDRESS Address,
- IN EFI_FVB_ATTRIBUTES_2 Attributes,
- OUT EFI_HANDLE *SmmFvbHandle
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
- EFI_PHYSICAL_ADDRESS FvbBaseAddress;
- EFI_FVB_ATTRIBUTES_2 FvbAttributes;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
-
- HandleBuffer = NULL;
-
- //
- // Locate all handles of SMM Fvb protocol.
- //
- Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- //
- // Find the proper SMM Fvb handle by the address and attributes.
- //
- for (Index = 0; Index < HandleCount; Index++) {
- Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
- if (EFI_ERROR (Status)) {
- break;
- }
- //
- // Compare the address.
- //
- Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
- if (EFI_ERROR (Status)) {
- continue;
- }
- if (Address != FvbBaseAddress) {
- continue;
- }
-
- //
- // Compare the attribute.
- //
- Status = Fvb->GetAttributes (Fvb, &FvbAttributes);
- if (EFI_ERROR (Status)) {
- continue;
- }
- if (Attributes != FvbAttributes) {
- continue;
- }
-
- //
- // Found the proper FVB handle.
- //
- *SmmFvbHandle = HandleBuffer[Index];
- FreePool (HandleBuffer);
- return EFI_SUCCESS;
- }
-
- FreePool (HandleBuffer);
- return EFI_ABORTED;
-}
-
-/**
- Communication service SMI Handler entry.
-
- This SMI handler provides services for the fault tolerant write wrapper driver.
-
- Caution: This function requires additional review when modified.
- This driver need to make sure the CommBuffer is not in the SMRAM range.
- Also in FTW_FUNCTION_GET_LAST_WRITE case, check SmmFtwGetLastWriteHeader->Data +
- SmmFtwGetLastWriteHeader->PrivateDataSize within communication buffer.
-
- @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
- @param[in] RegisterContext Points to an optional handler context which was specified when the
- handler was registered.
- @param[in, out] CommBuffer A pointer to a collection of data in memory that will be conveyed
- from a non-SMM environment into an SMM environment.
- @param[in, out] CommBufferSize The size of the CommBuffer.
-
- @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
- should still be called.
- @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
- still be called.
- @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
- be called.
- @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmFaultTolerantWriteHandler (
- IN EFI_HANDLE DispatchHandle,
- IN CONST VOID *RegisterContext,
- IN OUT VOID *CommBuffer,
- IN OUT UINTN *CommBufferSize
- )
-{
- EFI_STATUS Status;
- SMM_FTW_COMMUNICATE_FUNCTION_HEADER *SmmFtwFunctionHeader;
- SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *SmmGetMaxBlockSizeHeader;
- SMM_FTW_ALLOCATE_HEADER *SmmFtwAllocateHeader;
- SMM_FTW_WRITE_HEADER *SmmFtwWriteHeader;
- SMM_FTW_RESTART_HEADER *SmmFtwRestartHeader;
- SMM_FTW_GET_LAST_WRITE_HEADER *SmmFtwGetLastWriteHeader;
- VOID *PrivateData;
- EFI_HANDLE SmmFvbHandle;
- UINTN InfoSize;
- UINTN CommBufferPayloadSize;
- UINTN PrivateDataSize;
- UINTN Length;
- UINTN TempCommBufferSize;
-
- //
- // If input is invalid, stop processing this SMI
- //
- if (CommBuffer == NULL || CommBufferSize == NULL) {
- return EFI_SUCCESS;
- }
-
- TempCommBufferSize = *CommBufferSize;
-
- if (TempCommBufferSize < SMM_FTW_COMMUNICATE_HEADER_SIZE) {
- DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer size invalid!\n"));
- return EFI_SUCCESS;
- }
- CommBufferPayloadSize = TempCommBufferSize - SMM_FTW_COMMUNICATE_HEADER_SIZE;
-
- if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "SmmFtwHandler: SMM communication buffer in SMRAM or overflow!\n"));
- return EFI_SUCCESS;
- }
-
- SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *)CommBuffer;
-
- if (mEndOfDxe) {
- //
- // It will be not safe to expose the operations after End Of Dxe.
- //
- DEBUG ((EFI_D_ERROR, "SmmFtwHandler: Not safe to do the operation: %x after End Of Dxe, so access denied!\n", SmmFtwFunctionHeader->Function));
- SmmFtwFunctionHeader->ReturnStatus = EFI_ACCESS_DENIED;
- return EFI_SUCCESS;
- }
-
- switch (SmmFtwFunctionHeader->Function) {
- case FTW_FUNCTION_GET_MAX_BLOCK_SIZE:
- if (CommBufferPayloadSize < sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER)) {
- DEBUG ((EFI_D_ERROR, "GetMaxBlockSize: SMM communication buffer size invalid!\n"));
- return EFI_SUCCESS;
- }
- SmmGetMaxBlockSizeHeader = (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *) SmmFtwFunctionHeader->Data;
-
- Status = FtwGetMaxBlockSize (
- &mFtwDevice->FtwInstance,
- &SmmGetMaxBlockSizeHeader->BlockSize
- );
- break;
-
- case FTW_FUNCTION_ALLOCATE:
- if (CommBufferPayloadSize < sizeof (SMM_FTW_ALLOCATE_HEADER)) {
- DEBUG ((EFI_D_ERROR, "Allocate: SMM communication buffer size invalid!\n"));
- return EFI_SUCCESS;
- }
- SmmFtwAllocateHeader = (SMM_FTW_ALLOCATE_HEADER *) SmmFtwFunctionHeader->Data;
- Status = FtwAllocate (
- &mFtwDevice->FtwInstance,
- &SmmFtwAllocateHeader->CallerId,
- SmmFtwAllocateHeader->PrivateDataSize,
- SmmFtwAllocateHeader->NumberOfWrites
- );
- break;
-
- case FTW_FUNCTION_WRITE:
- if (CommBufferPayloadSize < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data)) {
- DEBUG ((EFI_D_ERROR, "Write: SMM communication buffer size invalid!\n"));
- return EFI_SUCCESS;
- }
- SmmFtwWriteHeader = (SMM_FTW_WRITE_HEADER *) SmmFtwFunctionHeader->Data;
- Length = SmmFtwWriteHeader->Length;
- PrivateDataSize = SmmFtwWriteHeader->PrivateDataSize;
- if (((UINTN)(~0) - Length < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data)) ||
- ((UINTN)(~0) - PrivateDataSize < OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length)) {
- //
- // Prevent InfoSize overflow
- //
- Status = EFI_ACCESS_DENIED;
- break;
- }
- InfoSize = OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length + PrivateDataSize;
-
- //
- // SMRAM range check already covered before
- //
- if (InfoSize > CommBufferPayloadSize) {
- DEBUG ((EFI_D_ERROR, "Write: Data size exceed communication buffer size limit!\n"));
- Status = EFI_ACCESS_DENIED;
- break;
- }
-
- if (PrivateDataSize == 0) {
- PrivateData = NULL;
- } else {
- PrivateData = (VOID *)&SmmFtwWriteHeader->Data[Length];
- }
- Status = GetFvbByAddressAndAttribute (
- SmmFtwWriteHeader->FvbBaseAddress,
- SmmFtwWriteHeader->FvbAttributes,
- &SmmFvbHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = FtwWrite(
- &mFtwDevice->FtwInstance,
- SmmFtwWriteHeader->Lba,
- SmmFtwWriteHeader->Offset,
- Length,
- PrivateData,
- SmmFvbHandle,
- SmmFtwWriteHeader->Data
- );
- }
- break;
-
- case FTW_FUNCTION_RESTART:
- if (CommBufferPayloadSize < sizeof (SMM_FTW_RESTART_HEADER)) {
- DEBUG ((EFI_D_ERROR, "Restart: SMM communication buffer size invalid!\n"));
- return EFI_SUCCESS;
- }
- SmmFtwRestartHeader = (SMM_FTW_RESTART_HEADER *) SmmFtwFunctionHeader->Data;
- Status = GetFvbByAddressAndAttribute (
- SmmFtwRestartHeader->FvbBaseAddress,
- SmmFtwRestartHeader->FvbAttributes,
- &SmmFvbHandle
- );
- if (!EFI_ERROR (Status)) {
- Status = FtwRestart (&mFtwDevice->FtwInstance, SmmFvbHandle);
- }
- break;
-
- case FTW_FUNCTION_ABORT:
- Status = FtwAbort (&mFtwDevice->FtwInstance);
- break;
-
- case FTW_FUNCTION_GET_LAST_WRITE:
- if (CommBufferPayloadSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)) {
- DEBUG ((EFI_D_ERROR, "GetLastWrite: SMM communication buffer size invalid!\n"));
- return EFI_SUCCESS;
- }
- SmmFtwGetLastWriteHeader = (SMM_FTW_GET_LAST_WRITE_HEADER *) SmmFtwFunctionHeader->Data;
- PrivateDataSize = SmmFtwGetLastWriteHeader->PrivateDataSize;
- if ((UINTN)(~0) - PrivateDataSize < OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data)){
- //
- // Prevent InfoSize overflow
- //
- Status = EFI_ACCESS_DENIED;
- break;
- }
- InfoSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + PrivateDataSize;
-
- //
- // SMRAM range check already covered before
- //
- if (InfoSize > CommBufferPayloadSize) {
- DEBUG ((EFI_D_ERROR, "Data size exceed communication buffer size limit!\n"));
- Status = EFI_ACCESS_DENIED;
- break;
- }
-
- Status = FtwGetLastWrite (
- &mFtwDevice->FtwInstance,
- &SmmFtwGetLastWriteHeader->CallerId,
- &SmmFtwGetLastWriteHeader->Lba,
- &SmmFtwGetLastWriteHeader->Offset,
- &SmmFtwGetLastWriteHeader->Length,
- &PrivateDataSize,
- (VOID *)SmmFtwGetLastWriteHeader->Data,
- &SmmFtwGetLastWriteHeader->Complete
- );
- SmmFtwGetLastWriteHeader->PrivateDataSize = PrivateDataSize;
- break;
-
- default:
- Status = EFI_UNSUPPORTED;
- }
-
- SmmFtwFunctionHeader->ReturnStatus = Status;
-
- return EFI_SUCCESS;
-}
-
-
-/**
- SMM Firmware Volume Block Protocol notification event handler.
-
- @param[in] Protocol Points to the protocol's unique identifier
- @param[in] Interface Points to the interface instance
- @param[in] Handle The handle on which the interface was installed
-
- @retval EFI_SUCCESS SmmEventCallback runs successfully
-
- **/
-EFI_STATUS
-EFIAPI
-FvbNotificationEvent (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
-{
- EFI_STATUS Status;
- EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
- EFI_HANDLE SmmFtwHandle;
- EFI_HANDLE FtwHandle;
-
- //
- // Just return to avoid install SMM FaultTolerantWriteProtocol again
- // if SMM Fault Tolerant Write protocol had been installed.
- //
- Status = gSmst->SmmLocateProtocol (
- &gEfiSmmFaultTolerantWriteProtocolGuid,
- NULL,
- (VOID **) &FtwProtocol
- );
- if (!EFI_ERROR (Status)) {
- return EFI_SUCCESS;
- }
-
- //
- // Found proper FVB protocol and initialize FtwDevice for protocol installation
- //
- Status = InitFtwProtocol (mFtwDevice);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- //
- // Install protocol interface
- //
- Status = gSmst->SmmInstallProtocolInterface (
- &mFtwDevice->Handle,
- &gEfiSmmFaultTolerantWriteProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mFtwDevice->FtwInstance
- );
- ASSERT_EFI_ERROR (Status);
-
- ///
- /// Register SMM FTW SMI handler
- ///
- Status = gSmst->SmiHandlerRegister (SmmFaultTolerantWriteHandler, &gEfiSmmFaultTolerantWriteProtocolGuid, &SmmFtwHandle);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Notify the Ftw wrapper driver SMM Ftw is ready
- //
- FtwHandle = NULL;
- Status = gBS->InstallProtocolInterface (
- &FtwHandle,
- &gEfiSmmFaultTolerantWriteProtocolGuid,
- EFI_NATIVE_INTERFACE,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
-
- return EFI_SUCCESS;
-}
-
-/**
- SMM END_OF_DXE protocol notification event handler.
-
- @param Protocol Points to the protocol's unique identifier
- @param Interface Points to the interface instance
- @param Handle The handle on which the interface was installed
-
- @retval EFI_SUCCESS SmmEndOfDxeCallback runs successfully
-
-**/
-EFI_STATUS
-EFIAPI
-SmmEndOfDxeCallback (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
-{
- mEndOfDxe = TRUE;
- return EFI_SUCCESS;
-}
-
-/**
- This function is the entry point of the Fault Tolerant Write driver.
-
- @param[in] ImageHandle A handle for the image that is initializing this driver
- @param[in] SystemTable A pointer to the EFI system table
-
- @retval EFI_SUCCESS The initialization finished successfully.
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
-
-**/
-EFI_STATUS
-EFIAPI
-SmmFaultTolerantWriteInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_STATUS Status;
- VOID *SmmEndOfDxeRegistration;
-
- //
- // Allocate private data structure for SMM FTW protocol and do some initialization
- //
- Status = InitFtwDevice (&mFtwDevice);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- //
- // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.
- //
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmEndOfDxeProtocolGuid,
- SmmEndOfDxeCallback,
- &SmmEndOfDxeRegistration
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Register FvbNotificationEvent () notify function.
- //
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmFirmwareVolumeBlockProtocolGuid,
- FvbNotificationEvent,
- &mFvbRegistration
- );
- ASSERT_EFI_ERROR (Status);
-
- FvbNotificationEvent (NULL, NULL, NULL);
-
- return EFI_SUCCESS;
-}
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf deleted file mode 100644 index 3b57c3cf64..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf +++ /dev/null @@ -1,98 +0,0 @@ -## @file
-# Fault Tolerant Write Smm Driver.
-#
-# This driver installs SMM Fault Tolerant Write (FTW) protocol, which provides fault
-# tolerant write capability in SMM environment for block devices. Its implementation
-# depends on the full functionality SMM FVB protocol that support read, write/erase
-# flash access.
-#
-# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
-#
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# 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]
- INF_VERSION = 0x00010005
- BASE_NAME = SmmFaultTolerantWriteDxe
- MODULE_UNI_FILE = SmmFaultTolerantWriteDxe.uni
- FILE_GUID = 470CB248-E8AC-473c-BB4F-81069A1FE6FD
- MODULE_TYPE = DXE_SMM_DRIVER
- VERSION_STRING = 1.0
- PI_SPECIFICATION_VERSION = 0x0001000A
- ENTRY_POINT = SmmFaultTolerantWriteInitialize
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources]
- FtwMisc.c
- UpdateWorkingBlock.c
- FaultTolerantWrite.c
- FaultTolerantWriteSmm.c
- FaultTolerantWrite.h
- FaultTolerantWriteSmmCommon.h
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- SmmServicesTableLib
- MemoryAllocationLib
- BaseMemoryLib
- UefiDriverEntryPoint
- DebugLib
- UefiLib
- PcdLib
- ReportStatusCodeLib
- SmmMemLib
-
-[Guids]
- #
- # Signature in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER
- #
- ## CONSUMES ## GUID
- ## PRODUCES ## GUID
- gEdkiiWorkingBlockSignatureGuid
-
-[Protocols]
- gEfiSmmSwapAddressRangeProtocolGuid | gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## SOMETIMES_CONSUMES
- ## NOTIFY
- ## CONSUMES
- gEfiSmmFirmwareVolumeBlockProtocolGuid
- ## PRODUCES
- ## UNDEFINED # SmiHandlerRegister
- gEfiSmmFaultTolerantWriteProtocolGuid
- gEfiSmmEndOfDxeProtocolGuid ## CONSUMES
-
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFullFtwServiceEnable ## CONSUMES
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES
-
-#
-# gBS->CalculateCrc32() is consumed in EntryPoint.
-# PI spec said: When the DXE Foundation is notified that the EFI_RUNTIME_ARCH_PROTOCOL
-# has been installed, then the Boot Service CalculateCrc32() is available.
-# So add gEfiRuntimeArchProtocolGuid Depex here.
-#
-[Depex]
- gEfiSmmFirmwareVolumeBlockProtocolGuid AND gEfiRuntimeArchProtocolGuid
-
-[UserExtensions.TianoCore."ExtraFiles"]
- SmmFaultTolerantWriteDxeExtra.uni
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmCommon.h b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmCommon.h deleted file mode 100644 index 061673bce2..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmCommon.h +++ /dev/null @@ -1,80 +0,0 @@ -/** @file
-
- The common header file for SMM FTW module and SMM FTW DXE Module.
-
-Copyright (c) 2011, Intel Corporation. All rights reserved. <BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-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.
-
-**/
-
-#ifndef __SMM_FTW_COMMON_H__
-#define __SMM_FTW_COMMON_H__
-
-#include <Protocol/SmmFirmwareVolumeBlock.h>
-#include <Protocol/SmmFaultTolerantWrite.h>
-
-#define FTW_FUNCTION_GET_MAX_BLOCK_SIZE 1
-#define FTW_FUNCTION_ALLOCATE 2
-#define FTW_FUNCTION_WRITE 3
-#define FTW_FUNCTION_RESTART 4
-#define FTW_FUNCTION_ABORT 5
-#define FTW_FUNCTION_GET_LAST_WRITE 6
-
-typedef struct {
- UINTN Function;
- EFI_STATUS ReturnStatus;
- UINT8 Data[1];
-} SMM_FTW_COMMUNICATE_FUNCTION_HEADER;
-
-///
-/// Size of SMM communicate header, without including the payload.
-///
-#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data))
-
-///
-/// Size of SMM FTW communicate function header, without including the payload.
-///
-#define SMM_FTW_COMMUNICATE_HEADER_SIZE (OFFSET_OF (SMM_FTW_COMMUNICATE_FUNCTION_HEADER, Data))
-
-typedef struct {
- UINTN BlockSize;
-} SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER;
-
-typedef struct {
- EFI_GUID CallerId;
- UINTN PrivateDataSize;
- UINTN NumberOfWrites;
-} SMM_FTW_ALLOCATE_HEADER;
-
-typedef struct {
- EFI_LBA Lba;
- UINTN Offset;
- UINTN PrivateDataSize;
- EFI_PHYSICAL_ADDRESS FvbBaseAddress;
- EFI_FVB_ATTRIBUTES_2 FvbAttributes;
- UINTN Length;
- UINT8 Data[1];
-} SMM_FTW_WRITE_HEADER;
-
-typedef struct {
- EFI_PHYSICAL_ADDRESS FvbBaseAddress;
- EFI_FVB_ATTRIBUTES_2 FvbAttributes;
-} SMM_FTW_RESTART_HEADER;
-
-typedef struct {
- EFI_GUID CallerId;
- EFI_LBA Lba;
- UINTN Offset;
- UINTN Length;
- UINTN PrivateDataSize;
- BOOLEAN Complete;
- UINT8 Data[1];
-} SMM_FTW_GET_LAST_WRITE_HEADER;
-
-#endif
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c deleted file mode 100644 index 772d10dcd4..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.c +++ /dev/null @@ -1,562 +0,0 @@ -/** @file
-
- Implement the Fault Tolerant Write (FTW) protocol based on SMM FTW
- module.
-
-Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved. <BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "FaultTolerantWriteSmmDxe.h"
-
-EFI_HANDLE mHandle = NULL;
-EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication = NULL;
-UINTN mPrivateDataSize = 0;
-
-EFI_FAULT_TOLERANT_WRITE_PROTOCOL mFaultTolerantWriteDriver = {
- FtwGetMaxBlockSize,
- FtwAllocate,
- FtwWrite,
- FtwRestart,
- FtwAbort,
- FtwGetLastWrite
-};
-
-/**
- Initialize the communicate buffer using DataSize and Function number.
-
- @param[out] CommunicateBuffer The communicate buffer. Caller should free it after use.
- @param[out] DataPtr Points to the data in the communicate buffer. Caller should not free it.
- @param[in] DataSize The payload size.
- @param[in] Function The function number used to initialize the communicate header.
-
-**/
-VOID
-InitCommunicateBuffer (
- OUT VOID **CommunicateBuffer,
- OUT VOID **DataPtr,
- IN UINTN DataSize,
- IN UINTN Function
- )
-{
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
- SMM_FTW_COMMUNICATE_FUNCTION_HEADER *SmmFtwFunctionHeader;
-
- //
- // The whole buffer size: SMM_COMMUNICATE_HEADER_SIZE + SMM_FTW_COMMUNICATE_HEADER_SIZE + DataSize.
- //
- SmmCommunicateHeader = AllocateZeroPool (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_FTW_COMMUNICATE_HEADER_SIZE);
- ASSERT (SmmCommunicateHeader != NULL);
-
- //
- // Prepare data buffer.
- //
- CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmFaultTolerantWriteProtocolGuid);
- SmmCommunicateHeader->MessageLength = DataSize + SMM_FTW_COMMUNICATE_HEADER_SIZE;
-
- SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *) SmmCommunicateHeader->Data;
- SmmFtwFunctionHeader->Function = Function;
-
- *CommunicateBuffer = SmmCommunicateHeader;
- if (DataPtr != NULL) {
- *DataPtr = SmmFtwFunctionHeader->Data;
- }
-}
-
-
-/**
- Send the data in communicate buffer to SMI handler and get response.
-
- @param[in, out] SmmCommunicateHeader The communicate buffer.
- @param[in] DataSize The payload size.
-
-**/
-EFI_STATUS
-SendCommunicateBuffer (
- IN OUT EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader,
- IN UINTN DataSize
- )
-{
- EFI_STATUS Status;
- UINTN CommSize;
- SMM_FTW_COMMUNICATE_FUNCTION_HEADER *SmmFtwFunctionHeader;
-
- CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_FTW_COMMUNICATE_HEADER_SIZE;
- Status = mSmmCommunication->Communicate (mSmmCommunication, SmmCommunicateHeader, &CommSize);
- ASSERT_EFI_ERROR (Status);
-
- SmmFtwFunctionHeader = (SMM_FTW_COMMUNICATE_FUNCTION_HEADER *) SmmCommunicateHeader->Data;
- return SmmFtwFunctionHeader->ReturnStatus;
-}
-
-
-/**
- Get the FvbBaseAddress and FvbAttributes from the FVB handle FvbHandle.
-
- @param[in] FvbHandle The handle of FVB protocol that provides services.
- @param[out] FvbBaseAddress The base address of the FVB attached with FvbHandle.
- @param[out] FvbAttributes The attributes of the FVB attached with FvbHandle.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval Others The function could not complete successfully.
-
-**/
-EFI_STATUS
-ConvertFvbHandle (
- IN EFI_HANDLE FvbHandle,
- OUT EFI_PHYSICAL_ADDRESS *FvbBaseAddress,
- OUT EFI_FVB_ATTRIBUTES_2 *FvbAttributes
- )
-{
- EFI_STATUS Status;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
-
- Status = gBS->HandleProtocol (FvbHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **) &Fvb);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = Fvb->GetPhysicalAddress (Fvb, FvbBaseAddress);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = Fvb->GetAttributes (Fvb, FvbAttributes);
- return Status;
-}
-
-
-/**
- Get the size of the largest block that can be updated in a fault-tolerant manner.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[out] BlockSize A pointer to a caller-allocated UINTN that is
- updated to indicate the size of the largest block
- that can be updated.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetMaxBlockSize (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT UINTN *BlockSize
- )
-{
- EFI_STATUS Status;
- UINTN PayloadSize;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
- SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER *SmmFtwBlockSizeHeader;
-
- //
- // Initialize the communicate buffer.
- //
- PayloadSize = sizeof (SMM_FTW_GET_MAX_BLOCK_SIZE_HEADER);
- InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwBlockSizeHeader, PayloadSize, FTW_FUNCTION_GET_MAX_BLOCK_SIZE);
-
- //
- // Send data to SMM.
- //
- Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
-
- //
- // Get data from SMM
- //
- *BlockSize = SmmFtwBlockSizeHeader->BlockSize;
- FreePool (SmmCommunicateHeader);
-
- return Status;
-}
-
-
-/**
- Allocates space for the protocol to maintain information about writes.
- Since writes must be completed in a fault-tolerant manner and multiple
- writes require more resources to be successful, this function
- enables the protocol to ensure that enough space exists to track
- information about upcoming writes.
-
- @param[in] This A pointer to the calling context.
- @param[in] CallerId The GUID identifying the write.
- @param[in] PrivateDataSize The size of the caller's private data that must be
- recorded for each write.
- @param[in] NumberOfWrites The number of fault tolerant block writes that will
- need to occur.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_ACCESS_DENIED Not all allocated writes have been completed. All
- writes must be completed or aborted before another
- fault tolerant write can occur.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAllocate (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_GUID *CallerId,
- IN UINTN PrivateDataSize,
- IN UINTN NumberOfWrites
- )
-{
- EFI_STATUS Status;
- UINTN PayloadSize;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
- SMM_FTW_ALLOCATE_HEADER *SmmFtwAllocateHeader;
-
- //
- // Initialize the communicate buffer.
- //
- PayloadSize = sizeof (SMM_FTW_ALLOCATE_HEADER);
- InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwAllocateHeader, PayloadSize, FTW_FUNCTION_ALLOCATE);
- CopyGuid (&SmmFtwAllocateHeader->CallerId, CallerId);
- SmmFtwAllocateHeader->PrivateDataSize = PrivateDataSize;
- SmmFtwAllocateHeader->NumberOfWrites = NumberOfWrites;
-
- //
- // Send data to SMM.
- //
- Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
- if (!EFI_ERROR( Status)) {
- mPrivateDataSize = PrivateDataSize;
- }
-
- FreePool (SmmCommunicateHeader);
- return Status;
-}
-
-
-/**
- Starts a target block update. This records information about the 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.
-
- @param[in] This The calling context.
- @param[in] Lba The logical block address of the target block.
- @param[in] Offset The offset within the target block to place the
- data.
- @param[in] Length The number of bytes to write to the target block.
- @param[in] PrivateData A pointer to private data that the caller requires
- to complete any pending writes in the event of a
- fault.
- @param[in] FvBlockHandle The handle of FVB protocol that provides services
- for reading, writing, and erasing the target block.
- @param[in] Buffer The data to write.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_BAD_BUFFER_SIZE The write would span a block boundary, which is not
- a valid action.
- @retval EFI_ACCESS_DENIED No writes have been allocated.
- @retval EFI_NOT_READY The last write has not been completed. Restart()
- must be called to complete it.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- IN VOID *PrivateData,
- IN EFI_HANDLE FvBlockHandle,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN PayloadSize;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
- SMM_FTW_WRITE_HEADER *SmmFtwWriteHeader;
-
- //
- // Initialize the communicate buffer.
- //
- PayloadSize = OFFSET_OF (SMM_FTW_WRITE_HEADER, Data) + Length;
- if (PrivateData != NULL) {
- //
- // The private data buffer size should be the same one in FtwAllocate API.
- //
- PayloadSize += mPrivateDataSize;
- }
- InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwWriteHeader, PayloadSize, FTW_FUNCTION_WRITE);
-
- //
- // FvBlockHandle can not be used in SMM environment. Here we get the FVB protocol first, then get FVB base address
- // and its attribute. Send these information to SMM handler, the SMM handler will find the proper FVB to write data.
- //
- Status = ConvertFvbHandle (FvBlockHandle, &SmmFtwWriteHeader->FvbBaseAddress, &SmmFtwWriteHeader->FvbAttributes);
- if (EFI_ERROR (Status)) {
- FreePool (SmmCommunicateHeader);
- return EFI_ABORTED;
- }
-
- SmmFtwWriteHeader->Lba = Lba;
- SmmFtwWriteHeader->Offset = Offset;
- SmmFtwWriteHeader->Length = Length;
- CopyMem (SmmFtwWriteHeader->Data, Buffer, Length);
- if (PrivateData == NULL) {
- SmmFtwWriteHeader->PrivateDataSize = 0;
- } else {
- SmmFtwWriteHeader->PrivateDataSize = mPrivateDataSize;
- CopyMem (&SmmFtwWriteHeader->Data[Length], PrivateData, mPrivateDataSize);
- }
-
- //
- // Send data to SMM.
- //
- Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
- FreePool (SmmCommunicateHeader);
- return Status;
-}
-
-
-/**
- Restarts a previously interrupted write. The caller must provide the
- block protocol needed to complete the interrupted write.
-
- @param[in] This The calling context.
- @param[in] FvBlockHandle The handle of FVB protocol that provides services.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_ACCESS_DENIED No pending writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwRestart (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_HANDLE FvBlockHandle
- )
-{
- EFI_STATUS Status;
- UINTN PayloadSize;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
- SMM_FTW_RESTART_HEADER *SmmFtwRestartHeader;
-
- //
- // Initialize the communicate buffer.
- //
- PayloadSize = sizeof (SMM_FTW_RESTART_HEADER);
- InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwRestartHeader, PayloadSize, FTW_FUNCTION_RESTART);
-
- //
- // FvBlockHandle can not be used in SMM environment. Here we get the FVB protocol first, then get FVB base address
- // and its attribute. Send these information to SMM handler, the SMM handler will find the proper FVB to write data.
- //
- Status = ConvertFvbHandle (FvBlockHandle, &SmmFtwRestartHeader->FvbBaseAddress, &SmmFtwRestartHeader->FvbAttributes);
- if (EFI_ERROR (Status)) {
- FreePool (SmmCommunicateHeader);
- return EFI_ABORTED;
- }
-
- //
- // Send data to SMM.
- //
- Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
- FreePool (SmmCommunicateHeader);
- return Status;
-}
-
-
-/**
- Aborts all previously allocated writes.
-
- @param[in] This The calling context.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_NOT_FOUND No allocated writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAbort (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
-
- //
- // Initialize the communicate buffer.
- //
- InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, NULL, 0, FTW_FUNCTION_ABORT);
-
- //
- // Send data to SMM.
- //
- Status = SendCommunicateBuffer (SmmCommunicateHeader, 0);
-
- FreePool (SmmCommunicateHeader);
- return Status;
-}
-
-
-/**
- Starts a target block update. This function records information about the write
- in fault-tolerant storage and completes the write in a recoverable
- manner, ensuring at all times that either the original contents or
- the modified contents are available.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[out] CallerId The GUID identifying the last write.
- @param[out] Lba The logical block address of the last write.
- @param[out] Offset The offset within the block of the last write.
- @param[out] Length The length of the last write.
- @param[in, out] PrivateDataSize On input, the size of the PrivateData buffer. On
- output, the size of the private data stored for
- this write.
- @param[out] PrivateData A pointer to a buffer. The function will copy
- PrivateDataSize bytes from the private data stored
- for this write.
- @param[out] Complete A Boolean value with TRUE indicating that the write
- was completed.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_NOT_FOUND No allocated writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetLastWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT EFI_GUID *CallerId,
- OUT EFI_LBA *Lba,
- OUT UINTN *Offset,
- OUT UINTN *Length,
- IN OUT UINTN *PrivateDataSize,
- OUT VOID *PrivateData,
- OUT BOOLEAN *Complete
- )
-{
- EFI_STATUS Status;
- UINTN PayloadSize;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
- SMM_FTW_GET_LAST_WRITE_HEADER *SmmFtwGetLastWriteHeader;
-
- //
- // Initialize the communicate buffer.
- //
- PayloadSize = OFFSET_OF (SMM_FTW_GET_LAST_WRITE_HEADER, Data) + *PrivateDataSize;
- InitCommunicateBuffer ((VOID **)&SmmCommunicateHeader, (VOID **)&SmmFtwGetLastWriteHeader, PayloadSize, FTW_FUNCTION_GET_LAST_WRITE);
- SmmFtwGetLastWriteHeader->PrivateDataSize = *PrivateDataSize;
-
- //
- // Send data to SMM.
- //
- Status = SendCommunicateBuffer (SmmCommunicateHeader, PayloadSize);
-
- //
- // Get data from SMM
- //
- *PrivateDataSize = SmmFtwGetLastWriteHeader->PrivateDataSize;
- if (Status == EFI_SUCCESS || Status == EFI_BUFFER_TOO_SMALL) {
- *Lba = SmmFtwGetLastWriteHeader->Lba;
- *Offset = SmmFtwGetLastWriteHeader->Offset;
- *Length = SmmFtwGetLastWriteHeader->Length;
- *Complete = SmmFtwGetLastWriteHeader->Complete;
- CopyGuid (CallerId, &SmmFtwGetLastWriteHeader->CallerId);
- if (Status == EFI_SUCCESS) {
- CopyMem (PrivateData, SmmFtwGetLastWriteHeader->Data, *PrivateDataSize);
- }
- } else if (Status == EFI_NOT_FOUND) {
- *Complete = SmmFtwGetLastWriteHeader->Complete;
- }
-
- FreePool (SmmCommunicateHeader);
- return Status;
-}
-
-/**
- SMM Fault Tolerant Write Protocol notification event handler.
-
- Install Fault Tolerant Write Protocol.
-
- @param[in] Event Event whose notification function is being invoked.
- @param[in] Context Pointer to the notification function's context.
-**/
-VOID
-EFIAPI
-SmmFtwReady (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
-
- //
- // Just return to avoid install SMM FaultTolerantWriteProtocol again
- // if Fault Tolerant Write protocol had been installed.
- //
- Status = gBS->LocateProtocol (&gEfiFaultTolerantWriteProtocolGuid, NULL, (VOID **)&FtwProtocol);
- if (!EFI_ERROR (Status)) {
- return;
- }
-
- Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Install protocol interface
- //
- Status = gBS->InstallProtocolInterface (
- &mHandle,
- &gEfiFaultTolerantWriteProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mFaultTolerantWriteDriver
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = gBS->CloseEvent (Event);
- ASSERT_EFI_ERROR (Status);
-}
-
-
-/**
- The driver entry point for Fault Tolerant Write driver.
-
- The function does the necessary initialization work.
-
- @param[in] ImageHandle The firmware allocated handle for the UEFI image.
- @param[in] SystemTable A pointer to the EFI system table.
-
- @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-FaultTolerantWriteSmmInitialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- VOID *SmmFtwRegistration;
-
- //
- // Smm FTW driver is ready
- //
- EfiCreateProtocolNotifyEvent (
- &gEfiSmmFaultTolerantWriteProtocolGuid,
- TPL_CALLBACK,
- SmmFtwReady,
- NULL,
- &SmmFtwRegistration
- );
-
- return EFI_SUCCESS;
-}
-
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.h b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.h deleted file mode 100644 index b4c20aee0f..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.h +++ /dev/null @@ -1,202 +0,0 @@ -/** @file
-
- The internal header file includes the common header files, defines
- internal structure and functions used by FTW module.
-
-Copyright (c) 2011, Intel Corporation. All rights reserved. <BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-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.
-
-**/
-
-#ifndef __SMM_FTW_DXE_H__
-#define __SMM_FTW_DXE_H__
-
-#include <PiDxe.h>
-
-#include <Protocol/SmmCommunication.h>
-
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiLib.h>
-#include <Library/BaseLib.h>
-#include <Library/MemoryAllocationLib.h>
-
-#include <Guid/EventGroup.h>
-
-#include "FaultTolerantWriteSmmCommon.h"
-
-/**
- Get the size of the largest block that can be updated in a fault-tolerant manner.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[out] BlockSize A pointer to a caller-allocated UINTN that is
- updated to indicate the size of the largest block
- that can be updated.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetMaxBlockSize (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT UINTN *BlockSize
- );
-
-
-/**
- Allocates space for the protocol to maintain information about writes.
- Since writes must be completed in a fault-tolerant manner and multiple
- writes require more resources to be successful, this function
- enables the protocol to ensure that enough space exists to track
- information about upcoming writes.
-
- @param[in] This A pointer to the calling context.
- @param[in] CallerId The GUID identifying the write.
- @param[in] PrivateDataSize The size of the caller's private data that must be
- recorded for each write.
- @param[in] NumberOfWrites The number of fault tolerant block writes that will
- need to occur.
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_ACCESS_DENIED Not all allocated writes have been completed. All
- writes must be completed or aborted before another
- fault tolerant write can occur.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAllocate (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_GUID *CallerId,
- IN UINTN PrivateDataSize,
- IN UINTN NumberOfWrites
- );
-
-
-/**
- Starts a target block update. This records information about the 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.
-
- @param[in] This The calling context.
- @param[in] Lba The logical block address of the target block.
- @param[in] Offset The offset within the target block to place the
- data.
- @param[in] Length The number of bytes to write to the target block.
- @param[in] PrivateData A pointer to private data that the caller requires
- to complete any pending writes in the event of a
- fault.
- @param[in] FvBlockHandle The handle of FVB protocol that provides services
- for reading, writing, and erasing the target block.
- @param[in] Buffer The data to write.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_BAD_BUFFER_SIZE The write would span a block boundary, which is not
- a valid action.
- @retval EFI_ACCESS_DENIED No writes have been allocated.
- @retval EFI_NOT_READY The last write has not been completed. Restart()
- must be called to complete it.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- IN VOID *PrivateData,
- IN EFI_HANDLE FvBlockHandle,
- IN VOID *Buffer
- );
-
-
-/**
- Restarts a previously interrupted write. The caller must provide the
- block protocol needed to complete the interrupted write.
-
- @param[in] This The calling context.
- @param[in] FvBlockHandle The handle of FVB protocol that provides services.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_ACCESS_DENIED No pending writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwRestart (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- IN EFI_HANDLE FvBlockHandle
- );
-
-
-/**
- Aborts all previously allocated writes.
-
- @param This The calling context.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_NOT_FOUND No allocated writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwAbort (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This
- );
-
-
-/**
- Starts a target block update. This function records information about the write
- in fault-tolerant storage and completes the write in a recoverable
- manner, ensuring at all times that either the original contents or
- the modified contents are available.
-
- @param[in] This Indicates a pointer to the calling context.
- @param[out] CallerId The GUID identifying the last write.
- @param[out] Lba The logical block address of the last write.
- @param[out] Offset The offset within the block of the last write.
- @param[out] Length The length of the last write.
- @param[in, out] PrivateDataSize On input, the size of the PrivateData buffer. On
- output, the size of the private data stored for
- this write.
- @param[out] PrivateData A pointer to a buffer. The function will copy
- PrivateDataSize bytes from the private data stored
- for this write.
- @param[out] Complete A Boolean value with TRUE indicating that the write
- was completed.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
- @retval EFI_NOT_FOUND No allocated writes exist.
-
-**/
-EFI_STATUS
-EFIAPI
-FtwGetLastWrite (
- IN EFI_FAULT_TOLERANT_WRITE_PROTOCOL *This,
- OUT EFI_GUID *CallerId,
- OUT EFI_LBA *Lba,
- OUT UINTN *Offset,
- OUT UINTN *Length,
- IN OUT UINTN *PrivateDataSize,
- OUT VOID *PrivateData,
- OUT BOOLEAN *Complete
- );
-
-#endif
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf deleted file mode 100644 index 82dd36c320..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf +++ /dev/null @@ -1,64 +0,0 @@ -## @file
-# This module is the Runtime DXE part corresponding to SMM Fault Tolerant Write (FTW) module.
-#
-# It installs FTW protocol and works with SMM FTW module together.
-# The FTW protocol will not work after End Of Dxe because it will be not safe to expose
-# the related operations in SMM handler in SMM FTW module. You can use the FTW protocol
-# before End Of Dxe or use FaultTolerantWriteDxe module instead if you really want to.
-#
-# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
-#
-# This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# 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]
- INF_VERSION = 0x00010005
- BASE_NAME = FaultTolerantWriteSmmDxe
- MODULE_UNI_FILE = FaultTolerantWriteSmmDxe.uni
- FILE_GUID = 98948C4A-70F2-4035-8E9F-5927493CFC07
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- ENTRY_POINT = FaultTolerantWriteSmmInitialize
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources]
- FaultTolerantWriteSmmDxe.c
- FaultTolerantWriteSmmDxe.h
- FaultTolerantWriteSmmCommon.h
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
-
-[LibraryClasses]
- BaseLib
- UefiBootServicesTableLib
- DebugLib
- DxeServicesTableLib
- UefiDriverEntryPoint
-
-[Protocols]
- gEfiFaultTolerantWriteProtocolGuid ## PRODUCES
- gEfiSmmCommunicationProtocolGuid ## CONSUMES
- ## NOTIFY
- ## UNDEFINED # Used to do smm communication
- ## CONSUMES
- gEfiSmmFaultTolerantWriteProtocolGuid
- gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES
-
-[Depex]
- gEfiSmmCommunicationProtocolGuid
-
-[UserExtensions.TianoCore."ExtraFiles"]
- FaultTolerantWriteSmmDxeExtra.uni
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.uni b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.uni Binary files differdeleted file mode 100644 index 14ecfa127e..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.uni +++ /dev/null diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxeExtra.uni b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxeExtra.uni Binary files differdeleted file mode 100644 index 6b0a8f99fd..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxeExtra.uni +++ /dev/null diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c deleted file mode 100644 index 09223217e4..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c +++ /dev/null @@ -1,1382 +0,0 @@ -/** @file
-
- Internal generic functions to operate flash block.
-
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "FaultTolerantWrite.h"
-
-/**
-
- Check whether a flash buffer is erased.
-
- @param Buffer Buffer to check
- @param BufferSize Size of the buffer
-
- @return A BOOLEAN value indicating erased or not.
-
-**/
-BOOLEAN
-IsErasedFlashBuffer (
- IN UINT8 *Buffer,
- IN UINTN BufferSize
- )
-{
- BOOLEAN IsEmpty;
- UINT8 *Ptr;
- UINTN Index;
-
- Ptr = Buffer;
- IsEmpty = TRUE;
- for (Index = 0; Index < BufferSize; Index += 1) {
- if (*Ptr++ != FTW_ERASED_BYTE) {
- IsEmpty = FALSE;
- break;
- }
- }
-
- return IsEmpty;
-}
-
-/**
- To erase the block with specified blocks.
-
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock FVB Protocol interface
- @param Lba Lba of the firmware block
- @param NumberOfBlocks The number of consecutive blocks starting with Lba
-
- @retval EFI_SUCCESS Block LBA is Erased successfully
- @retval Others Error occurs
-
-**/
-EFI_STATUS
-FtwEraseBlock (
- IN EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- EFI_LBA Lba,
- UINTN NumberOfBlocks
- )
-{
- return FvBlock->EraseBlocks (
- FvBlock,
- Lba,
- NumberOfBlocks,
- EFI_LBA_LIST_TERMINATOR
- );
-}
-
-/**
- Erase spare block.
-
- @param FtwDevice The private data of FTW driver
-
- @retval EFI_SUCCESS The erase request was successfully completed.
- @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state.
- @retval EFI_DEVICE_ERROR The block device is not functioning
- correctly and could not be written.
- The firmware device may have been
- partially erased.
- @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
- in the variable argument list do
- not exist in the firmware volume.
-
-
-**/
-EFI_STATUS
-FtwEraseSpareBlock (
- IN EFI_FTW_DEVICE *FtwDevice
- )
-{
- return FtwDevice->FtwBackupFvb->EraseBlocks (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba,
- FtwDevice->NumberOfSpareBlock,
- EFI_LBA_LIST_TERMINATOR
- );
-}
-
-/**
-
- Is it in working block?
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock Fvb protocol instance
- @param Lba The block specified
-
- @return A BOOLEAN value indicating in working block or not.
-
-**/
-BOOLEAN
-IsWorkingBlock (
- EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- EFI_LBA Lba
- )
-{
- //
- // 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 == FtwDevice->FtwFvBlock) &&
- (Lba >= FtwDevice->FtwWorkBlockLba) &&
- (Lba <= FtwDevice->FtwWorkSpaceLba)
- );
-}
-
-/**
-
- Get firmware volume block by address.
-
-
- @param Address Address specified the block
- @param FvBlock The block caller wanted
-
- @retval EFI_SUCCESS The protocol instance if found.
- @retval EFI_NOT_FOUND Block not found
-
-**/
-EFI_HANDLE
-GetFvbByAddress (
- IN EFI_PHYSICAL_ADDRESS Address,
- OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
- EFI_PHYSICAL_ADDRESS FvbBaseAddress;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
- EFI_HANDLE FvbHandle;
- UINTN BlockSize;
- UINTN NumberOfBlocks;
-
- *FvBlock = NULL;
- FvbHandle = NULL;
- HandleBuffer = NULL;
- //
- // Locate all handles of Fvb protocol
- //
- Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
- //
- // Get the FVB to access variable store
- //
- for (Index = 0; Index < HandleCount; Index += 1) {
- Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
- if (EFI_ERROR (Status)) {
- break;
- }
- //
- // Compare the address and select the right one
- //
- Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- //
- // Now, one FVB has one type of BlockSize
- //
- Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + BlockSize * NumberOfBlocks))) {
- *FvBlock = Fvb;
- FvbHandle = HandleBuffer[Index];
- break;
- }
- }
-
- FreePool (HandleBuffer);
- return FvbHandle;
-}
-
-/**
-
- Is it in boot block?
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock Fvb protocol instance
-
- @return A BOOLEAN value indicating in boot block or not.
-
-**/
-BOOLEAN
-IsBootBlock (
- EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock
- )
-{
- EFI_STATUS Status;
- EFI_SWAP_ADDRESS_RANGE_PROTOCOL *SarProtocol;
- EFI_PHYSICAL_ADDRESS BootBlockBase;
- UINTN BootBlockSize;
- EFI_PHYSICAL_ADDRESS BackupBlockBase;
- UINTN BackupBlockSize;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
- BOOLEAN IsSwapped;
- EFI_HANDLE FvbHandle;
-
- if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {
- return FALSE;
- }
-
- Status = FtwGetSarProtocol ((VOID **) &SarProtocol);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- //
- // Get the boot block range
- //
- Status = SarProtocol->GetRangeLocation (
- SarProtocol,
- &BootBlockBase,
- &BootBlockSize,
- &BackupBlockBase,
- &BackupBlockSize
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
-
- Status = SarProtocol->GetSwapState (SarProtocol, &IsSwapped);
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- //
- // Get FVB by address
- //
- if (!IsSwapped) {
- FvbHandle = GetFvbByAddress (BootBlockBase, &BootFvb);
- } else {
- FvbHandle = GetFvbByAddress (BackupBlockBase, &BootFvb);
- }
-
- if (FvbHandle == NULL) {
- return FALSE;
- }
- //
- // Compare the Fvb
- //
- return (BOOLEAN) (FvBlock == BootFvb);
-}
-
-/**
- Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.
- Spare block is accessed by FTW working FVB protocol interface.
- Target block is accessed by FvBlock protocol interface.
-
- 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 may be:
- 1. GetRangeLocation(), if the Range is inside the boot block, FTW know
- that boot block will be update. It shall add a FLAG in the working block.
- 2. When spare block is ready,
- 3. SetSwapState(SWAPPED)
- 4. erasing boot block,
- 5. programming boot block until the boot block is ok.
- 6. SetSwapState(UNSWAPPED)
- FTW shall not allow to update boot block when battery state is error.
-
- @param FtwDevice The private data of FTW driver
-
- @retval EFI_SUCCESS Spare block content is copied to boot block
- @retval EFI_INVALID_PARAMETER Input parameter error
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FlushSpareBlockToBootBlock (
- EFI_FTW_DEVICE *FtwDevice
- )
-{
- EFI_STATUS Status;
- UINTN Length;
- UINT8 *Buffer;
- UINTN Count;
- UINT8 *Ptr;
- UINTN Index;
- BOOLEAN TopSwap;
- EFI_SWAP_ADDRESS_RANGE_PROTOCOL *SarProtocol;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb;
- EFI_LBA BootLba;
-
- if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Locate swap address range protocol
- //
- Status = FtwGetSarProtocol ((VOID **) &SarProtocol);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Allocate a memory buffer
- //
- Length = FtwDevice->SpareAreaLength;
- Buffer = AllocatePool (Length);
- if (Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Get TopSwap bit state
- //
- Status = SarProtocol->GetSwapState (SarProtocol, &TopSwap);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Get Top Swapped status - %r\n", Status));
- FreePool (Buffer);
- return EFI_ABORTED;
- }
-
- if (TopSwap) {
- //
- // Get FVB of current boot block
- //
- if (GetFvbByAddress (FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength, &BootFvb) == NULL) {
- FreePool (Buffer);
- return EFI_ABORTED;
- }
- //
- // Read data from current boot block
- //
- BootLba = 0;
- Ptr = Buffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Count = FtwDevice->SpareBlockSize;
- 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 < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Count = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Read (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &Count,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return Status;
- }
-
- Ptr += Count;
- }
- //
- // Set TopSwap bit
- //
- Status = SarProtocol->SetSwapState (SarProtocol, TRUE);
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return Status;
- }
- }
- //
- // Erase current spare block
- // Because TopSwap is set, this actually erase the top block (boot block)!
- //
- Status = FtwEraseSpareBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return EFI_ABORTED;
- }
- //
- // Write memory buffer to current spare block. Still top block.
- //
- Ptr = Buffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Count = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Write (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &Count,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: FVB Write boot block - %r\n", Status));
- FreePool (Buffer);
- return Status;
- }
-
- Ptr += Count;
- }
-
- FreePool (Buffer);
-
- //
- // Clear TopSwap bit
- //
- Status = SarProtocol->SetSwapState (SarProtocol, FALSE);
-
- return Status;
-}
-
-/**
- Copy the content of spare block to a target block.
- Spare block is accessed by FTW backup FVB protocol interface.
- Target block is accessed by FvBlock protocol interface.
-
-
- @param FtwDevice The private data of FTW driver
- @param FvBlock FVB Protocol interface to access target block
- @param Lba Lba of the target block
- @param BlockSize The size of the block
- @param NumberOfBlocks The number of consecutive blocks starting with Lba
-
- @retval EFI_SUCCESS Spare block content is copied to target block
- @retval EFI_INVALID_PARAMETER Input parameter error
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FlushSpareBlockToTargetBlock (
- EFI_FTW_DEVICE *FtwDevice,
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- EFI_LBA Lba,
- UINTN BlockSize,
- UINTN NumberOfBlocks
- )
-{
- EFI_STATUS Status;
- UINTN Length;
- UINT8 *Buffer;
- UINTN Count;
- UINT8 *Ptr;
- UINTN Index;
-
- if ((FtwDevice == NULL) || (FvBlock == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Allocate a memory buffer
- //
- Length = FtwDevice->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 < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Count = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Read (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &Count,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return Status;
- }
-
- Ptr += Count;
- }
- //
- // Erase the target block
- //
- Status = FtwEraseBlock (FtwDevice, FvBlock, Lba, NumberOfBlocks);
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return EFI_ABORTED;
- }
- //
- // Write memory buffer to block, using the FvBlock protocol interface
- //
- Ptr = Buffer;
- for (Index = 0; Index < NumberOfBlocks; Index += 1) {
- Count = BlockSize;
- Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: FVB Write block - %r\n", Status));
- FreePool (Buffer);
- return Status;
- }
-
- Ptr += Count;
- }
-
- FreePool (Buffer);
-
- return Status;
-}
-
-/**
- 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
- FtwDevice->FtwSpareLba.
- Working block is accessed by FTW working FVB protocol interface. LBA is
- FtwDevice->FtwWorkBlockLba.
-
- 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.
-
- @param FtwDevice The private data of FTW driver
-
- @retval EFI_SUCCESS Spare block content is copied to target block
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FlushSpareBlockToWorkingBlock (
- EFI_FTW_DEVICE *FtwDevice
- )
-{
- EFI_STATUS Status;
- UINTN Length;
- UINT8 *Buffer;
- EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
- UINTN Count;
- UINT8 *Ptr;
- UINTN Index;
-
- //
- // Allocate a memory buffer
- //
- Length = FtwDevice->SpareAreaLength;
- Buffer = AllocatePool (Length);
- if (Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // To guarantee that the WorkingBlockValid is set on spare block
- //
- // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
- // WorkingBlockValid);
- // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32).
- //
- FtwUpdateFvState (
- FtwDevice->FtwBackupFvb,
- FtwDevice->SpareBlockSize,
- FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
- FtwDevice->FtwWorkSpaceBaseInSpare + sizeof (EFI_GUID) + sizeof (UINT32),
- WORKING_BLOCK_VALID
- );
- //
- // Read from spare block to memory buffer
- //
- Ptr = Buffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Count = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Read (
- FtwDevice->FtwBackupFvb,
- FtwDevice->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) FtwDevice->FtwWorkSpaceLbaInSpare * FtwDevice->SpareBlockSize + FtwDevice->FtwWorkSpaceBaseInSpare);
- 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 = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
- // WorkingBlockInvalid);
- // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to
- // skip Signature and Crc.
- //
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
- WORKING_BLOCK_INVALID
- );
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return EFI_ABORTED;
- }
-
- FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
-
- //
- // Erase the working block
- //
- Status = FtwEraseBlock (FtwDevice, FtwDevice->FtwFvBlock, FtwDevice->FtwWorkBlockLba, FtwDevice->NumberOfWorkBlock);
- if (EFI_ERROR (Status)) {
- FreePool (Buffer);
- return EFI_ABORTED;
- }
- //
- // Write memory buffer to working block, using the FvBlock protocol interface
- //
- Ptr = Buffer;
- for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {
- Count = FtwDevice->WorkBlockSize;
- Status = FtwDevice->FtwFvBlock->Write (
- FtwDevice->FtwFvBlock,
- FtwDevice->FtwWorkBlockLba + Index,
- 0,
- &Count,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: 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 = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER, WorkingBlockValid);
- // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to skip Signature and Crc.
- //
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
- WORKING_BLOCK_VALID
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
- FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;
-
- return EFI_SUCCESS;
-}
-
-/**
- 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.
-
-
- @param FvBlock FVB Protocol interface to access SrcBlock and DestBlock
- @param BlockSize The size of the block
- @param Lba Lba of a block
- @param Offset Offset on the Lba
- @param NewBit New value that will override the old value if it can be change
-
- @retval EFI_SUCCESS A state bit has been updated successfully
- @retval Others Access block device error.
- Notes:
- Assume all bits of State are inside the same BYTE.
- @retval EFI_ABORTED Read block fail
-
-**/
-EFI_STATUS
-FtwUpdateFvState (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- IN UINTN BlockSize,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINT8 NewBit
- )
-{
- EFI_STATUS Status;
- UINT8 State;
- UINTN Length;
-
- //
- // Calculate the real Offset and Lba to write.
- //
- while (Offset >= BlockSize) {
- Offset -= BlockSize;
- Lba++;
- }
-
- //
- // 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;
-}
-
-/**
- Get the last Write Header pointer.
- The last write header is the header whose 'complete' state hasn't been set.
- After all, this header may be a EMPTY header entry for next Allocate.
-
-
- @param FtwWorkSpaceHeader Pointer of the working block header
- @param FtwWorkSpaceSize Size of the work space
- @param FtwWriteHeader Pointer to retrieve the last write header
-
- @retval EFI_SUCCESS Get the last write record successfully
- @retval EFI_ABORTED The FTW work space is damaged
-
-**/
-EFI_STATUS
-FtwGetLastWriteHeader (
- IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader,
- IN UINTN FtwWorkSpaceSize,
- OUT EFI_FAULT_TOLERANT_WRITE_HEADER **FtwWriteHeader
- )
-{
- UINTN Offset;
- EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
-
- *FtwWriteHeader = NULL;
- FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) (FtwWorkSpaceHeader + 1);
- Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
-
- while (FtwHeader->Complete == FTW_VALID_STATE) {
- Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
- //
- // If Offset exceed the FTW work space boudary, return error.
- //
- if (Offset >= FtwWorkSpaceSize) {
- *FtwWriteHeader = FtwHeader;
- return EFI_ABORTED;
- }
-
- FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) ((UINT8 *) FtwWorkSpaceHeader + Offset);
- }
- //
- // Last write header is found
- //
- *FtwWriteHeader = FtwHeader;
-
- return EFI_SUCCESS;
-}
-
-/**
- Get the last Write Record pointer. The last write Record is the Record
- whose DestinationCompleted state hasn't been set. After all, this Record
- may be a EMPTY record entry for next write.
-
-
- @param FtwWriteHeader Pointer to the write record header
- @param FtwWriteRecord Pointer to retrieve the last write record
-
- @retval EFI_SUCCESS Get the last write record successfully
- @retval EFI_ABORTED The FTW work space is damaged
-
-**/
-EFI_STATUS
-FtwGetLastWriteRecord (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwWriteHeader,
- OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwWriteRecord
- )
-{
- UINTN Index;
- EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord;
-
- *FtwWriteRecord = NULL;
- FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) (FtwWriteHeader + 1);
-
- //
- // Try to find the last write record "that has not completed"
- //
- for (Index = 0; Index < FtwWriteHeader->NumberOfWrites; Index += 1) {
- if (FtwRecord->DestinationComplete != FTW_VALID_STATE) {
- //
- // The last write record is found
- //
- *FtwWriteRecord = FtwRecord;
- return EFI_SUCCESS;
- }
-
- FtwRecord++;
-
- if (FtwWriteHeader->PrivateDataSize != 0) {
- FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + (UINTN) FtwWriteHeader->PrivateDataSize);
- }
- }
- //
- // if Index == NumberOfWrites, then
- // the last record has been written successfully,
- // but the Header->Complete Flag has not been set.
- // also return the last record.
- //
- if (Index == FtwWriteHeader->NumberOfWrites) {
- *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize));
- return EFI_SUCCESS;
- }
-
- return EFI_ABORTED;
-}
-
-/**
- To check if FtwRecord is the first record of FtwHeader.
-
- @param FtwHeader Pointer to the write record header
- @param FtwRecord Pointer to the write record
-
- @retval TRUE FtwRecord is the first Record of the FtwHeader
- @retval FALSE FtwRecord is not the first Record of the FtwHeader
-
-**/
-BOOLEAN
-IsFirstRecordOfWrites (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
- IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord
- )
-{
- UINT8 *Head;
- UINT8 *Ptr;
-
- Head = (UINT8 *) FtwHeader;
- Ptr = (UINT8 *) FtwRecord;
-
- Head += sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER);
- return (BOOLEAN) (Head == Ptr);
-}
-
-/**
- To check if FtwRecord is the last record of FtwHeader. Because the
- FtwHeader has NumberOfWrites & PrivateDataSize, the FtwRecord can be
- determined if it is the last record of FtwHeader.
-
- @param FtwHeader Pointer to the write record header
- @param FtwRecord Pointer to the write record
-
- @retval TRUE FtwRecord is the last Record of the FtwHeader
- @retval FALSE FtwRecord is not the last Record of the FtwHeader
-
-**/
-BOOLEAN
-IsLastRecordOfWrites (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
- IN EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord
- )
-{
- UINT8 *Head;
- UINT8 *Ptr;
-
- Head = (UINT8 *) FtwHeader;
- Ptr = (UINT8 *) FtwRecord;
-
- Head += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);
- return (BOOLEAN) (Head == Ptr);
-}
-
-/**
- To check if FtwRecord is the first record of FtwHeader.
-
- @param FtwHeader Pointer to the write record header
- @param FtwRecord Pointer to retrieve the previous write record
-
- @retval EFI_ACCESS_DENIED Input record is the first record, no previous record is return.
- @retval EFI_SUCCESS The previous write record is found.
-
-**/
-EFI_STATUS
-GetPreviousRecordOfWrites (
- IN EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader,
- IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD **FtwRecord
- )
-{
- UINT8 *Ptr;
-
- if (IsFirstRecordOfWrites (FtwHeader, *FtwRecord)) {
- *FtwRecord = NULL;
- return EFI_ACCESS_DENIED;
- }
-
- Ptr = (UINT8 *) (*FtwRecord);
- Ptr -= FTW_RECORD_SIZE (FtwHeader->PrivateDataSize);
- *FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;
- return EFI_SUCCESS;
-}
-
-/**
- Allocate private data for FTW driver and initialize it.
-
- @param[out] FtwData Pointer to the FTW device structure
-
- @retval EFI_SUCCESS Initialize the FTW device successfully.
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_INVALID_PARAMETER Workspace or Spare block does not exist
-
-**/
-EFI_STATUS
-InitFtwDevice (
- OUT EFI_FTW_DEVICE **FtwData
- )
-{
- EFI_FTW_DEVICE *FtwDevice;
-
- //
- // Allocate private data of this driver,
- // Including the FtwWorkSpace[FTW_WORK_SPACE_SIZE].
- //
- FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));
- if (FtwDevice == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- //
- // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
- //
- FtwDevice->WorkSpaceLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
- FtwDevice->SpareAreaLength = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);
- if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));
- FreePool (FtwDevice);
- return EFI_INVALID_PARAMETER;
- }
-
- FtwDevice->Signature = FTW_DEVICE_SIGNATURE;
- FtwDevice->FtwFvBlock = NULL;
- FtwDevice->FtwBackupFvb = NULL;
- FtwDevice->FtwWorkSpaceLba = (EFI_LBA) (-1);
- FtwDevice->FtwSpareLba = (EFI_LBA) (-1);
-
- FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);
- if (FtwDevice->WorkSpaceAddress == 0) {
- FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
- }
-
- FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);
- if (FtwDevice->SpareAreaAddress == 0) {
- FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);
- }
-
- *FtwData = FtwDevice;
- return EFI_SUCCESS;
-}
-
-
-/**
- Find the proper Firmware Volume Block protocol for FTW operation.
-
- @param[in, out] FtwDevice Pointer to the FTW device structure
-
- @retval EFI_SUCCESS Find the FVB protocol successfully.
- @retval EFI_NOT_FOUND No proper FVB protocol was found.
- @retval EFI_ABORTED Some data can not be got or be invalid.
-
-**/
-EFI_STATUS
-FindFvbForFtw (
- IN OUT EFI_FTW_DEVICE *FtwDevice
- )
-{
- EFI_STATUS Status;
- EFI_HANDLE *HandleBuffer;
- UINTN HandleCount;
- UINTN Index;
- EFI_PHYSICAL_ADDRESS FvbBaseAddress;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
- EFI_FVB_ATTRIBUTES_2 Attributes;
- UINT32 LbaIndex;
- UINTN BlockSize;
- UINTN NumberOfBlocks;
-
- HandleBuffer = NULL;
-
- //
- // Get all FVB handle.
- //
- Status = GetFvbCountAndBuffer (&HandleCount, &HandleBuffer);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Get the FVB to access variable store
- //
- Fvb = NULL;
- for (Index = 0; Index < HandleCount; Index += 1) {
- Status = FtwGetFvbByHandle (HandleBuffer[Index], &Fvb);
- if (EFI_ERROR (Status)) {
- Status = EFI_NOT_FOUND;
- break;
- }
-
- //
- // Ensure this FVB protocol support Write operation.
- //
- Status = Fvb->GetAttributes (Fvb, &Attributes);
- if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {
- continue;
- }
- //
- // Compare the address and select the right one
- //
- Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- //
- // Now, one FVB has one type of BlockSize.
- //
- Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&
- ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + BlockSize * NumberOfBlocks))) {
- FtwDevice->FtwFvBlock = Fvb;
- //
- // To get the LBA of work space
- //
- for (LbaIndex = 1; LbaIndex <= NumberOfBlocks; LbaIndex += 1) {
- if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + BlockSize * (LbaIndex - 1)))
- && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + BlockSize * LbaIndex))) {
- FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;
- //
- // Get the Work space size and Base(Offset)
- //
- FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;
- FtwDevice->WorkBlockSize = BlockSize;
- FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FtwDevice->WorkBlockSize * (LbaIndex - 1)));
- FtwDevice->NumberOfWorkSpaceBlock = FTW_BLOCKS (FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize, FtwDevice->WorkBlockSize);
- if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) {
- //
- // Check the alignment of work space address and length, they should be block size aligned when work space size is larger than one block size.
- //
- if (((FtwDevice->WorkSpaceAddress & (FtwDevice->WorkBlockSize - 1)) != 0) ||
- ((FtwDevice->WorkSpaceLength & (FtwDevice->WorkBlockSize - 1)) != 0)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Work space address or length is not block size aligned when work space size is larger than one block size\n"));
- FreePool (HandleBuffer);
- ASSERT (FALSE);
- return EFI_ABORTED;
- }
- } else if ((FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize) > FtwDevice->WorkBlockSize) {
- DEBUG ((EFI_D_ERROR, "Ftw: The work space range should not span blocks when work space size is less than one block size\n"));
- FreePool (HandleBuffer);
- ASSERT (FALSE);
- return EFI_ABORTED;
- }
- break;
- }
- }
- }
-
- if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&
- ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + BlockSize * NumberOfBlocks))) {
- FtwDevice->FtwBackupFvb = Fvb;
- //
- // To get the LBA of spare
- //
- for (LbaIndex = 1; LbaIndex <= NumberOfBlocks; LbaIndex += 1) {
- if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + BlockSize * (LbaIndex - 1)))
- && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + BlockSize * LbaIndex))) {
- //
- // Get the NumberOfSpareBlock and BlockSize
- //
- FtwDevice->FtwSpareLba = LbaIndex - 1;
- FtwDevice->SpareBlockSize = BlockSize;
- FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->SpareBlockSize;
- //
- // Check the range of spare area to make sure that it's in FV range
- //
- if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > NumberOfBlocks) {
- DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n"));
- FreePool (HandleBuffer);
- ASSERT (FALSE);
- return EFI_ABORTED;
- }
- //
- // Check the alignment of spare area address and length, they should be block size aligned
- //
- if (((FtwDevice->SpareAreaAddress & (FtwDevice->SpareBlockSize - 1)) != 0) ||
- ((FtwDevice->SpareAreaLength & (FtwDevice->SpareBlockSize - 1)) != 0)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Spare area address or length is not block size aligned\n"));
- FreePool (HandleBuffer);
- //
- // Report Status Code EFI_SW_EC_ABORTED.
- //
- REPORT_STATUS_CODE ((EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ABORTED));
- ASSERT (FALSE);
- CpuDeadLoop ();
- }
- break;
- }
- }
- }
- }
- FreePool (HandleBuffer);
-
- if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||
- (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {
- return EFI_ABORTED;
- }
- DEBUG ((EFI_D_INFO, "Ftw: FtwWorkSpaceLba - 0x%lx, WorkBlockSize - 0x%x, FtwWorkSpaceBase - 0x%x\n", FtwDevice->FtwWorkSpaceLba, FtwDevice->WorkBlockSize, FtwDevice->FtwWorkSpaceBase));
- DEBUG ((EFI_D_INFO, "Ftw: FtwSpareLba - 0x%lx, SpareBlockSize - 0x%x\n", FtwDevice->FtwSpareLba, FtwDevice->SpareBlockSize));
-
- return EFI_SUCCESS;
-}
-
-
-/**
- Initialization for Fault Tolerant Write protocol.
-
- @param[in, out] FtwDevice Pointer to the FTW device structure
-
- @retval EFI_SUCCESS Initialize the FTW protocol successfully.
- @retval EFI_NOT_FOUND No proper FVB protocol was found.
-
-**/
-EFI_STATUS
-InitFtwProtocol (
- IN OUT EFI_FTW_DEVICE *FtwDevice
- )
-{
- EFI_STATUS Status;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
- EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;
- UINTN Offset;
- EFI_HANDLE FvbHandle;
- EFI_LBA WorkSpaceLbaOffset;
-
- //
- // Find the right SMM Fvb protocol instance for FTW.
- //
- Status = FindFvbForFtw (FtwDevice);
- if (EFI_ERROR (Status)) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Calculate the start LBA of working block.
- //
- if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) {
- //
- // Working block is a standalone area which only contains working space.
- //
- FtwDevice->NumberOfWorkBlock = FtwDevice->NumberOfWorkSpaceBlock;
- } else {
- //
- // 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.
- //
- FtwDevice->NumberOfWorkBlock = (UINTN) (FtwDevice->FtwWorkSpaceLba + FtwDevice->NumberOfWorkSpaceBlock);
- while (FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize > FtwDevice->SpareAreaLength) {
- FtwDevice->NumberOfWorkBlock--;
- }
- }
- FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba + FtwDevice->NumberOfWorkSpaceBlock - FtwDevice->NumberOfWorkBlock;
- DEBUG ((EFI_D_INFO, "Ftw: NumberOfWorkBlock - 0x%x, FtwWorkBlockLba - 0x%lx\n", FtwDevice->NumberOfWorkBlock, FtwDevice->FtwWorkBlockLba));
-
- //
- // Calcualte the LBA and base of work space in spare block.
- // Note: Do not assume Spare Block and Work Block have same block size.
- //
- WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
- FtwDevice->FtwWorkSpaceLbaInSpare = (EFI_LBA) (((UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize + FtwDevice->FtwWorkSpaceBase) / FtwDevice->SpareBlockSize);
- FtwDevice->FtwWorkSpaceBaseInSpare = ((UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize + FtwDevice->FtwWorkSpaceBase) % FtwDevice->SpareBlockSize;
- DEBUG ((EFI_D_INFO, "Ftw: WorkSpaceLbaInSpare - 0x%lx, WorkSpaceBaseInSpare - 0x%x\n", FtwDevice->FtwWorkSpaceLbaInSpare, FtwDevice->FtwWorkSpaceBaseInSpare));
-
- //
- // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.
- //
- FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1);
- FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace;
-
- FtwDevice->FtwLastWriteHeader = NULL;
- FtwDevice->FtwLastWriteRecord = NULL;
-
- InitializeLocalWorkSpaceHeader ();
-
- //
- // Refresh the working space data from working block
- //
- Status = WorkSpaceRefresh (FtwDevice);
- ASSERT_EFI_ERROR (Status);
- //
- // If the working block workspace is not valid, try the spare block
- //
- if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
- //
- // Read from spare block
- //
- Status = ReadWorkSpaceData (
- FtwDevice->FtwBackupFvb,
- FtwDevice->SpareBlockSize,
- FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
- FtwDevice->FtwWorkSpaceBaseInSpare,
- FtwDevice->FtwWorkSpaceSize,
- FtwDevice->FtwWorkSpace
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // If spare block is valid, then replace working block content.
- //
- if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
- Status = FlushSpareBlockToWorkingBlock (FtwDevice);
- DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in InitFtwProtocol() - %r\n", Status));
- FtwAbort (&FtwDevice->FtwInstance);
- //
- // Refresh work space.
- //
- Status = WorkSpaceRefresh (FtwDevice);
- ASSERT_EFI_ERROR (Status);
- } else {
- DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n"));
- //
- // If both are invalid, then initialize work space.
- //
- SetMem (
- FtwDevice->FtwWorkSpace,
- FtwDevice->FtwWorkSpaceSize,
- FTW_ERASED_BYTE
- );
- InitWorkSpaceHeader (FtwDevice->FtwWorkSpaceHeader);
- //
- // Initialize the work space
- //
- Status = FtwReclaimWorkSpace (FtwDevice, FALSE);
- ASSERT_EFI_ERROR (Status);
- }
- }
- //
- // If the FtwDevice->FtwLastWriteRecord is 1st record of write header &&
- // (! SpareComplete) THEN call Abort().
- //
- if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) &&
- (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&
- IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
- ) {
- DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));
- FtwAbort (&FtwDevice->FtwInstance);
- }
- //
- // If Header is incompleted and the last record has completed, then
- // call Abort() to set the Header->Complete FLAG.
- //
- if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
- (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&
- IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)
- ) {
- DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));
- FtwAbort (&FtwDevice->FtwInstance);
- }
- //
- // To check the workspace buffer following last Write header/records is EMPTY or not.
- // If it's not EMPTY, FTW also need to call reclaim().
- //
- FtwHeader = FtwDevice->FtwLastWriteHeader;
- Offset = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;
- if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {
- Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
- }
-
- if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {
- Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
- ASSERT_EFI_ERROR (Status);
- }
-
- //
- // Restart if it's boot block
- //
- if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&
- (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)
- ) {
- if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) {
- Status = FlushSpareBlockToBootBlock (FtwDevice);
- DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status));
- ASSERT_EFI_ERROR (Status);
- FtwAbort (&FtwDevice->FtwInstance);
- } else {
- //
- // if (SpareCompleted) THEN Restart to fault tolerant write.
- //
- FvbHandle = NULL;
- FvbHandle = GetFvbByAddress ((EFI_PHYSICAL_ADDRESS) (UINTN) ((INT64) FtwDevice->SpareAreaAddress + FtwDevice->FtwLastWriteRecord->RelativeOffset), &Fvb);
- if (FvbHandle != NULL) {
- Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);
- DEBUG ((EFI_D_ERROR, "Ftw: Restart last write - %r\n", Status));
- ASSERT_EFI_ERROR (Status);
- }
- FtwAbort (&FtwDevice->FtwInstance);
- }
- }
- //
- // Hook the protocol API
- //
- FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize;
- FtwDevice->FtwInstance.Allocate = FtwAllocate;
- FtwDevice->FtwInstance.Write = FtwWrite;
- FtwDevice->FtwInstance.Restart = FtwRestart;
- FtwDevice->FtwInstance.Abort = FtwAbort;
- FtwDevice->FtwInstance.GetLastWrite = FtwGetLastWrite;
-
- return EFI_SUCCESS;
-}
-
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/SmmFaultTolerantWriteDxe.uni b/MdeModulePkg/Universal/FaultTolerantWriteDxe/SmmFaultTolerantWriteDxe.uni Binary files differdeleted file mode 100644 index 8b7cf4863b..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/SmmFaultTolerantWriteDxe.uni +++ /dev/null diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/SmmFaultTolerantWriteDxeExtra.uni b/MdeModulePkg/Universal/FaultTolerantWriteDxe/SmmFaultTolerantWriteDxeExtra.uni Binary files differdeleted file mode 100644 index 54aec337c5..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/SmmFaultTolerantWriteDxeExtra.uni +++ /dev/null diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c deleted file mode 100644 index 31f1e0bda6..0000000000 --- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c +++ /dev/null @@ -1,619 +0,0 @@ -/** @file
-
- Internal functions to operate Working Block Space.
-
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-
-#include "FaultTolerantWrite.h"
-
-EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER mWorkingBlockHeader = {ZERO_GUID, 0, 0, 0, 0, {0, 0, 0}, 0};
-
-/**
- Initialize a local work space header.
-
- Since Signature and WriteQueueSize have been known, Crc can be calculated out,
- then the work space header will be fixed.
-**/
-VOID
-InitializeLocalWorkSpaceHeader (
- VOID
- )
-{
- EFI_STATUS Status;
-
- //
- // Check signature with gEdkiiWorkingBlockSignatureGuid.
- //
- if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) {
- //
- // The local work space header has been initialized.
- //
- return;
- }
-
- SetMem (
- &mWorkingBlockHeader,
- sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
- FTW_ERASED_BYTE
- );
-
- //
- // Here using gEdkiiWorkingBlockSignatureGuid as the signature.
- //
- CopyMem (
- &mWorkingBlockHeader.Signature,
- &gEdkiiWorkingBlockSignatureGuid,
- sizeof (EFI_GUID)
- );
- mWorkingBlockHeader.WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
-
- //
- // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.
- //
-
- //
- // Calculate the Crc of woking block header
- //
- Status = gBS->CalculateCrc32 (
- &mWorkingBlockHeader,
- sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
- &mWorkingBlockHeader.Crc
- );
- ASSERT_EFI_ERROR (Status);
-
- mWorkingBlockHeader.WorkingBlockValid = FTW_VALID_STATE;
- mWorkingBlockHeader.WorkingBlockInvalid = FTW_INVALID_STATE;
-}
-
-/**
- Check to see if it is a valid work space.
-
-
- @param WorkingHeader Pointer of working block header
-
- @retval TRUE The work space is valid.
- @retval FALSE The work space is invalid.
-
-**/
-BOOLEAN
-IsValidWorkSpace (
- IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
- )
-{
- if (WorkingHeader == NULL) {
- return FALSE;
- }
-
- if (CompareMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) == 0) {
- return TRUE;
- }
-
- DEBUG ((EFI_D_ERROR, "Ftw: Work block header check error\n"));
- return FALSE;
-}
-
-/**
- Initialize a work space when there is no work space.
-
- @param WorkingHeader Pointer of working block header
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-InitWorkSpaceHeader (
- IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader
- )
-{
- if (WorkingHeader == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- CopyMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));
-
- return EFI_SUCCESS;
-}
-
-/**
- Read work space data from work block or spare block.
-
- @param FvBlock FVB Protocol interface to access the block.
- @param BlockSize The size of the block.
- @param Lba Lba of the block.
- @param Offset The offset within the block.
- @param Length The number of bytes to read from the block.
- @param Buffer The data is read.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-ReadWorkSpaceData (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- IN UINTN BlockSize,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- OUT UINT8 *Buffer
- )
-{
- EFI_STATUS Status;
- UINT8 *Ptr;
- UINTN MyLength;
-
- //
- // Calculate the real Offset and Lba to write.
- //
- while (Offset >= BlockSize) {
- Offset -= BlockSize;
- Lba++;
- }
-
- Ptr = Buffer;
- while (Length > 0) {
- if ((Offset + Length) > BlockSize) {
- MyLength = BlockSize - Offset;
- } else {
- MyLength = Length;
- }
-
- Status = FvBlock->Read (
- FvBlock,
- Lba,
- Offset,
- &MyLength,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- Offset = 0;
- Length -= MyLength;
- Ptr += MyLength;
- Lba++;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Write work space data to work block.
-
- @param FvBlock FVB Protocol interface to access the block.
- @param BlockSize The size of the block.
- @param Lba Lba of the block.
- @param Offset The offset within the block to place the data.
- @param Length The number of bytes to write to the block.
- @param Buffer The data to write.
-
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-WriteWorkSpaceData (
- IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,
- IN UINTN BlockSize,
- IN EFI_LBA Lba,
- IN UINTN Offset,
- IN UINTN Length,
- IN UINT8 *Buffer
- )
-{
- EFI_STATUS Status;
- UINT8 *Ptr;
- UINTN MyLength;
-
- //
- // Calculate the real Offset and Lba to write.
- //
- while (Offset >= BlockSize) {
- Offset -= BlockSize;
- Lba++;
- }
-
- Ptr = Buffer;
- while (Length > 0) {
- if ((Offset + Length) > BlockSize) {
- MyLength = BlockSize - Offset;
- } else {
- MyLength = Length;
- }
-
- Status = FvBlock->Write (
- FvBlock,
- Lba,
- Offset,
- &MyLength,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- Offset = 0;
- Length -= MyLength;
- Ptr += MyLength;
- Lba++;
- }
- return EFI_SUCCESS;
-}
-
-/**
- Read from working block to refresh the work space in memory.
-
- @param FtwDevice Point to private data of FTW driver
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_ABORTED The function could not complete successfully.
-
-**/
-EFI_STATUS
-WorkSpaceRefresh (
- IN EFI_FTW_DEVICE *FtwDevice
- )
-{
- EFI_STATUS Status;
- UINTN RemainingSpaceSize;
-
- //
- // Initialize WorkSpace as FTW_ERASED_BYTE
- //
- SetMem (
- FtwDevice->FtwWorkSpace,
- FtwDevice->FtwWorkSpaceSize,
- FTW_ERASED_BYTE
- );
-
- //
- // Read from working block
- //
- Status = ReadWorkSpaceData (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase,
- FtwDevice->FtwWorkSpaceSize,
- FtwDevice->FtwWorkSpace
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- //
- // Refresh the FtwLastWriteHeader
- //
- Status = FtwGetLastWriteHeader (
- FtwDevice->FtwWorkSpaceHeader,
- FtwDevice->FtwWorkSpaceSize,
- &FtwDevice->FtwLastWriteHeader
- );
- RemainingSpaceSize = FtwDevice->FtwWorkSpaceSize - ((UINTN) FtwDevice->FtwLastWriteHeader - (UINTN) FtwDevice->FtwWorkSpace);
- DEBUG ((EFI_D_INFO, "Ftw: Remaining work space size - %x\n", RemainingSpaceSize));
- //
- // If FtwGetLastWriteHeader() returns error, or the remaining space size is even not enough to contain
- // one EFI_FAULT_TOLERANT_WRITE_HEADER + one EFI_FAULT_TOLERANT_WRITE_RECORD(It will cause that the header
- // pointed by FtwDevice->FtwLastWriteHeader or record pointed by FtwDevice->FtwLastWriteRecord may contain invalid data),
- // it needs to reclaim work space.
- //
- if (EFI_ERROR (Status) || RemainingSpaceSize < sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD)) {
- //
- // reclaim work space in working block.
- //
- Status = FtwReclaimWorkSpace (FtwDevice, TRUE);
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "Ftw: Reclaim workspace - %r\n", Status));
- return EFI_ABORTED;
- }
- //
- // Read from working block again
- //
- Status = ReadWorkSpaceData (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase,
- FtwDevice->FtwWorkSpaceSize,
- FtwDevice->FtwWorkSpace
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- Status = FtwGetLastWriteHeader (
- FtwDevice->FtwWorkSpaceHeader,
- FtwDevice->FtwWorkSpaceSize,
- &FtwDevice->FtwLastWriteHeader
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
- }
- //
- // Refresh the FtwLastWriteRecord
- //
- Status = FtwGetLastWriteRecord (
- FtwDevice->FtwLastWriteHeader,
- &FtwDevice->FtwLastWriteRecord
- );
- if (EFI_ERROR (Status)) {
- return EFI_ABORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Reclaim the work space on the working block.
-
- @param FtwDevice Point to private data of FTW driver
- @param PreserveRecord Whether to preserve the working record is needed
-
- @retval EFI_SUCCESS The function completed successfully
- @retval EFI_OUT_OF_RESOURCES Allocate memory error
- @retval EFI_ABORTED The function could not complete successfully
-
-**/
-EFI_STATUS
-FtwReclaimWorkSpace (
- IN EFI_FTW_DEVICE *FtwDevice,
- IN BOOLEAN PreserveRecord
- )
-{
- EFI_STATUS Status;
- UINTN Length;
- EFI_FAULT_TOLERANT_WRITE_HEADER *Header;
- UINT8 *TempBuffer;
- UINTN TempBufferSize;
- UINTN SpareBufferSize;
- UINT8 *SpareBuffer;
- EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;
- UINTN Index;
- UINT8 *Ptr;
- EFI_LBA WorkSpaceLbaOffset;
-
- DEBUG ((EFI_D_INFO, "Ftw: start to reclaim work space\n"));
-
- WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;
-
- //
- // Read all original data from working block to a memory buffer
- //
- TempBufferSize = FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize;
- TempBuffer = AllocateZeroPool (TempBufferSize);
- if (TempBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- Ptr = TempBuffer;
- for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {
- Length = FtwDevice->WorkBlockSize;
- Status = FtwDevice->FtwFvBlock->Read (
- FtwDevice->FtwFvBlock,
- FtwDevice->FtwWorkBlockLba + Index,
- 0,
- &Length,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (TempBuffer);
- return EFI_ABORTED;
- }
-
- Ptr += Length;
- }
- //
- // Clean up the workspace, remove all the completed records.
- //
- Ptr = TempBuffer +
- (UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +
- FtwDevice->FtwWorkSpaceBase;
-
- //
- // Clear the content of buffer that will save the new work space data
- //
- SetMem (Ptr, FtwDevice->FtwWorkSpaceSize, FTW_ERASED_BYTE);
-
- //
- // Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer
- //
- CopyMem (
- Ptr,
- FtwDevice->FtwWorkSpaceHeader,
- sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)
- );
- if (PreserveRecord) {
- //
- // Get the last record following the header,
- //
- Status = FtwGetLastWriteHeader (
- FtwDevice->FtwWorkSpaceHeader,
- FtwDevice->FtwWorkSpaceSize,
- &FtwDevice->FtwLastWriteHeader
- );
- Header = FtwDevice->FtwLastWriteHeader;
- if (!EFI_ERROR (Status) && (Header != NULL) && (Header->Complete != FTW_VALID_STATE) && (Header->HeaderAllocated == FTW_VALID_STATE)) {
- CopyMem (
- Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),
- FtwDevice->FtwLastWriteHeader,
- FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)
- );
- }
- }
-
- CopyMem (
- FtwDevice->FtwWorkSpace,
- Ptr,
- FtwDevice->FtwWorkSpaceSize
- );
-
- FtwGetLastWriteHeader (
- FtwDevice->FtwWorkSpaceHeader,
- FtwDevice->FtwWorkSpaceSize,
- &FtwDevice->FtwLastWriteHeader
- );
-
- FtwGetLastWriteRecord (
- FtwDevice->FtwLastWriteHeader,
- &FtwDevice->FtwLastWriteRecord
- );
-
- //
- // Set the WorkingBlockValid and WorkingBlockInvalid as INVALID
- //
- WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (TempBuffer +
- (UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +
- FtwDevice->FtwWorkSpaceBase);
- WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE;
- WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;
-
- //
- // Try to keep the content of spare block
- // Save spare block into a spare backup memory buffer (Sparebuffer)
- //
- SpareBufferSize = FtwDevice->SpareAreaLength;
- SpareBuffer = AllocatePool (SpareBufferSize);
- if (SpareBuffer == NULL) {
- FreePool (TempBuffer);
- return EFI_OUT_OF_RESOURCES;
- }
-
- Ptr = SpareBuffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Length = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Read (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &Length,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (TempBuffer);
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- Ptr += Length;
- }
- //
- // Write the memory buffer to spare block
- //
- Status = FtwEraseSpareBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- FreePool (TempBuffer);
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
- Ptr = TempBuffer;
- for (Index = 0; TempBufferSize > 0; Index += 1) {
- if (TempBufferSize > FtwDevice->SpareBlockSize) {
- Length = FtwDevice->SpareBlockSize;
- } else {
- Length = TempBufferSize;
- }
- Status = FtwDevice->FtwBackupFvb->Write (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &Length,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (TempBuffer);
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- Ptr += Length;
- TempBufferSize -= Length;
- }
- //
- // Free TempBuffer
- //
- FreePool (TempBuffer);
-
- //
- // Set the WorkingBlockValid in spare block
- //
- Status = FtwUpdateFvState (
- FtwDevice->FtwBackupFvb,
- FtwDevice->SpareBlockSize,
- FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,
- FtwDevice->FtwWorkSpaceBaseInSpare + sizeof (EFI_GUID) + sizeof (UINT32),
- WORKING_BLOCK_VALID
- );
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
- //
- // Before erase the working block, set WorkingBlockInvalid in working block.
- //
- // Offset = OFFSET_OF(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER,
- // WorkingBlockInvalid);
- //
- Status = FtwUpdateFvState (
- FtwDevice->FtwFvBlock,
- FtwDevice->WorkBlockSize,
- FtwDevice->FtwWorkSpaceLba,
- FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),
- WORKING_BLOCK_INVALID
- );
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE;
-
- //
- // Write the spare block to working block
- //
- Status = FlushSpareBlockToWorkingBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return Status;
- }
- //
- // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.
- //
- Status = FtwEraseSpareBlock (FtwDevice);
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
- Ptr = SpareBuffer;
- for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {
- Length = FtwDevice->SpareBlockSize;
- Status = FtwDevice->FtwBackupFvb->Write (
- FtwDevice->FtwBackupFvb,
- FtwDevice->FtwSpareLba + Index,
- 0,
- &Length,
- Ptr
- );
- if (EFI_ERROR (Status)) {
- FreePool (SpareBuffer);
- return EFI_ABORTED;
- }
-
- Ptr += Length;
- }
-
- FreePool (SpareBuffer);
-
- DEBUG ((EFI_D_INFO, "Ftw: reclaim work space successfully\n"));
-
- return EFI_SUCCESS;
-}
|