]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
MdeModulePkg/FaultTolerantWriteDxe: factor out boot service accesses
[mirror_edk2.git] / MdeModulePkg / Universal / FaultTolerantWriteDxe / UpdateWorkingBlock.c
index 425aa403c3b520c569a06f56c8c0f8021928294b..d09e9719cf0586e1bfaec06298213fafb198cc78 100644 (file)
@@ -2,91 +2,98 @@
 \r
    Internal functions to operate Working Block Space.\r
 \r
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
-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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+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
 \r
 #include "FaultTolerantWrite.h"\r
 \r
-/**\r
-  Check to see if it is a valid work space.\r
-\r
+EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER mWorkingBlockHeader = {ZERO_GUID, 0, 0, 0, 0, {0, 0, 0}, 0};\r
 \r
-  @param WorkingHeader   Pointer of working block header\r
-\r
-  @retval  EFI_SUCCESS    The function completed successfully\r
-  @retval  EFI_ABORTED    The function could not complete successfully.\r
+/**\r
+  Initialize a local work space header.\r
 \r
+  Since Signature and WriteQueueSize have been known, Crc can be calculated out,\r
+  then the work space header will be fixed.\r
 **/\r
-BOOLEAN\r
-IsValidWorkSpace (\r
-  IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader\r
+VOID\r
+InitializeLocalWorkSpaceHeader (\r
+  VOID\r
   )\r
 {\r
-  EFI_STATUS                              Status;\r
-  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER WorkingBlockHeader;\r
-\r
-  if (WorkingHeader == NULL) {\r
-    return FALSE;\r
-  }\r
-\r
-  if (WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Work block header valid bit check error\n"));\r
-    return FALSE;\r
-  }\r
   //\r
-  // Check signature with gEfiSystemNvDataFvGuid\r
+  // Check signature with gEdkiiWorkingBlockSignatureGuid.\r
   //\r
-  if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Work block header signature check error\n"));\r
-    return FALSE;\r
+  if (CompareGuid (&gEdkiiWorkingBlockSignatureGuid, &mWorkingBlockHeader.Signature)) {\r
+    //\r
+    // The local work space header has been initialized.\r
+    //\r
+    return;\r
   }\r
+\r
+  SetMem (\r
+    &mWorkingBlockHeader,\r
+    sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),\r
+    FTW_ERASED_BYTE\r
+    );\r
+\r
   //\r
-  // Check the CRC of header\r
+  // Here using gEdkiiWorkingBlockSignatureGuid as the signature.\r
   //\r
   CopyMem (\r
-    &WorkingBlockHeader,\r
-    WorkingHeader,\r
-    sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)\r
+    &mWorkingBlockHeader.Signature,\r
+    &gEdkiiWorkingBlockSignatureGuid,\r
+    sizeof (EFI_GUID)\r
     );\r
+  mWorkingBlockHeader.WriteQueueSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
 \r
   //\r
-  // Filter out the Crc and State fields\r
+  // Crc is calculated with all the fields except Crc and STATE, so leave them as FTW_ERASED_BYTE.\r
   //\r
-  SetMem (\r
-    &WorkingBlockHeader.Crc,\r
-    sizeof (UINT32),\r
-    FTW_ERASED_BYTE\r
-    );\r
-  WorkingBlockHeader.WorkingBlockValid    = FTW_ERASE_POLARITY;\r
-  WorkingBlockHeader.WorkingBlockInvalid  = FTW_ERASE_POLARITY;\r
 \r
   //\r
   // Calculate the Crc of woking block header\r
   //\r
