]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c
Retiring the ANT/JAVA build and removing the older EDK II packages that required...
[mirror_edk2.git] / EdkModulePkg / Universal / FirmwareVolume / FaultTolerantWriteLite / Dxe / FtwLite.c
diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c
deleted file mode 100644 (file)
index a120c7f..0000000
+++ /dev/null
@@ -1,931 +0,0 @@
-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation                                                         \r
-All rights reserved. This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-                                                                                          \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.  \r
-\r
-\r
-Module Name:\r
-\r
-  FtwLite.c\r
-\r
-Abstract:\r
-\r
-  This is a simple fault tolerant write driver, based on PlatformFd library.\r
-  And it only supports write BufferSize <= SpareAreaLength.\r
-\r
-  This boot service only protocol provides fault tolerant write capability for \r
-  block devices.  The protocol has internal non-volatile intermediate storage \r
-  of the data and private information. It should be able to recover \r
-  automatically from a critical fault, such as power failure. \r
-\r
-Notes:\r
-\r
-  The implementation uses an FTW Lite (Fault Tolerant Write) Work Space. \r
-  This work space is a memory copy of the work space on the Woring Block,\r
-  the size of the work space is the FTW_WORK_SPACE_SIZE bytes.\r
-\r
---*/\r
-\r
-#include <FtwLite.h>\r
-\r
-//\r
-// In write function, we should check the target range to prevent the user\r
-// from writing Spare block and Working space directly.\r
-//\r
-//\r
-// Fault Tolerant Write Protocol API\r
-//\r
-EFI_STATUS\r
-EFIAPI\r
-FtwLiteWrite (\r
-  IN EFI_FTW_LITE_PROTOCOL                 *This,\r
-  IN EFI_HANDLE                            FvbHandle,\r
-  IN EFI_LBA                               Lba,\r
-  IN UINTN                                 Offset,\r
-  IN OUT UINTN                             *NumBytes,\r
-  IN VOID                                  *Buffer\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-    Starts a target block update. This function will record data about write \r
-    in fault tolerant storage and will complete the write in a recoverable \r
-    manner, ensuring at all times that either the original contents or \r
-    the modified contents are available.\r
-\r
-Arguments:\r
-    This             - Calling context\r
-    FvbHandle        - The handle of FVB protocol that provides services for \r
-                       reading, writing, and erasing the target block.\r
-    Lba              - The logical block address of the target block.  \r
-    Offset           - The offset within the target block to place the data.\r
-    NumBytes         - The number of bytes to write to the target block.\r
-    Buffer           - The data to write.\r
-\r
-Returns:\r
-    EFI_SUCCESS          - The function completed successfully\r
-    EFI_BAD_BUFFER_SIZE  - The write would span a target block, which is not \r
-                           a valid action.\r
-    EFI_ACCESS_DENIED    - No writes have been allocated.\r
-    EFI_NOT_FOUND        - Cannot find FVB by handle.\r
-    EFI_OUT_OF_RESOURCES - Cannot allocate memory.\r
-    EFI_ABORTED          - The function could not complete successfully.\r
-\r
---*/\r
-{\r
-  EFI_STATUS                          Status;\r
-  EFI_FTW_LITE_DEVICE                 *FtwLiteDevice;\r
-  EFI_FTW_LITE_RECORD                 *Record;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_PHYSICAL_ADDRESS                FvbPhysicalAddress;\r
-  UINTN                               MyLength;\r
-  UINTN                               MyOffset;\r
-  UINTN                               MyBufferSize;\r
-  UINT8                               *MyBuffer;\r
-  UINTN                               SpareBufferSize;\r
-  UINT8                               *SpareBuffer;\r
-  UINTN                               Index;\r
-  UINT8                               *Ptr;\r
-  EFI_DEV_PATH_PTR                    DevPtr;\r
-\r
-  //\r
-  // Refresh work space and get last record\r
-  //\r
-  FtwLiteDevice = FTW_LITE_CONTEXT_FROM_THIS (This);\r
-  Status        = WorkSpaceRefresh (FtwLiteDevice);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  Record = FtwLiteDevice->FtwLastRecord;\r
-\r
-  //\r
-  // Check the flags of last write record\r
-  //\r
-  if ((Record->WriteAllocated == FTW_VALID_STATE) || (Record->SpareCompleted == FTW_VALID_STATE)) {\r
-    return EFI_ACCESS_DENIED;\r
-  }\r
-  //\r
-  // IF former record has completed, THEN use next record\r
-  //\r
-  if (Record->WriteCompleted == FTW_VALID_STATE) {\r
-    Record++;\r
-    FtwLiteDevice->FtwLastRecord = Record;\r
-  }\r
-\r
-  MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
-\r
-  //\r
-  // Check if the input data can fit within the target block\r
-  //\r
-  if ((Offset +*NumBytes) > FtwLiteDevice->SpareAreaLength) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
-  //\r
-  // Check if there is enough free space for allocate a record\r
-  //\r
-  if ((MyOffset + WRITE_TOTAL_SIZE) > FtwLiteDevice->FtwWorkSpaceSize) {\r
-    Status = FtwReclaimWorkSpace (FtwLiteDevice);\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "FtwLite: Reclaim work space - %r", Status));\r
-      return EFI_ABORTED;\r
-    }\r
-  }\r
-  //\r
-  // Get the FVB protocol by handle\r
-  //\r
-  Status = FtwGetFvbByHandle (FvbHandle, &Fvb);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-  //\r
-  // Allocate a write record in workspace.\r
-  // Update Header->WriteAllocated as VALID\r
-  //\r
-  Status = FtwUpdateFvState (\r
-            FtwLiteDevice->FtwFvBlock,\r
-            FtwLiteDevice->FtwWorkSpaceLba,\r
-            FtwLiteDevice->FtwWorkSpaceBase + MyOffset,\r
-            WRITE_ALLOCATED\r
-            );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Allocate record - %r\n", Status));\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  Record->WriteAllocated = FTW_VALID_STATE;\r
-\r
-  //\r
-  // Prepare data of write record, filling DevPath with memory mapped address.\r
-  //\r
-  DevPtr.MemMap                 = (MEMMAP_DEVICE_PATH *) &Record->DevPath;\r
-  DevPtr.MemMap->Header.Type    = HARDWARE_DEVICE_PATH;\r
-  DevPtr.MemMap->Header.SubType = HW_MEMMAP_DP;\r
-  SetDevicePathNodeLength (&DevPtr.MemMap->Header, sizeof (MEMMAP_DEVICE_PATH));\r
-\r
-  Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Get FVB physical address - %r\n", Status));\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  DevPtr.MemMap->MemoryType       = EfiMemoryMappedIO;\r
-  DevPtr.MemMap->StartingAddress  = FvbPhysicalAddress;\r
-  DevPtr.MemMap->EndingAddress    = FvbPhysicalAddress +*NumBytes;\r
-  //\r
-  // ignored!\r
-  //\r
-  Record->Lba       = Lba;\r
-  Record->Offset    = Offset;\r
-  Record->NumBytes  = *NumBytes;\r
-\r
-  //\r
-  // Write the record to the work space.\r
-  //\r
-  MyOffset  = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
-  MyLength  = FTW_LITE_RECORD_SIZE;\r
-\r
-  Status = FtwLiteDevice->FtwFvBlock->Write (\r
-                                        FtwLiteDevice->FtwFvBlock,\r
-                                        FtwLiteDevice->FtwWorkSpaceLba,\r
-                                        FtwLiteDevice->FtwWorkSpaceBase + MyOffset,\r
-                                        &MyLength,\r
-                                        (UINT8 *) Record\r
-                                        );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_ABORTED;\r
-  }\r
-  //\r
-  // Record has been written to working block, then write data.\r
-  //\r
-  //\r
-  // Allocate a memory buffer\r
-  //\r
-  MyBufferSize  = FtwLiteDevice->SpareAreaLength;\r
-  MyBuffer      = AllocatePool (MyBufferSize);\r
-  if (MyBuffer == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  //\r
-  // Starting at Lba, if the number of the rest blocks on Fvb is less\r
-  // than NumberOfSpareBlock.\r
-  //\r
-  //\r
-  // Read all original data from target block to memory buffer\r
-  //\r
-  if (IsInWorkingBlock (FtwLiteDevice, Fvb, Lba)) {\r
-    //\r
-    // If target block falls into working block, we must follow the process of\r
-    // updating working block.\r
-    //\r
-    Ptr = MyBuffer;\r
-    for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-      MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
-      Status = FtwLiteDevice->FtwFvBlock->Read (\r
-                                            FtwLiteDevice->FtwFvBlock,\r
-                                            FtwLiteDevice->FtwWorkBlockLba + Index,\r
-                                            0,\r
-                                            &MyLength,\r
-                                            Ptr\r
-                                            );\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (MyBuffer);\r
-        return EFI_ABORTED;\r
-      }\r
-\r
-      Ptr += MyLength;\r
-    }\r
-    //\r
-    // Update Offset by adding the offset from the start LBA of working block to\r
-    // the target LBA. The target block can not span working block!\r
-    //\r
-    Offset = (((UINTN) (Lba - FtwLiteDevice->FtwWorkBlockLba)) * FtwLiteDevice->SizeOfSpareBlock + Offset);\r
-    ASSERT ((Offset +*NumBytes) <= FtwLiteDevice->SpareAreaLength);\r
-\r
-  } else {\r
-\r
-    Ptr = MyBuffer;\r
-    for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-      MyLength  = FtwLiteDevice->SizeOfSpareBlock;\r
-      Status    = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr);\r
-      if (EFI_ERROR (Status)) {\r
-        FreePool (MyBuffer);\r
-        return EFI_ABORTED;\r
-      }\r
-\r
-      Ptr += MyLength;\r
-    }\r
-  }\r
-  //\r
-  // Overwrite the updating range data with\r
-  // the input buffer content\r
-  //\r
-  CopyMem (MyBuffer + Offset, Buffer, *NumBytes);\r
-\r
-  //\r
-  // Try to keep the content of spare block\r
-  // Save spare block into a spare backup memory buffer (Sparebuffer)\r
-  //\r
-  SpareBufferSize = FtwLiteDevice->SpareAreaLength;\r
-  SpareBuffer     = AllocatePool (SpareBufferSize);\r
-  if (SpareBuffer == NULL) {\r
-    FreePool (MyBuffer);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  Ptr = SpareBuffer;\r
-  for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-    MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
-    Status = FtwLiteDevice->FtwBackupFvb->Read (\r
-                                            FtwLiteDevice->FtwBackupFvb,\r
-                                            FtwLiteDevice->FtwSpareLba + Index,\r
-                                            0,\r
-                                            &MyLength,\r
-                                            Ptr\r
-                                            );\r
-    if (EFI_ERROR (Status)) {\r
-      FreePool (MyBuffer);\r
-      FreePool (SpareBuffer);\r
-      return EFI_ABORTED;\r
-    }\r
-\r
-    Ptr += MyLength;\r
-  }\r
-  //\r
-  // Write the memory buffer to spare block\r
-  // Don't forget to erase Flash first.\r
-  //\r
-  Status  = FtwEraseSpareBlock (FtwLiteDevice);\r
-  Ptr     = MyBuffer;\r
-  for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-    MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
-    Status = FtwLiteDevice->FtwBackupFvb->Write (\r
-                                            FtwLiteDevice->FtwBackupFvb,\r
-                                            FtwLiteDevice->FtwSpareLba + Index,\r
-                                            0,\r
-                                            &MyLength,\r
-                                            Ptr\r
-                                            );\r
-    if (EFI_ERROR (Status)) {\r
-      FreePool (MyBuffer);\r
-      FreePool (SpareBuffer);\r
-      return EFI_ABORTED;\r
-    }\r
-\r
-    Ptr += MyLength;\r
-  }\r
-  //\r
-  // Free MyBuffer\r
-  //\r
-  FreePool (MyBuffer);\r
-\r
-  //\r
-  // Set the SpareCompleteD in the FTW record,\r
-  //\r
-  MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
-  Status = FtwUpdateFvState (\r
-            FtwLiteDevice->FtwFvBlock,\r
-            FtwLiteDevice->FtwWorkSpaceLba,\r
-            FtwLiteDevice->FtwWorkSpaceBase + MyOffset,\r
-            SPARE_COMPLETED\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (SpareBuffer);\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  Record->SpareCompleted = FTW_VALID_STATE;\r
-\r
-  //\r
-  //  Since the content has already backuped in spare block, the write is\r
-  //  guaranteed to be completed with fault tolerant manner.\r
-  //\r
-  Status = FtwWriteRecord (FtwLiteDevice, Fvb);\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (SpareBuffer);\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  Record++;\r
-  FtwLiteDevice->FtwLastRecord = Record;\r
-\r
-  //\r
-  // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.\r
-  //\r
-  Status  = FtwEraseSpareBlock (FtwLiteDevice);\r
-  Ptr     = SpareBuffer;\r
-  for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-    MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
-    Status = FtwLiteDevice->FtwBackupFvb->Write (\r
-                                            FtwLiteDevice->FtwBackupFvb,\r
-                                            FtwLiteDevice->FtwSpareLba + Index,\r
-                                            0,\r
-                                            &MyLength,\r
-                                            Ptr\r
-                                            );\r
-    if (EFI_ERROR (Status)) {\r
-      FreePool (SpareBuffer);\r
-      return EFI_ABORTED;\r
-    }\r
-\r
-    Ptr += MyLength;\r
-  }\r
-  //\r
-  // All success.\r
-  //\r
-  FreePool (SpareBuffer);\r
-\r
-  DEBUG (\r
-    (EFI_D_FTW_LITE,\r
-    "FtwLite: Write() success, (Lba:Offset)=(%lx:0x%x), NumBytes: 0x%x\n",\r
-    Lba,\r
-    Offset,\r
-    *NumBytes)\r
-    );\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-FtwWriteRecord (\r
-  IN EFI_FTW_LITE_DEVICE                   *FtwLiteDevice,\r
-  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *Fvb\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-    Write a record with fault tolerant mannaer.\r
-    Since the content has already backuped in spare block, the write is \r
-    guaranteed to be completed with fault tolerant manner.\r
-    \r
-Arguments:\r
-    FtwLiteDevice       - The private data of FTW_LITE driver\r
-    Fvb                 - The FVB protocol that provides services for \r
-                          reading, writing, and erasing the target block.\r
-\r
-Returns:\r
-    EFI_SUCCESS         - The function completed successfully\r
-    EFI_ABORTED         - The function could not complete successfully\r
-\r
---*/\r
-{\r
-  EFI_STATUS          Status;\r
-  EFI_FTW_LITE_RECORD *Record;\r
-  EFI_LBA             WorkSpaceLbaOffset;  \r
-  UINTN               Offset;\r
-\r
-  //\r
-  // Spare Complete but Destination not complete,\r
-  // Recover the targt block with the spare block.\r
-  //\r
-  Record = FtwLiteDevice->FtwLastRecord;\r
-\r
-  //\r
-  // IF target block is working block, THEN Flush Spare Block To Working Block;\r
-  // ELSE IF target block is boot block, THEN Flush Spare Block To boot Block;\r
-  // ELSE flush spare block to normal target block.ENDIF\r
-  //\r
-  if (IsInWorkingBlock (FtwLiteDevice, Fvb, Record->Lba)) {\r
-    //\r
-    // If target block is working block, Attention:\r
-    // it's required to set SPARE_COMPLETED to spare block.\r
-    //\r
-    WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba;\r
-    Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
-    Status = FtwUpdateFvState (\r
-              FtwLiteDevice->FtwBackupFvb,\r
-              FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset,\r
-              FtwLiteDevice->FtwWorkSpaceBase + Offset,\r
-              SPARE_COMPLETED\r
-              );\r
-    ASSERT_EFI_ERROR (Status);\r
-\r
-    Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);\r
-  } else if (IsBootBlock (FtwLiteDevice, Fvb, Record->Lba)) {\r
-    //\r
-    // Update boot block\r
-    //\r
-    Status = FlushSpareBlockToBootBlock (FtwLiteDevice);\r
-  } else {\r
-    //\r
-    // Update blocks other than working block or boot block\r
-    //\r
-    Status = FlushSpareBlockToTargetBlock (FtwLiteDevice, Fvb, Record->Lba);\r
-  }\r
-\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Set WriteCompleted flag in record\r
-  //\r
-  Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
-  Status = FtwUpdateFvState (\r
-            FtwLiteDevice->FtwFvBlock,\r
-            FtwLiteDevice->FtwWorkSpaceLba,\r
-            FtwLiteDevice->FtwWorkSpaceBase + Offset,\r
-            WRITE_COMPLETED\r
-            );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Record->WriteCompleted = FTW_VALID_STATE;\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-FtwRestart (\r
-  IN EFI_FTW_LITE_DEVICE    *FtwLiteDevice\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-    Restarts a previously interrupted write. The caller must provide the \r
-    block protocol needed to complete the interrupted write.\r
-    \r
-Arguments:\r
-    FtwLiteDevice       - The private data of FTW_LITE driver\r
-    FvbHandle           - The handle of FVB protocol that provides services for \r
-                          reading, writing, and erasing the target block.\r
-\r
-Returns:\r
-    EFI_SUCCESS         - The function completed successfully\r
-    EFI_ACCESS_DENIED   - No pending writes exist\r
-    EFI_NOT_FOUND       - FVB protocol not found by the handle\r
-    EFI_ABORTED         - The function could not complete successfully\r
-\r
---*/\r
-{\r
-  EFI_STATUS                          Status;\r
-  EFI_FTW_LITE_RECORD                 *Record;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_DEV_PATH_PTR                    DevPathPtr;\r
-\r
-  //\r
-  // Spare Completed but Destination not complete,\r
-  // Recover the targt block with the spare block.\r
-  //\r
-  Record = FtwLiteDevice->FtwLastRecord;\r
-\r
-  //\r
-  // Only support memory mapped FVB device path by now.\r
-  //\r
-  DevPathPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath;\r
-  if (!((DevPathPtr.MemMap->Header.Type == HARDWARE_DEVICE_PATH) && (DevPathPtr.MemMap->Header.SubType == HW_MEMMAP_DP))\r
-      ) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Device Path is not memory mapped\n"));\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  Status = GetFvbByAddress (DevPathPtr.MemMap->StartingAddress, &Fvb);\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-  //\r
-  //  Since the content has already backuped in spare block, the write is\r
-  //  guaranteed to be completed with fault tolerant manner.\r
-  //\r
-  Status = FtwWriteRecord (FtwLiteDevice, Fvb);\r
-  DEBUG ((EFI_D_FTW_INFO, "FtwLite: Restart() - %r\n", Status));\r
-\r
-  Record++;\r
-  FtwLiteDevice->FtwLastRecord = Record;\r
-\r
-  //\r
-  // Erase Spare block\r
-  // This is restart, no need to keep spareblock content.\r
-  //\r
-  FtwEraseSpareBlock (FtwLiteDevice);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-FtwAbort (\r
-  IN EFI_FTW_LITE_DEVICE    *FtwLiteDevice\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-    Aborts all previous allocated writes.\r
-\r
-Arguments:\r
-    FtwLiteDevice    - The private data of FTW_LITE driver\r
-\r
-Returns:\r
-    EFI_SUCCESS      - The function completed successfully\r
-    EFI_ABORTED      - The function could not complete successfully.\r
-    EFI_NOT_FOUND    - No allocated writes exist.\r
-\r
---*/\r
-{\r
-  EFI_STATUS  Status;\r
-  UINTN       Offset;\r
-\r
-  if (FtwLiteDevice->FtwLastRecord->WriteCompleted == FTW_VALID_STATE) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-  //\r
-  // Update the complete state of the header as VALID and abort.\r
-  //\r
-  Offset = (UINT8 *) FtwLiteDevice->FtwLastRecord - FtwLiteDevice->FtwWorkSpace;\r
-  Status = FtwUpdateFvState (\r
-            FtwLiteDevice->FtwFvBlock,\r
-            FtwLiteDevice->FtwWorkSpaceLba,\r
-            FtwLiteDevice->FtwWorkSpaceBase + Offset,\r
-            WRITE_COMPLETED\r
-            );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_ABORTED;\r
-  }\r
-\r
-  FtwLiteDevice->FtwLastRecord->WriteCompleted  = FTW_VALID_STATE;\r
-\r
-  Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord);\r
-\r
-  //\r
-  // Erase the spare block\r
-  //\r
-  Status = FtwEraseSpareBlock (FtwLiteDevice);\r
-\r
-  DEBUG ((EFI_D_FTW_INFO, "FtwLite: Abort() success \n"));\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-InitializeFtwLite (\r
-  IN EFI_HANDLE         ImageHandle,\r
-  IN EFI_SYSTEM_TABLE   *SystemTable\r
-  )\r
-/*++\r
-  Routine Description: \r
-    This function is the entry point of the Fault Tolerant Write driver.\r
-  \r
-  Arguments: \r
-    ImageHandle   - EFI_HANDLE: A handle for the image that is initializing \r
-                    this driver\r
-    SystemTable   - EFI_SYSTEM_TABLE: A pointer to the EFI system table\r
-        \r
-  Returns:  \r
-    EFI_SUCCESS           - FTW has finished the initialization\r
-    EFI_ABORTED           - FTW initialization error\r
-\r
---*/\r
-{\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  UINTN                               Index;\r
-  EFI_HANDLE                          *HandleBuffer;\r
-  UINTN                               HandleCount;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
-  EFI_PHYSICAL_ADDRESS                BaseAddress;\r
-  EFI_FTW_LITE_DEVICE                 *FtwLiteDevice;\r
-  EFI_FTW_LITE_RECORD                 *Record;\r
-  UINTN                               Length;\r
-  EFI_STATUS                          Status;\r
-  UINTN                               Offset;\r
-  EFI_FV_BLOCK_MAP_ENTRY              *FvbMapEntry;\r
-  UINT32                              LbaIndex;\r
-\r
-  //\r
-  // Allocate Private data of this driver,\r
-  // INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE].\r
-  //\r
-  FtwLiteDevice = NULL;\r
-  FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + FTW_WORK_SPACE_SIZE);\r
-  if (FtwLiteDevice != NULL) {\r
-    Status = EFI_SUCCESS;\r
-  } else {\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ZeroMem (FtwLiteDevice, sizeof (EFI_FTW_LITE_DEVICE));\r
-  FtwLiteDevice->Signature = FTW_LITE_DEVICE_SIGNATURE;\r
-\r
-  //\r
-  // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.\r
-  //\r
-  FtwLiteDevice->FtwWorkSpace     = (UINT8 *) (FtwLiteDevice + 1);\r
-  FtwLiteDevice->FtwWorkSpaceSize = FTW_WORK_SPACE_SIZE;\r
-  SetMem (\r
-    FtwLiteDevice->FtwWorkSpace,\r
-    FtwLiteDevice->FtwWorkSpaceSize,\r
-    FTW_ERASED_BYTE\r
-    );\r
-  FtwLiteDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwLiteDevice->FtwWorkSpace;\r
-\r
-  FtwLiteDevice->FtwLastRecord      = NULL;\r
-\r
-  FtwLiteDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);\r
-  FtwLiteDevice->WorkSpaceLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);\r
-\r
-  FtwLiteDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);\r
-  FtwLiteDevice->SpareAreaLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);\r
-\r
-  ASSERT ((FtwLiteDevice->WorkSpaceLength != 0) && (FtwLiteDevice->SpareAreaLength != 0));\r
-\r
-  //\r
-  // Locate FVB protocol\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                  NULL,\r
-                  &HandleCount,\r
-                  &HandleBuffer\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  ASSERT (HandleCount > 0);\r
-\r
-  FtwLiteDevice->FtwFvBlock       = NULL;\r
-  FtwLiteDevice->FtwBackupFvb     = NULL;\r
-  FtwLiteDevice->FtwWorkSpaceLba  = (EFI_LBA) (-1);\r
-  FtwLiteDevice->FtwSpareLba      = (EFI_LBA) (-1);\r
-  for (Index = 0; Index < HandleCount; Index += 1) {\r
-    Status = gBS->HandleProtocol (\r
-                    HandleBuffer[Index],\r
-                    &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                    (VOID **) &Fvb\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
-\r
-    Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);\r
-    if (EFI_ERROR (Status)) {\r
-      continue;\r
-    }\r
-\r
-    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress);\r
-\r
-    if ((FtwLiteDevice->WorkSpaceAddress >= BaseAddress) &&\r
-        (FtwLiteDevice->WorkSpaceAddress <= (BaseAddress + FwVolHeader->FvLength))\r
-        ) {\r
-      FtwLiteDevice->FtwFvBlock = Fvb;\r
-      //\r
-      // To get the LBA of work space\r
-      //\r
-      if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
-        //\r
-        // FV may have multiple types of BlockLength\r
-        //\r
-        FvbMapEntry = &FwVolHeader->FvBlockMap[0];\r
-        while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->BlockLength == 0))) {\r
-          for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-            if (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->BlockLength * LbaIndex)) {\r
-              FtwLiteDevice->FtwWorkSpaceLba = LbaIndex - 1;\r
-              //\r
-              // Get the Work space size and Base(Offset)\r
-              //\r
-              FtwLiteDevice->FtwWorkSpaceSize = FtwLiteDevice->WorkSpaceLength;\r
-              FtwLiteDevice->FtwWorkSpaceBase = (UINTN) (FtwLiteDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->BlockLength * (LbaIndex - 1)));\r
-              break;\r
-            }\r
-          }\r
-          //\r
-          // end for\r
-          //\r
-          FvbMapEntry++;\r
-        }\r
-        //\r
-        // end while\r
-        //\r
-      }\r
-    }\r
-\r
-    if ((FtwLiteDevice->SpareAreaAddress >= BaseAddress) &&\r
-        (FtwLiteDevice->SpareAreaAddress <= (BaseAddress + FwVolHeader->FvLength))\r
-        ) {\r
-      FtwLiteDevice->FtwBackupFvb = Fvb;\r
-      //\r
-      // To get the LBA of spare\r
-      //\r
-      if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
-        //\r
-        // FV may have multiple types of BlockLength\r
-        //\r
-        FvbMapEntry = &FwVolHeader->FvBlockMap[0];\r
-        while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->BlockLength == 0))) {\r
-          for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-            if (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->BlockLength * LbaIndex)) {\r
-              //\r
-              // Get the NumberOfSpareBlock and SizeOfSpareBlock\r
-              //\r
-              FtwLiteDevice->FtwSpareLba        = LbaIndex - 1;\r
-              FtwLiteDevice->SizeOfSpareBlock   = FvbMapEntry->BlockLength;\r
-              FtwLiteDevice->NumberOfSpareBlock = FtwLiteDevice->SpareAreaLength / FtwLiteDevice->SizeOfSpareBlock;\r
-              //\r
-              // Check the range of spare area to make sure that it's in FV range\r
-              //\r
-              ASSERT ((FtwLiteDevice->FtwSpareLba + FtwLiteDevice->NumberOfSpareBlock) <= FvbMapEntry->NumBlocks);\r
-              break;\r
-            }\r
-          }\r
-\r
-          FvbMapEntry++;\r
-        }\r
-        //\r
-        // end while\r
-        //\r
-      }\r
-    }\r
-  }\r
-  //\r
-  // Calculate the start LBA of working block. Working block is an area which\r
-  // contains working space in its last block and has the same size as spare\r
-  // block, unless there are not enough blocks before the block that contains\r
-  // working space.\r
-  //\r
-  FtwLiteDevice->FtwWorkBlockLba = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->NumberOfSpareBlock + 1;\r
-  if ((INT64) (FtwLiteDevice->FtwWorkBlockLba) < 0) {\r
-    FtwLiteDevice->FtwWorkBlockLba = 0;\r
-  }\r
-\r
-  if ((FtwLiteDevice->FtwFvBlock == NULL) ||\r
-      (FtwLiteDevice->FtwBackupFvb == NULL) ||\r
-      (FtwLiteDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) ||\r
-      (FtwLiteDevice->FtwSpareLba == (EFI_LBA) (-1))\r
-      ) {\r
-    DEBUG ((EFI_D_ERROR, "FtwLite: Working or spare FVB not ready\n"));\r
-    ASSERT_EFI_ERROR (Status);\r
-  }\r
-  //\r
-  // Refresh workspace data from working block\r
-  //\r
-  Status = WorkSpaceRefresh (FtwLiteDevice);\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // If the working block workspace is not valid, try the spare block\r
-  //\r
-  if (!IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace invalid, read from backup\n"));\r
-    //\r
-    // Read from spare block\r
-    //\r
-    Length = FtwLiteDevice->FtwWorkSpaceSize;\r
-    Status = FtwLiteDevice->FtwBackupFvb->Read (\r
-                                            FtwLiteDevice->FtwBackupFvb,\r
-                                            FtwLiteDevice->FtwSpareLba,\r
-                                            FtwLiteDevice->FtwWorkSpaceBase,\r
-                                            &Length,\r
-                                            FtwLiteDevice->FtwWorkSpace\r
-                                            );\r
-    ASSERT_EFI_ERROR (Status);\r
-\r
-    //\r
-    // If spare block is valid, then replace working block content.\r
-    //\r
-    if (IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) {\r
-      Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice);\r
-      DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart working block in Init() - %r\n", Status));\r
-      ASSERT_EFI_ERROR (Status);\r
-\r
-      FtwAbort (FtwLiteDevice);\r
-      //\r
-      // Refresh work space.\r
-      //\r
-      Status = WorkSpaceRefresh (FtwLiteDevice);\r
-      if (EFI_ERROR (Status)) {\r
-        return EFI_ABORTED;\r
-      }\r
-    } else {\r
-      DEBUG ((EFI_D_FTW_LITE, "FtwLite: Both are invalid, init workspace\n"));\r
-      //\r
-      // If both are invalid, then initialize work space.\r
-      //\r
-      SetMem (\r
-        FtwLiteDevice->FtwWorkSpace,\r
-        FtwLiteDevice->FtwWorkSpaceSize,\r
-        FTW_ERASED_BYTE\r
-        );\r
-      InitWorkSpaceHeader (FtwLiteDevice->FtwWorkSpaceHeader);\r
-      //\r
-      // Write to work space on the working block\r
-      //\r
-      Length = FtwLiteDevice->FtwWorkSpaceSize;\r
-      Status = FtwLiteDevice->FtwFvBlock->Write (\r
-                                            FtwLiteDevice->FtwFvBlock,\r
-                                            FtwLiteDevice->FtwWorkSpaceLba,\r
-                                            FtwLiteDevice->FtwWorkSpaceBase,\r
-                                            &Length,\r
-                                            FtwLiteDevice->FtwWorkSpace\r
-                                            );\r
-      if (EFI_ERROR (Status)) {\r
-        return EFI_ABORTED;\r
-      }\r
-    }\r
-  }\r
-  //\r
-  // Hook the protocol API\r
-  //\r
-  FtwLiteDevice->FtwLiteInstance.Write = FtwLiteWrite;\r
-\r
-  //\r
-  // Install protocol interface\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &FtwLiteDevice->Handle,\r
-                  &gEfiFaultTolerantWriteLiteProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &FtwLiteDevice->FtwLiteInstance\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_ABORTED;\r
-  }\r
-  //\r
-  // If (!SpareCompleted)  THEN  Abort to rollback.\r
-  //\r
-  if ((FtwLiteDevice->FtwLastRecord->WriteAllocated == FTW_VALID_STATE) &&\r
-      (FtwLiteDevice->FtwLastRecord->SpareCompleted != FTW_VALID_STATE)\r
-      ) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Init.. record not SpareCompleted, abort()\n"));\r
-    FtwAbort (FtwLiteDevice);\r
-  }\r
-  //\r
-  // if (SpareCompleted) THEN  Restart to fault tolerant write.\r
-  //\r
-  if ((FtwLiteDevice->FtwLastRecord->SpareCompleted == FTW_VALID_STATE) &&\r
-      (FtwLiteDevice->FtwLastRecord->WriteCompleted != FTW_VALID_STATE)\r
-      ) {\r
-\r
-    Status = FtwRestart (FtwLiteDevice);\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart last write - %r\n", Status));\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
-  }\r
-  //\r
-  // To check the workspace buffer behind last records is EMPTY or not.\r
-  // If it's not EMPTY, FTW_LITE also need to call reclaim().\r
-  //\r
-  Record  = FtwLiteDevice->FtwLastRecord;\r
-  Offset  = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
-  if (FtwLiteDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {\r
-    Offset += WRITE_TOTAL_SIZE;\r
-  }\r
-\r
-  if (!IsErasedFlashBuffer (\r
-        FTW_ERASE_POLARITY,\r
-        FtwLiteDevice->FtwWorkSpace + Offset,\r
-        FtwLiteDevice->FtwWorkSpaceSize - Offset\r
-        )) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace is dirty, call reclaim...\n"));\r
-    Status = FtwReclaimWorkSpace (FtwLiteDevice);\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace reclaim - %r\n", Status));\r
-      return EFI_ABORTED;\r
-    }\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r