]> git.proxmox.com Git - mirror_edk2.git/blobdiff - FmpDevicePkg/FmpDxe/VariableSupport.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / FmpDevicePkg / FmpDxe / VariableSupport.c
index 6a4330ad6a832f854617cd7ae669323e721e6472..541e5e0f5fc75668b56512289b8cb763955671ce 100644 (file)
-/**  @file\r
+/** @file\r
   UEFI variable support functions for Firmware Management Protocol based\r
   firmware updates.\r
 \r
   Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
-  Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
-\r
-  Redistribution and use in source and binary forms, with or without\r
-  modification, are permitted provided that the following conditions are met:\r
-  1. Redistributions of source code must retain the above copyright notice,\r
-  this list of conditions and the following disclaimer.\r
-  2. Redistributions in binary form must reproduce the above copyright notice,\r
-  this list of conditions and the following disclaimer in the documentation\r
-  and/or other materials provided with the distribution.\r
-\r
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND\r
-  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
-  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\r
-  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
-  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
-  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
-  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE\r
-  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\r
-  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+  Copyright (c) 2018 - 2021, Intel Corporation. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-#include <PiDxe.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Protocol/VariableLock.h>\r
+#include "FmpDxe.h"\r
 #include "VariableSupport.h"\r
 \r
-///\r
-/// Array of UEFI variable names that are locked in LockAllFmpVariables().\r
-///\r
-const CHAR16  *mFmpVariableLockList[] = {\r
-  VARNAME_VERSION,\r
-  VARNAME_LSV,\r
-  VARNAME_LASTATTEMPTSTATUS,\r
-  VARNAME_LASTATTEMPTVERSION\r
-};\r
-\r
 /**\r
-  Returns the value used to fill in the Version field of the\r
-  EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r
-  service of the Firmware Management Protocol.  The value is read from a UEFI\r
-  variable.  If the UEFI variables does not exist, then a default version value\r
-  is returned.\r
+  Retrieve the value of a 32-bit UEFI Variable specified by VariableName and\r
+  a GUID of gEfiCallerIdGuid.\r
+\r
+  @param[in]  VariableName  Pointer to the UEFI Variable name to retrieve.\r
+  @param[out] Valid         Set to TRUE if UEFI Variable is present and the size\r
+                            of the UEFI Variable value is 32-bits.  Otherwise\r
+                            FALSE.\r
+  @param[out] Value         If Valid is set to TRUE, then the 32-bit value of\r
+                            the UEFI Variable.  Otherwise 0.\r
+**/\r
+static\r
+VOID\r
+GetFmpVariable (\r
+  IN  CHAR16   *VariableName,\r
+  OUT BOOLEAN  *Valid,\r
+  OUT UINT32   *Value\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Size;\r
+  UINT32      *Buffer;\r
+\r
+  *Valid = FALSE;\r
+  *Value = 0;\r
+  Size   = 0;\r
+  Buffer = NULL;\r
+  Status = GetVariable2 (\r
+             VariableName,\r
+             &gEfiCallerIdGuid,\r
+             (VOID **)&Buffer,\r
+             &Size\r
+             );\r
+  if (!EFI_ERROR (Status) && (Size == sizeof (*Value)) && (Buffer != NULL)) {\r
+    *Valid = TRUE;\r
+    *Value = *Buffer;\r
+  }\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"\r
+  if (Buffer != NULL) {\r
+    FreePool (Buffer);\r
+  }\r
+}\r
 \r
-  @return  The version of the firmware image in the firmware device.\r
+/**\r
+  Delete the UEFI Variable with name specified by VariableName and GUID of\r
+  gEfiCallerIdGuid.  If the variable can not be deleted, then print a\r
+  DEBUG_ERROR message.\r
 \r
+  @param[in] VariableName  Pointer to the UEFI Variable name to delete.\r
 **/\r
-UINT32\r
-GetVersionFromVariable (\r
-  VOID\r
+static\r
+VOID\r
+DeleteFmpVariable (\r
+  IN CHAR16  *VariableName\r
   )\r
 {\r
   EFI_STATUS  Status;\r
-  UINT32      *Value;\r
-  UINTN       Size;\r
-  UINT32      Version;\r
+  BOOLEAN     Valid;\r
+  UINT32      Value;\r
 \r
-  Value = NULL;\r
-  Size = 0;\r
-  Version = DEFAULT_VERSION;\r
+  GetFmpVariable (VariableName, &Valid, &Value);\r
+  if (Valid) {\r
+    Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to delete variable %s.  Status = %r\n", mImageIdName, VariableName, Status));\r
+    } else {\r
+      DEBUG ((DEBUG_INFO, "FmpDxe(%s): Deleted variable %s\n", mImageIdName, VariableName));\r
+    }\r
+  }\r
+}\r
 \r
