]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/FirmwareVolume/FaultTolerantWriteDxe/FtwLite.c
Code clean for Ftw driver, remove the obsolete logic for boot block. Correct some...
[mirror_edk2.git] / MdeModulePkg / Universal / FirmwareVolume / FaultTolerantWriteDxe / FtwLite.c
index 62f22da07e1b052e5e91d71eb2c29e323576f60f..c7897cd58d0f9327e29f037e1a566702f8cbedaa 100644 (file)
@@ -3,7 +3,7 @@
   This is a simple fault tolerant write driver.\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
   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 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 write record structure records the information of write operation.\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. It also assumes that \r
+  working block is an area which contains working space in its last block and has the same size as 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
 Copyright (c) 2006 - 2008, Intel Corporation                                                         \r
 All rights reserved. This program and the accompanying materials                          \r
@@ -29,11 +45,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   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. We should check the target\r
-  range to prevent the user from writing Spare block and Working \r
-  space directly.\r
+  the modified contents are available.\r
 \r
-  @param This            Calling context\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
@@ -41,13 +55,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
   @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_BAD_BUFFER_SIZE   The write would span a target block, which is not\r
-                                 a valid action.\r
-  @retval  EFI_ACCESS_DENIED     No writes have been allocated.\r
-  @retval  EFI_NOT_FOUND         Cannot find FVB by handle.\r
-  @retval  EFI_OUT_OF_RESOURCES  Cannot allocate memory.\r
-  @retval  EFI_ABORTED           The function could not complete successfully.\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
@@ -112,7 +126,7 @@ FtwLiteWrite (
   //\r
   // Check if there is enough free space for allocate a record\r
   //\r
-  if ((MyOffset + WRITE_TOTAL_SIZE) > FtwLiteDevice->FtwWorkSpaceSize) {\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
@@ -309,7 +323,7 @@ FtwLiteWrite (
   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
@@ -428,11 +442,6 @@ FtwWriteRecord (
     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
@@ -607,8 +616,13 @@ InitializeFtwLite (
   //\r
   // Allocate Private data of this driver, including the FtwWorkSpace[FTW_WORK_SPACE_SIZE].\r
   //\r
+  Length = FTW_WORK_SPACE_SIZE;\r
+  if (Length < PcdGet32 (PcdFlashNvStorageFtwWorkingSize)) {\r
+    Length = PcdGet32 (PcdFlashNvStorageFtwWorkingSize);\r
+  }\r
+\r
   FtwLiteDevice = NULL;\r
-  FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + FTW_WORK_SPACE_SIZE);\r
+  FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + Length);\r
   if (FtwLiteDevice != NULL) {\r
     Status = EFI_SUCCESS;\r
   } else {\r
@@ -625,6 +639,7 @@ InitializeFtwLite (
   //\r
   FtwLiteDevice->FtwWorkSpace     = (UINT8 *) (FtwLiteDevice + 1);\r
   FtwLiteDevice->FtwWorkSpaceSize = FTW_WORK_SPACE_SIZE;\r
+  FtwLiteDevice->FtwWorkSpaceBase = FTW_WORK_SPACE_BASE;\r
   SetMem (\r
     FtwLiteDevice->FtwWorkSpace,\r
     FtwLiteDevice->FtwWorkSpaceSize,\r
@@ -676,7 +691,7 @@ InitializeFtwLite (
     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress);\r
 \r
     if ((FtwLiteDevice->WorkSpaceAddress >= BaseAddress) &&\r
-        (FtwLiteDevice->WorkSpaceAddress <= (BaseAddress + FwVolHeader->FvLength))\r
+        (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FwVolHeader->FvLength))\r
         ) {\r
       FtwLiteDevice->FtwFvBlock = Fvb;\r
       //\r
@@ -689,7 +704,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
@@ -702,6 +718,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
@@ -724,7 +746,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->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
               //\r
@@ -738,7 +761,12 @@ InitializeFtwLite (
               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
@@ -873,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