-  Status = gBS->CalculateCrc32 (\r
-                  (UINT8 *) &WorkingBlockHeader,\r
-                  sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),\r
-                  &WorkingBlockHeader.Crc\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
+  mWorkingBlockHeader.Crc = FtwCalculateCrc32 (&mWorkingBlockHeader,\r
+                              sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));\r
+\r
+  mWorkingBlockHeader.WorkingBlockValid    = FTW_VALID_STATE;\r
+  mWorkingBlockHeader.WorkingBlockInvalid  = FTW_INVALID_STATE;\r
+}\r
+\r
+/**\r
+  Check to see if it is a valid work space.\r
+\r
+\r
+  @param WorkingHeader   Pointer of working block header\r
+\r
+  @retval TRUE          The work space is valid.\r
+  @retval FALSE         The work space is invalid.\r
+\r
+**/\r
+BOOLEAN\r
+IsValidWorkSpace (\r
+  IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader\r
+  )\r
+{\r
+  if (WorkingHeader == NULL) {\r
     return FALSE;\r
   }\r
 \r
-  if (WorkingBlockHeader.Crc != WorkingHeader->Crc) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Work block header CRC check error\n"));\r
-    return FALSE;\r
+  if (CompareMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) == 0) {\r
+    return TRUE;\r
   }\r
 \r