-  Status = GetVariable2 (VARNAME_VERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
-  if (EFI_ERROR (Status) || (Value == NULL)) {\r
-    DEBUG ((DEBUG_ERROR, "Failed to get the Version from variable.  Status = %r\n", Status));\r
-    return Version;\r
+/**\r
+  Retrieve the FMP Controller State UEFI Variable value.  Return NULL if\r
+  the variable does not exist or if the size of the UEFI Variable is not the\r
+  size of FMP_CONTROLLER_STATE.  The buffer for the UEFI Variable value\r
+  if allocated using the UEFI Boot Service AllocatePool().\r
+\r
+  @param[in] Private  Private context structure for the managed controller.\r
+\r
+  @return  Pointer to the allocated FMP Controller State.  Returns NULL\r
+           if the variable does not exist or is a different size than expected.\r
+**/\r
+static\r
+FMP_CONTROLLER_STATE *\r
+GetFmpControllerState (\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  UINTN                 Size;\r
+\r
+  FmpControllerState = NULL;\r
+  Size               = 0;\r
+  Status             = GetVariable2 (\r
+                         Private->FmpStateVariableName,\r
+                         &gEfiCallerIdGuid,\r
+                         (VOID **)&FmpControllerState,\r
+                         &Size\r
+                         );\r
+  if (EFI_ERROR (Status) || (FmpControllerState == NULL)) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to get the controller state.  Status = %r\n", mImageIdName, Status));\r
+  } else {\r
+    if (Size == sizeof (*FmpControllerState)) {\r
+      return FmpControllerState;\r
+    }\r
+\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Getting controller state returned a size different than expected. Size = 0x%x\n", mImageIdName, Size));\r
+  }\r
+\r
+  if (FmpControllerState != NULL) {\r
+    FreePool (FmpControllerState);\r
   }\r
 \r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Generates a Null-terminated Unicode string UEFI Variable name from a base name\r
+  and a hardware instance.  If the hardware instance value is 0, then the base\r
+  name is returned.  If the hardware instance value is non-zero, then the 64-bit\r
+  hardware instance value is converted to a 16 character hex string and appended\r
+  to base name.  The UEFI Variable name returned is allocated using the UEFI\r
+  Boot Service AllocatePool().\r
+\r
+  @param[in] HardwareInstance  64-bit hardware instance value.\r
+  @param[in] BaseVariableName  Null-terminated Unicode string that is the base\r
+                               name of the UEFI Variable.\r
+\r
+  @return  Pointer to the allocated UEFI Variable name.  Returns NULL if the\r
+           UEFI Variable can not be allocated.\r
+**/\r
+static\r
+CHAR16 *\r
+GenerateFmpVariableName (\r
+  IN  UINT64  HardwareInstance,\r
+  IN  CHAR16  *BaseVariableName\r
+  )\r
+{\r
+  UINTN   Size;\r
+  CHAR16  *VariableName;\r
+\r
   //\r
-  // No error from call\r
+  // Allocate Unicode string with room for BaseVariableName and a 16 digit\r
+  // hexadecimal value for the HardwareInstance value.\r
   //\r
-  if (Size == sizeof (*Value)) {\r
+  Size         = StrSize (BaseVariableName) + 16 * sizeof (CHAR16);\r
+  VariableName = AllocateCopyPool (Size, BaseVariableName);\r
+  if (VariableName == NULL) {\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to generate variable name %s.\n", mImageIdName, BaseVariableName));\r
+    return VariableName;\r
+  }\r
+\r
+  if (HardwareInstance == 0) {\r
+    return VariableName;\r
+  }\r
+\r
+  UnicodeValueToStringS (\r
+    &VariableName[StrLen (BaseVariableName)],\r
+    Size,\r
+    PREFIX_ZERO | RADIX_HEX,\r
+    HardwareInstance,\r
+    16\r
+    );\r
+  return VariableName;\r
+}\r
+\r
+/**\r
+  Generate the names of the UEFI Variables used to store state information for\r
+  a managed controller.  The UEFI Variables names are a combination of a base\r
+  name and an optional hardware instance value as a 16 character hex value.  If\r
+  the hardware instance value is 0, then the 16 character hex value is not\r
+  included.  These storage for the UEFI Variable names are allocated using the\r
+  UEFI Boot Service AllocatePool() and the pointers are stored in the Private.\r
+  The following are examples of variable names produces for hardware instance\r
+  value 0 and value 0x1234567812345678.\r
+\r
+    FmpVersion\r
+    FmpLsv\r
+    LastAttemptStatus\r
+    LastAttemptVersion\r
+    FmpState\r
+\r
+    FmpVersion1234567812345678\r
+    FmpLsv1234567812345678\r
+    LastAttemptStatus1234567812345678\r
+    LastAttemptVersion1234567812345678\r
+    FmpState1234567812345678\r
+\r
+  @param[in,out] Private  Private context structure for the managed controller.\r
+**/\r
+VOID\r
+GenerateFmpVariableNames (\r
+  IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  VOID                  *Buffer;\r
+  FMP_CONTROLLER_STATE  FmpControllerState;\r
+\r
+  if (Private->VersionVariableName != NULL) {\r
+    FreePool (Private->VersionVariableName);\r
+  }\r
+\r
+  if (Private->LsvVariableName != NULL) {\r
+    FreePool (Private->LsvVariableName);\r
+  }\r
+\r
+  if (Private->LastAttemptStatusVariableName != NULL) {\r
+    FreePool (Private->LastAttemptStatusVariableName);\r
+  }\r
+\r
+  if (Private->LastAttemptVersionVariableName != NULL) {\r
+    FreePool (Private->LastAttemptVersionVariableName);\r
+  }\r
+\r
+  if (Private->FmpStateVariableName != NULL) {\r
+    FreePool (Private->FmpStateVariableName);\r
+  }\r
+\r
+  Private->VersionVariableName = GenerateFmpVariableName (\r
+                                   Private->Descriptor.HardwareInstance,\r
+                                   VARNAME_VERSION\r
+                                   );\r
+  Private->LsvVariableName = GenerateFmpVariableName (\r
+                               Private->Descriptor.HardwareInstance,\r
+                               VARNAME_LSV\r
+                               );\r
+  Private->LastAttemptStatusVariableName = GenerateFmpVariableName (\r
+                                             Private->Descriptor.HardwareInstance,\r
+                                             VARNAME_LASTATTEMPTSTATUS\r
+                                             );\r
+  Private->LastAttemptVersionVariableName = GenerateFmpVariableName (\r
+                                              Private->Descriptor.HardwareInstance,\r
+                                              VARNAME_LASTATTEMPTVERSION\r
+                                              );\r
+  Private->FmpStateVariableName = GenerateFmpVariableName (\r
+                                    Private->Descriptor.HardwareInstance,\r
+                                    VARNAME_FMPSTATE\r
+                                    );\r
+\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->VersionVariableName));\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LsvVariableName));\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Variable %g %s\n", mImageIdName, &gEfiCallerIdGuid, Private->FmpStateVariableName));\r
+\r
+  Buffer = GetFmpControllerState (Private);\r
+  if (Buffer != NULL) {\r
     //\r
-    // Successful read\r
+    // FMP Controller State was found with correct size.\r
+    // Delete old variables if they exist.\r
     //\r
-    Version = *Value;\r
-  } else {\r
+    FreePool (Buffer);\r
+    DeleteFmpVariable (Private->VersionVariableName);\r
+    DeleteFmpVariable (Private->LsvVariableName);\r
+    DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r
+    DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r
+    return;\r
+  }\r
+\r
+  //\r
+  // FMP Controller State was either not found or is wrong size.\r
+  // Create a new FMP Controller State variable with the correct size.\r
+  //\r
+  DEBUG ((DEBUG_INFO, "FmpDxe(%s): Create controller state\n", mImageIdName));\r
+  GetFmpVariable (\r
+    Private->VersionVariableName,\r
+    &FmpControllerState.VersionValid,\r
+    &FmpControllerState.Version\r
+    );\r
+  GetFmpVariable (\r
+    Private->LsvVariableName,\r
+    &FmpControllerState.LsvValid,\r
+    &FmpControllerState.Lsv\r
+    );\r
+  GetFmpVariable (\r
+    Private->LastAttemptStatusVariableName,\r
+    &FmpControllerState.LastAttemptStatusValid,\r
+    &FmpControllerState.LastAttemptStatus\r
+    );\r
+  GetFmpVariable (\r
+    Private->LastAttemptVersionVariableName,\r
+    &FmpControllerState.LastAttemptVersionValid,\r
+    &FmpControllerState.LastAttemptVersion\r
+    );\r
+  Status = gRT->SetVariable (\r
+                  Private->FmpStateVariableName,\r
+                  &gEfiCallerIdGuid,\r
+                  EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                  sizeof (FmpControllerState),\r
+                  &FmpControllerState\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
     //\r
-    // Return default since size was unknown\r
+    // Failed to create FMP Controller State.  In this case, do not\r
+    // delete the individual variables.  They can be used again on next boot\r
+    // to create the FMP Controller State.\r
     //\r
-    DEBUG ((DEBUG_ERROR, "Getting version Variable returned a size different than expected. Size = 0x%x\n", Size));\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to create controller state.  Status = %r\n", mImageIdName, Status));\r
+  } else {\r
+    DeleteFmpVariable (Private->VersionVariableName);\r
+    DeleteFmpVariable (Private->LsvVariableName);\r
+    DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r
+    DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r
   }\r
