]> git.proxmox.com Git - mirror_edk2.git/commitdiff
The list of locked variables is traversed at runtime, hence we must
authorLaszlo Ersek <lersek@redhat.com>
Fri, 14 Jun 2013 01:55:12 +0000 (01:55 +0000)
committerniruiyu <niruiyu@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 14 Jun 2013 01:55:12 +0000 (01:55 +0000)
convert the list when transferring from physical to virtual mode.

Contributed-under: TianoCore Contribution Agreement 1.0

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14403 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c

index 3cb2c6bcf309dcc6d632017fbafc1ac9c838117c..2aa29469047adb535fc9b6656d710ad5bed758a4 100644 (file)
-/** @file\r
-\r
-  Implement all four UEFI Runtime Variable services for the nonvolatile\r
-  and volatile storage space and install variable architecture protocol.\r
-  \r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials                          \r
-are licensed and made available under the terms and conditions of the BSD License         \r
-which accompanies this distribution.  The full text of the license may be found at        \r
-http://opensource.org/licenses/bsd-license.php                                            \r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
-\r
-**/\r
-\r
-#include "Variable.h"\r
-\r
-extern VARIABLE_STORE_HEADER   *mNvVariableCache;\r
-extern VARIABLE_INFO_ENTRY     *gVariableInfo;\r
-EFI_HANDLE                     mHandle                    = NULL;\r
-EFI_EVENT                      mVirtualAddressChangeEvent = NULL;\r
-EFI_EVENT                      mFtwRegistration           = NULL;\r
-extern BOOLEAN                 mEndOfDxe;\r
-EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { VariableLockRequestToLock };\r
-\r
-/**\r
-  Return TRUE if ExitBootServices () has been called.\r
-  \r
-  @retval TRUE If ExitBootServices () has been called.\r
-**/\r
-BOOLEAN\r
-AtRuntime (\r
-  VOID\r
-  )\r
-{\r
-  return EfiAtRuntime ();\r
-}\r
-\r
-\r
-/**\r
-  Initializes a basic mutual exclusion lock.\r
-\r
-  This function initializes a basic mutual exclusion lock to the released state \r
-  and returns the lock.  Each lock provides mutual exclusion access at its task \r
-  priority level.  Since there is no preemption or multiprocessor support in EFI,\r
-  acquiring the lock only consists of raising to the locks TPL.\r
-  If Lock is NULL, then ASSERT().\r
-  If Priority is not a valid TPL value, then ASSERT().\r
-\r
-  @param  Lock       A pointer to the lock data structure to initialize.\r
-  @param  Priority   EFI TPL is associated with the lock.\r
-\r
-  @return The lock.\r
-\r
-**/\r
-EFI_LOCK *\r
-InitializeLock (\r
-  IN OUT EFI_LOCK                         *Lock,\r
-  IN     EFI_TPL                          Priority\r
-  )\r
-{\r
-  return EfiInitializeLock (Lock, Priority);\r
-}\r
-\r
-\r
-/**\r
-  Acquires lock only at boot time. Simply returns at runtime.\r
-\r
-  This is a temperary function that will be removed when\r
-  EfiAcquireLock() in UefiLib can handle the call in UEFI\r
-  Runtimer driver in RT phase.\r
-  It calls EfiAcquireLock() at boot time, and simply returns\r
-  at runtime.\r
-\r
-  @param  Lock         A pointer to the lock to acquire.\r
-\r
-**/\r
-VOID\r
-AcquireLockOnlyAtBootTime (\r
-  IN EFI_LOCK                             *Lock\r
-  )\r
-{\r
-  if (!AtRuntime ()) {\r
-    EfiAcquireLock (Lock);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Releases lock only at boot time. Simply returns at runtime.\r
-\r
-  This is a temperary function which will be removed when\r
-  EfiReleaseLock() in UefiLib can handle the call in UEFI\r
-  Runtimer driver in RT phase.\r
-  It calls EfiReleaseLock() at boot time and simply returns\r
-  at runtime.\r
-\r
-  @param  Lock         A pointer to the lock to release.\r
-\r
-**/\r
-VOID\r
-ReleaseLockOnlyAtBootTime (\r
-  IN EFI_LOCK                             *Lock\r
-  )\r
-{\r
-  if (!AtRuntime ()) {\r
-    EfiReleaseLock (Lock);\r
-  }\r
-}\r
-\r
-/**\r
-  Retrive the Fault Tolerent Write protocol interface.\r
-\r
-  @param[out] FtwProtocol       The interface of Ftw protocol\r
-\r
-  @retval EFI_SUCCESS           The FTW protocol instance was found and returned in FtwProtocol.\r
-  @retval EFI_NOT_FOUND         The FTW protocol instance was not found.\r
-  @retval EFI_INVALID_PARAMETER SarProtocol is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-GetFtwProtocol (\r
-  OUT VOID                                **FtwProtocol\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-\r
-  //\r
-  // Locate Fault Tolerent Write protocol\r
-  //\r
-  Status = gBS->LocateProtocol (\r
-                  &gEfiFaultTolerantWriteProtocolGuid,\r
-                  NULL,\r
-                  FtwProtocol\r
-                  );                    \r
-  return Status;\r
-}\r
-\r
-/**\r
-  Retrive the FVB protocol interface by HANDLE.\r
-\r
-  @param[in]  FvBlockHandle     The handle of FVB protocol that provides services for\r
-                                reading, writing, and erasing the target block.\r
-  @param[out] FvBlock           The interface of FVB protocol\r
-\r
-  @retval EFI_SUCCESS           The interface information for the specified protocol was returned.\r
-  @retval EFI_UNSUPPORTED       The device does not support the FVB protocol.\r
-  @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.\r
-  \r
-**/\r
-EFI_STATUS\r
-GetFvbByHandle (\r
-  IN  EFI_HANDLE                          FvBlockHandle,\r
-  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvBlock\r
-  )\r
-{\r
-  //\r
-  // To get the FVB protocol interface on the handle\r
-  //\r
-  return gBS->HandleProtocol (\r
-                FvBlockHandle,\r
-                &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                (VOID **) FvBlock\r
-                );\r
-}\r
-\r
-\r
-/**\r
-  Function returns an array of handles that support the FVB protocol\r
-  in a buffer allocated from pool. \r
-\r
-  @param[out]  NumberHandles    The number of handles returned in Buffer.\r
-  @param[out]  Buffer           A pointer to the buffer to return the requested\r
-                                array of  handles that support FVB protocol.\r
-\r
-  @retval EFI_SUCCESS           The array of handles was returned in Buffer, and the number of\r
-                                handles in Buffer was returned in NumberHandles.\r
-  @retval EFI_NOT_FOUND         No FVB handle was found.\r
-  @retval EFI_OUT_OF_RESOURCES  There is not enough pool memory to store the matching results.\r
-  @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.\r
-  \r
-**/\r
-EFI_STATUS\r
-GetFvbCountAndBuffer (\r
-  OUT UINTN                               *NumberHandles,\r
-  OUT EFI_HANDLE                          **Buffer\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-\r
-  //\r
-  // Locate all handles of Fvb protocol\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                  NULL,\r
-                  NumberHandles,\r
-                  Buffer\r
-                  );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r
-\r
-  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
-  It convers pointer to new virtual address.\r
-\r
-  @param  Event        Event whose notification function is being invoked.\r
-  @param  Context      Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VariableClassAddressChangeEvent (\r
-  IN EFI_EVENT                            Event,\r
-  IN VOID                                 *Context\r
-  )\r
-{\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);\r
-  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);  \r
-}\r
-\r
-\r
-/**\r
-  Notification function of EVT_GROUP_READY_TO_BOOT event group.\r
-\r
-  This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.\r
-  When the Boot Manager is about to load and execute a boot option, it reclaims variable\r
-  storage if free size is below the threshold.\r
-\r
-  @param  Event        Event whose notification function is being invoked.\r
-  @param  Context      Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-OnReadyToBoot (\r
-  EFI_EVENT                               Event,\r
-  VOID                                    *Context\r
-  )\r
-{\r
-  //\r
-  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.\r
-  //\r
-  mEndOfDxe = TRUE;\r
-  ReclaimForOS ();\r
-  if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
-    gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);\r
-  }\r
-}\r
-\r
-/**\r
-  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
-\r
-  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
-\r
-  @param  Event        Event whose notification function is being invoked.\r
-  @param  Context      Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-OnEndOfDxe (\r
-  EFI_EVENT                               Event,\r
-  VOID                                    *Context\r
-  )\r
-{\r
-  mEndOfDxe = TRUE;\r
-}\r
-\r
-/**\r
-  Fault Tolerant Write protocol notification event handler.\r
-\r
-  Non-Volatile variable write may needs FTW protocol to reclaim when \r
-  writting variable.\r
-\r
-  @param[in] Event    Event whose notification function is being invoked.\r
-  @param[in] Context  Pointer to the notification function's context.\r
-  \r
-**/\r
-VOID\r
-EFIAPI\r
-FtwNotificationEvent (\r
-  IN  EFI_EVENT                           Event,\r
-  IN  VOID                                *Context\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *FvbProtocol;\r
-  EFI_FAULT_TOLERANT_WRITE_PROTOCOL       *FtwProtocol;\r
-  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR         GcdDescriptor;\r
-  EFI_PHYSICAL_ADDRESS                    BaseAddress;\r
-  UINT64                                  Length;\r
-  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;\r
-  UINT64                                  VariableStoreLength;\r
-\r
-  //\r
-  // Ensure FTW protocol is installed.\r
-  //\r
-  Status = GetFtwProtocol ((VOID**) &FtwProtocol);\r
-  if (EFI_ERROR (Status)) {\r
-    return ;\r
-  }\r
-  \r
-  //\r
-  // Find the proper FVB protocol for variable.\r
-  //\r
-  NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-  if (NvStorageVariableBase == 0) {\r
-    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  }\r
-  Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);\r
-  if (EFI_ERROR (Status)) {\r
-    return ;\r
-  }\r
-  mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
-\r
-  //\r
-  // Mark the variable storage region of the FLASH as RUNTIME.\r
-  //\r
-  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
-  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;\r
-  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);\r
-  Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);\r
-  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);\r
-\r
-  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));\r
-  } else {\r
-    Status = gDS->SetMemorySpaceAttributes (\r
-                    BaseAddress,\r
-                    Length,\r
-                    GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));\r
-    }\r
-  }\r
-  \r
-  Status = VariableWriteServiceInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
\r
-  //\r
-  // Install the Variable Write Architectural protocol.\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mHandle,\r
-                  &gEfiVariableWriteArchProtocolGuid, \r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-  \r
-  //\r
-  // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.\r
-  //\r
-  gBS->CloseEvent (Event);\r
-\r
-}\r
-\r
-\r
-/**\r
-  Variable Driver main entry point. The Variable driver places the 4 EFI\r
-  runtime services in the EFI System Table and installs arch protocols \r
-  for variable read and write services being availible. It also registers\r
-  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
-\r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
-  @retval EFI_SUCCESS       Variable service successfully initialized.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-VariableServiceInitialize (\r
-  IN EFI_HANDLE                         ImageHandle,\r
-  IN EFI_SYSTEM_TABLE                   *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS                            Status;\r
-  EFI_EVENT                             ReadyToBootEvent;\r
-  EFI_EVENT                             EndOfDxeEvent;\r
-\r
-  Status = VariableCommonInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &mHandle,\r
-                  &gEdkiiVariableLockProtocolGuid,\r
-                  &mVariableLock,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  SystemTable->RuntimeServices->GetVariable         = VariableServiceGetVariable;\r
-  SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;\r
-  SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;\r
-  SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;\r
-    \r
-  //\r
-  // Now install the Variable Runtime Architectural protocol on a new handle.\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mHandle,\r
-                  &gEfiVariableArchProtocolGuid, \r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Register FtwNotificationEvent () notify function.\r
-  // \r
-  EfiCreateProtocolNotifyEvent (\r
-    &gEfiFaultTolerantWriteProtocolGuid,\r
-    TPL_CALLBACK,\r
-    FtwNotificationEvent,\r
-    (VOID *)SystemTable,\r
-    &mFtwRegistration\r
-    );\r
-\r
-  Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  VariableClassAddressChangeEvent,\r
-                  NULL,\r
-                  &gEfiEventVirtualAddressChangeGuid,\r
-                  &mVirtualAddressChangeEvent\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Register the event handling function to reclaim variable for OS usage.\r
-  //\r
-  Status = EfiCreateEventReadyToBootEx (\r
-             TPL_NOTIFY, \r
-             OnReadyToBoot, \r
-             NULL, \r
-             &ReadyToBootEvent\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Register the event handling function to set the End Of DXE flag.\r
-  //\r
-  Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  OnEndOfDxe,\r
-                  NULL,\r
-                  &gEfiEndOfDxeEventGroupGuid,\r
-                  &EndOfDxeEvent\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
+/** @file
+
+  Implement all four UEFI Runtime Variable services for the nonvolatile
+  and volatile storage space and install variable architecture protocol.
+  
+Copyright (C) 2013, Red Hat, Inc.
+Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution.  The full text of the license may be found at        
+http://opensource.org/licenses/bsd-license.php                                            
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+**/
+
+#include "Variable.h"
+
+extern VARIABLE_STORE_HEADER   *mNvVariableCache;
+extern VARIABLE_INFO_ENTRY     *gVariableInfo;
+EFI_HANDLE                     mHandle                    = NULL;
+EFI_EVENT                      mVirtualAddressChangeEvent = NULL;
+EFI_EVENT                      mFtwRegistration           = NULL;
+extern LIST_ENTRY              mLockedVariableList;
+extern BOOLEAN                 mEndOfDxe;
+EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { VariableLockRequestToLock };
+
+/**
+  Return TRUE if ExitBootServices () has been called.
+  
+  @retval TRUE If ExitBootServices () has been called.
+**/
+BOOLEAN
+AtRuntime (
+  VOID
+  )
+{
+  return EfiAtRuntime ();
+}
+
+
+/**
+  Initializes a basic mutual exclusion lock.
+
+  This function initializes a basic mutual exclusion lock to the released state 
+  and returns the lock.  Each lock provides mutual exclusion access at its task 
+  priority level.  Since there is no preemption or multiprocessor support in EFI,
+  acquiring the lock only consists of raising to the locks TPL.
+  If Lock is NULL, then ASSERT().
+  If Priority is not a valid TPL value, then ASSERT().
+
+  @param  Lock       A pointer to the lock data structure to initialize.
+  @param  Priority   EFI TPL is associated with the lock.
+
+  @return The lock.
+
+**/
+EFI_LOCK *
+InitializeLock (
+  IN OUT EFI_LOCK                         *Lock,
+  IN     EFI_TPL                          Priority
+  )
+{
+  return EfiInitializeLock (Lock, Priority);
+}
+
+
+/**
+  Acquires lock only at boot time. Simply returns at runtime.
+
+  This is a temperary function that will be removed when
+  EfiAcquireLock() in UefiLib can handle the call in UEFI
+  Runtimer driver in RT phase.
+  It calls EfiAcquireLock() at boot time, and simply returns
+  at runtime.
+
+  @param  Lock         A pointer to the lock to acquire.
+
+**/
+VOID
+AcquireLockOnlyAtBootTime (
+  IN EFI_LOCK                             *Lock
+  )
+{
+  if (!AtRuntime ()) {
+    EfiAcquireLock (Lock);
+  }
+}
+
+
+/**
+  Releases lock only at boot time. Simply returns at runtime.
+
+  This is a temperary function which will be removed when
+  EfiReleaseLock() in UefiLib can handle the call in UEFI
+  Runtimer driver in RT phase.
+  It calls EfiReleaseLock() at boot time and simply returns
+  at runtime.
+
+  @param  Lock         A pointer to the lock to release.
+
+**/
+VOID
+ReleaseLockOnlyAtBootTime (
+  IN EFI_LOCK                             *Lock
+  )
+{
+  if (!AtRuntime ()) {
+    EfiReleaseLock (Lock);
+  }
+}
+
+/**
+  Retrive the Fault Tolerent Write protocol interface.
+
+  @param[out] FtwProtocol       The interface of Ftw protocol
+
+  @retval EFI_SUCCESS           The FTW protocol instance was found and returned in FtwProtocol.
+  @retval EFI_NOT_FOUND         The FTW protocol instance was not found.
+  @retval EFI_INVALID_PARAMETER SarProtocol is NULL.
+
+**/
+EFI_STATUS
+GetFtwProtocol (
+  OUT VOID                                **FtwProtocol
+  )
+{
+  EFI_STATUS                              Status;
+
+  //
+  // Locate Fault Tolerent Write protocol
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiFaultTolerantWriteProtocolGuid,
+                  NULL,
+                  FtwProtocol
+                  );                    
+  return Status;
+}
+
+/**
+  Retrive the FVB protocol interface by HANDLE.
+
+  @param[in]  FvBlockHandle     The handle of FVB protocol that provides services for
+                                reading, writing, and erasing the target block.
+  @param[out] FvBlock           The interface of FVB protocol
+
+  @retval EFI_SUCCESS           The interface information for the specified protocol was returned.
+  @retval EFI_UNSUPPORTED       The device does not support the FVB protocol.
+  @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
+  
+**/
+EFI_STATUS
+GetFvbByHandle (
+  IN  EFI_HANDLE                          FvBlockHandle,
+  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvBlock
+  )
+{
+  //
+  // To get the FVB protocol interface on the handle
+  //
+  return gBS->HandleProtocol (
+                FvBlockHandle,
+                &gEfiFirmwareVolumeBlockProtocolGuid,
+                (VOID **) FvBlock
+                );
+}
+
+
+/**
+  Function returns an array of handles that support the FVB protocol
+  in a buffer allocated from pool. 
+
+  @param[out]  NumberHandles    The number of handles returned in Buffer.
+  @param[out]  Buffer           A pointer to the buffer to return the requested
+                                array of  handles that support FVB protocol.
+
+  @retval EFI_SUCCESS           The array of handles was returned in Buffer, and the number of
+                                handles in Buffer was returned in NumberHandles.
+  @retval EFI_NOT_FOUND         No FVB handle was found.
+  @retval EFI_OUT_OF_RESOURCES  There is not enough pool memory to store the matching results.
+  @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
+  
+**/
+EFI_STATUS
+GetFvbCountAndBuffer (
+  OUT UINTN                               *NumberHandles,
+  OUT EFI_HANDLE                          **Buffer
+  )
+{
+  EFI_STATUS                              Status;
+
+  //
+  // Locate all handles of Fvb protocol
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareVolumeBlockProtocolGuid,
+                  NULL,
+                  NumberHandles,
+                  Buffer
+                  );
+  return Status;
+}
+
+
+/**
+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+  It convers pointer to new virtual address.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+VariableClassAddressChangeEvent (
+  IN EFI_EVENT                            Event,
+  IN VOID                                 *Context
+  )
+{
+  LIST_ENTRY     *Link;
+  VARIABLE_ENTRY *Entry;
+  EFI_STATUS     Status;
+
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
+  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);  
+
+  //
+  // in the list of locked variables, convert the name pointers first
+  //
+  for ( Link = GetFirstNode (&mLockedVariableList)
+      ; !IsNull (&mLockedVariableList, Link)
+      ; Link = GetNextNode (&mLockedVariableList, Link)
+      ) {
+    Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
+    Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name);
+    ASSERT_EFI_ERROR (Status);
+  }
+  //
+  // second, convert the list itself using UefiRuntimeLib
+  //
+  Status = EfiConvertList (0x0, &mLockedVariableList);
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+  Notification function of EVT_GROUP_READY_TO_BOOT event group.
+
+  This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
+  When the Boot Manager is about to load and execute a boot option, it reclaims variable
+  storage if free size is below the threshold.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+  EFI_EVENT                               Event,
+  VOID                                    *Context
+  )
+{
+  //
+  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
+  //
+  mEndOfDxe = TRUE;
+  ReclaimForOS ();
+  if (FeaturePcdGet (PcdVariableCollectStatistics)) {
+    gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);
+  }
+}
+
+/**
+  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnEndOfDxe (
+  EFI_EVENT                               Event,
+  VOID                                    *Context
+  )
+{
+  mEndOfDxe = TRUE;
+}
+
+/**
+  Fault Tolerant Write protocol notification event handler.
+
+  Non-Volatile variable write may needs FTW protocol to reclaim when 
+  writting variable.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+  
+**/
+VOID
+EFIAPI
+FtwNotificationEvent (
+  IN  EFI_EVENT                           Event,
+  IN  VOID                                *Context
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *FvbProtocol;
+  EFI_FAULT_TOLERANT_WRITE_PROTOCOL       *FtwProtocol;
+  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR         GcdDescriptor;
+  EFI_PHYSICAL_ADDRESS                    BaseAddress;
+  UINT64                                  Length;
+  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;
+  UINT64                                  VariableStoreLength;
+
+  //
+  // Ensure FTW protocol is installed.
+  //
+  Status = GetFtwProtocol ((VOID**) &FtwProtocol);
+  if (EFI_ERROR (Status)) {
+    return ;
+  }
+  
+  //
+  // Find the proper FVB protocol for variable.
+  //
+  NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
+  if (NvStorageVariableBase == 0) {
+    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
+  }
+  Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
+  if (EFI_ERROR (Status)) {
+    return ;
+  }
+  mVariableModuleGlobal->FvbInstance = FvbProtocol;
+
+  //
+  // Mark the variable storage region of the FLASH as RUNTIME.
+  //
+  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
+  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
+  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
+  Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);
+  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);
+
+  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
+  } else {
+    Status = gDS->SetMemorySpaceAttributes (
+                    BaseAddress,
+                    Length,
+                    GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
+    }
+  }
+  
+  Status = VariableWriteServiceInitialize ();
+  ASSERT_EFI_ERROR (Status);
+  //
+  // Install the Variable Write Architectural protocol.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mHandle,
+                  &gEfiVariableWriteArchProtocolGuid, 
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+  
+  //
+  // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
+  //
+  gBS->CloseEvent (Event);
+
+}
+
+
+/**
+  Variable Driver main entry point. The Variable driver places the 4 EFI
+  runtime services in the EFI System Table and installs arch protocols 
+  for variable read and write services being availible. It also registers
+  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  
+  @param[in] SystemTable    A pointer to the EFI System Table.
+  
+  @retval EFI_SUCCESS       Variable service successfully initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+VariableServiceInitialize (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_EVENT                             ReadyToBootEvent;
+  EFI_EVENT                             EndOfDxeEvent;
+
+  Status = VariableCommonInitialize ();
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mHandle,
+                  &gEdkiiVariableLockProtocolGuid,
+                  &mVariableLock,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  SystemTable->RuntimeServices->GetVariable         = VariableServiceGetVariable;
+  SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
+  SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;
+  SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;
+    
+  //
+  // Now install the Variable Runtime Architectural protocol on a new handle.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mHandle,
+                  &gEfiVariableArchProtocolGuid, 
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register FtwNotificationEvent () notify function.
+  // 
+  EfiCreateProtocolNotifyEvent (
+    &gEfiFaultTolerantWriteProtocolGuid,
+    TPL_CALLBACK,
+    FtwNotificationEvent,
+    (VOID *)SystemTable,
+    &mFtwRegistration
+    );
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  VariableClassAddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &mVirtualAddressChangeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register the event handling function to reclaim variable for OS usage.
+  //
+  Status = EfiCreateEventReadyToBootEx (
+             TPL_NOTIFY, 
+             OnReadyToBoot, 
+             NULL, 
+             &ReadyToBootEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register the event handling function to set the End Of DXE flag.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  OnEndOfDxe,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+
index a2e764cf610c5d4046e6c947fc2e2d46006fdd69..e0c7ee13da0ca69a7cbdf254441e6c8df35debb4 100644 (file)
-/** @file\r
-  Implement all four UEFI Runtime Variable services for the nonvolatile\r
-  and volatile storage space and install variable architecture protocol.\r
-\r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include "Variable.h"\r
-#include "AuthService.h"\r
-\r
-extern VARIABLE_STORE_HEADER   *mNvVariableCache;\r
-extern VARIABLE_INFO_ENTRY     *gVariableInfo;\r
-EFI_HANDLE                     mHandle                    = NULL;\r
-EFI_EVENT                      mVirtualAddressChangeEvent = NULL;\r
-EFI_EVENT                      mFtwRegistration           = NULL;\r
-extern BOOLEAN                 mEndOfDxe;\r
-EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { VariableLockRequestToLock };\r
-\r
-/**\r
-  Return TRUE if ExitBootServices () has been called.\r
-\r
-  @retval TRUE If ExitBootServices () has been called.\r
-**/\r
-BOOLEAN\r
-AtRuntime (\r
-  VOID\r
-  )\r
-{\r
-  return EfiAtRuntime ();\r
-}\r
-\r
-\r
-/**\r
-  Initializes a basic mutual exclusion lock.\r
-\r
-  This function initializes a basic mutual exclusion lock to the released state\r
-  and returns the lock.  Each lock provides mutual exclusion access at its task\r
-  priority level.  Since there is no preemption or multiprocessor support in EFI,\r
-  acquiring the lock only consists of raising to the locks TPL.\r
-  If Lock is NULL, then ASSERT().\r
-  If Priority is not a valid TPL value, then ASSERT().\r
-\r
-  @param  Lock       A pointer to the lock data structure to initialize.\r
-  @param  Priority   EFI TPL is associated with the lock.\r
-\r
-  @return The lock.\r
-\r
-**/\r
-EFI_LOCK *\r
-InitializeLock (\r
-  IN OUT EFI_LOCK                         *Lock,\r
-  IN     EFI_TPL                          Priority\r
-  )\r
-{\r
-  return EfiInitializeLock (Lock, Priority);\r
-}\r
-\r
-\r
-/**\r
-  Acquires lock only at boot time. Simply returns at runtime.\r
-\r
-  This is a temperary function that will be removed when\r
-  EfiAcquireLock() in UefiLib can handle the call in UEFI\r
-  Runtimer driver in RT phase.\r
-  It calls EfiAcquireLock() at boot time, and simply returns\r
-  at runtime.\r
-\r
-  @param  Lock         A pointer to the lock to acquire.\r
-\r
-**/\r
-VOID\r
-AcquireLockOnlyAtBootTime (\r
-  IN EFI_LOCK                             *Lock\r
-  )\r
-{\r
-  if (!AtRuntime ()) {\r
-    EfiAcquireLock (Lock);\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Releases lock only at boot time. Simply returns at runtime.\r
-\r
-  This is a temperary function which will be removed when\r
-  EfiReleaseLock() in UefiLib can handle the call in UEFI\r
-  Runtimer driver in RT phase.\r
-  It calls EfiReleaseLock() at boot time and simply returns\r
-  at runtime.\r
-\r
-  @param  Lock         A pointer to the lock to release.\r
-\r
-**/\r
-VOID\r
-ReleaseLockOnlyAtBootTime (\r
-  IN EFI_LOCK                             *Lock\r
-  )\r
-{\r
-  if (!AtRuntime ()) {\r
-    EfiReleaseLock (Lock);\r
-  }\r
-}\r
-\r
-/**\r
-  Retrive the Fault Tolerent Write protocol interface.\r
-\r
-  @param[out] FtwProtocol       The interface of Ftw protocol\r
-\r
-  @retval EFI_SUCCESS           The FTW protocol instance was found and returned in FtwProtocol.\r
-  @retval EFI_NOT_FOUND         The FTW protocol instance was not found.\r
-  @retval EFI_INVALID_PARAMETER SarProtocol is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-GetFtwProtocol (\r
-  OUT VOID                                **FtwProtocol\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-\r
-  //\r
-  // Locate Fault Tolerent Write protocol\r
-  //\r
-  Status = gBS->LocateProtocol (\r
-                  &gEfiFaultTolerantWriteProtocolGuid,\r
-                  NULL,\r
-                  FtwProtocol\r
-                  );\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Retrive the FVB protocol interface by HANDLE.\r
-\r
-  @param[in]  FvBlockHandle     The handle of FVB protocol that provides services for\r
-                                reading, writing, and erasing the target block.\r
-  @param[out] FvBlock           The interface of FVB protocol\r
-\r
-  @retval EFI_SUCCESS           The interface information for the specified protocol was returned.\r
-  @retval EFI_UNSUPPORTED       The device does not support the FVB protocol.\r
-  @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-GetFvbByHandle (\r
-  IN  EFI_HANDLE                          FvBlockHandle,\r
-  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvBlock\r
-  )\r
-{\r
-  //\r
-  // To get the FVB protocol interface on the handle\r
-  //\r
-  return gBS->HandleProtocol (\r
-                FvBlockHandle,\r
-                &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                (VOID **) FvBlock\r
-                );\r
-}\r
-\r
-\r
-/**\r
-  Function returns an array of handles that support the FVB protocol\r
-  in a buffer allocated from pool.\r
-\r
-  @param[out]  NumberHandles    The number of handles returned in Buffer.\r
-  @param[out]  Buffer           A pointer to the buffer to return the requested\r
-                                array of  handles that support FVB protocol.\r
-\r
-  @retval EFI_SUCCESS           The array of handles was returned in Buffer, and the number of\r
-                                handles in Buffer was returned in NumberHandles.\r
-  @retval EFI_NOT_FOUND         No FVB handle was found.\r
-  @retval EFI_OUT_OF_RESOURCES  There is not enough pool memory to store the matching results.\r
-  @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-GetFvbCountAndBuffer (\r
-  OUT UINTN                               *NumberHandles,\r
-  OUT EFI_HANDLE                          **Buffer\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-\r
-  //\r
-  // Locate all handles of Fvb protocol\r
-  //\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiFirmwareVolumeBlockProtocolGuid,\r
-                  NULL,\r
-                  NumberHandles,\r
-                  Buffer\r
-                  );\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.\r
-\r
-  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
-  It convers pointer to new virtual address.\r
-\r
-  @param  Event        Event whose notification function is being invoked.\r
-  @param  Context      Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-VariableClassAddressChangeEvent (\r
-  IN EFI_EVENT                            Event,\r
-  IN VOID                                 *Context\r
-  )\r
-{\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
-  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);\r
-  EfiConvertPointer (0x0, (VOID **) &mHashCtx);\r
-  EfiConvertPointer (0x0, (VOID **) &mStorageArea);\r
-  EfiConvertPointer (0x0, (VOID **) &mSerializationRuntimeBuffer);\r
-  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);\r
-}\r
-\r
-\r
-/**\r
-  Notification function of EVT_GROUP_READY_TO_BOOT event group.\r
-\r
-  This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.\r
-  When the Boot Manager is about to load and execute a boot option, it reclaims variable\r
-  storage if free size is below the threshold.\r
-\r
-  @param  Event        Event whose notification function is being invoked.\r
-  @param  Context      Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-OnReadyToBoot (\r
-  EFI_EVENT                               Event,\r
-  VOID                                    *Context\r
-  )\r
-{\r
-  //\r
-  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.\r
-  //\r
-  mEndOfDxe = TRUE;\r
-  ReclaimForOS ();\r
-  if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
-    gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);\r
-  }\r
-}\r
-\r
-/**\r
-  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
-\r
-  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
-\r
-  @param  Event        Event whose notification function is being invoked.\r
-  @param  Context      Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-OnEndOfDxe (\r
-  EFI_EVENT                               Event,\r
-  VOID                                    *Context\r
-  )\r
-{\r
-  mEndOfDxe = TRUE;\r
-}\r
-\r
-/**\r
-  Fault Tolerant Write protocol notification event handler.\r
-\r
-  Non-Volatile variable write may needs FTW protocol to reclaim when\r
-  writting variable.\r
-\r
-  @param[in] Event    Event whose notification function is being invoked.\r
-  @param[in] Context  Pointer to the notification function's context.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-FtwNotificationEvent (\r
-  IN  EFI_EVENT                           Event,\r
-  IN  VOID                                *Context\r
-  )\r
-{\r
-  EFI_STATUS                              Status;\r
-  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *FvbProtocol;\r
-  EFI_FAULT_TOLERANT_WRITE_PROTOCOL       *FtwProtocol;\r
-  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR         GcdDescriptor;\r
-  EFI_PHYSICAL_ADDRESS                    BaseAddress;\r
-  UINT64                                  Length;\r
-  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;\r
-  UINT64                                  VariableStoreLength;\r
-\r
-  //\r
-  // Ensure FTW protocol is installed.\r
-  //\r
-  Status = GetFtwProtocol ((VOID**) &FtwProtocol);\r
-  if (EFI_ERROR (Status)) {\r
-    return ;\r
-  }\r
-\r
-  //\r
-  // Find the proper FVB protocol for variable.\r
-  //\r
-  NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
-  if (NvStorageVariableBase == 0) {\r
-    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);\r
-  }\r
-  Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);\r
-  if (EFI_ERROR (Status)) {\r
-    return ;\r
-  }\r
-  mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
-\r
-  //\r
-  // Mark the variable storage region of the FLASH as RUNTIME.\r
-  //\r
-  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;\r
-  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;\r
-  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);\r
-  Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);\r
-  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);\r
-\r
-  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));\r
-  } else {\r
-    Status = gDS->SetMemorySpaceAttributes (\r
-                    BaseAddress,\r
-                    Length,\r
-                    GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));\r
-    }\r
-  }\r
-\r
-  Status = VariableWriteServiceInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Install the Variable Write Architectural protocol.\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mHandle,\r
-                  &gEfiVariableWriteArchProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.\r
-  //\r
-  gBS->CloseEvent (Event);\r
-\r
-}\r
-\r
-\r
-/**\r
-  Variable Driver main entry point. The Variable driver places the 4 EFI\r
-  runtime services in the EFI System Table and installs arch protocols\r
-  for variable read and write services being available. It also registers\r
-  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
-\r
-  @param[in] ImageHandle    The firmware allocated handle for the EFI image.\r
-  @param[in] SystemTable    A pointer to the EFI System Table.\r
-\r
-  @retval EFI_SUCCESS       Variable service successfully initialized.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-VariableServiceInitialize (\r
-  IN EFI_HANDLE                         ImageHandle,\r
-  IN EFI_SYSTEM_TABLE                   *SystemTable\r
-  )\r
-{\r
-  EFI_STATUS                            Status;\r
-  EFI_EVENT                             ReadyToBootEvent;\r
-  EFI_EVENT                             EndOfDxeEvent;\r
-\r
-  Status = VariableCommonInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &mHandle,\r
-                  &gEdkiiVariableLockProtocolGuid,\r
-                  &mVariableLock,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  SystemTable->RuntimeServices->GetVariable         = VariableServiceGetVariable;\r
-  SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;\r
-  SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;\r
-  SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;\r
-\r
-  //\r
-  // Now install the Variable Runtime Architectural protocol on a new handle.\r
-  //\r
-  Status = gBS->InstallProtocolInterface (\r
-                  &mHandle,\r
-                  &gEfiVariableArchProtocolGuid,\r
-                  EFI_NATIVE_INTERFACE,\r
-                  NULL\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Register FtwNotificationEvent () notify function.\r
-  //\r
-  EfiCreateProtocolNotifyEvent (\r
-    &gEfiFaultTolerantWriteProtocolGuid,\r
-    TPL_CALLBACK,\r
-    FtwNotificationEvent,\r
-    (VOID *)SystemTable,\r
-    &mFtwRegistration\r
-    );\r
-\r
-  Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  VariableClassAddressChangeEvent,\r
-                  NULL,\r
-                  &gEfiEventVirtualAddressChangeGuid,\r
-                  &mVirtualAddressChangeEvent\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Register the event handling function to reclaim variable for OS usage.\r
-  //\r
-  Status = EfiCreateEventReadyToBootEx (\r
-             TPL_NOTIFY,\r
-             OnReadyToBoot,\r
-             NULL,\r
-             &ReadyToBootEvent\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  //\r
-  // Register the event handling function to set the End Of DXE flag.\r
-  //\r
-  Status = gBS->CreateEventEx (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  OnEndOfDxe,\r
-                  NULL,\r
-                  &gEfiEndOfDxeEventGroupGuid,\r
-                  &EndOfDxeEvent\r
-                  );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
+/** @file
+  Implement all four UEFI Runtime Variable services for the nonvolatile
+  and volatile storage space and install variable architecture protocol.
+
+Copyright (C) 2013, Red Hat, Inc.
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Variable.h"
+#include "AuthService.h"
+
+extern VARIABLE_STORE_HEADER   *mNvVariableCache;
+extern VARIABLE_INFO_ENTRY     *gVariableInfo;
+EFI_HANDLE                     mHandle                    = NULL;
+EFI_EVENT                      mVirtualAddressChangeEvent = NULL;
+EFI_EVENT                      mFtwRegistration           = NULL;
+extern LIST_ENTRY              mLockedVariableList;
+extern BOOLEAN                 mEndOfDxe;
+EDKII_VARIABLE_LOCK_PROTOCOL   mVariableLock              = { VariableLockRequestToLock };
+
+/**
+  Return TRUE if ExitBootServices () has been called.
+
+  @retval TRUE If ExitBootServices () has been called.
+**/
+BOOLEAN
+AtRuntime (
+  VOID
+  )
+{
+  return EfiAtRuntime ();
+}
+
+
+/**
+  Initializes a basic mutual exclusion lock.
+
+  This function initializes a basic mutual exclusion lock to the released state
+  and returns the lock.  Each lock provides mutual exclusion access at its task
+  priority level.  Since there is no preemption or multiprocessor support in EFI,
+  acquiring the lock only consists of raising to the locks TPL.
+  If Lock is NULL, then ASSERT().
+  If Priority is not a valid TPL value, then ASSERT().
+
+  @param  Lock       A pointer to the lock data structure to initialize.
+  @param  Priority   EFI TPL is associated with the lock.
+
+  @return The lock.
+
+**/
+EFI_LOCK *
+InitializeLock (
+  IN OUT EFI_LOCK                         *Lock,
+  IN     EFI_TPL                          Priority
+  )
+{
+  return EfiInitializeLock (Lock, Priority);
+}
+
+
+/**
+  Acquires lock only at boot time. Simply returns at runtime.
+
+  This is a temperary function that will be removed when
+  EfiAcquireLock() in UefiLib can handle the call in UEFI
+  Runtimer driver in RT phase.
+  It calls EfiAcquireLock() at boot time, and simply returns
+  at runtime.
+
+  @param  Lock         A pointer to the lock to acquire.
+
+**/
+VOID
+AcquireLockOnlyAtBootTime (
+  IN EFI_LOCK                             *Lock
+  )
+{
+  if (!AtRuntime ()) {
+    EfiAcquireLock (Lock);
+  }
+}
+
+
+/**
+  Releases lock only at boot time. Simply returns at runtime.
+
+  This is a temperary function which will be removed when
+  EfiReleaseLock() in UefiLib can handle the call in UEFI
+  Runtimer driver in RT phase.
+  It calls EfiReleaseLock() at boot time and simply returns
+  at runtime.
+
+  @param  Lock         A pointer to the lock to release.
+
+**/
+VOID
+ReleaseLockOnlyAtBootTime (
+  IN EFI_LOCK                             *Lock
+  )
+{
+  if (!AtRuntime ()) {
+    EfiReleaseLock (Lock);
+  }
+}
+
+/**
+  Retrive the Fault Tolerent Write protocol interface.
+
+  @param[out] FtwProtocol       The interface of Ftw protocol
+
+  @retval EFI_SUCCESS           The FTW protocol instance was found and returned in FtwProtocol.
+  @retval EFI_NOT_FOUND         The FTW protocol instance was not found.
+  @retval EFI_INVALID_PARAMETER SarProtocol is NULL.
+
+**/
+EFI_STATUS
+GetFtwProtocol (
+  OUT VOID                                **FtwProtocol
+  )
+{
+  EFI_STATUS                              Status;
+
+  //
+  // Locate Fault Tolerent Write protocol
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiFaultTolerantWriteProtocolGuid,
+                  NULL,
+                  FtwProtocol
+                  );
+  return Status;
+}
+
+/**
+  Retrive the FVB protocol interface by HANDLE.
+
+  @param[in]  FvBlockHandle     The handle of FVB protocol that provides services for
+                                reading, writing, and erasing the target block.
+  @param[out] FvBlock           The interface of FVB protocol
+
+  @retval EFI_SUCCESS           The interface information for the specified protocol was returned.
+  @retval EFI_UNSUPPORTED       The device does not support the FVB protocol.
+  @retval EFI_INVALID_PARAMETER FvBlockHandle is not a valid EFI_HANDLE or FvBlock is NULL.
+
+**/
+EFI_STATUS
+GetFvbByHandle (
+  IN  EFI_HANDLE                          FvBlockHandle,
+  OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvBlock
+  )
+{
+  //
+  // To get the FVB protocol interface on the handle
+  //
+  return gBS->HandleProtocol (
+                FvBlockHandle,
+                &gEfiFirmwareVolumeBlockProtocolGuid,
+                (VOID **) FvBlock
+                );
+}
+
+
+/**
+  Function returns an array of handles that support the FVB protocol
+  in a buffer allocated from pool.
+
+  @param[out]  NumberHandles    The number of handles returned in Buffer.
+  @param[out]  Buffer           A pointer to the buffer to return the requested
+                                array of  handles that support FVB protocol.
+
+  @retval EFI_SUCCESS           The array of handles was returned in Buffer, and the number of
+                                handles in Buffer was returned in NumberHandles.
+  @retval EFI_NOT_FOUND         No FVB handle was found.
+  @retval EFI_OUT_OF_RESOURCES  There is not enough pool memory to store the matching results.
+  @retval EFI_INVALID_PARAMETER NumberHandles is NULL or Buffer is NULL.
+
+**/
+EFI_STATUS
+GetFvbCountAndBuffer (
+  OUT UINTN                               *NumberHandles,
+  OUT EFI_HANDLE                          **Buffer
+  )
+{
+  EFI_STATUS                              Status;
+
+  //
+  // Locate all handles of Fvb protocol
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiFirmwareVolumeBlockProtocolGuid,
+                  NULL,
+                  NumberHandles,
+                  Buffer
+                  );
+  return Status;
+}
+
+
+/**
+  Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+  This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+  It convers pointer to new virtual address.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+VariableClassAddressChangeEvent (
+  IN EFI_EVENT                            Event,
+  IN VOID                                 *Context
+  )
+{
+  LIST_ENTRY     *Link;
+  VARIABLE_ENTRY *Entry;
+  EFI_STATUS     Status;
+
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetBlockSize);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetPhysicalAddress);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->GetAttributes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->SetAttributes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Read);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->Write);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance->EraseBlocks);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->FvbInstance);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);
+  EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
+  EfiConvertPointer (0x0, (VOID **) &mHashCtx);
+  EfiConvertPointer (0x0, (VOID **) &mStorageArea);
+  EfiConvertPointer (0x0, (VOID **) &mSerializationRuntimeBuffer);
+  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);
+
+  //
+  // in the list of locked variables, convert the name pointers first
+  //
+  for ( Link = GetFirstNode (&mLockedVariableList)
+      ; !IsNull (&mLockedVariableList, Link)
+      ; Link = GetNextNode (&mLockedVariableList, Link)
+      ) {
+    Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
+    Status = EfiConvertPointer (0x0, (VOID **) &Entry->Name);
+    ASSERT_EFI_ERROR (Status);
+  }
+  //
+  // second, convert the list itself using UefiRuntimeLib
+  //
+  Status = EfiConvertList (0x0, &mLockedVariableList);
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+  Notification function of EVT_GROUP_READY_TO_BOOT event group.
+
+  This is a notification function registered on EVT_GROUP_READY_TO_BOOT event group.
+  When the Boot Manager is about to load and execute a boot option, it reclaims variable
+  storage if free size is below the threshold.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnReadyToBoot (
+  EFI_EVENT                               Event,
+  VOID                                    *Context
+  )
+{
+  //
+  // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
+  //
+  mEndOfDxe = TRUE;
+  ReclaimForOS ();
+  if (FeaturePcdGet (PcdVariableCollectStatistics)) {
+    gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);
+  }
+}
+
+/**
+  Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
+
+  @param  Event        Event whose notification function is being invoked.
+  @param  Context      Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+OnEndOfDxe (
+  EFI_EVENT                               Event,
+  VOID                                    *Context
+  )
+{
+  mEndOfDxe = TRUE;
+}
+
+/**
+  Fault Tolerant Write protocol notification event handler.
+
+  Non-Volatile variable write may needs FTW protocol to reclaim when
+  writting variable.
+
+  @param[in] Event    Event whose notification function is being invoked.
+  @param[in] Context  Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+FtwNotificationEvent (
+  IN  EFI_EVENT                           Event,
+  IN  VOID                                *Context
+  )
+{
+  EFI_STATUS                              Status;
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL      *FvbProtocol;
+  EFI_FAULT_TOLERANT_WRITE_PROTOCOL       *FtwProtocol;
+  EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR         GcdDescriptor;
+  EFI_PHYSICAL_ADDRESS                    BaseAddress;
+  UINT64                                  Length;
+  EFI_PHYSICAL_ADDRESS                    VariableStoreBase;
+  UINT64                                  VariableStoreLength;
+
+  //
+  // Ensure FTW protocol is installed.
+  //
+  Status = GetFtwProtocol ((VOID**) &FtwProtocol);
+  if (EFI_ERROR (Status)) {
+    return ;
+  }
+
+  //
+  // Find the proper FVB protocol for variable.
+  //
+  NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);
+  if (NvStorageVariableBase == 0) {
+    NvStorageVariableBase = (EFI_PHYSICAL_ADDRESS) PcdGet32 (PcdFlashNvStorageVariableBase);
+  }
+  Status = GetFvbInfoByAddress (NvStorageVariableBase, NULL, &FvbProtocol);
+  if (EFI_ERROR (Status)) {
+    return ;
+  }
+  mVariableModuleGlobal->FvbInstance = FvbProtocol;
+
+  //
+  // Mark the variable storage region of the FLASH as RUNTIME.
+  //
+  VariableStoreBase   = mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase;
+  VariableStoreLength = ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase)->Size;
+  BaseAddress = VariableStoreBase & (~EFI_PAGE_MASK);
+  Length      = VariableStoreLength + (VariableStoreBase - BaseAddress);
+  Length      = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK);
+
+  Status      = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
+  } else {
+    Status = gDS->SetMemorySpaceAttributes (
+                    BaseAddress,
+                    Length,
+                    GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
+                    );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));
+    }
+  }
+
+  Status = VariableWriteServiceInitialize ();
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Install the Variable Write Architectural protocol.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mHandle,
+                  &gEfiVariableWriteArchProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.
+  //
+  gBS->CloseEvent (Event);
+
+}
+
+
+/**
+  Variable Driver main entry point. The Variable driver places the 4 EFI
+  runtime services in the EFI System Table and installs arch protocols
+  for variable read and write services being available. It also registers
+  a notification function for an EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       Variable service successfully initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+VariableServiceInitialize (
+  IN EFI_HANDLE                         ImageHandle,
+  IN EFI_SYSTEM_TABLE                   *SystemTable
+  )
+{
+  EFI_STATUS                            Status;
+  EFI_EVENT                             ReadyToBootEvent;
+  EFI_EVENT                             EndOfDxeEvent;
+
+  Status = VariableCommonInitialize ();
+  ASSERT_EFI_ERROR (Status);
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mHandle,
+                  &gEdkiiVariableLockProtocolGuid,
+                  &mVariableLock,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  SystemTable->RuntimeServices->GetVariable         = VariableServiceGetVariable;
+  SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;
+  SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;
+  SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;
+
+  //
+  // Now install the Variable Runtime Architectural protocol on a new handle.
+  //
+  Status = gBS->InstallProtocolInterface (
+                  &mHandle,
+                  &gEfiVariableArchProtocolGuid,
+                  EFI_NATIVE_INTERFACE,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register FtwNotificationEvent () notify function.
+  //
+  EfiCreateProtocolNotifyEvent (
+    &gEfiFaultTolerantWriteProtocolGuid,
+    TPL_CALLBACK,
+    FtwNotificationEvent,
+    (VOID *)SystemTable,
+    &mFtwRegistration
+    );
+
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  VariableClassAddressChangeEvent,
+                  NULL,
+                  &gEfiEventVirtualAddressChangeGuid,
+                  &mVirtualAddressChangeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register the event handling function to reclaim variable for OS usage.
+  //
+  Status = EfiCreateEventReadyToBootEx (
+             TPL_NOTIFY,
+             OnReadyToBoot,
+             NULL,
+             &ReadyToBootEvent
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Register the event handling function to set the End Of DXE flag.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  OnEndOfDxe,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &EndOfDxeEvent
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+}
+