]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / FaultTolerantWriteDxe / FtwMisc.c
index dc110a226d9eeb5bd8be9decd5280a6594b34b87..661e1487673b0ffc1277b86a57cf5814b6796bb1 100644 (file)
@@ -2,14 +2,8 @@
 \r
   Internal generic functions to operate flash block.\r
 \r
-Copyright (c) 2006 - 2010, 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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -27,13 +21,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 BOOLEAN\r
 IsErasedFlashBuffer (\r
-  IN UINT8           *Buffer,\r
-  IN UINTN           BufferSize\r
+  IN UINT8  *Buffer,\r
+  IN UINTN  BufferSize\r
   )\r
 {\r
-  BOOLEAN IsEmpty;\r
-  UINT8   *Ptr;\r
-  UINTN   Index;\r
+  BOOLEAN  IsEmpty;\r
+  UINT8    *Ptr;\r
+  UINTN    Index;\r
 \r
   Ptr     = Buffer;\r
   IsEmpty = TRUE;\r
@@ -48,12 +42,13 @@ IsErasedFlashBuffer (
 }\r
 \r
 /**\r
-  To erase the block with the spare block size.\r
+  To erase the block with specified blocks.\r
 \r
 \r
   @param FtwDevice       The private data of FTW driver\r
   @param FvBlock         FVB Protocol interface\r
   @param Lba             Lba of the firmware block\r
+  @param NumberOfBlocks  The number of consecutive blocks starting with Lba\r
 \r
   @retval  EFI_SUCCESS    Block LBA is Erased successfully\r
   @retval  Others         Error occurs\r
@@ -63,13 +58,14 @@ EFI_STATUS
 FtwEraseBlock (\r
   IN EFI_FTW_DEVICE                   *FtwDevice,\r
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvBlock,\r
-  EFI_LBA                             Lba\r
+  EFI_LBA                             Lba,\r
+  UINTN                               NumberOfBlocks\r
   )\r
 {\r
   return FvBlock->EraseBlocks (\r
                     FvBlock,\r
                     Lba,\r
-                    FtwDevice->NumberOfSpareBlock,\r
+                    NumberOfBlocks,\r
                     EFI_LBA_LIST_TERMINATOR\r
                     );\r
 }\r
@@ -87,13 +83,13 @@ FtwEraseBlock (
                                 partially erased.\r
   @retval EFI_INVALID_PARAMETER One or more of the LBAs listed\r
                                 in the variable argument list do\r
-                                not exist in the firmware volume.  \r
+                                not exist in the firmware volume.\r
 \r
 \r
 **/\r
 EFI_STATUS\r
 FtwEraseSpareBlock (\r
-  IN EFI_FTW_DEVICE   *FtwDevice\r
+  IN EFI_FTW_DEVICE  *FtwDevice\r
   )\r
 {\r
   return FtwDevice->FtwBackupFvb->EraseBlocks (\r
@@ -128,16 +124,16 @@ IsWorkingBlock (
   // 2. Lba falls into the range of working block.\r
   //\r
   return (BOOLEAN)\r
-    (\r
-      (FvBlock == FtwDevice->FtwFvBlock) &&\r
-      (Lba >= FtwDevice->FtwWorkBlockLba) &&\r
-      (Lba <= FtwDevice->FtwWorkSpaceLba)\r
-    );\r
+         (\r
+          (FvBlock == FtwDevice->FtwFvBlock) &&\r
+          (Lba >= FtwDevice->FtwWorkBlockLba) &&\r
+          (Lba <= FtwDevice->FtwWorkSpaceLba)\r
+         );\r
 }\r
 \r
 /**\r
 \r
-  Get firmware block by address.\r
+  Get firmware volume block by address.\r
 \r
 \r
   @param Address         Address specified the block\r
@@ -149,8 +145,8 @@ IsWorkingBlock (
 **/\r
 EFI_HANDLE\r
 GetFvbByAddress (\r
-  IN  EFI_PHYSICAL_ADDRESS               Address,\r
-  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock\r
+  IN  EFI_PHYSICAL_ADDRESS                Address,\r
+  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvBlock\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
@@ -159,11 +155,13 @@ GetFvbByAddress (
   UINTN                               Index;\r
   EFI_PHYSICAL_ADDRESS                FvbBaseAddress;\r
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
   EFI_HANDLE                          FvbHandle;\r
+  UINTN                               BlockSize;\r
+  UINTN                               NumberOfBlocks;\r
 \r
-  *FvBlock  = NULL;\r
-  FvbHandle = NULL;\r
+  *FvBlock     = NULL;\r
+  FvbHandle    = NULL;\r
+  HandleBuffer = NULL;\r
   //\r
   // Locate all handles of Fvb protocol\r
   //\r
@@ -171,6 +169,7 @@ GetFvbByAddress (
   if (EFI_ERROR (Status)) {\r
     return NULL;\r
   }\r
+\r
   //\r
   // Get the FVB to access variable store\r
   //\r
@@ -179,6 +178,7 @@ GetFvbByAddress (
     if (EFI_ERROR (Status)) {\r
       break;\r
     }\r
+\r
     //\r
     // Compare the address and select the right one\r
     //\r
@@ -187,10 +187,17 @@ GetFvbByAddress (
       continue;\r
     }\r
 \r
-    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
-    if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + (FwVolHeader->FvLength - 1)))) {\r
+    //\r
+    // Now, one FVB has one type of BlockSize\r
+    //\r
+    Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    if ((Address >= FvbBaseAddress) && (Address < (FvbBaseAddress + BlockSize * NumberOfBlocks))) {\r
       *FvBlock  = Fvb;\r
-      FvbHandle  = HandleBuffer[Index];\r
+      FvbHandle = HandleBuffer[Index];\r
       break;\r
     }\r
   }\r
@@ -205,7 +212,6 @@ GetFvbByAddress (
 \r
   @param FtwDevice       The private data of FTW driver\r
   @param FvBlock         Fvb protocol instance\r
-  @param Lba             The block specified\r
 \r
   @return A BOOLEAN value indicating in boot block or not.\r
 \r
@@ -213,8 +219,7 @@ GetFvbByAddress (
 BOOLEAN\r
 IsBootBlock (\r
   EFI_FTW_DEVICE                      *FtwDevice,\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvBlock,\r
-  EFI_LBA                             Lba\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvBlock\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
@@ -227,14 +232,15 @@ IsBootBlock (
   BOOLEAN                             IsSwapped;\r
   EFI_HANDLE                          FvbHandle;\r
 \r
-  if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {\r
+  if (!FeaturePcdGet (PcdFullFtwServiceEnable)) {\r
     return FALSE;\r
   }\r
 \r
-  Status = FtwGetSarProtocol ((VOID **) &SarProtocol);\r
+  Status = FtwGetSarProtocol ((VOID **)&SarProtocol);\r
   if (EFI_ERROR (Status)) {\r
     return FALSE;\r
   }\r
+\r
   //\r
   // Get the boot block range\r
   //\r
@@ -253,6 +259,7 @@ IsBootBlock (
   if (EFI_ERROR (Status)) {\r
     return FALSE;\r
   }\r
+\r
   //\r
   // Get FVB by address\r
   //\r
@@ -265,16 +272,17 @@ IsBootBlock (
   if (FvbHandle == NULL) {\r
     return FALSE;\r
   }\r
+\r
   //\r
   // Compare the Fvb\r
   //\r
-  return (BOOLEAN) (FvBlock == BootFvb);\r
+  return (BOOLEAN)(FvBlock == BootFvb);\r
 }\r
 \r
 /**\r
   Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE.\r
-  Spare block is accessed by FTW working FVB protocol interface. LBA is 1.\r
-  Target block is accessed by FvbBlock protocol interface. LBA is Lba.\r
+  Spare block is accessed by FTW working FVB protocol interface.\r
+  Target block is accessed by FvBlock protocol interface.\r
 \r
   FTW will do extra work on boot block update.\r
   FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL,\r
@@ -283,7 +291,7 @@ IsBootBlock (
   1. GetRangeLocation(), if the Range is inside the boot block, FTW know\r
   that boot block will be update. It shall add a FLAG in the working block.\r
   2. When spare block is ready,\r
-  3. SetSwapState(EFI_SWAPPED)\r
+  3. SetSwapState(SWAPPED)\r
   4. erasing boot block,\r
   5. programming boot block until the boot block is ok.\r
   6. SetSwapState(UNSWAPPED)\r
@@ -299,7 +307,7 @@ IsBootBlock (
 **/\r
 EFI_STATUS\r
 FlushSpareBlockToBootBlock (\r
-  EFI_FTW_DEVICE                      *FtwDevice\r
+  EFI_FTW_DEVICE  *FtwDevice\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
@@ -313,31 +321,33 @@ FlushSpareBlockToBootBlock (
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *BootFvb;\r
   EFI_LBA                             BootLba;\r
 \r
-  if (!FeaturePcdGet(PcdFullFtwServiceEnable)) {\r
+  if (!FeaturePcdGet (PcdFullFtwServiceEnable)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   //\r
   // Locate swap address range protocol\r
   //\r
-  Status = FtwGetSarProtocol ((VOID **) &SarProtocol);\r
+  Status = FtwGetSarProtocol ((VOID **)&SarProtocol);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+\r
   //\r
   // Allocate a memory buffer\r
   //\r
   Length = FtwDevice->SpareAreaLength;\r
-  Buffer  = AllocatePool (Length);\r
+  Buffer = AllocatePool (Length);\r
   if (Buffer == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   //\r
   // Get TopSwap bit state\r
   //\r
   Status = SarProtocol->GetSwapState (SarProtocol, &TopSwap);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Get Top Swapped status - %r\n", Status));\r
+    DEBUG ((DEBUG_ERROR, "Ftw: Get Top Swapped status - %r\n", Status));\r
     FreePool (Buffer);\r
     return EFI_ABORTED;\r
   }\r
@@ -350,13 +360,14 @@ FlushSpareBlockToBootBlock (
       FreePool (Buffer);\r
       return EFI_ABORTED;\r
     }\r
+\r
     //\r
     // Read data from current boot block\r
     //\r
     BootLba = 0;\r
     Ptr     = Buffer;\r
     for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-      Count = FtwDevice->BlockSize;\r
+      Count  = FtwDevice->SpareBlockSize;\r
       Status = BootFvb->Read (\r
                           BootFvb,\r
                           BootLba + Index,\r
@@ -377,7 +388,7 @@ FlushSpareBlockToBootBlock (
     //\r
     Ptr = Buffer;\r
     for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-      Count = FtwDevice->BlockSize;\r
+      Count  = FtwDevice->SpareBlockSize;\r
       Status = FtwDevice->FtwBackupFvb->Read (\r
                                           FtwDevice->FtwBackupFvb,\r
                                           FtwDevice->FtwSpareLba + Index,\r
@@ -392,6 +403,7 @@ FlushSpareBlockToBootBlock (
 \r
       Ptr += Count;\r
     }\r
+\r
     //\r
     // Set TopSwap bit\r
     //\r
@@ -401,6 +413,7 @@ FlushSpareBlockToBootBlock (
       return Status;\r
     }\r
   }\r
+\r
   //\r
   // Erase current spare block\r
   // Because TopSwap is set, this actually erase the top block (boot block)!\r
@@ -410,12 +423,13 @@ FlushSpareBlockToBootBlock (
     FreePool (Buffer);\r
     return EFI_ABORTED;\r
   }\r
+\r
   //\r
-  // Write memory buffer currenet spare block. Still top block.\r
+  // Write memory buffer to current spare block. Still top block.\r
   //\r
   Ptr = Buffer;\r
   for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Count = FtwDevice->BlockSize;\r
+    Count  = FtwDevice->SpareBlockSize;\r
     Status = FtwDevice->FtwBackupFvb->Write (\r
                                         FtwDevice->FtwBackupFvb,\r
                                         FtwDevice->FtwSpareLba + Index,\r
@@ -424,7 +438,7 @@ FlushSpareBlockToBootBlock (
                                         Ptr\r
                                         );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Ftw: FVB Write boot block - %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "Ftw: FVB Write boot block - %r\n", Status));\r
       FreePool (Buffer);\r
       return Status;\r
     }\r
@@ -443,14 +457,16 @@ FlushSpareBlockToBootBlock (
 }\r
 \r
 /**\r
-  Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE.\r
-  Spare block is accessed by FTW backup FVB protocol interface. LBA is 1.\r
-  Target block is accessed by FvbBlock protocol interface. LBA is Lba.\r
+  Copy the content of spare block to a target block.\r
+  Spare block is accessed by FTW backup FVB protocol interface.\r
+  Target block is accessed by FvBlock protocol interface.\r
 \r
 \r
   @param FtwDevice       The private data of FTW driver\r
   @param FvBlock         FVB Protocol interface to access target block\r
   @param Lba             Lba of the target block\r
+  @param BlockSize       The size of the block\r
+  @param NumberOfBlocks  The number of consecutive blocks starting with Lba\r
 \r
   @retval  EFI_SUCCESS               Spare block content is copied to target block\r
   @retval  EFI_INVALID_PARAMETER     Input parameter error\r
@@ -462,7 +478,9 @@ EFI_STATUS
 FlushSpareBlockToTargetBlock (\r
   EFI_FTW_DEVICE                      *FtwDevice,\r
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvBlock,\r
-  EFI_LBA                             Lba\r
+  EFI_LBA                             Lba,\r
+  UINTN                               BlockSize,\r
+  UINTN                               NumberOfBlocks\r
   )\r
 {\r
   EFI_STATUS  Status;\r
@@ -475,20 +493,22 @@ FlushSpareBlockToTargetBlock (
   if ((FtwDevice == NULL) || (FvBlock == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   //\r
   // Allocate a memory buffer\r
   //\r
   Length = FtwDevice->SpareAreaLength;\r
-  Buffer  = AllocatePool (Length);\r
+  Buffer = AllocatePool (Length);\r
   if (Buffer == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   //\r
   // Read all content of spare block to memory buffer\r
   //\r
   Ptr = Buffer;\r
   for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Count = FtwDevice->BlockSize;\r
+    Count  = FtwDevice->SpareBlockSize;\r
     Status = FtwDevice->FtwBackupFvb->Read (\r
                                         FtwDevice->FtwBackupFvb,\r
                                         FtwDevice->FtwSpareLba + Index,\r
@@ -503,23 +523,25 @@ FlushSpareBlockToTargetBlock (
 \r
     Ptr += Count;\r
   }\r
+\r
   //\r
   // Erase the target block\r
   //\r
-  Status = FtwEraseBlock (FtwDevice, FvBlock, Lba);\r
+  Status = FtwEraseBlock (FtwDevice, FvBlock, Lba, NumberOfBlocks);\r
   if (EFI_ERROR (Status)) {\r
     FreePool (Buffer);\r
     return EFI_ABORTED;\r
   }\r
+\r
   //\r
-  // Write memory buffer to block, using the FvbBlock protocol interface\r
+  // Write memory buffer to block, using the FvBlock protocol interface\r
   //\r
   Ptr = Buffer;\r
-  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Count   = FtwDevice->BlockSize;\r
-    Status  = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);\r
+  for (Index = 0; Index < NumberOfBlocks; Index += 1) {\r
+    Count  BlockSize;\r
+    Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Ftw: FVB Write block - %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "Ftw: FVB Write block - %r\n", Status));\r
       FreePool (Buffer);\r
       return Status;\r
     }\r
@@ -552,26 +574,26 @@ FlushSpareBlockToTargetBlock (
 **/\r
 EFI_STATUS\r
 FlushSpareBlockToWorkingBlock (\r
-  EFI_FTW_DEVICE                      *FtwDevice\r
+  EFI_FTW_DEVICE  *FtwDevice\r
   )\r
 {\r
-  EFI_STATUS                              Status;\r
-  UINTN                                   Length;\r
-  UINT8                                   *Buffer;\r
-  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader;\r
-  UINTN                                   Count;\r
-  UINT8                                   *Ptr;\r
-  UINTN                                   Index;\r
-  EFI_LBA                                 WorkSpaceLbaOffset;\r
+  EFI_STATUS                               Status;\r
+  UINTN                                    Length;\r
+  UINT8                                    *Buffer;\r
+  EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER  *WorkingBlockHeader;\r
+  UINTN                                    Count;\r
+  UINT8                                    *Ptr;\r
+  UINTN                                    Index;\r
 \r
   //\r
   // Allocate a memory buffer\r
   //\r
   Length = FtwDevice->SpareAreaLength;\r
-  Buffer  = AllocatePool (Length);\r
+  Buffer = AllocatePool (Length);\r
   if (Buffer == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   //\r
   // To guarantee that the WorkingBlockValid is set on spare block\r
   //\r
@@ -581,8 +603,9 @@ FlushSpareBlockToWorkingBlock (
   //\r
   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
   //\r
@@ -590,7 +613,7 @@ FlushSpareBlockToWorkingBlock (
   //\r
   Ptr = Buffer;\r
   for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Count = FtwDevice->BlockSize;\r
+    Count  = FtwDevice->SpareBlockSize;\r
     Status = FtwDevice->FtwBackupFvb->Read (\r
                                         FtwDevice->FtwBackupFvb,\r
                                         FtwDevice->FtwSpareLba + Index,\r
@@ -605,11 +628,11 @@ FlushSpareBlockToWorkingBlock (
 \r
     Ptr += Count;\r
   }\r
+\r
   //\r
   // Clear the CRC and STATE, copy data from spare to working block.\r
   //\r
-  WorkSpaceLbaOffset = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;\r
-  WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (Buffer + (UINTN) WorkSpaceLbaOffset * FtwDevice->BlockSize + FtwDevice->FtwWorkSpaceBase);\r
+  WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)(Buffer + (UINTN)FtwDevice->FtwWorkSpaceLbaInSpare * FtwDevice->SpareBlockSize + FtwDevice->FtwWorkSpaceBaseInSpare);\r
   InitWorkSpaceHeader (WorkingBlockHeader);\r
   WorkingBlockHeader->WorkingBlockValid   = FTW_ERASE_POLARITY;\r
   WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY;\r
@@ -625,11 +648,12 @@ FlushSpareBlockToWorkingBlock (
   // skip Signature and Crc.\r
   //\r
   Status = FtwUpdateFvState (\r
-            FtwDevice->FtwFvBlock,\r
-            FtwDevice->FtwWorkSpaceLba,\r
-            FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
-            WORKING_BLOCK_INVALID\r
-            );\r
+             FtwDevice->FtwFvBlock,\r
+             FtwDevice->WorkBlockSize,\r
+             FtwDevice->FtwWorkSpaceLba,\r
+             FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
+             WORKING_BLOCK_INVALID\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     FreePool (Buffer);\r
     return EFI_ABORTED;\r
@@ -640,17 +664,18 @@ FlushSpareBlockToWorkingBlock (
   //\r
   // Erase the working block\r
   //\r
-  Status = FtwEraseBlock (FtwDevice, FtwDevice->FtwFvBlock, FtwDevice->FtwWorkBlockLba);\r
+  Status = FtwEraseBlock (FtwDevice, FtwDevice->FtwFvBlock, FtwDevice->FtwWorkBlockLba, FtwDevice->NumberOfWorkBlock);\r
   if (EFI_ERROR (Status)) {\r
     FreePool (Buffer);\r
     return EFI_ABORTED;\r
   }\r
+\r
   //\r
-  // Write memory buffer to working block, using the FvbBlock protocol interface\r
+  // Write memory buffer to working block, using the FvBlock protocol interface\r
   //\r
   Ptr = Buffer;\r
-  for (Index = 0; Index < FtwDevice->NumberOfSpareBlock; Index += 1) {\r
-    Count = FtwDevice->BlockSize;\r
+  for (Index = 0; Index < FtwDevice->NumberOfWorkBlock; Index += 1) {\r
+    Count  = FtwDevice->WorkBlockSize;\r
     Status = FtwDevice->FtwFvBlock->Write (\r
                                       FtwDevice->FtwFvBlock,\r
                                       FtwDevice->FtwWorkBlockLba + Index,\r
@@ -659,13 +684,14 @@ FlushSpareBlockToWorkingBlock (
                                       Ptr\r
                                       );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "Ftw: FVB Write block - %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "Ftw: FVB Write block - %r\n", Status));\r
       FreePool (Buffer);\r
       return Status;\r
     }\r
 \r
     Ptr += Count;\r
   }\r
+\r
   //\r
   // Since the memory buffer will not be used, free memory Buffer.\r
   //\r
@@ -678,16 +704,18 @@ FlushSpareBlockToWorkingBlock (
   // So hardcode offset as sizeof(EFI_GUID)+sizeof(UINT32) to skip Signature and Crc.\r
   //\r
   Status = FtwUpdateFvState (\r
-            FtwDevice->FtwFvBlock,\r
-            FtwDevice->FtwWorkSpaceLba,\r
-            FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
-            WORKING_BLOCK_VALID\r
-            );\r
+             FtwDevice->FtwFvBlock,\r
+             FtwDevice->WorkBlockSize,\r
+             FtwDevice->FtwWorkSpaceLba,\r
+             FtwDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32),\r
+             WORKING_BLOCK_VALID\r
+             );\r
   if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
 \r
-  FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE;\r
+  FtwDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_INVALID_STATE;\r
+  FtwDevice->FtwWorkSpaceHeader->WorkingBlockValid   = FTW_VALID_STATE;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -699,6 +727,7 @@ FlushSpareBlockToWorkingBlock (
 \r
 \r
   @param FvBlock         FVB Protocol interface to access SrcBlock and DestBlock\r
+  @param BlockSize       The size of the block\r
   @param Lba             Lba of a block\r
   @param Offset          Offset on the Lba\r
   @param NewBit          New value that will override the old value if it can be change\r
@@ -713,6 +742,7 @@ FlushSpareBlockToWorkingBlock (
 EFI_STATUS\r
 FtwUpdateFvState (\r
   IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *FvBlock,\r
+  IN UINTN                               BlockSize,\r
   IN EFI_LBA                             Lba,\r
   IN UINTN                               Offset,\r
   IN UINT8                               NewBit\r
@@ -722,24 +752,32 @@ FtwUpdateFvState (
   UINT8       State;\r
   UINTN       Length;\r
 \r
+  //\r
+  // Calculate the real Offset and Lba to write.\r
+  //\r
+  while (Offset >= BlockSize) {\r
+    Offset -= BlockSize;\r
+    Lba++;\r
+  }\r
+\r
   //\r
   // Read state from device, assume State is only one byte.\r
   //\r
-  Length  = sizeof (UINT8);\r
-  Status  = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State);\r
+  Length = sizeof (UINT8);\r
+  Status = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_ABORTED;\r
   }\r
 \r
   State ^= FTW_POLARITY_REVERT;\r
-  State  = (UINT8) (State | NewBit);\r
+  State  = (UINT8)(State | NewBit);\r
   State ^= FTW_POLARITY_REVERT;\r
 \r
   //\r
   // Write state back to device\r
   //\r
-  Length  = sizeof (UINT8);\r
-  Status  = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State);\r
+  Length = sizeof (UINT8);\r
+  Status = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State);\r
 \r
   return Status;\r
 }\r
@@ -765,25 +803,26 @@ FtwGetLastWriteHeader (
   OUT EFI_FAULT_TOLERANT_WRITE_HEADER         **FtwWriteHeader\r
   )\r
 {\r
-  UINTN                           Offset;\r
-  EFI_FAULT_TOLERANT_WRITE_HEADER *FtwHeader;\r
+  UINTN                            Offset;\r
+  EFI_FAULT_TOLERANT_WRITE_HEADER  *FtwHeader;\r
 \r
   *FtwWriteHeader = NULL;\r
-  FtwHeader       = (EFI_FAULT_TOLERANT_WRITE_HEADER *) (FtwWorkSpaceHeader + 1);\r
+  FtwHeader       = (EFI_FAULT_TOLERANT_WRITE_HEADER *)(FtwWorkSpaceHeader + 1);\r
   Offset          = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);\r
 \r
   while (FtwHeader->Complete == FTW_VALID_STATE) {\r
-    Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);\r
+    Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);\r
     //\r
     // If Offset exceed the FTW work space boudary, return error.\r
     //\r
-    if (Offset > FtwWorkSpaceSize) {\r
+    if (Offset >= FtwWorkSpaceSize) {\r
       *FtwWriteHeader = FtwHeader;\r
       return EFI_ABORTED;\r
     }\r
 \r
-    FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *) ((UINT8 *) FtwWorkSpaceHeader + Offset);\r
+    FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *)((UINT8 *)FtwWorkSpaceHeader + Offset);\r
   }\r
+\r
   //\r
   // Last write header is found\r
   //\r
@@ -807,15 +846,15 @@ FtwGetLastWriteHeader (
 **/\r
 EFI_STATUS\r
 FtwGetLastWriteRecord (\r
-  IN EFI_FAULT_TOLERANT_WRITE_HEADER          *FtwWriteHeader,\r
-  OUT EFI_FAULT_TOLERANT_WRITE_RECORD         **FtwWriteRecord\r
+  IN EFI_FAULT_TOLERANT_WRITE_HEADER   *FtwWriteHeader,\r
+  OUT EFI_FAULT_TOLERANT_WRITE_RECORD  **FtwWriteRecord\r
   )\r
 {\r
-  UINTN                           Index;\r
-  EFI_FAULT_TOLERANT_WRITE_RECORD *FtwRecord;\r
+  UINTN                            Index;\r
+  EFI_FAULT_TOLERANT_WRITE_RECORD  *FtwRecord;\r
 \r
   *FtwWriteRecord = NULL;\r
-  FtwRecord       = (EFI_FAULT_TOLERANT_WRITE_RECORD *) (FtwWriteHeader + 1);\r
+  FtwRecord       = (EFI_FAULT_TOLERANT_WRITE_RECORD *)(FtwWriteHeader + 1);\r
 \r
   //\r
   // Try to find the last write record "that has not completed"\r
@@ -832,9 +871,10 @@ FtwGetLastWriteRecord (
     FtwRecord++;\r
 \r
     if (FtwWriteHeader->PrivateDataSize != 0) {\r
-      FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord + FtwWriteHeader->PrivateDataSize);\r
+      FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)((UINTN)FtwRecord + (UINTN)FtwWriteHeader->PrivateDataSize);\r
     }\r
   }\r
+\r
   //\r
   //  if Index == NumberOfWrites, then\r
   //  the last record has been written successfully,\r
@@ -842,7 +882,7 @@ FtwGetLastWriteRecord (
   //  also return the last record.\r
   //\r
   if (Index == FtwWriteHeader->NumberOfWrites) {\r
-    *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) ((UINTN) FtwRecord - RECORD_SIZE (FtwWriteHeader->PrivateDataSize));\r
+    *FtwWriteRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)((UINTN)FtwRecord - FTW_RECORD_SIZE (FtwWriteHeader->PrivateDataSize));\r
     return EFI_SUCCESS;\r
   }\r
 \r
@@ -861,18 +901,18 @@ FtwGetLastWriteRecord (
 **/\r
 BOOLEAN\r
 IsFirstRecordOfWrites (\r
-  IN EFI_FAULT_TOLERANT_WRITE_HEADER    *FtwHeader,\r
-  IN EFI_FAULT_TOLERANT_WRITE_RECORD    *FtwRecord\r
+  IN EFI_FAULT_TOLERANT_WRITE_HEADER  *FtwHeader,\r
+  IN EFI_FAULT_TOLERANT_WRITE_RECORD  *FtwRecord\r
   )\r
 {\r
-  UINT8 *Head;\r
-  UINT8 *Ptr;\r
+  UINT8  *Head;\r
+  UINT8  *Ptr;\r
 \r
-  Head  = (UINT8 *) FtwHeader;\r
-  Ptr   = (UINT8 *) FtwRecord;\r
+  Head = (UINT8 *)FtwHeader;\r
+  Ptr  = (UINT8 *)FtwRecord;\r
 \r
   Head += sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER);\r
-  return (BOOLEAN) (Head == Ptr);\r
+  return (BOOLEAN)(Head == Ptr);\r
 }\r
 \r
 /**\r
@@ -889,18 +929,18 @@ IsFirstRecordOfWrites (
 **/\r
 BOOLEAN\r
 IsLastRecordOfWrites (\r
-  IN EFI_FAULT_TOLERANT_WRITE_HEADER    *FtwHeader,\r
-  IN EFI_FAULT_TOLERANT_WRITE_RECORD    *FtwRecord\r
+  IN EFI_FAULT_TOLERANT_WRITE_HEADER  *FtwHeader,\r
+  IN EFI_FAULT_TOLERANT_WRITE_RECORD  *FtwRecord\r
   )\r
 {\r
-  UINT8 *Head;\r
-  UINT8 *Ptr;\r
+  UINT8  *Head;\r
+  UINT8  *Ptr;\r
 \r
-  Head  = (UINT8 *) FtwHeader;\r
-  Ptr   = (UINT8 *) FtwRecord;\r
+  Head = (UINT8 *)FtwHeader;\r
+  Ptr  = (UINT8 *)FtwRecord;\r
 \r
-  Head += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);\r
-  return (BOOLEAN) (Head == Ptr);\r
+  Head += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites - 1, FtwHeader->PrivateDataSize);\r
+  return (BOOLEAN)(Head == Ptr);\r
 }\r
 \r
 /**\r
@@ -915,20 +955,20 @@ IsLastRecordOfWrites (
 **/\r
 EFI_STATUS\r
 GetPreviousRecordOfWrites (\r
-  IN     EFI_FAULT_TOLERANT_WRITE_HEADER    *FtwHeader,\r
-  IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD    **FtwRecord\r
+  IN     EFI_FAULT_TOLERANT_WRITE_HEADER  *FtwHeader,\r
+  IN OUT EFI_FAULT_TOLERANT_WRITE_RECORD  **FtwRecord\r
   )\r
 {\r
-  UINT8 *Ptr;\r
+  UINT8  *Ptr;\r
 \r
   if (IsFirstRecordOfWrites (FtwHeader, *FtwRecord)) {\r
     *FtwRecord = NULL;\r
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
-  Ptr = (UINT8 *) (*FtwRecord);\r
-  Ptr -= RECORD_SIZE (FtwHeader->PrivateDataSize);\r
-  *FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *) Ptr;\r
+  Ptr        = (UINT8 *)(*FtwRecord);\r
+  Ptr       -= FTW_RECORD_SIZE (FtwHeader->PrivateDataSize);\r
+  *FtwRecord = (EFI_FAULT_TOLERANT_WRITE_RECORD *)Ptr;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -944,11 +984,11 @@ GetPreviousRecordOfWrites (
 **/\r
 EFI_STATUS\r
 InitFtwDevice (\r
-  OUT EFI_FTW_DEVICE               **FtwData \r
+  OUT EFI_FTW_DEVICE  **FtwData\r
   )\r
 {\r
-  EFI_FTW_DEVICE                   *FtwDevice;\r
-  \r
+  EFI_FTW_DEVICE  *FtwDevice;\r
+\r
   //\r
   // Allocate private data of this driver,\r
   // Including the FtwWorkSpace[FTW_WORK_SPACE_SIZE].\r
@@ -961,35 +1001,34 @@ InitFtwDevice (
   //\r
   // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.\r
   //\r
-  FtwDevice->WorkSpaceLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);\r
-  FtwDevice->SpareAreaLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);\r
+  FtwDevice->WorkSpaceLength = (UINTN)PcdGet32 (PcdFlashNvStorageFtwWorkingSize);\r
+  FtwDevice->SpareAreaLength = (UINTN)PcdGet32 (PcdFlashNvStorageFtwSpareSize);\r
   if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));\r
+    DEBUG ((DEBUG_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));\r
     FreePool (FtwDevice);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  FtwDevice->Signature        = FTW_DEVICE_SIGNATURE;\r
-  FtwDevice->FtwFvBlock       = NULL;\r
-  FtwDevice->FtwBackupFvb     = NULL;\r
-  FtwDevice->FtwWorkSpaceLba  = (EFI_LBA) (-1);\r
-  FtwDevice->FtwSpareLba      = (EFI_LBA) (-1);\r
+  FtwDevice->Signature       = FTW_DEVICE_SIGNATURE;\r
+  FtwDevice->FtwFvBlock      = NULL;\r
+  FtwDevice->FtwBackupFvb    = NULL;\r
+  FtwDevice->FtwWorkSpaceLba = (EFI_LBA)(-1);\r
+  FtwDevice->FtwSpareLba     = (EFI_LBA)(-1);\r
 \r
-  FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);\r
+  FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFlashNvStorageFtwWorkingBase64);\r
   if (FtwDevice->WorkSpaceAddress == 0) {\r
-    FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);\r
+    FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFlashNvStorageFtwWorkingBase);\r
   }\r
-  \r
-  FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageFtwSpareBase64);\r
+\r
+  FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFlashNvStorageFtwSpareBase64);\r
   if (FtwDevice->SpareAreaAddress == 0) {\r
-    FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);\r
-  }  \r
+    FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFlashNvStorageFtwSpareBase);\r
+  }\r
 \r
   *FtwData = FtwDevice;\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Find the proper Firmware Volume Block protocol for FTW operation.\r
 \r
@@ -998,11 +1037,11 @@ InitFtwDevice (
   @retval EFI_SUCCESS           Find the FVB protocol successfully.\r
   @retval EFI_NOT_FOUND         No proper FVB protocol was found.\r
   @retval EFI_ABORTED           Some data can not be got or be invalid.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 FindFvbForFtw (\r
-  IN OUT EFI_FTW_DEVICE               *FtwDevice\r
+  IN OUT EFI_FTW_DEVICE  *FtwDevice\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
@@ -1011,10 +1050,12 @@ FindFvbForFtw (
   UINTN                               Index;\r
   EFI_PHYSICAL_ADDRESS                FvbBaseAddress;\r
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
   EFI_FVB_ATTRIBUTES_2                Attributes;\r
-  EFI_FV_BLOCK_MAP_ENTRY              *FvbMapEntry;\r
   UINT32                              LbaIndex;\r
+  UINTN                               BlockSize;\r
+  UINTN                               NumberOfBlocks;\r
+\r
+  HandleBuffer = NULL;\r
 \r
   //\r
   // Get all FVB handle.\r
@@ -1040,8 +1081,9 @@ FindFvbForFtw (
     //\r
     Status = Fvb->GetAttributes (Fvb, &Attributes);\r
     if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
-      continue;     \r
+      continue;\r
     }\r
+\r
     //\r
     // Compare the address and select the right one\r
     //\r
@@ -1050,81 +1092,120 @@ FindFvbForFtw (
       continue;\r
     }\r
 \r
-    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
+    //\r
+    // Now, one FVB has one type of BlockSize.\r
+    //\r
+    Status = Fvb->GetBlockSize (Fvb, 0, &BlockSize, &NumberOfBlocks);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
     if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&\r
-      ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength))\r
-      ) {\r
+        ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + BlockSize * NumberOfBlocks)))\r
+    {\r
       FtwDevice->FtwFvBlock = Fvb;\r
       //\r
       // To get the LBA of work space\r
       //\r
-      if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
-        //\r
-        // Now, one FV has one type of BlockLength\r
-        //\r
-        FvbMapEntry = &FwVolHeader->BlockMap[0];\r
-        for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-          if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
-              && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {\r
-            FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;\r
+      for (LbaIndex = 1; LbaIndex <= NumberOfBlocks; LbaIndex += 1) {\r
+        if (  (FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + BlockSize * (LbaIndex - 1)))\r
+           && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + BlockSize * LbaIndex)))\r
+        {\r
+          FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;\r
+          //\r
+          // Get the Work space size and Base(Offset)\r
+          //\r
+          FtwDevice->FtwWorkSpaceSize       = FtwDevice->WorkSpaceLength;\r
+          FtwDevice->WorkBlockSize          = BlockSize;\r
+          FtwDevice->FtwWorkSpaceBase       = (UINTN)(FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FtwDevice->WorkBlockSize * (LbaIndex - 1)));\r
+          FtwDevice->NumberOfWorkSpaceBlock = FTW_BLOCKS (FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize, FtwDevice->WorkBlockSize);\r
+          if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) {\r
             //\r
-            // Get the Work space size and Base(Offset)\r
+            // 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.\r
             //\r
-            FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;\r
-            FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
-            break;\r
+            if (((FtwDevice->WorkSpaceAddress & (FtwDevice->WorkBlockSize - 1)) != 0) ||\r
+                ((FtwDevice->WorkSpaceLength & (FtwDevice->WorkBlockSize - 1)) != 0))\r
+            {\r
+              DEBUG ((DEBUG_ERROR, "Ftw: Work space address or length is not block size aligned when work space size is larger than one block size\n"));\r
+              FreePool (HandleBuffer);\r
+              ASSERT (FALSE);\r
+              return EFI_ABORTED;\r
+            }\r
+          } else if ((FtwDevice->FtwWorkSpaceBase + FtwDevice->FtwWorkSpaceSize) > FtwDevice->WorkBlockSize) {\r
+            DEBUG ((DEBUG_ERROR, "Ftw: The work space range should not span blocks when work space size is less than one block size\n"));\r
+            FreePool (HandleBuffer);\r
+            ASSERT (FALSE);\r
+            return EFI_ABORTED;\r
           }\r
+\r
+          break;\r
         }\r
       }\r
     }\r