+}\r
+\r
+/**\r
+  Returns the value used to fill in the Version field of the\r
+  EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r
+  service of the Firmware Management Protocol.  The value is read from a UEFI\r
+  variable.  If the UEFI variables does not exist, then a default version value\r
+  is returned.\r
 \r
-  FreePool (Value);\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
-  return Version;\r
+  @param[in] Private  Private context structure for the managed controller.\r
+\r
+  @return  The version of the firmware image in the firmware device.\r
+**/\r
+UINT32\r
+GetVersionFromVariable (\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
+  )\r
+{\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  UINT32                Value;\r
+\r
+  Value              = DEFAULT_VERSION;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState != NULL) {\r
+    if (FmpControllerState->VersionValid) {\r
+      Value = FmpControllerState->Version;\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Get variable %g %s Version %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        Value\r
+        ));\r
+    }\r
+\r
+    FreePool (FmpControllerState);\r
+  }\r
+\r
+  return Value;\r
 }\r
 \r
 /**\r
@@ -104,50 +369,40 @@ GetVersionFromVariable (
   variable.  If the UEFI variables does not exist, then a default lowest\r
   supported version value is returned.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
+\r
+  @param[in] Private  Private context structure for the managed controller.\r
 \r
   @return  The lowest supported version of the firmware image in the firmware\r
            device.\r
-\r
 **/\r
 UINT32\r
 GetLowestSupportedVersionFromVariable (\r
-  VOID\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      *Value;\r
-  UINTN       Size;\r
-  UINT32      Version;\r
-\r
-  Value   = NULL;\r
-  Size    = 0;\r
-  Version = DEFAULT_LOWESTSUPPORTEDVERSION;\r
-\r
-  Status = GetVariable2 (VARNAME_LSV, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
-  if (EFI_ERROR (Status) || (Value == NULL)) {\r
-    DEBUG ((DEBUG_WARN, "Warning: Failed to get the Lowest Supported Version from variable.  Status = %r\n", Status));\r
-    return Version;\r
-  }\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  UINT32                Value;\r
+\r
+  Value              = DEFAULT_LOWESTSUPPORTEDVERSION;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState != NULL) {\r
+    if (FmpControllerState->LsvValid) {\r
+      Value = FmpControllerState->Lsv;\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Get variable %g %s LowestSupportedVersion %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        Value\r
+        ));\r
+    }\r
 \r
