]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c
retire gEfiAlternateFvBlockGuid. All platform FvbRuntimeDxe drivers will not produce...
[mirror_edk2.git] / MdeModulePkg / Universal / FaultTolerantWriteDxe / FaultTolerantWrite.c
index 53352881c4233aab40eb2397e6dac70aa176ef74..e0ac6ee17c87e2da01d33a71285f8670c130b736 100644 (file)
@@ -53,6 +53,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "FaultTolerantWrite.h"\r
 \r
+EFI_EVENT          mFvbRegistration = NULL;\r
 \r
 //\r
 // Fault Tolerant Write Protocol API\r
@@ -862,116 +863,80 @@ FtwGetLastWrite (
   return Status;\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
-  @return EFI_SUCCESS           FTW has finished the initialization\r
-  @retval EFI_NOT_FOUND         Locate FVB protocol error\r
-  @retval EFI_OUT_OF_RESOURCES  Allocate memory error\r
-  @retval EFI_VOLUME_CORRUPTED  Firmware volume is error\r
-  @retval EFI_ABORTED           FTW initialization error\r
-\r
-**/\r
-EFI_STATUS\r
+VOID\r
 EFIAPI\r
-InitializeFaultTolerantWrite (\r
-  IN EFI_HANDLE         ImageHandle,\r
-  IN EFI_SYSTEM_TABLE   *SystemTable\r
+FvbNotificationEvent (\r
+  IN  EFI_EVENT       Event,\r
+  IN  VOID            *Context\r
   )\r
 {\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
-  UINTN                               Index;\r
+  EFI_STATUS                          Status;\r
   EFI_HANDLE                          *HandleBuffer;\r
   UINTN                               HandleCount;\r
+  UINTN                               Index;\r
+  EFI_PHYSICAL_ADDRESS                FvbBaseAddress;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;\r
   EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;\r
-  EFI_PHYSICAL_ADDRESS                BaseAddress;\r
+  EFI_FVB_ATTRIBUTES_2                Attributes;\r
   EFI_FTW_DEVICE                      *FtwDevice;\r
-  EFI_FAULT_TOLERANT_WRITE_HEADER     *FtwHeader;\r
-  UINTN                               Length;\r
-  EFI_STATUS                          Status;\r
-  UINTN                               Offset;\r
   EFI_FV_BLOCK_MAP_ENTRY              *FvbMapEntry;\r
   UINT32                              LbaIndex;\r
+  UINTN                               Length;\r
+  EFI_FAULT_TOLERANT_WRITE_HEADER     *FtwHeader;\r
+  UINTN                               Offset;\r
   EFI_HANDLE                          FvbHandle;\r
 \r
-  //\r
-  // Allocate Private data of this driver,\r
-  // INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE].\r
-  //\r
+  FtwDevice = (EFI_FTW_DEVICE *)Context;\r
   FvbHandle = NULL;\r
-  FtwDevice = NULL;\r
-  FtwDevice = AllocatePool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));\r
-  if (FtwDevice == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  ZeroMem (FtwDevice, sizeof (EFI_FTW_DEVICE));\r
-  FtwDevice->Signature = FTW_DEVICE_SIGNATURE;\r
+  Fvb       = NULL;\r
 \r
   //\r
-  // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.\r
-  //\r
-\r
-  FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);\r
-  FtwDevice->WorkSpaceLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);\r
-\r
-  FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);\r
-  FtwDevice->SpareAreaLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);\r
-\r
-  if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));\r
-    FreePool (FtwDevice);\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-  //\r
-  // Locate FVB protocol by handle\r
+  // Locate all handles of Fvb protocol\r
   //\r
   Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                  NULL,\r
-                  &HandleCount,\r
-                  &HandleBuffer\r
-                  );\r
+                ByProtocol,\r
+                &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                NULL,\r
+                &HandleCount,\r
+                &HandleBuffer\r
+                );\r
   if (EFI_ERROR (Status)) {\r
-    FreePool (FtwDevice);\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  if (HandleCount <= 0) {\r
-    FreePool (FtwDevice);\r
-    return EFI_NOT_FOUND;\r
+    return;\r
   }\r
 \r
-  Fvb                         = NULL;\r
-  FtwDevice->FtwFvBlock       = NULL;\r
-  FtwDevice->FtwBackupFvb     = NULL;\r
-  FtwDevice->FtwWorkSpaceLba  = (EFI_LBA) (-1);\r
-  FtwDevice->FtwSpareLba      = (EFI_LBA) (-1);\r
+  //\r
+  // Get the FVB to access variable store\r
+  //\r
   for (Index = 0; Index < HandleCount; Index += 1) {\r
     Status = gBS->HandleProtocol (\r
-                    HandleBuffer[Index],\r
-                    &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                    (VOID **) &Fvb\r
-                    );\r
+                  HandleBuffer[Index],\r
+                  &gEfiFirmwareVolumeBlockProtocolGuid,\r
+                  (VOID **) &Fvb\r
+                  );\r
     if (EFI_ERROR (Status)) {\r
-      FreePool (FtwDevice);\r
-      return Status;\r
+      Status = EFI_NOT_FOUND;\r
+      break;\r
     }\r
 \r
-    Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress);\r
+    //\r
+    // Ensure this FVB protocol supported Write operation.\r
+    //\r
+    Status = Fvb->GetAttributes (Fvb, &Attributes);\r
+    if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
+      continue;     \r
+    }\r
+    //\r
+    // Compare the address and select the right one\r
+    //\r
+    Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
     if (EFI_ERROR (Status)) {\r
       continue;\r
     }\r
 \r
