]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteDxe/FtwLite.c
Clean up FaultTolerantWriteDxe to remove the duplicated definition.
[mirror_edk2.git] / MdeModulePkg / Universal / FirmwareVolume / FaultTolerantWriteDxe / FtwLite.c
index 81d6f6bd70b1e2983e81698700eb0ba1167f3953..5e3b7af3f01588fcfa9dcffc3f6b0872ddb650f9 100644 (file)
@@ -1,46 +1,81 @@
-/*++\r
+/** @file\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
+  This is a simple fault tolerant write driver.\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
+  This boot service protocol only 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
+  This work space is a memory copy of the work space on the Working Block,\r
   the size of the work space is the FTW_WORK_SPACE_SIZE bytes.\r
+  \r
+  The work space stores each write record as EFI_FTW_LITE_RECORD structure.\r
+  The spare block stores the write buffer before write to the target block.\r
+  \r
+  The write record has three states to specify the different phase of write operation.\r
+  1) WRITE_ALLOCATED is that the record is allocated in write space.\r
+     The information of write operation is stored in write record structure.\r
+  2) SPARE_COMPLETED is that the data from write buffer is writed into the spare block as the backup.\r
+  3) WRITE_COMPLETED is that the data is copied from the spare block to the target block.\r
+\r
+  This driver operates the data as the whole size of spare block.\r
+  It first read the SpareAreaLength data from the target block into the spare memory buffer.\r
+  Then copy the write buffer data into the spare memory buffer.\r
+  Then write the spare memory buffer into the spare block.\r
+  Final copy the data from the spare block to the target block.\r
+\r
+  To make this drive work well, the following conditions must be satisfied:\r
+  1. The write NumBytes data must be fit within Spare area. \r
+     Offset + NumBytes <= SpareAreaLength\r
+  2. The whole flash range has the same block size.\r
+  3. Working block is an area which contains working space in its last block and has the same size as spare block.\r
+  4. Working Block area must be in the single one Firmware Volume Block range which FVB protocol is produced on.  \r
+  5. Spare area must be in the single one Firmware Volume Block range which FVB protocol is produced on.\r
+  6. Any write data area (SpareAreaLength Area) which the data will be written into must be \r
+     in the single one Firmware Volume Block range which FVB protocol is produced on.\r
+  7. If write data area (such as Variable range) is enlarged, the spare area range must be enlarged.\r
+     The spare area must be enough large to store the write data before write them into the target range.\r
+  If one of them is not satisfied, FtwLiteWrite may fail.\r
+  Usually, Spare area only takes one block. That's SpareAreaLength = BlockSize, NumberOfSpareBlock = 1.\r
+\r
+Copyright (c) 2006 - 2009, 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
-\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
+**/\r
+\r
+#include "FtwLite.h"\r
+\r
+/**\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
+  @param This            The pointer to this protocol instance. \r
+  @param FvbHandle       The handle of FVB protocol that provides services for\r
+                         reading, writing, and erasing the target block.\r
+  @param Lba             The logical block address of the target block.\r
+  @param Offset          The offset within the target block to place the data.\r
+  @param NumBytes        The number of bytes to write to the target block.\r
+  @param Buffer          The data to write.\r
+\r
+  @retval EFI_SUCCESS          The function completed successfully \r
+  @retval EFI_ABORTED          The function could not complete successfully. \r
+  @retval EFI_BAD_BUFFER_SIZE  The input data can't fit within the spare block. \r
+                               Offset + *NumBytes > SpareAreaLength.\r
+  @retval EFI_ACCESS_DENIED    No writes have been allocated. \r
+  @retval EFI_OUT_OF_RESOURCES Cannot allocate enough memory resource.\r
+  @retval EFI_NOT_FOUND        Cannot find FVB protocol by handle.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FtwLiteWrite (\r
@@ -51,33 +86,6 @@ FtwLiteWrite (
   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
@@ -93,7 +101,6 @@ Returns:
   UINTN                               Index;\r
   UINT8                               *Ptr;\r
   EFI_DEV_PATH_PTR                    DevPtr;\r
-\r
   //\r
   // Refresh work space and get last record\r
   //\r
@@ -125,13 +132,14 @@ Returns:
   // Check if the input data can fit within the target block\r
   //\r
   if ((Offset +*NumBytes) > FtwLiteDevice->SpareAreaLength) {\r
+    *NumBytes = FtwLiteDevice->SpareAreaLength - Offset;\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 ((MyOffset + FTW_LITE_RECORD_SIZE) > FtwLiteDevice->FtwWorkSpaceSize) {\r
+    Status = FtwReclaimWorkSpace (FtwLiteDevice, TRUE);\r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_ERROR, "FtwLite: Reclaim work space - %r", Status));\r
       return EFI_ABORTED;\r
@@ -156,7 +164,7 @@ Returns:
             );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Allocate record - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "FtwLite: Allocate record - %r\n", Status));\r
     return EFI_ABORTED;\r
   }\r
 \r
@@ -172,7 +180,7 @@ Returns:
 \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
+    DEBUG ((EFI_D_ERROR, "FtwLite: Get FVB physical address - %r\n", Status));\r
     return EFI_ABORTED;\r
   }\r
 \r
@@ -227,7 +235,7 @@ Returns:
     //\r
     Ptr = MyBuffer;\r
     for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-      MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
+      MyLength = FtwLiteDevice->BlockSize;\r
       Status = FtwLiteDevice->FtwFvBlock->Read (\r
                                             FtwLiteDevice->FtwFvBlock,\r
                                             FtwLiteDevice->FtwWorkBlockLba + Index,\r
@@ -246,14 +254,14 @@ Returns:
     // 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
+    Offset = (((UINTN) (Lba - FtwLiteDevice->FtwWorkBlockLba)) * FtwLiteDevice->BlockSize + 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
+      MyLength  = FtwLiteDevice->BlockSize;\r
       Status    = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr);\r
       if (EFI_ERROR (Status)) {\r
         FreePool (MyBuffer);\r
@@ -282,7 +290,7 @@ Returns:
 \r
   Ptr = SpareBuffer;\r
   for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-    MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
+    MyLength = FtwLiteDevice->BlockSize;\r
     Status = FtwLiteDevice->FtwBackupFvb->Read (\r
                                             FtwLiteDevice->FtwBackupFvb,\r
                                             FtwLiteDevice->FtwSpareLba + Index,\r
@@ -305,7 +313,7 @@ Returns:
   Status  = FtwEraseSpareBlock (FtwLiteDevice);\r
   Ptr     = MyBuffer;\r
   for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-    MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
+    MyLength = FtwLiteDevice->BlockSize;\r
     Status = FtwLiteDevice->FtwBackupFvb->Write (\r
                                             FtwLiteDevice->FtwBackupFvb,\r
                                             FtwLiteDevice->FtwSpareLba + Index,\r
@@ -327,7 +335,7 @@ Returns:
   FreePool (MyBuffer);\r
 \r
   //\r
-  // Set the SpareCompleteD in the FTW record,\r
+  // Set the SpareComplete in the FTW record,\r
   //\r
   MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
   Status = FtwUpdateFvState (\r
@@ -362,7 +370,7 @@ Returns:
   Status  = FtwEraseSpareBlock (FtwLiteDevice);\r
   Ptr     = SpareBuffer;\r
   for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) {\r
-    MyLength = FtwLiteDevice->SizeOfSpareBlock;\r
+    MyLength = FtwLiteDevice->BlockSize;\r
     Status = FtwLiteDevice->FtwBackupFvb->Write (\r
                                             FtwLiteDevice->FtwBackupFvb,\r
                                             FtwLiteDevice->FtwSpareLba + Index,\r
@@ -383,7 +391,7 @@ Returns:
   FreePool (SpareBuffer);\r
 \r
   DEBUG (\r
-    (EFI_D_FTW_LITE,\r
+    (EFI_D_ERROR,\r
     "FtwLite: Write() success, (Lba:Offset)=(%lx:0x%x), NumBytes: 0x%x\n",\r
     Lba,\r
     Offset,\r
@@ -394,28 +402,25 @@ Returns:
 }\r
 \r
 \r
+/**\r
+  Write a record with fault tolerant manner.\r
+  Since the content has already backuped in spare block, the write is\r
+  guaranteed to be completed with fault tolerant manner.\r
+\r
+\r
+  @param FtwLiteDevice   The private data of FTW_LITE driver\r
+  @param Fvb             The FVB protocol that provides services for\r
+                         reading, writing, and erasing the target block.\r
+\r
+  @retval  EFI_SUCCESS          The function completed successfully\r
+  @retval  EFI_ABORTED          The function could not complete successfully\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
@@ -430,7 +435,6 @@ Returns:
 \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
@@ -449,14 +453,9 @@ Returns:
     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
+    // Update blocks other than working block\r
     //\r
     Status = FlushSpareBlockToTargetBlock (FtwLiteDevice, Fvb, Record->Lba);\r
   }\r
@@ -480,28 +479,25 @@ Returns:
 }\r
 \r
 \r
+/**\r
+  Restarts a previously interrupted write. The caller must provide the\r
+  block protocol needed to complete the interrupted write.\r
+\r
+\r
+  @param 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
+  @retval  EFI_SUCCESS          The function completed successfully\r
+  @retval  EFI_ACCESS_DENIED    No pending writes exist\r
+  @retval  EFI_NOT_FOUND        FVB protocol not found by the handle\r
+  @retval  EFI_ABORTED          The function could not complete successfully\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
@@ -520,7 +516,7 @@ Returns:
   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
+    DEBUG ((EFI_D_ERROR, "FtwLite: FVB Device Path is not memory mapped\n"));\r
     return EFI_ABORTED;\r
   }\r
 \r
@@ -533,7 +529,7 @@ Returns:
   //  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
+  DEBUG ((EFI_D_INFO, "FtwLite: Restart() - %r\n", Status));\r
 \r
   Record++;\r
   FtwLiteDevice->FtwLastRecord = Record;\r
@@ -548,24 +544,21 @@ Returns:
 }\r
 \r
 \r
-EFI_STATUS\r
-FtwAbort (\r
-  IN EFI_FTW_LITE_DEVICE    *FtwLiteDevice\r
-  )\r
-/*++\r
+/**\r
+  Aborts all previous allocated writes.\r
 \r
-Routine Description:\r
-    Aborts all previous allocated writes.\r
 \r
-Arguments:\r
-    FtwLiteDevice    - The private data of FTW_LITE driver\r
+  @param 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
+  @retval  EFI_SUCCESS       The function completed successfully\r
+  @retval  EFI_ABORTED       The function could not complete successfully.\r
+  @retval  EFI_NOT_FOUND     No allocated writes exist.\r
 \r
---*/\r
+**/\r
+EFI_STATUS\r
+FtwAbort (\r
+  IN EFI_FTW_LITE_DEVICE    *FtwLiteDevice\r
+  )\r
 {\r
   EFI_STATUS  Status;\r
   UINTN       Offset;\r
@@ -596,30 +589,26 @@ Returns:
   //\r
   Status = FtwEraseSpareBlock (FtwLiteDevice);\r
 \r
-  DEBUG ((EFI_D_FTW_INFO, "FtwLite: Abort() success \n"));\r
+  DEBUG ((EFI_D_INFO, "FtwLite: Abort() success \n"));\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function is the entry point of the Fault Tolerant Write driver.\r
+\r
+  @param ImageHandle     A handle for the image that is initializing this driver\r
+  @param SystemTable     A pointer to the EFI system table\r
+\r
+  @retval  EFI_SUCCESS            FTW has finished the initialization\r
+  @retval  EFI_ABORTED            FTW initialization error\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
@@ -629,25 +618,17 @@ InitializeFtwLite (
   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
+  UINTN                               Length;\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
+  // Allocate Private data of this driver, 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
+  FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));\r
+  ASSERT (FtwLiteDevice != NULL);\r
 \r
   ZeroMem (FtwLiteDevice, sizeof (EFI_FTW_LITE_DEVICE));\r
   FtwLiteDevice->Signature = FTW_LITE_DEVICE_SIGNATURE;\r