-  //\r
-  // No error from call\r
-  //\r
-  if (Size == sizeof (*Value)) {\r
-    //\r
-    // Successful read\r
-    //\r
-    Version = *Value;\r
-  } else {\r
-    //\r
-    // Return default since size was unknown\r
-    //\r
-    DEBUG ((DEBUG_ERROR, "Getting LSV Variable returned a size different than expected. Size = 0x%x\n", Size));\r
+    FreePool (FmpControllerState);\r
   }\r
 \r
-  FreePool (Value);\r
-\r
-  return Version;\r
+  return Value;\r
 }\r
 \r
 /**\r
@@ -157,53 +412,39 @@ GetLowestSupportedVersionFromVariable (
   variable.  If the UEFI variables does not exist, then a default last attempt\r
   status value is returned.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
-  @return  The last attempt status value for the most recent capsule update.\r
+  @param[in] Private  Private context structure for the managed controller.\r
 \r
+  @return  The last attempt status value for the most recent capsule update.\r
 **/\r
 UINT32\r
 GetLastAttemptStatusFromVariable (\r
-  VOID\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      *Value;\r
-  UINTN       Size;\r
-  UINT32      LastAttemptStatus;\r
-\r
-  Value = NULL;\r
-  Size  = 0;\r
-  LastAttemptStatus     = DEFAULT_LASTATTEMPT;\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  UINT32                Value;\r
+\r
+  Value              = DEFAULT_LASTATTEMPTSTATUS;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState != NULL) {\r
+    if (FmpControllerState->LastAttemptStatusValid) {\r
+      Value = FmpControllerState->LastAttemptStatus;\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Get variable %g %s LastAttemptStatus %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        Value\r
+        ));\r
+    }\r
 \r