-  return TRUE;\r
+  DEBUG ((EFI_D_INFO, "Ftw: Work block header check mismatch\n"));\r
+  return FALSE;\r
 }\r
 \r
 /**\r
@@ -103,50 +110,137 @@ InitWorkSpaceHeader (
   IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-\r
   if (WorkingHeader == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  //\r
-  // Here using gEfiSystemNvDataFvGuid as the signature.\r
-  //\r
-  CopyMem (\r
-    &WorkingHeader->Signature,\r
-    &gEfiSystemNvDataFvGuid,\r
-    sizeof (EFI_GUID)\r
-    );\r
-  WorkingHeader->WriteQueueSize = (UINT64) (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));\r
 \r
-  //\r
-  // Crc is calculated with all the fields except Crc and STATE\r
-  //\r
-  WorkingHeader->WorkingBlockValid    = FTW_ERASE_POLARITY;\r
-  WorkingHeader->WorkingBlockInvalid  = FTW_ERASE_POLARITY;\r
+  CopyMem (WorkingHeader, &mWorkingBlockHeader, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER));\r
 \r
-  SetMem (\r
-    &WorkingHeader->Crc,\r
-    sizeof (UINT32),\r
-    FTW_ERASED_BYTE\r
-    );\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Read work space data from work block or spare block.\r
+\r
+  @param FvBlock        FVB Protocol interface to access the block.\r
+  @param BlockSize      The size of the block.\r
+  @param Lba            Lba of the block.\r
+  @param Offset         The offset within the block.\r
+  @param Length         The number of bytes to read from the block.\r
+  @param Buffer         The data is read.\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
+ReadWorkSpaceData (\r
+  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
+  IN UINTN                              BlockSize,\r
+  IN EFI_LBA                            Lba,\r
+  IN UINTN                              Offset,\r
+  IN UINTN                              Length,\r
+  OUT UINT8                             *Buffer\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINT8                 *Ptr;\r
+  UINTN                 MyLength;\r
 \r
   //\r
-  // Calculate the CRC value\r
+  // Calculate the real Offset and Lba to write.\r
   //\r
-  Status = gBS->CalculateCrc32 (\r
-                  (UINT8 *) WorkingHeader,\r
-                  sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),\r
-                  &WorkingHeader->Crc\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_ABORTED;\r
+  while (Offset >= BlockSize) {\r
+    Offset -= BlockSize;\r
+    Lba++;\r
+  }\r
+\r
+  Ptr = Buffer;\r
+  while (Length > 0) {\r
+    if ((Offset + Length) > BlockSize) {\r
+      MyLength = BlockSize - Offset;\r
+    } else {\r
+      MyLength = Length;\r
+    }\r
+\r
+    Status = FvBlock->Read (\r
+                        FvBlock,\r
+                        Lba,\r
+                        Offset,\r
+                        &MyLength,\r
+                        Ptr\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_ABORTED;\r
+    }\r
+    Offset = 0;\r
+    Length -= MyLength;\r
+    Ptr += MyLength;\r
+    Lba++;\r
   }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Write work space data to work block.\r
+\r
+  @param FvBlock        FVB Protocol interface to access the block.\r
+  @param BlockSize      The size of the block.\r
+  @param Lba            Lba of the block.\r
+  @param Offset         The offset within the block to place the data.\r
+  @param Length         The number of bytes to write to the 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
+\r
+**/\r
+EFI_STATUS\r
+WriteWorkSpaceData (\r
+  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock,\r
+  IN UINTN                              BlockSize,\r
+  IN EFI_LBA                            Lba,\r
+  IN UINTN                              Offset,\r
+  IN UINTN                              Length,\r
+  IN UINT8                              *Buffer\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  UINT8                 *Ptr;\r
+  UINTN                 MyLength;\r
+\r
   //\r
-  // Restore the WorkingBlockValid flag to VALID state\r
+  // Calculate the real Offset and Lba to write.\r
   //\r
-  WorkingHeader->WorkingBlockValid    = FTW_VALID_STATE;\r
-  WorkingHeader->WorkingBlockInvalid  = FTW_INVALID_STATE;\r
+  while (Offset >= BlockSize) {\r
+    Offset -= BlockSize;\r
+    Lba++;\r
+  }\r
+\r
+  Ptr = Buffer;\r
+  while (Length > 0) {\r
+    if ((Offset + Length) > BlockSize) {\r
+      MyLength = BlockSize - Offset;\r
+    } else {\r
+      MyLength = Length;\r
+    }\r
 \r
+    Status = FvBlock->Write (\r
+                        FvBlock,\r
+                        Lba,\r
+                        Offset,\r
+                        &MyLength,\r
+                        Ptr\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_ABORTED;\r
+    }\r
+    Offset = 0;\r
+    Length -= MyLength;\r
+    Ptr += MyLength;\r
+    Lba++;\r
+  }\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -165,9 +259,7 @@ WorkSpaceRefresh (
   )\r
 {\r
   EFI_STATUS                      Status;\r
-  UINTN                           Length;\r
-  UINTN                           Offset;\r
-  EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;\r
+  UINTN                           RemainingSpaceSize;\r
 \r
   //\r
   // Initialize WorkSpace as FTW_ERASED_BYTE\r
@@ -181,14 +273,14 @@ WorkSpaceRefresh (
   //\r
   // Read from working block\r
   //\r
-  Length = FtwDevice->FtwWorkSpaceSize;\r
-  Status = FtwDevice->FtwFvBlock->Read (\r
-                                    FtwDevice->FtwFvBlock,\r
-                                    FtwDevice->FtwWorkSpaceLba,\r
-                                    FtwDevice->FtwWorkSpaceBase,\r
-                                    &Length,\r
-                                    FtwDevice->FtwWorkSpace\r
-                                    );\r
+  Status = ReadWorkSpaceData (\r
+             FtwDevice->FtwFvBlock,\r
+             FtwDevice->WorkBlockSize,\r
+             FtwDevice->FtwWorkSpaceLba,\r
+             FtwDevice->FtwWorkSpaceBase,\r
+             FtwDevice->FtwWorkSpaceSize,\r
+             FtwDevice->FtwWorkSpace\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
@@ -200,14 +292,15 @@ WorkSpaceRefresh (
             FtwDevice->FtwWorkSpaceSize,\r
             &FtwDevice->FtwLastWriteHeader\r
             );\r
-\r
-  FtwHeader = FtwDevice->FtwLastWriteHeader;\r
-  Offset    = (UINTN) (UINT8 *) FtwHeader - (UINTN) FtwDevice->FtwWorkSpace;\r
-\r
+  RemainingSpaceSize = FtwDevice->FtwWorkSpaceSize - ((UINTN) FtwDevice->FtwLastWriteHeader - (UINTN) FtwDevice->FtwWorkSpace);\r
+  DEBUG ((EFI_D_INFO, "Ftw: Remaining work space size - %x\n", RemainingSpaceSize));\r
   //\r
-  // if the Header is out of the workspace limit, call reclaim.\r
+  // If FtwGetLastWriteHeader() returns error, or the remaining space size is even not enough to contain\r
+  // one EFI_FAULT_TOLERANT_WRITE_HEADER + one EFI_FAULT_TOLERANT_WRITE_RECORD(It will cause that the header\r
+  // pointed by FtwDevice->FtwLastWriteHeader or record pointed by FtwDevice->FtwLastWriteRecord may contain invalid data),\r
+  // it needs to reclaim work space.\r
   //\r
-  if (EFI_ERROR (Status) && (Offset >= FtwDevice->FtwWorkSpaceSize)) {\r
+  if (EFI_ERROR (Status) || RemainingSpaceSize < sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER) + sizeof (EFI_FAULT_TOLERANT_WRITE_RECORD)) {\r
     //\r
     // reclaim work space in working block.\r
     //\r
@@ -219,14 +312,14 @@ WorkSpaceRefresh (
     //\r
     // Read from working block again\r
     //\r
-    Length = FtwDevice->FtwWorkSpaceSize;\r
-    Status = FtwDevice->FtwFvBlock->Read (\r
-                                      FtwDevice->FtwFvBlock,\r
-                                      FtwDevice->FtwWorkSpaceLba,\r
-                                      FtwDevice->FtwWorkSpaceBase,\r
-                                      &Length,\r
-                                      FtwDevice->FtwWorkSpace\r
-                                      );\r
+    Status = ReadWorkSpaceData (\r
+               FtwDevice->FtwFvBlock,\r
+               FtwDevice->WorkBlockSize,\r
+               FtwDevice->FtwWorkSpaceLba,\r
+               FtwDevice->FtwWorkSpaceBase,\r
+               FtwDevice->FtwWorkSpaceSize,\r
+               FtwDevice->FtwWorkSpace\r
+               );\r
     if (EFI_ERROR (Status)) {\r
       return EFI_ABORTED;\r
     }\r
@@ -236,6 +329,9 @@ WorkSpaceRefresh (
               FtwDevice->FtwWorkSpaceSize,\r
               &FtwDevice->FtwLastWriteHeader\r
               );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_ABORTED;\r
+    }\r
   }\r
   //\r
   // Refresh the FtwLastWriteRecord\r
@@ -278,21 +374,24 @@ FtwReclaimWorkSpace (
   EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;\r
   UINTN                                   Index;\r
   UINT8                                   *Ptr;\r
+  EFI_LBA                                 WorkSpaceLbaOffset;\r
+\r
+  DEBUG ((EFI_D_INFO, "Ftw: start to reclaim work space\n"));\r
 \r
-  DEBUG ((EFI_D_ERROR, "Ftw: start to reclaim work space\n"));\r
+  WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;\r
 \r
   //\r
   // Read all original data from working block to a memory buffer\r
   //\r
-  TempBufferSize = FtwDevice->SpareAreaLength;\r
+  TempBufferSize = FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize;\r
   TempBuffer     = AllocateZeroPool (TempBufferSize);\r
   if (TempBuffer == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   Ptr = TempBuffer;\r
-  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Length = FtwDevice->BlockSize;\r
+  for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {\r
+    Length = FtwDevice->WorkBlockSize;\r
     Status = FtwDevice->FtwFvBlock->Read (\r
                                           FtwDevice->FtwFvBlock,\r
                                           FtwDevice->FtwWorkBlockLba + Index,\r
@@ -311,7 +410,7 @@ FtwReclaimWorkSpace (
   // Clean up the workspace, remove all the completed records.\r
   //\r
   Ptr = TempBuffer +\r
-        ((UINTN) (FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba)) * FtwDevice->BlockSize + \r
+        (UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +\r
         FtwDevice->FtwWorkSpaceBase;\r
 \r
   //\r
@@ -341,7 +440,7 @@ FtwReclaimWorkSpace (
       CopyMem (\r
         Ptr + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER),\r
         FtwDevice->FtwLastWriteHeader,\r
-        WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)\r
+        FTW_WRITE_TOTAL_SIZE (Header->NumberOfWrites, Header->PrivateDataSize)\r
         );\r
     }\r
   }\r
@@ -358,10 +457,17 @@ FtwReclaimWorkSpace (
     &FtwDevice->FtwLastWriteHeader\r
     );\r
 \r
+  FtwGetLastWriteRecord (\r
+    FtwDevice->FtwLastWriteHeader,\r
+    &FtwDevice->FtwLastWriteRecord\r
+    );\r
+\r
   //\r
   // Set the WorkingBlockValid and WorkingBlockInvalid as INVALID\r
   //\r
-  WorkingBlockHeader                      = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (TempBuffer + FtwDevice->FtwWorkSpaceBase);\r
+  WorkingBlockHeader                      = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (TempBuffer +\r
+                                            (UINTN) WorkSpaceLbaOffset * FtwDevice->WorkBlockSize +\r
+                                            FtwDevice->FtwWorkSpaceBase);\r
   WorkingBlockHeader->WorkingBlockValid   = FTW_INVALID_STATE;\r
   WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE;\r
 \r
@@ -378,7 +484,7 @@ FtwReclaimWorkSpace (
 \r
   Ptr = SpareBuffer;\r
   for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Length = FtwDevice->BlockSize;\r
+    Length = FtwDevice->SpareBlockSize;\r
     Status = FtwDevice->FtwBackupFvb->Read (\r
                                         FtwDevice->FtwBackupFvb,\r
                                         FtwDevice->FtwSpareLba + Index,\r
@@ -398,9 +504,18 @@ FtwReclaimWorkSpace (
   // Write the memory buffer to spare block\r
   //\r
   Status  = FtwEraseSpareBlock (FtwDevice);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (TempBuffer);\r
+    FreePool (SpareBuffer);\r
+    return EFI_ABORTED;\r
+  }\r
   Ptr     = TempBuffer;\r
-  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Length = FtwDevice->BlockSize;\r
+  for (Index = 0; TempBufferSize > 0; Index += 1) {\r
+    if (TempBufferSize > FtwDevice->SpareBlockSize) {\r
+      Length = FtwDevice->SpareBlockSize;\r
+    } else {\r
+      Length = TempBufferSize;\r
+    }\r
     Status = FtwDevice->FtwBackupFvb->Write (\r
                                             FtwDevice->FtwBackupFvb,\r
                                             FtwDevice->FtwSpareLba + Index,\r
@@ -415,6 +530,7 @@ FtwReclaimWorkSpace (
     }\r
 \r
     Ptr += Length;\r
+    TempBufferSize -= Length;\r
   }\r
   //\r
   // Free TempBuffer\r
@@ -426,8 +542,9 @@ FtwReclaimWorkSpace (
   //\r
   Status = FtwUpdateFvState (\r
             FtwDevice->FtwBackupFvb,\r
-            FtwDevice->FtwWorkSpaceLba,\r
-            FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
+            FtwDevice->SpareBlockSize,\r
+            FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,\r
+            FtwDevice->FtwWorkSpaceBaseInSpare + sizeof (EFI_GUID) + sizeof (UINT32),\r
             WORKING_BLOCK_VALID\r
             );\r
   if (EFI_ERROR (Status)) {\r
@@ -442,6 +559,7 @@ FtwReclaimWorkSpace (
   //\r
   Status = FtwUpdateFvState (\r
             FtwDevice->FtwFvBlock,\r
+            FtwDevice->WorkBlockSize,\r
             FtwDevice->FtwWorkSpaceLba,\r
             FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
             WORKING_BLOCK_INVALID\r
@@ -465,9 +583,13 @@ FtwReclaimWorkSpace (
   // Restore spare backup buffer into spare block , if no failure happened during FtwWrite.\r
   //\r
   Status  = FtwEraseSpareBlock (FtwDevice);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (SpareBuffer);\r
+    return EFI_ABORTED;\r
+  }\r
   Ptr     = SpareBuffer;\r
   for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Length = FtwDevice->BlockSize;\r
+    Length = FtwDevice->SpareBlockSize;\r
     Status = FtwDevice->FtwBackupFvb->Write (\r
                                         FtwDevice->FtwBackupFvb,\r
                                         FtwDevice->FtwSpareLba + Index,\r
@@ -485,7 +607,7 @@ FtwReclaimWorkSpace (
 \r
   FreePool (SpareBuffer);\r
 \r
-  DEBUG ((EFI_D_ERROR, "Ftw: reclaim work space successfully\n"));\r
+  DEBUG ((EFI_D_INFO, "Ftw: reclaim work space successfully\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r