-    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress);\r
-\r
-    if ((FtwDevice->WorkSpaceAddress >= BaseAddress) &&\r
-        ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (BaseAddress + FwVolHeader->FvLength))\r
-        ) {\r
+    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
+    if ((FtwDevice->FtwFvBlock == NULL) && (FtwDevice->WorkSpaceAddress >= FvbBaseAddress) &&\r
+      ((FtwDevice->WorkSpaceAddress + FtwDevice->WorkSpaceLength) <= (FvbBaseAddress + FwVolHeader->FvLength))\r
+      ) {\r
       FtwDevice->FtwFvBlock = Fvb;\r
       //\r
       // To get the LBA of work space\r
@@ -982,23 +947,23 @@ InitializeFaultTolerantWrite (
         //\r
         FvbMapEntry = &FwVolHeader->BlockMap[0];\r
         for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-            if ((FtwDevice->WorkSpaceAddress >= (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
-              && (FtwDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex))) {\r
+          if ((FtwDevice->WorkSpaceAddress >= (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
+              && (FtwDevice->WorkSpaceAddress < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex))) {\r
             FtwDevice->FtwWorkSpaceLba = LbaIndex - 1;\r
             //\r
             // Get the Work space size and Base(Offset)\r
             //\r
             FtwDevice->FtwWorkSpaceSize = FtwDevice->WorkSpaceLength;\r
-            FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
+            FtwDevice->FtwWorkSpaceBase = (UINTN) (FtwDevice->WorkSpaceAddress - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
             break;\r
           }\r
         }\r
       }\r
     }\r
-\r
-    if ((FtwDevice->SpareAreaAddress >= BaseAddress) &&\r
-        ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (BaseAddress + FwVolHeader->FvLength))\r
-        ) {\r
+    \r
+    if ((FtwDevice->FtwBackupFvb == NULL) && (FtwDevice->SpareAreaAddress >= FvbBaseAddress) &&\r
+      ((FtwDevice->SpareAreaAddress + FtwDevice->SpareAreaLength) <= (FvbBaseAddress + FwVolHeader->FvLength))\r
+      ) {\r
       FtwDevice->FtwBackupFvb = Fvb;\r
       //\r
       // To get the LBA of spare\r
@@ -1009,21 +974,21 @@ InitializeFaultTolerantWrite (
         //\r
         FvbMapEntry = &FwVolHeader->BlockMap[0];\r
         for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
-            if ((FtwDevice->SpareAreaAddress >= (BaseAddress + FvbMapEntry->Length * (LbaIndex - 1)))\r
-              && (FtwDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->Length * LbaIndex))) {\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->FtwSpareLba   = LbaIndex - 1;\r
+            FtwDevice->BlockSize     = FvbMapEntry->Length;\r
             FtwDevice->NumberOfSpareBlock = FtwDevice->SpareAreaLength / FtwDevice->BlockSize;\r
             //\r
             // Check the range of spare area to make sure that it's in FV range\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 (FtwDevice);\r
-              return EFI_ABORTED;\r
+              ASSERT (FALSE);\r
+              return;\r
             }\r
             break;\r
           }\r
@@ -1032,6 +997,12 @@ InitializeFaultTolerantWrite (
     }\r
   }\r
 \r
+  if ((FtwDevice->FtwBackupFvb == NULL) || (FtwDevice->FtwFvBlock == NULL) ||\r
+    (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))) {\r
+    return;\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "Ftw: Working and spare FVB is ready\n"));\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
@@ -1039,21 +1010,8 @@ InitializeFaultTolerantWrite (
   // working space.\r
   //\r
   FtwDevice->FtwWorkBlockLba = FtwDevice->FtwWorkSpaceLba - FtwDevice->NumberOfSpareBlock + 1;\r
-  if ((INT64) (FtwDevice->FtwWorkBlockLba) < 0) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: The spare block range is too large than the working block range!\n"));\r
-    FreePool (FtwDevice);\r
-    return EFI_ABORTED;\r
-  }\r
+  ASSERT ((INT64) (FtwDevice->FtwWorkBlockLba) >= 0); \r
 \r
-  if ((FtwDevice->FtwFvBlock == NULL) ||\r
-      (FtwDevice->FtwBackupFvb == NULL) ||\r
-      (FtwDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) ||\r
-      (FtwDevice->FtwSpareLba == (EFI_LBA) (-1))\r
-      ) {\r
-    DEBUG ((EFI_D_ERROR, "Ftw: Working or spare FVB not ready\n"));\r
-    FreePool (FtwDevice);\r
-    return EFI_ABORTED;\r
-  }\r
   //\r
   // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.\r
   //\r
@@ -1067,9 +1025,7 @@ InitializeFaultTolerantWrite (
   // Refresh the working space data from working block\r
   //\r
   Status = WorkSpaceRefresh (FtwDevice);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Recovery;\r
-  }\r
+  ASSERT_EFI_ERROR (Status);\r
   //\r
   // If the working block workspace is not valid, try the spare block\r
   //\r
@@ -1079,15 +1035,14 @@ InitializeFaultTolerantWrite (
     //\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
-    if (EFI_ERROR (Status)) {\r
-      goto Recovery;\r
-    }\r
+                    FtwDevice->FtwBackupFvb,\r
+                    FtwDevice->FtwSpareLba,\r
+                    FtwDevice->FtwWorkSpaceBase,\r
+                    &Length,\r
+                    FtwDevice->FtwWorkSpace\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+\r
     //\r
     // If spare block is valid, then replace working block content.\r
     //\r
@@ -1099,9 +1054,7 @@ InitializeFaultTolerantWrite (
       // Refresh work space.\r
       //\r
       Status = WorkSpaceRefresh (FtwDevice);\r
-      if (EFI_ERROR (Status)) {\r
-        goto Recovery;\r
-      }\r
+      ASSERT_EFI_ERROR (Status);\r
     } else {\r
       DEBUG ((EFI_D_ERROR, "Ftw: Both are invalid, init workspace\n"));\r
       //\r
@@ -1117,20 +1070,17 @@ InitializeFaultTolerantWrite (
       // Initialize the work space\r
       //\r
       Status = FtwReclaimWorkSpace (FtwDevice, FALSE);\r
-      if (EFI_ERROR (Status)) {\r
-        goto Recovery;\r
-      }\r
+      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
+  // (! 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
+    (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
     FtwAbort (&FtwDevice->FtwInstance);\r
   }\r
@@ -1139,9 +1089,9 @@ InitializeFaultTolerantWrite (
   // 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
+    (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
     FtwAbort (&FtwDevice->FtwInstance);\r
   }\r
@@ -1154,29 +1104,22 @@ InitializeFaultTolerantWrite (
   if (FtwDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) {\r
     Offset += WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);\r
   }\r
-\r
-  if (!IsErasedFlashBuffer (\r
-        FtwDevice->FtwWorkSpace + Offset,\r
-        FtwDevice->FtwWorkSpaceSize - Offset\r
-        )) {\r
+  \r
+  if (!IsErasedFlashBuffer (FtwDevice->FtwWorkSpace + Offset, FtwDevice->FtwWorkSpaceSize - Offset)) {\r
     Status = FtwReclaimWorkSpace (FtwDevice, TRUE);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Recovery;\r
-    }\r
+    ASSERT_EFI_ERROR (Status);\r
   }\r
+\r
   //\r
   // 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
     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
-      if (EFI_ERROR (Status)) {\r
-        goto Recovery;\r
-      }\r
-  \r
+      ASSERT_EFI_ERROR (Status);\r
       FtwAbort (&FtwDevice->FtwInstance);\r
     } else {\r
       //\r
@@ -1186,46 +1129,107 @@ InitializeFaultTolerantWrite (
       if (FvbHandle != NULL) {\r
         Status = FtwRestart (&FtwDevice->FtwInstance, FvbHandle);\r
         DEBUG ((EFI_D_ERROR, "FtwLite: Restart last write - %r\n", Status));\r
-        if (EFI_ERROR (Status)) {\r
-          goto Recovery;\r
-        }\r
+        ASSERT_EFI_ERROR (Status);\r
       }\r
       FtwAbort (&FtwDevice->FtwInstance);\r
     }\r
   }\r
-\r
   //\r
   // Hook the protocol API\r
   //\r
-  FtwDevice->FtwInstance.GetMaxBlockSize  = FtwGetMaxBlockSize;\r
-  FtwDevice->FtwInstance.Allocate         = FtwAllocate;\r
-  FtwDevice->FtwInstance.Write            = FtwWrite;\r
-  FtwDevice->FtwInstance.Restart          = FtwRestart;\r
-  FtwDevice->FtwInstance.Abort            = FtwAbort;\r
-  FtwDevice->FtwInstance.GetLastWrite     = FtwGetLastWrite;\r
-\r
+  FtwDevice->FtwInstance.GetMaxBlockSize = FtwGetMaxBlockSize;\r
+  FtwDevice->FtwInstance.Allocate        = FtwAllocate;\r
+  FtwDevice->FtwInstance.Write           = FtwWrite;\r
+  FtwDevice->FtwInstance.Restart         = FtwRestart;\r
+  FtwDevice->FtwInstance.Abort           = FtwAbort;\r
+  FtwDevice->FtwInstance.GetLastWrite    = FtwGetLastWrite;\r
+  \r
   //\r
   // Install protocol interface\r
   //\r
   Status = gBS->InstallProtocolInterface (\r
-                  &FtwDevice->Handle,\r
-                  &gEfiFaultTolerantWriteProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  &FtwDevice->FtwInstance\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto Recovery;\r
+            &FtwDevice->Handle,\r
+            &gEfiFaultTolerantWriteProtocolGuid,\r
+            EFI_NATIVE_INTERFACE,\r
+            &FtwDevice->FtwInstance\r
+            );\r
+\r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  //\r
+  // Close the notify event to avoid install FaultTolerantWriteProtocol again.\r
+  //\r
+  Status = gBS->CloseEvent (Event);    \r
+  ASSERT_EFI_ERROR (Status);\r
+  \r
+  return;\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
+  @return EFI_SUCCESS           FTW has finished the initialization\r
+  @retval EFI_NOT_FOUND         Locate FVB protocol error\r
+  @retval EFI_OUT_OF_RESOURCES  Allocate memory error\r
+  @retval EFI_VOLUME_CORRUPTED  Firmware volume is error\r
+  @retval EFI_ABORTED           FTW initialization error\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeFaultTolerantWrite (\r
+  IN EFI_HANDLE         ImageHandle,\r
+  IN EFI_SYSTEM_TABLE   *SystemTable\r
+  )\r
+{\r
+  EFI_FTW_DEVICE                      *FtwDevice;\r
+\r
+  //\r
+  // Allocate Private data of this driver,\r
+  // INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE].\r
+  //\r
+  FtwDevice = NULL;\r
+  FtwDevice = AllocateZeroPool (sizeof (EFI_FTW_DEVICE) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize));\r
+  if (FtwDevice == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  return EFI_SUCCESS;\r
+  ZeroMem (FtwDevice, sizeof (EFI_FTW_DEVICE));\r
+  FtwDevice->Signature = FTW_DEVICE_SIGNATURE;\r
 \r
-Recovery:\r
+  //\r
+  // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE.\r
+  //\r
+\r
+  FtwDevice->WorkSpaceAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwWorkingBase);\r
+  FtwDevice->WorkSpaceLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwWorkingSize);\r
+\r
+  FtwDevice->SpareAreaAddress = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageFtwSpareBase);\r
+  FtwDevice->SpareAreaLength  = (UINTN) PcdGet32 (PcdFlashNvStorageFtwSpareSize);\r
 \r
-  if (FtwDevice != NULL) {\r
+  if ((FtwDevice->WorkSpaceLength == 0) || (FtwDevice->SpareAreaLength == 0)) {\r
+    DEBUG ((EFI_D_ERROR, "Ftw: Workspace or Spare block does not exist!\n"));\r
     FreePool (FtwDevice);\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
+  FtwDevice->FtwFvBlock       = NULL;\r
+  FtwDevice->FtwBackupFvb     = NULL;\r
+  FtwDevice->FtwWorkSpaceLba  = (EFI_LBA) (-1);\r
+  FtwDevice->FtwSpareLba      = (EFI_LBA) (-1);\r
 \r
-  DEBUG ((EFI_D_ERROR, "Ftw: Severe Error occurs, need to recovery\n"));\r
+  //\r
+  // Register FvbNotificationEvent () notify function.\r
+  // \r
+  EfiCreateProtocolNotifyEvent (\r
+    &gEfiFirmwareVolumeBlockProtocolGuid,\r
+    TPL_CALLBACK,\r
+    FvbNotificationEvent,\r
+    (VOID *)FtwDevice,\r
+    &mFvbRegistration\r
+    );\r
 \r
-  return EFI_VOLUME_CORRUPTED;\r
+  return EFI_SUCCESS;\r
 }\r