-  Status = GetVariable2 (VARNAME_LASTATTEMPTSTATUS, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
-  if (EFI_ERROR (Status) || (Value == NULL)) {\r
-    DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Status from variable.  Status = %r\n", Status));\r
-    return LastAttemptStatus;\r
+    FreePool (FmpControllerState);\r
   }\r
 \r
-  //\r
-  // No error from call\r
-  //\r
-  if (Size == sizeof (*Value)) {\r
-    //\r
-    // Successful read\r
-    //\r
-    LastAttemptStatus = *Value;\r
-  } else {\r
-    //\r
-    // Return default since size was unknown\r
-    //\r
-    DEBUG (\r
-      (DEBUG_ERROR,\r
-      "Getting Last Attempt Status Variable returned a size different than expected. Size = 0x%x\n",\r
-      Size)\r
-      );\r
-  }\r
-\r
-  FreePool (Value);\r
-\r
-  return LastAttemptStatus;\r
+  return Value;\r
 }\r
 \r
 /**\r
@@ -213,249 +454,394 @@ GetLastAttemptStatusFromVariable (
   variable.  If the UEFI variables does not exist, then a default last attempt\r
   version value is returned.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
-  @return  The last attempt version value for the most recent capsule update.\r
+  @param[in] Private  Private context structure for the managed controller.\r
 \r
+  @return  The last attempt version value for the most recent capsule update.\r
 **/\r
 UINT32\r
 GetLastAttemptVersionFromVariable (\r
-  VOID\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      *Value;\r
-  UINTN       Size;\r
-  UINT32      Version;\r
-\r
-  Value   = NULL;\r
-  Size    = 0;\r
-  Version = DEFAULT_LASTATTEMPT;\r
-\r
-  Status = GetVariable2 (VARNAME_LASTATTEMPTVERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
-  if (EFI_ERROR (Status) || (Value == NULL)) {\r
-    DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Version from variable.  Status = %r\n", Status));\r
-    return Version;\r
-  }\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  UINT32                Value;\r
+\r
+  Value              = DEFAULT_LASTATTEMPTVERSION;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState != NULL) {\r
+    if (FmpControllerState->LastAttemptVersionValid) {\r
+      Value = FmpControllerState->LastAttemptVersion;\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Get variable %g %s LastAttemptVersion %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        Value\r
+        ));\r
+    }\r
 \r
-  //\r
-  // No error from call\r
-  //\r
-  if (Size == sizeof (*Value)) {\r
-    //\r
-    // Successful read\r
-    //\r
-    Version = *Value;\r
-  } else {\r
-    //\r
-    // Return default since size was unknown\r
-    //\r
-    DEBUG (\r
-      (DEBUG_ERROR,\r
-      "Getting Last Attempt Version variable returned a size different than expected. Size = 0x%x\n",\r
-      Size)\r
-      );\r
+    FreePool (FmpControllerState);\r
   }\r
 \r
-  FreePool (Value);\r
-\r
-  return Version;\r
+  return Value;\r
 }\r
 \r
-\r
 /**\r
   Saves the version current of the firmware image in the firmware device to a\r
   UEFI variable.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
+  @param[in] Private  Private context structure for the managed controller.\r
   @param[in] Version  The version of the firmware image in the firmware device.\r
-\r
 **/\r
 VOID\r
 SetVersionInVariable (\r
-   UINT32  Version\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,\r
+  IN UINT32                            Version\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      Current;\r
+  EFI_STATUS            Status;\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  BOOLEAN               Update;\r
 \r
-  Status = EFI_SUCCESS;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState == NULL) {\r
+    //\r
+    // Can not update value if FMP Controller State does not exist.\r
+    // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+    //\r
+    return;\r
+  }\r
 \r