-    \r
+\r
     if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&\r
-      ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength))\r
-      ) {\r
+        ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + BlockSize * NumberOfBlocks)))\r
+    {\r
       FtwDevice->FtwBackupFvb = Fvb;\r
       //\r
       // To get the LBA of spare\r
       //\r
-      if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
-        //\r
-        // Now, one FV has one type of BlockLength\r
-        //\r
-        FvbMapEntry = &FwVolHeader->BlockMap[0];\r
-        for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-          if ((FtwDevice->SpareAreaAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
-              && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {\r
-            //\r
-            // Get the NumberOfSpareBlock and BlockSize\r
-            //\r
-            FtwDevice->FtwSpareLba   = LbaIndex - 1;\r
-            FtwDevice->BlockSize     = FvbMapEntry->Length;\r
-            FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize;\r
+      for (LbaIndex = 1; LbaIndex <= NumberOfBlocks; LbaIndex += 1) {\r
+        if (  (FtwDevice->SpareAreaAddress >= (FvbBaseAddress + BlockSize * (LbaIndex - 1)))\r
+           && (FtwDevice->SpareAreaAddress < (FvbBaseAddress + BlockSize * LbaIndex)))\r
+        {\r
+          //\r
+          // Get the NumberOfSpareBlock and BlockSize\r
+          //\r
+          FtwDevice->FtwSpareLba        = LbaIndex - 1;\r
+          FtwDevice->SpareBlockSize     = BlockSize;\r
+          FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->SpareBlockSize;\r
+          //\r
+          // Check the range of spare area to make sure that it's in FV range\r
+          //\r
+          if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > NumberOfBlocks) {\r
+            DEBUG ((DEBUG_ERROR, "Ftw: Spare area is out of FV range\n"));\r
+            FreePool (HandleBuffer);\r
+            ASSERT (FALSE);\r
+            return EFI_ABORTED;\r
+          }\r
+\r
+          //\r
+          // Check the alignment of spare area address and length, they should be block size aligned\r
+          //\r
+          if (((FtwDevice->SpareAreaAddress & (FtwDevice->SpareBlockSize - 1)) != 0) ||\r
+              ((FtwDevice->SpareAreaLength & (FtwDevice->SpareBlockSize - 1)) != 0))\r
+          {\r
+            DEBUG ((DEBUG_ERROR, "Ftw: Spare area address or length is not block size aligned\n"));\r
+            FreePool (HandleBuffer);\r
             //\r
-            // Check the range of spare area to make sure that it's in FV range\r
+            // Report Status Code EFI_SW_EC_ABORTED.\r
             //\r
-            if ((FtwDevice->FtwSpareLba + FtwDevice->NumberOfSpareBlock) > FvbMapEntry->NumBlocks) {\r
-              DEBUG ((EFI_D_ERROR, "Ftw: Spare area is out of FV range\n"));\r
-              FreePool (HandleBuffer);\r
-              ASSERT (FALSE);\r
-              return EFI_ABORTED;\r
-            }\r
-            break;\r
+            REPORT_STATUS_CODE ((EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ABORTED));\r
+            ASSERT (FALSE);\r
+            CpuDeadLoop ();\r
           }\r
+\r
+          break;\r
         }\r
       }\r
     }\r
   }\r
+\r
   FreePool (HandleBuffer);\r
\r
+\r
   if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||\r
-    (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {\r
+      (FtwDevice->FtwWorkSpaceLba == (EFI_LBA)(-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA)(-1)))\r
+  {\r
     return EFI_ABORTED;\r
   }\r
-    \r
+\r
+  DEBUG ((DEBUG_INFO, "Ftw: FtwWorkSpaceLba - 0x%lx, WorkBlockSize  - 0x%x, FtwWorkSpaceBase - 0x%x\n", FtwDevice->FtwWorkSpaceLba, FtwDevice->WorkBlockSize, FtwDevice->FtwWorkSpaceBase));\r
+  DEBUG ((DEBUG_INFO, "Ftw: FtwSpareLba     - 0x%lx, SpareBlockSize - 0x%x\n", FtwDevice->FtwSpareLba, FtwDevice->SpareBlockSize));\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Initialization for Fault Tolerant Write protocol.\r
 \r
@@ -1132,19 +1213,19 @@ FindFvbForFtw (
 \r
   @retval EFI_SUCCESS           Initialize the FTW protocol successfully.\r
   @retval EFI_NOT_FOUND         No proper FVB protocol was found.\r
-  \r
+\r
 **/\r
 EFI_STATUS\r
 InitFtwProtocol (\r
-  IN OUT EFI_FTW_DEVICE               *FtwDevice\r
+  IN OUT EFI_FTW_DEVICE  *FtwDevice\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  UINTN                               Length;\r
   EFI_FAULT_TOLERANT_WRITE_HEADER     *FtwHeader;\r
   UINTN                               Offset;\r
   EFI_HANDLE                          FvbHandle;\r
+  EFI_LBA                             WorkSpaceLbaOffset;\r
 \r
   //\r
   // Find the right SMM Fvb protocol instance for FTW.\r
@@ -1152,26 +1233,52 @@ InitFtwProtocol (
   Status = FindFvbForFtw (FtwDevice);\r
   if (EFI_ERROR (Status)) {\r
     return EFI_NOT_FOUND;\r
-  }  \r
-  \r
+  }\r
+\r
+  //\r
+  // Calculate the start LBA of working block.\r
+  //\r
+  if (FtwDevice->FtwWorkSpaceSize >= FtwDevice->WorkBlockSize) {\r
+    //\r
+    // Working block is a standalone area which only contains working space.\r
+    //\r
+    FtwDevice->NumberOfWorkBlock = FtwDevice->NumberOfWorkSpaceBlock;\r
+  } else {\r
+    //\r
+    // 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
+    FtwDevice->NumberOfWorkBlock = (UINTN)(FtwDevice->FtwWorkSpaceLba + FtwDevice->NumberOfWorkSpaceBlock);\r
+    while (FtwDevice->NumberOfWorkBlock * FtwDevice->WorkBlockSize > FtwDevice->SpareAreaLength) {\r
+      FtwDevice->NumberOfWorkBlock--;\r
+    }\r
+  }\r
+\r
+  FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba + FtwDevice->NumberOfWorkSpaceBlock - FtwDevice->NumberOfWorkBlock;\r
+  DEBUG ((DEBUG_INFO, "Ftw: NumberOfWorkBlock - 0x%x, FtwWorkBlockLba - 0x%lx\n", FtwDevice->NumberOfWorkBlock, FtwDevice->FtwWorkBlockLba));\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
+  // Calcualte the LBA and base of work space in spare block.\r
+  // Note: Do not assume Spare Block and Work Block have same block size.\r
   //\r
-  FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1;\r
-  ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0); \r
+  WorkSpaceLbaOffset                 = FtwDevice->FtwWorkSpaceLba - FtwDevice->FtwWorkBlockLba;\r
+  FtwDevice->FtwWorkSpaceLbaInSpare  = (EFI_LBA)(((UINTN)WorkSpaceLbaOffset * FtwDevice->WorkBlockSize + FtwDevice->FtwWorkSpaceBase) / FtwDevice->SpareBlockSize);\r
+  FtwDevice->FtwWorkSpaceBaseInSpare = ((UINTN)WorkSpaceLbaOffset * FtwDevice->WorkBlockSize + FtwDevice->FtwWorkSpaceBase) % FtwDevice->SpareBlockSize;\r
+  DEBUG ((DEBUG_INFO, "Ftw: WorkSpaceLbaInSpare - 0x%lx, WorkSpaceBaseInSpare - 0x%x\n", FtwDevice->FtwWorkSpaceLbaInSpare, FtwDevice->FtwWorkSpaceBaseInSpare));\r
 \r
   //\r
   // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.\r
   //\r
-  FtwDevice->FtwWorkSpace = (UINT8 *) (FtwDevice + 1);\r
-  FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwDevice->FtwWorkSpace;\r
+  FtwDevice->FtwWorkSpace       = (UINT8 *)(FtwDevice + 1);\r
+  FtwDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *)FtwDevice->FtwWorkSpace;\r
 \r
   FtwDevice->FtwLastWriteHeader = NULL;\r
   FtwDevice->FtwLastWriteRecord = NULL;\r
 \r
+  InitializeLocalWorkSpaceHeader ();\r
+\r
   //\r
   // Refresh the working space data from working block\r
   //\r
@@ -1184,14 +1291,14 @@ InitFtwProtocol (
     //\r
     // Read from spare block\r
     //\r
-    Length = FtwDevice->FtwWorkSpaceSize;\r
-    Status = FtwDevice->FtwBackupFvb->Read (\r
-                    FtwDevice->FtwBackupFvb,\r
-                    FtwDevice->FtwSpareLba,\r
-                    FtwDevice->FtwWorkSpaceBase,\r
-                    &Length,\r
-                    FtwDevice->FtwWorkSpace\r
-                    );\r
+    Status = ReadWorkSpaceData (\r
+               FtwDevice->FtwBackupFvb,\r
+               FtwDevice->SpareBlockSize,\r
+               FtwDevice->FtwSpareLba + FtwDevice->FtwWorkSpaceLbaInSpare,\r
+               FtwDevice->FtwWorkSpaceBaseInSpare,\r
+               FtwDevice->FtwWorkSpaceSize,\r
+               FtwDevice->FtwWorkSpace\r
+               );\r
     ASSERT_EFI_ERROR (Status);\r
 \r
     //\r
@@ -1199,7 +1306,12 @@ InitFtwProtocol (
     //\r
     if (IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {\r
       Status = FlushSpareBlockToWorkingBlock (FtwDevice);\r
-      DEBUG ((EFI_D_ERROR, "Ftw: Restart working block update in InitFtwProtocol() - %r\n", Status));\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "Ftw: Restart working block update in %a() - %r\n",\r
+        __FUNCTION__,\r
+        Status\r
+        ));\r
       FtwAbort (&FtwDevice->FtwInstance);\r
       //\r
       // Refresh work space.\r
@@ -1207,7 +1319,10 @@ InitFtwProtocol (
       Status = WorkSpaceRefresh (FtwDevice);\r
       ASSERT_EFI_ERROR (Status);\r
     } else {\r
-      DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n"));\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "Ftw: Both working and spare blocks are invalid, init workspace\n"\r
+        ));\r
       //\r
       // If both are invalid, then initialize work space.\r
       //\r
@@ -1224,38 +1339,43 @@ InitFtwProtocol (
       ASSERT_EFI_ERROR (Status);\r
     }\r
   }\r
+\r
   //\r
   // If the FtwDevice->FtwLastWriteRecord is 1st record of write header &&\r
   // (! SpareComplete) THEN call Abort().\r
   //\r
   if ((FtwDevice->FtwLastWriteHeader->HeaderAllocated == FTW_VALID_STATE) &&\r
-    (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&\r
-    IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)\r
-    ) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));\r
+      (FtwDevice->FtwLastWriteRecord->SpareComplete != FTW_VALID_STATE) &&\r
+      IsFirstRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)\r
+      )\r
+  {\r
+    DEBUG ((DEBUG_ERROR, "Ftw: Init.. find first record not SpareCompleted, abort()\n"));\r
     FtwAbort (&FtwDevice->FtwInstance);\r
   }\r