@@ -656,14 +637,7 @@ InitializeFtwLite (
   // 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
@@ -708,7 +682,7 @@ InitializeFtwLite (
     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress);\r
 \r
     if ((FtwLiteDevice->WorkSpaceAddress >= BaseAddress) &&\r
-        (FtwLiteDevice->WorkSpaceAddress <= (BaseAddress + FwVolHeader->FvLength))\r
+        ((FtwLiteDevice->WorkSpaceAddress + FtwLiteDevice->WorkSpaceLength) <= (BaseAddress + FwVolHeader->FvLength))\r
         ) {\r
       FtwLiteDevice->FtwFvBlock = Fvb;\r
       //\r
@@ -721,7 +695,8 @@ InitializeFtwLite (
         FvbMapEntry = &FwVolHeader->BlockMap[0];\r
         while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->Length == 0))) {\r
           for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-            if (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex)) {\r
+            if ((FtwLiteDevice->WorkSpaceAddress >= (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
+              && (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex))) {\r
               FtwLiteDevice->FtwWorkSpaceLba = LbaIndex - 1;\r
               //\r
               // Get the Work space size and Base(Offset)\r
@@ -734,6 +709,12 @@ InitializeFtwLite (
           //\r
           // end for\r
           //\r
+          if (LbaIndex <= FvbMapEntry->NumBlocks) {\r
+            //\r
+            // Work space range is found.\r
+            //\r
+            break;\r
+          }\r
           FvbMapEntry++;\r
         }\r
         //\r
@@ -743,7 +724,7 @@ InitializeFtwLite (
     }\r
 \r
     if ((FtwLiteDevice->SpareAreaAddress >= BaseAddress) &&\r
-        (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FwVolHeader->FvLength))\r
+        ((FtwLiteDevice->SpareAreaAddress + FtwLiteDevice->SpareAreaLength) <= (BaseAddress + FwVolHeader->FvLength))\r
         ) {\r
       FtwLiteDevice->FtwBackupFvb = Fvb;\r
       //\r
@@ -756,21 +737,28 @@ InitializeFtwLite (
         FvbMapEntry = &FwVolHeader->BlockMap[0];\r
         while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->Length == 0))) {\r
           for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-            if (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex)) {\r
+            if ((FtwLiteDevice->SpareAreaAddress >= (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
+              && (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex))) {\r
               //\r
-              // Get the NumberOfSpareBlock and SizeOfSpareBlock\r
+              // Get the NumberOfSpareBlock and BlockSize\r
               //\r
               FtwLiteDevice->FtwSpareLba        = LbaIndex - 1;\r
-              FtwLiteDevice->SizeOfSpareBlock   = FvbMapEntry->Length;\r
-              FtwLiteDevice->NumberOfSpareBlock = FtwLiteDevice->SpareAreaLength / FtwLiteDevice->SizeOfSpareBlock;\r
+              FtwLiteDevice->BlockSize   = FvbMapEntry->Length;\r
+              FtwLiteDevice->NumberOfSpareBlock = FtwLiteDevice->SpareAreaLength / FtwLiteDevice->BlockSize;\r
               //\r
               // Check the range of spare area to make sure that it's in FV range\r
+              // To do delete\r
               //\r
               ASSERT ((FtwLiteDevice->FtwSpareLba + FtwLiteDevice->NumberOfSpareBlock) <= FvbMapEntry->NumBlocks);\r
               break;\r
             }\r
           }\r
-\r
+          if (LbaIndex <= FvbMapEntry->NumBlocks) {\r
+            //\r
+            // Spare FV range is found.\r
+            //\r
+            break;\r
+          }\r
           FvbMapEntry++;\r
         }\r
         //\r
@@ -779,6 +767,7 @@ InitializeFtwLite (
       }\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
@@ -787,7 +776,9 @@ InitializeFtwLite (
   //\r
   FtwLiteDevice->FtwWorkBlockLba = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->NumberOfSpareBlock + 1;\r
   if ((INT64) (FtwLiteDevice->FtwWorkBlockLba) < 0) {\r
-    FtwLiteDevice->FtwWorkBlockLba = 0;\r
+    DEBUG ((EFI_D_ERROR, "FtwLite: The spare block range is too large than the working block range!\n"));\r
+    FreePool (FtwLiteDevice);\r
+    return EFI_ABORTED;\r
   }\r
 \r
   if ((FtwLiteDevice->FtwFvBlock == NULL) ||\r
@@ -796,8 +787,10 @@ InitializeFtwLite (
       (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
+    FreePool (FtwLiteDevice);\r
+    return EFI_ABORTED;\r
   }\r
+\r
   //\r
   // Refresh workspace data from working block\r
   //\r
@@ -808,7 +801,7 @@ InitializeFtwLite (
   // 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
+    DEBUG ((EFI_D_ERROR, "FtwLite: Workspace invalid, read from backup\n"));\r
     //\r
     // Read from spare block\r
     //\r
@@ -827,7 +820,7 @@ InitializeFtwLite (
     //\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
+      DEBUG ((EFI_D_ERROR, "FtwLite: Restart working block in Init() - %r\n", Status));\r
       ASSERT_EFI_ERROR (Status);\r
 \r
       FtwAbort (FtwLiteDevice);\r
@@ -836,10 +829,11 @@ InitializeFtwLite (
       //\r
       Status = WorkSpaceRefresh (FtwLiteDevice);\r
       if (EFI_ERROR (Status)) {\r
+        FreePool (FtwLiteDevice);\r
         return EFI_ABORTED;\r
       }\r
     } else {\r
-      DEBUG ((EFI_D_FTW_LITE, "FtwLite: Both are invalid, init workspace\n"));\r
+      DEBUG ((EFI_D_ERROR, "FtwLite: Both are invalid, init workspace\n"));\r
       //\r
       // If both are invalid, then initialize work space.\r
       //\r
@@ -850,17 +844,12 @@ InitializeFtwLite (
         );\r
       InitWorkSpaceHeader (FtwLiteDevice->FtwWorkSpaceHeader);\r
       //\r
-      // Write to work space on the working block\r
+      // Initialize the work space\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
+      Status = FtwReclaimWorkSpace (FtwLiteDevice, FALSE);\r
+\r
       if (EFI_ERROR (Status)) {\r
+        FreePool (FtwLiteDevice);\r
         return EFI_ABORTED;\r
       }\r
     }\r
@@ -880,6 +869,7 @@ InitializeFtwLite (
                   &FtwLiteDevice->FtwLiteInstance\r
                   );\r
   if (EFI_ERROR (Status)) {\r
+    FreePool (FtwLiteDevice);\r
     return EFI_ABORTED;\r
   }\r
   //\r
@@ -888,7 +878,7 @@ InitializeFtwLite (
   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
+    DEBUG ((EFI_D_ERROR, "FtwLite: Init.. record not SpareCompleted, abort()\n"));\r
     FtwAbort (FtwLiteDevice);\r
   }\r
   //\r
@@ -899,7 +889,7 @@ InitializeFtwLite (
       ) {\r
 \r
     Status = FtwRestart (FtwLiteDevice);\r
-    DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart last write - %r\n", Status));\r
+    DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
@@ -911,7 +901,7 @@ InitializeFtwLite (
   Record  = FtwLiteDevice->FtwLastRecord;\r
   Offset  = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace;\r
   if (FtwLiteDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {\r
-    Offset += WRITE_TOTAL_SIZE;\r
+    Offset += FTW_LITE_RECORD_SIZE;\r
   }\r
 \r
   if (!IsErasedFlashBuffer (\r
@@ -919,10 +909,11 @@ InitializeFtwLite (
         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
+    DEBUG ((EFI_D_ERROR, "FtwLite: Workspace is dirty, call reclaim...\n"));\r
+    Status = FtwReclaimWorkSpace (FtwLiteDevice, TRUE);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace reclaim - %r\n", Status));\r
+      DEBUG ((EFI_D_ERROR, "FtwLite: Workspace reclaim - %r\n", Status));\r
+      FreePool (FtwLiteDevice);\r
       return EFI_ABORTED;\r
     }\r
   }\r