-  Current = GetVersionFromVariable();\r
-  if (Current != Version) {\r
-    Status = gRT->SetVariable (\r
-                    VARNAME_VERSION,\r
-                    &gEfiCallerIdGuid,\r
-                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                    sizeof (Version),\r
-                    &Version\r
-                    );\r
+  Update = FALSE;\r
+  if (!FmpControllerState->VersionValid) {\r
+    Update = TRUE;\r
+  }\r
+\r
+  if (FmpControllerState->Version != Version) {\r
+    Update = TRUE;\r
+  }\r
+\r
+  if (!Update) {\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));\r
+  } else {\r
+    FmpControllerState->VersionValid = TRUE;\r
+    FmpControllerState->Version      = Version;\r
+    Status                           = gRT->SetVariable (\r
+                                              Private->FmpStateVariableName,\r
+                                              &gEfiCallerIdGuid,\r
+                                              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                                              sizeof (*FmpControllerState),\r
+                                              FmpControllerState\r
+                                              );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "Failed to set the Version into a variable.  Status = %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Set variable %g %s Version %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        Version\r
+        ));\r
     }\r
-  } else {\r
-    DEBUG ((DEBUG_INFO, "Version variable doesn't need to update.  Same value as before.\n"));\r
   }\r
+\r
+  FreePool (FmpControllerState);\r
 }\r
 \r
 /**\r
   Saves the lowest supported version current of the firmware image in the\r
   firmware device to a UEFI variable.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"\r
-\r
-  @param[in] LowestSupported  The lowest supported version of the firmware image\r
-                              in the firmware device.\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
+  @param[in] Private                 Private context structure for the managed\r
+                                     controller.\r
+  @param[in] LowestSupportedVersion  The lowest supported version of the\r
+                                     firmware image in the firmware device.\r
 **/\r
 VOID\r
 SetLowestSupportedVersionInVariable (\r
-   UINT32  LowestSupportedVersion\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,\r
+  IN UINT32                            LowestSupportedVersion\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      Current;\r
+  EFI_STATUS            Status;\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  BOOLEAN               Update;\r
 \r
-  Status = EFI_SUCCESS;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState == NULL) {\r
+    //\r
+    // Can not update value if FMP Controller State does not exist.\r
+    // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+    //\r
+    return;\r
+  }\r
+\r
+  Update = FALSE;\r
+  if (!FmpControllerState->LsvValid) {\r
+    Update = TRUE;\r
+  }\r
 \r
-  Current = GetLowestSupportedVersionFromVariable();\r
-  if (LowestSupportedVersion > Current) {\r
-    Status = gRT->SetVariable (\r
-                    VARNAME_LSV,\r
-                    &gEfiCallerIdGuid,\r
-                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                    sizeof (LowestSupportedVersion), &LowestSupportedVersion\r
-                    );\r
+  if (FmpControllerState->Lsv < LowestSupportedVersion) {\r
+    Update = TRUE;\r
+  }\r
+\r
+  if (!Update) {\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));\r
+  } else {\r
+    FmpControllerState->LsvValid = TRUE;\r
+    FmpControllerState->Lsv      = LowestSupportedVersion;\r
+    Status                       = gRT->SetVariable (\r
+                                          Private->FmpStateVariableName,\r
+                                          &gEfiCallerIdGuid,\r
+                                          EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                                          sizeof (*FmpControllerState),\r
+                                          FmpControllerState\r
+                                          );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "Failed to set the LSV into a variable.  Status = %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Set variable %g %s LowestSupportedVersion %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        LowestSupportedVersion\r
+        ));\r
     }\r
-  } else {\r
-    DEBUG ((DEBUG_INFO, "LSV variable doesn't need to update.  Same value as before.\n"));\r
   }\r
+\r
+  FreePool (FmpControllerState);\r
 }\r
 \r
 /**\r
   Saves the last attempt status value of the most recent FMP capsule update to a\r
   UEFI variable.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
+  @param[in] Private            Private context structure for the managed\r
+                                controller.\r
   @param[in] LastAttemptStatus  The last attempt status of the most recent FMP\r
                                 capsule update.\r
-\r
 **/\r
 VOID\r
 SetLastAttemptStatusInVariable (\r
-   UINT32  LastAttemptStatus\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,\r
+  IN UINT32                            LastAttemptStatus\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      Current;\r
+  EFI_STATUS            Status;\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  BOOLEAN               Update;\r
 \r
-  Status = EFI_SUCCESS;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState == NULL) {\r
+    //\r
+    // Can not update value if FMP Controller State does not exist.\r
+    // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+    //\r
+    return;\r
+  }\r
+\r
+  Update = FALSE;\r
+  if (!FmpControllerState->LastAttemptStatusValid) {\r
+    Update = TRUE;\r
+  }\r
 \r