+\r
   //\r
   // If Header is incompleted and the last record has completed, then\r
   // call Abort() to set the Header->Complete FLAG.\r
   //\r
   if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&\r
-    (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&\r
-    IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)\r
-    ) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));\r
+      (FtwDevice->FtwLastWriteRecord->DestinationComplete == FTW_VALID_STATE) &&\r
+      IsLastRecordOfWrites (FtwDevice->FtwLastWriteHeader, FtwDevice->FtwLastWriteRecord)\r
+      )\r
+  {\r
+    DEBUG ((DEBUG_ERROR, "Ftw: Init.. find last record completed but header not, abort()\n"));\r
     FtwAbort (&FtwDevice->FtwInstance);\r
   }\r
+\r
   //\r
   // To check the workspace buffer following last Write header/records is EMPTY or not.\r
   // If it's not EMPTY, FTW also need to call reclaim().\r
   //\r
   FtwHeader = FtwDevice->FtwLastWriteHeader;\r
-  Offset    = (UINT8 *) FtwHeader - FtwDevice->FtwWorkSpace;\r
+  Offset    = (UINT8 *)FtwHeader - FtwDevice->FtwWorkSpace;\r
   if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {\r
-    Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);\r
+    Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);\r
   }\r
-  \r
+\r
   if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {\r
     Status = FtwReclaimWorkSpace (FtwDevice, TRUE);\r
     ASSERT_EFI_ERROR (Status);\r
@@ -1265,11 +1385,12 @@ InitFtwProtocol (
   // Restart if it's boot block\r
   //\r
   if ((FtwDevice->FtwLastWriteHeader->Complete != FTW_VALID_STATE) &&\r
-    (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)\r
-    ) {\r
+      (FtwDevice->FtwLastWriteRecord->SpareComplete == FTW_VALID_STATE)\r
+      )\r
+  {\r
     if (FtwDevice->FtwLastWriteRecord->BootBlockUpdate == FTW_VALID_STATE) {\r
       Status = FlushSpareBlockToBootBlock (FtwDevice);\r
-      DEBUG ((EFI_D_ERROR, "Ftw: Restart boot block update - %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "Ftw: Restart boot block update - %r\n", Status));\r
       ASSERT_EFI_ERROR (Status);\r
       FtwAbort (&FtwDevice->FtwInstance);\r
     } else {\r
@@ -1277,15 +1398,17 @@ InitFtwProtocol (
       // if (SpareCompleted) THEN  Restart to fault tolerant write.\r
       //\r
       FvbHandle = NULL;\r
-      FvbHandle = GetFvbByAddress (FtwDevice->FtwLastWriteRecord->FvBaseAddress, &Fvb);\r
+      FvbHandle = GetFvbByAddress ((EFI_PHYSICAL_ADDRESS)(UINTN)((INT64)FtwDevice->SpareAreaAddress + FtwDevice->FtwLastWriteRecord->RelativeOffset), &Fvb);\r
       if (FvbHandle != NULL) {\r
         Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);\r
-        DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));\r
+        DEBUG ((DEBUG_ERROR, "Ftw: Restart last write - %r\n", Status));\r
         ASSERT_EFI_ERROR (Status);\r
       }\r
+\r
       FtwAbort (&FtwDevice->FtwInstance);\r
     }\r
   }\r
+\r
   //\r
   // Hook the protocol API\r
   //\r
@@ -1295,7 +1418,6 @@ InitFtwProtocol (
   FtwDevice->FtwInstance.Restart         = FtwRestart;\r
   FtwDevice->FtwInstance.Abort           = FtwAbort;\r
   FtwDevice->FtwInstance.GetLastWrite    = FtwGetLastWrite;\r
-    \r
+\r
   return EFI_SUCCESS;\r
 }\r
-\r