-  Current = GetLastAttemptStatusFromVariable();\r
-  if (Current != LastAttemptStatus) {\r
-    Status = gRT->SetVariable (\r
-                    VARNAME_LASTATTEMPTSTATUS,\r
-                    &gEfiCallerIdGuid,\r
-                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                    sizeof (LastAttemptStatus),\r
-                    &LastAttemptStatus\r
-                    );\r
+  if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {\r
+    Update = TRUE;\r
+  }\r
+\r
+  if (!Update) {\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));\r
+  } else {\r
+    FmpControllerState->LastAttemptStatusValid = TRUE;\r
+    FmpControllerState->LastAttemptStatus      = LastAttemptStatus;\r
+    Status                                     = gRT->SetVariable (\r
+                                                        Private->FmpStateVariableName,\r
+                                                        &gEfiCallerIdGuid,\r
+                                                        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                                                        sizeof (*FmpControllerState),\r
+                                                        FmpControllerState\r
+                                                        );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "Failed to set the LastAttemptStatus into a variable.  Status = %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Set variable %g %s LastAttemptStatus %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        LastAttemptStatus\r
+        ));\r
     }\r
-  } else {\r
-    DEBUG ((DEBUG_INFO, "LastAttemptStatus variable doesn't need to update.  Same value as before.\n"));\r
   }\r
+\r
+  FreePool (FmpControllerState);\r
 }\r
 \r
 /**\r
   Saves the last attempt version value of the most recent FMP capsule update to\r
   a UEFI variable.\r
 \r
-  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"\r
+  UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
 \r
+  @param[in] Private             Private context structure for the managed\r
+                                 controller.\r
   @param[in] LastAttemptVersion  The last attempt version value of the most\r
                                  recent FMP capsule update.\r
-\r
 **/\r
 VOID\r
 SetLastAttemptVersionInVariable (\r
-   UINT32  LastAttemptVersion\r
+  IN FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private,\r
+  IN UINT32                            LastAttemptVersion\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
-  UINT32      Current;\r
+  EFI_STATUS            Status;\r
+  FMP_CONTROLLER_STATE  *FmpControllerState;\r
+  BOOLEAN               Update;\r
 \r
-  Status = EFI_SUCCESS;\r
+  FmpControllerState = GetFmpControllerState (Private);\r
+  if (FmpControllerState == NULL) {\r
+    //\r
+    // Can not update value if FMP Controller State does not exist.\r
+    // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+    //\r
+    return;\r
+  }\r
+\r
+  Update = FALSE;\r
+  if (!FmpControllerState->LastAttemptVersionValid) {\r
+    Update = TRUE;\r
+  }\r
 \r
-  Current = GetLastAttemptVersionFromVariable();\r
-  if (Current != LastAttemptVersion) {\r
-    Status = gRT->SetVariable (\r
-                    VARNAME_LASTATTEMPTVERSION,\r
-                    &gEfiCallerIdGuid,\r
-                    EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
-                    sizeof (LastAttemptVersion),\r
-                    &LastAttemptVersion\r
-                    );\r
+  if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {\r
+    Update = TRUE;\r
+  }\r
+\r
+  if (!Update) {\r
+    DEBUG ((DEBUG_INFO, "FmpDxe(%s): No need to update controller state.  Same value as before.\n", mImageIdName));\r
+  } else {\r
+    FmpControllerState->LastAttemptVersionValid = TRUE;\r
+    FmpControllerState->LastAttemptVersion      = LastAttemptVersion;\r
+    Status                                      = gRT->SetVariable (\r
+                                                         Private->FmpStateVariableName,\r
+                                                         &gEfiCallerIdGuid,\r
+                                                         EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+                                                         sizeof (*FmpControllerState),\r
+                                                         FmpControllerState\r
+                                                         );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "Failed to set the LastAttemptVersion into a variable.  Status = %r\n", Status));\r
+      DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to update controller state.  Status = %r\n", mImageIdName, Status));\r
+    } else {\r
+      DEBUG ((\r
+        DEBUG_INFO,\r
+        "FmpDxe(%s): Set variable %g %s LastAttemptVersion %08x\n",\r
+        mImageIdName,\r
+        &gEfiCallerIdGuid,\r
+        Private->FmpStateVariableName,\r
+        LastAttemptVersion\r
+        ));\r
     }\r
-  } else {\r
-    DEBUG ((DEBUG_INFO, "LastAttemptVersion variable doesn't need to update.  Same value as before.\n"));\r
   }\r
+\r
+  FreePool (FmpControllerState);\r
 }\r
 \r
 /**\r
-  Locks all the UEFI Variables used by this module.\r
+  Attempts to lock a single UEFI Variable propagating the error state of the\r
+  first lock attempt that fails.  Uses gEfiCallerIdGuid as the variable GUID.\r
+\r
+  @param[in] PreviousStatus  The previous UEFI Variable lock attempt status.\r
+  @param[in] VariableLock    The EDK II Variable Lock Protocol instance.\r
+  @param[in] VariableName    The name of the UEFI Variable to lock.\r
+\r
+  @retval  EFI_SUCCESS  The UEFI Variable was locked and the previous variable\r
+                        lock attempt also succeeded.\r
+  @retval  Other        The UEFI Variable could not be locked or the previous\r
+                        variable lock attempt failed.\r
+**/\r
+static\r
+EFI_STATUS\r
+LockFmpVariable (\r
+  IN EFI_STATUS                      PreviousStatus,\r
+  IN EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy,\r
+  IN CHAR16                          *VariableName\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  // If success, go ahead and set the policies to protect the target variables.\r
+  Status = RegisterBasicVariablePolicy (\r
+             VariablePolicy,\r
+             &gEfiCallerIdGuid,\r
+             VariableName,\r
+             VARIABLE_POLICY_NO_MIN_SIZE,\r
+             VARIABLE_POLICY_NO_MAX_SIZE,\r
+             VARIABLE_POLICY_NO_MUST_ATTR,\r
+             VARIABLE_POLICY_NO_CANT_ATTR,\r
+             VARIABLE_POLICY_TYPE_LOCK_NOW\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((\r
+      DEBUG_ERROR,\r
+      "FmpDxe(%s): Failed to lock variable %g %s. Status = %r\n",\r
+      mImageIdName,\r
+      &gEfiCallerIdGuid,\r
+      VariableName,\r
+      Status\r
+      ));\r
+  }\r
+\r
+  if (EFI_ERROR (PreviousStatus)) {\r
+    return PreviousStatus;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently\r
+  executing module.\r
+\r
+  @param[in] Private  Private context structure for the managed controller.\r
 \r
   @retval  EFI_SUCCESS      All UEFI variables are locked.\r
   @retval  EFI_UNSUPPORTED  Variable Lock Protocol not found.\r
   @retval  Other            One of the UEFI variables could not be locked.\r
-\r
 **/\r
 EFI_STATUS\r
 LockAllFmpVariables (\r
-  VOID\r
+  FIRMWARE_MANAGEMENT_PRIVATE_DATA  *Private\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EDKII_VARIABLE_LOCK_PROTOCOL  *VariableLock;\r
-  EFI_STATUS                    ReturnStatus;\r
-  UINTN                         Index;\r
-\r
-  VariableLock = NULL;\r
-  Status = gBS->LocateProtocol (\r
-                  &gEdkiiVariableLockProtocolGuid,\r
-                  NULL,\r
-                  (VOID **)&VariableLock\r
-                  );\r
+  EFI_STATUS                      Status;\r
+  EDKII_VARIABLE_POLICY_PROTOCOL  *VariablePolicy;\r
+\r
+  // Locate the VariablePolicy protocol.\r
+  Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to locate Variable Lock Protocol (%r).\n", Status));\r
-    return EFI_UNSUPPORTED;\r
+    DEBUG ((DEBUG_ERROR, "FmpDxe %a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status));\r
+    return Status;\r
   }\r
 \r
-  ReturnStatus = EFI_SUCCESS;\r
-  for (Index = 0; Index < ARRAY_SIZE (mFmpVariableLockList); Index++) {\r
-    Status = VariableLock->RequestToLock (\r
-                             VariableLock,\r
-                             (CHAR16 *)mFmpVariableLockList[Index],\r
-                             &gEfiCallerIdGuid\r
-                             );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variable %g %s.  Status = %r\n",\r
-        &gEfiCallerIdGuid,\r
-        mFmpVariableLockList[Index],\r
-        Status\r
-        ));\r
-      if (!EFI_ERROR (ReturnStatus)) {\r
-        ReturnStatus = Status;\r
-      }\r
-    }\r
-  }\r
+  Status = EFI_SUCCESS;\r
+  Status = LockFmpVariable (Status, VariablePolicy, Private->VersionVariableName);\r
+  Status = LockFmpVariable (Status, VariablePolicy, Private->LsvVariableName);\r
+  Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptStatusVariableName);\r
+  Status = LockFmpVariable (Status, VariablePolicy, Private->LastAttemptVersionVariableName);\r
+  Status = LockFmpVariable (Status, VariablePolicy, Private->FmpStateVariableName);\r
 \r
-  return ReturnStatus;\r
+  return Status;\r
 }\r