public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Kubacki, Michael A" <michael.a.kubacki@intel.com>
To: devel@edk2.groups.io
Cc: Dandan Bi <dandan.bi@intel.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Eric Dong <eric.dong@intel.com>, Laszlo Ersek <lersek@redhat.com>,
	Liming Gao <liming.gao@intel.com>,
	Michael D Kinney <michael.d.kinney@intel.com>,
	Ray Ni <ray.ni@intel.com>, Jian J Wang <jian.j.wang@intel.com>,
	Hao A Wu <hao.a.wu@intel.com>, Jiewen Yao <jiewen.yao@intel.com>
Subject: [PATCH V1 1/5] MdeModulePkg/Variable: Consolidate common parsing functions
Date: Wed, 25 Sep 2019 21:50:42 -0700	[thread overview]
Message-ID: <20190926045046.34592-2-michael.a.kubacki@intel.com> (raw)
In-Reply-To: <20190926045046.34592-1-michael.a.kubacki@intel.com>

This change moves the following functions into a dedicated file
so they may be used in other variable files as needed. Furthermore,
it reduces the overall size of the common Variable.c file.

 * DataSizeOfVariable ()
 * FindVariableEx ()
 * GetEndPointer ()
 * GetNextVariableEx ()
 * GetNextVariablePtr ()
 * GetStartPointer ()
 * GetVariableDataOffset ()
 * GetVariableDataPtr ()
 * GetVariableHeaderSize ()
 * GetVariableNamePtr ()
 * GetVariableStoreStatus ()
 * GetVendorGuidPtr ()
 * IsAuthenticatedVariable ()
 * IsValidVariableHeader ()
 * NameSizeOfVariable ()
 * SetDataSizeOfVariable ()
 * SetNameSizeOfVariable ()
 * UpdateVariableInfo ()
 * VariableCompareTimeStampInternal ()

Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Michael Kubacki <michael.a.kubacki@intel.com>
---
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf    |   4 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf           |   4 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf |   8 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf  |   9 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h                | 119 ---
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h     |  25 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h         | 342 ++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c                | 784 +------------------
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c           |  11 +-
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c     |  28 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c         | 816 ++++++++++++++++++++
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c             |   2 +
 MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c   |   3 +-
 13 files changed, 1273 insertions(+), 882 deletions(-)

diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 641376c9c5..08a5490787 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -36,6 +36,10 @@
   Variable.c
   VariableDxe.c
   Variable.h
+  VariableNonVolatile.c
+  VariableNonVolatile.h
+  VariableParsing.c
+  VariableParsing.h
   PrivilegePolymorphic.h
   Measurement.c
   TcgMorLockDxe.c
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index 0a160d269d..6dc2721b81 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -45,6 +45,10 @@
   Variable.c
   VariableTraditionalMm.c
   VariableSmm.c
+  VariableNonVolatile.c
+  VariableNonVolatile.h
+  VariableParsing.c
+  VariableParsing.h
   VarCheck.c
   Variable.h
   PrivilegePolymorphic.h
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index 14894e6f13..1873b4fe43 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -13,7 +13,7 @@
 #  may not be modified without authorization. If platform fails to protect these resources,
 #  the authentication service provided in this driver will be broken, and the behavior is undefined.
 #
-# Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -39,6 +39,9 @@
   VariableSmmRuntimeDxe.c
   PrivilegePolymorphic.h
   Measurement.c
+  Variable.h
+  VariableParsing.c
+  VariableParsing.h
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -65,6 +68,9 @@
   gEdkiiVariableLockProtocolGuid                ## PRODUCES
   gEdkiiVarCheckProtocolGuid                    ## PRODUCES
 
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics            ## CONSUMES
+
 [Guids]
   gEfiEventVirtualAddressChangeGuid             ## CONSUMES ## Event
   gEfiEventExitBootServicesGuid                 ## CONSUMES ## Event
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index 21bc81163b..ca9d23ce9f 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -45,6 +45,10 @@
   Variable.c
   VariableSmm.c
   VariableStandaloneMm.c
+  VariableNonVolatile.c
+  VariableNonVolatile.h
+  VariableParsing.c
+  VariableParsing.h
   VarCheck.c
   Variable.h
   PrivilegePolymorphic.h
@@ -99,6 +103,11 @@
   ## SOMETIMES_PRODUCES   ## Variable:L"Lang"
   gEfiGlobalVariableGuid
 
+  ## SOMETIMES_CONSUMES   ## Variable:L"db"
+  ## SOMETIMES_CONSUMES   ## Variable:L"dbx"
+  ## SOMETIMES_CONSUMES   ## Variable:L"dbt"
+  gEfiImageSecurityDatabaseGuid
+
   gEfiMemoryOverwriteControlDataGuid            ## SOMETIMES_CONSUMES   ## Variable:L"MemoryOverwriteRequestControl"
   gEfiMemoryOverwriteRequestControlLockGuid     ## SOMETIMES_PRODUCES   ## Variable:L"MemoryOverwriteRequestControlLock"
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
index 9eac43759f..fb574b2e32 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
@@ -179,89 +179,6 @@ FindVariable (
   IN  BOOLEAN                 IgnoreRtCheck
   );
 
-/**
-
-  Gets the pointer to the end of the variable storage area.
-
-  This function gets pointer to the end of the variable storage
-  area, according to the input variable store header.
-
-  @param VarStoreHeader  Pointer to the Variable Store Header.
-
-  @return Pointer to the end of the variable storage area.
-
-**/
-VARIABLE_HEADER *
-GetEndPointer (
-  IN VARIABLE_STORE_HEADER       *VarStoreHeader
-  );
-
-/**
-  This code gets the size of variable header.
-
-  @return Size of variable header in bytes in type UINTN.
-
-**/
-UINTN
-GetVariableHeaderSize (
-  VOID
-  );
-
-/**
-
-  This code gets the pointer to the variable name.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Pointer to Variable Name which is Unicode encoding.
-
-**/
-CHAR16 *
-GetVariableNamePtr (
-  IN  VARIABLE_HEADER   *Variable
-  );
-
-/**
-  This code gets the pointer to the variable guid.
-
-  @param Variable   Pointer to the Variable Header.
-
-  @return A EFI_GUID* pointer to Vendor Guid.
-
-**/
-EFI_GUID *
-GetVendorGuidPtr (
-  IN VARIABLE_HEADER    *Variable
-  );
-
-/**
-
-  This code gets the pointer to the variable data.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Pointer to Variable Data.
-
-**/
-UINT8 *
-GetVariableDataPtr (
-  IN  VARIABLE_HEADER   *Variable
-  );
-
-/**
-
-  This code gets the size of variable data.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Size of variable in bytes.
-
-**/
-UINTN
-DataSizeOfVariable (
-  IN  VARIABLE_HEADER   *Variable
-  );
-
 /**
   This function is to check if the remaining variable space is enough to set
   all Variables from argument list successfully. The purpose of the check
@@ -450,17 +367,6 @@ ReclaimForOS(
   VOID
   );
 
-/**
-  Get non-volatile maximum variable size.
-
-  @return Non-volatile maximum variable size.
-
-**/
-UINTN
-GetNonVolatileMaxVariableSize (
-  VOID
-  );
-
 /**
   Get maximum variable size, covering both non-volatile and volatile variables.
 
@@ -546,31 +452,6 @@ VariableServiceGetVariable (
   OUT     VOID              *Data OPTIONAL
   );
 
-/**
-  This code Finds the Next available variable.
-
-  Caution: This function may receive untrusted input.
-  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
-
-  @param[in] VariableName   Pointer to variable name.
-  @param[in] VendorGuid     Variable Vendor Guid.
-  @param[out] VariablePtr   Pointer to variable header address.
-
-  @retval EFI_SUCCESS           The function completed successfully.
-  @retval EFI_NOT_FOUND         The next variable was not found.
-  @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL.
-  @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and
-                                GUID of an existing variable.
-
-**/
-EFI_STATUS
-EFIAPI
-VariableServiceGetNextVariableInternal (
-  IN  CHAR16                *VariableName,
-  IN  EFI_GUID              *VendorGuid,
-  OUT VARIABLE_HEADER       **VariablePtr
-  );
-
 /**
 
   This code Finds the Next available variable.
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h
new file mode 100644
index 0000000000..82572262ef
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.h
@@ -0,0 +1,25 @@
+/** @file
+  Common variable non-volatile store routines.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VARIABLE_NON_VOLATILE_H_
+#define _VARIABLE_NON_VOLATILE_H_
+
+#include "Variable.h"
+
+/**
+  Get non-volatile maximum variable size.
+
+  @return Non-volatile maximum variable size.
+
+**/
+UINTN
+GetNonVolatileMaxVariableSize (
+  VOID
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h
new file mode 100644
index 0000000000..bd617fca10
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.h
@@ -0,0 +1,342 @@
+/** @file
+  Common variable helper routines are shared by the DXE_RUNTIME variable
+  module and the DXE_SMM variable module.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VARIABLE_PARSING_H_
+#define _VARIABLE_PARSING_H_
+
+#include <Guid/ImageAuthentication.h>
+#include "Variable.h"
+
+/**
+
+  This code checks if variable header is valid or not.
+
+  @param Variable           Pointer to the Variable Header.
+  @param VariableStoreEnd   Pointer to the Variable Store End.
+
+  @retval TRUE              Variable header is valid.
+  @retval FALSE             Variable header is not valid.
+
+**/
+BOOLEAN
+IsValidVariableHeader (
+  IN  VARIABLE_HEADER       *Variable,
+  IN  VARIABLE_HEADER       *VariableStoreEnd
+  );
+
+/**
+
+  This code gets the current status of Variable Store.
+
+  @param VarStoreHeader  Pointer to the Variable Store Header.
+
+  @retval EfiRaw         Variable store status is raw.
+  @retval EfiValid       Variable store status is valid.
+  @retval EfiInvalid     Variable store status is invalid.
+
+**/
+VARIABLE_STORE_STATUS
+GetVariableStoreStatus (
+  IN VARIABLE_STORE_HEADER *VarStoreHeader
+  );
+
+/**
+  This code gets the size of variable header.
+
+  @return Size of variable header in bytes in type UINTN.
+
+**/
+UINTN
+GetVariableHeaderSize (
+  VOID
+  );
+
+/**
+
+  This code gets the size of name of variable.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return UINTN          Size of variable in bytes.
+
+**/
+UINTN
+NameSizeOfVariable (
+  IN  VARIABLE_HEADER   *Variable
+  );
+
+/**
+  This code sets the size of name of variable.
+
+  @param[in] Variable   Pointer to the Variable Header.
+  @param[in] NameSize   Name size to set.
+
+**/
+VOID
+SetNameSizeOfVariable (
+  IN VARIABLE_HEADER    *Variable,
+  IN UINTN              NameSize
+  );
+
+/**
+
+  This code gets the size of variable data.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Size of variable in bytes.
+
+**/
+UINTN
+DataSizeOfVariable (
+  IN  VARIABLE_HEADER   *Variable
+  );
+
+/**
+  This code sets the size of variable data.
+
+  @param[in] Variable   Pointer to the Variable Header.
+  @param[in] DataSize   Data size to set.
+
+**/
+VOID
+SetDataSizeOfVariable (
+  IN VARIABLE_HEADER    *Variable,
+  IN UINTN              DataSize
+  );
+
+/**
+
+  This code gets the pointer to the variable name.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Pointer to Variable Name which is Unicode encoding.
+
+**/
+CHAR16 *
+GetVariableNamePtr (
+  IN  VARIABLE_HEADER   *Variable
+  );
+
+/**
+  This code gets the pointer to the variable guid.
+
+  @param Variable   Pointer to the Variable Header.
+
+  @return A EFI_GUID* pointer to Vendor Guid.
+
+**/
+EFI_GUID *
+GetVendorGuidPtr (
+  IN VARIABLE_HEADER    *Variable
+  );
+
+/**
+
+  This code gets the pointer to the variable data.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Pointer to Variable Data.
+
+**/
+UINT8 *
+GetVariableDataPtr (
+  IN  VARIABLE_HEADER   *Variable
+  );
+
+/**
+  This code gets the variable data offset related to variable header.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Variable Data offset.
+
+**/
+UINTN
+GetVariableDataOffset (
+  IN  VARIABLE_HEADER   *Variable
+  );
+
+/**
+
+  This code gets the pointer to the next variable header.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Pointer to next variable header.
+
+**/
+VARIABLE_HEADER *
+GetNextVariablePtr (
+  IN  VARIABLE_HEADER   *Variable
+  );
+
+/**
+
+  Gets the pointer to the first variable header in given variable store area.
+
+  @param VarStoreHeader  Pointer to the Variable Store Header.
+
+  @return Pointer to the first variable header.
+
+**/
+VARIABLE_HEADER *
+GetStartPointer (
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader
+  );
+
+/**
+
+  Gets the pointer to the end of the variable storage area.
+
+  This function gets pointer to the end of the variable storage
+  area, according to the input variable store header.
+
+  @param VarStoreHeader  Pointer to the Variable Store Header.
+
+  @return Pointer to the end of the variable storage area.
+
+**/
+VARIABLE_HEADER *
+GetEndPointer (
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader
+  );
+
+/**
+  Returns if this is a variable that always requires authenticated writes.
+  There may be other scenarios that result in a variable not identified by the
+  function to also require authentication.
+
+  @param[in]  VariableName       Name of variable.
+  @param[in]  VendorGuid         Guid of variable.
+
+  @retval  TRUE            The variable always requires authenticated writes
+  @retval  FALSE           The variable may or may not require authenticated writes
+**/
+BOOLEAN
+IsAuthenticatedVariable (
+  IN CHAR16                   *VariableName,
+  IN EFI_GUID                 *VendorGuid
+  );
+
+/**
+  Compare two EFI_TIME data.
+
+
+  @param FirstTime           A pointer to the first EFI_TIME data.
+  @param SecondTime          A pointer to the second EFI_TIME data.
+
+  @retval  TRUE              The FirstTime is not later than the SecondTime.
+  @retval  FALSE             The FirstTime is later than the SecondTime.
+
+**/
+BOOLEAN
+VariableCompareTimeStampInternal (
+  IN EFI_TIME               *FirstTime,
+  IN EFI_TIME               *SecondTime
+  );
+
+/**
+  Find the variable in the specified variable store.
+
+  @param[in]       VariableName        Name of the variable to be found
+  @param[in]       VendorGuid          Vendor GUID to be found.
+  @param[in]       IgnoreRtCheck       Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
+                                       check at runtime when searching variable.
+  @param[in, out]  PtrTrack            Variable Track Pointer structure that contains Variable Information.
+
+  @retval          EFI_SUCCESS         Variable found successfully
+  @retval          EFI_NOT_FOUND       Variable not found
+**/
+EFI_STATUS
+FindVariableEx (
+  IN     CHAR16                  *VariableName,
+  IN     EFI_GUID                *VendorGuid,
+  IN     BOOLEAN                 IgnoreRtCheck,
+  IN OUT VARIABLE_POINTER_TRACK  *PtrTrack
+  );
+
+/**
+  This code finds the next available variable.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
+
+  @param[in]  VariableName      Pointer to variable name.
+  @param[in]  VendorGuid        Variable Vendor Guid.
+  @param[in]  VariableStoreList A list of variable stores that should be used to get the next variable.
+                                The maximum number of entries is the max value of VARIABLE_STORE_TYPE.
+  @param[out] VariablePtr       Pointer to variable header address.
+
+  @retval EFI_SUCCESS           The function completed successfully.
+  @retval EFI_NOT_FOUND         The next variable was not found.
+  @retval EFI_INVALID_PARAMETER If VariableName is nt an empty string, while VendorGuid is NULL.
+  @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and
+                                GUID of an existing variable.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextVariableEx (
+  IN  CHAR16                *VariableName,
+  IN  EFI_GUID              *VendorGuid,
+  IN  VARIABLE_STORE_HEADER **VariableStoreList,
+  OUT VARIABLE_HEADER       **VariablePtr
+  );
+
+/**
+  Routine used to track statistical information about variable usage.
+  The data is stored in the EFI system table so it can be accessed later.
+  VariableInfo.efi can dump out the table. Only Boot Services variable
+  accesses are tracked by this code. The PcdVariableCollectStatistics
+  build flag controls if this feature is enabled.
+
+  A read that hits in the cache will have Read and Cache true for
+  the transaction. Data is allocated by this routine, but never
+  freed.
+
+  @param[in]      VariableName   Name of the Variable to track.
+  @param[in]      VendorGuid     Guid of the Variable to track.
+  @param[in]      Volatile       TRUE if volatile FALSE if non-volatile.
+  @param[in]      Read           TRUE if GetVariable() was called.
+  @param[in]      Write          TRUE if SetVariable() was called.
+  @param[in]      Delete         TRUE if deleted via SetVariable().
+  @param[in]      Cache          TRUE for a cache hit.
+  @param[in,out]  VariableInfo   Pointer to a pointer of VARIABLE_INFO_ENTRY structures.
+
+**/
+VOID
+UpdateVariableInfo (
+  IN  CHAR16                  *VariableName,
+  IN  EFI_GUID                *VendorGuid,
+  IN  BOOLEAN                 Volatile,
+  IN  BOOLEAN                 Read,
+  IN  BOOLEAN                 Write,
+  IN  BOOLEAN                 Delete,
+  IN  BOOLEAN                 Cache,
+  IN OUT VARIABLE_INFO_ENTRY  **VariableInfo
+  );
+
+/**
+  Initializes context needed for variable helpers.
+
+  @param[in]       AuthFormat          If true then indicates authenticated variables are supported
+
+  @retval          EFI_SUCCESS         Initialized successfully
+  @retval          Others              An error occurred during initialization
+**/
+EFI_STATUS
+EFIAPI
+InitVariableHelpers (
+  IN  BOOLEAN   AuthFormat
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index f32c9c2808..d14fecc830 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -23,6 +23,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "Variable.h"
+#include "VariableNonVolatile.h"
+#include "VariableParsing.h"
 
 VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
 
@@ -92,131 +94,6 @@ AUTH_VAR_LIB_CONTEXT_IN mAuthContextIn = {
 
 AUTH_VAR_LIB_CONTEXT_OUT mAuthContextOut;
 
-/**
-  Routine used to track statistical information about variable usage.
-  The data is stored in the EFI system table so it can be accessed later.
-  VariableInfo.efi can dump out the table. Only Boot Services variable
-  accesses are tracked by this code. The PcdVariableCollectStatistics
-  build flag controls if this feature is enabled.
-
-  A read that hits in the cache will have Read and Cache true for
-  the transaction. Data is allocated by this routine, but never
-  freed.
-
-  @param[in] VariableName   Name of the Variable to track.
-  @param[in] VendorGuid     Guid of the Variable to track.
-  @param[in] Volatile       TRUE if volatile FALSE if non-volatile.
-  @param[in] Read           TRUE if GetVariable() was called.
-  @param[in] Write          TRUE if SetVariable() was called.
-  @param[in] Delete         TRUE if deleted via SetVariable().
-  @param[in] Cache          TRUE for a cache hit.
-
-**/
-VOID
-UpdateVariableInfo (
-  IN  CHAR16                  *VariableName,
-  IN  EFI_GUID                *VendorGuid,
-  IN  BOOLEAN                 Volatile,
-  IN  BOOLEAN                 Read,
-  IN  BOOLEAN                 Write,
-  IN  BOOLEAN                 Delete,
-  IN  BOOLEAN                 Cache
-  )
-{
-  VARIABLE_INFO_ENTRY   *Entry;
-
-  if (FeaturePcdGet (PcdVariableCollectStatistics)) {
-
-    if (AtRuntime ()) {
-      // Don't collect statistics at runtime.
-      return;
-    }
-
-    if (gVariableInfo == NULL) {
-      //
-      // On the first call allocate a entry and place a pointer to it in
-      // the EFI System Table.
-      //
-      gVariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
-      ASSERT (gVariableInfo != NULL);
-
-      CopyGuid (&gVariableInfo->VendorGuid, VendorGuid);
-      gVariableInfo->Name = AllocateZeroPool (StrSize (VariableName));
-      ASSERT (gVariableInfo->Name != NULL);
-      StrCpyS (gVariableInfo->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName);
-      gVariableInfo->Volatile = Volatile;
-    }
-
-
-    for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {
-      if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
-        if (StrCmp (VariableName, Entry->Name) == 0) {
-          if (Read) {
-            Entry->ReadCount++;
-          }
-          if (Write) {
-            Entry->WriteCount++;
-          }
-          if (Delete) {
-            Entry->DeleteCount++;
-          }
-          if (Cache) {
-            Entry->CacheCount++;
-          }
-
-          return;
-        }
-      }
-
-      if (Entry->Next == NULL) {
-        //
-        // If the entry is not in the table add it.
-        // Next iteration of the loop will fill in the data.
-        //
-        Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
-        ASSERT (Entry->Next != NULL);
-
-        CopyGuid (&Entry->Next->VendorGuid, VendorGuid);
-        Entry->Next->Name = AllocateZeroPool (StrSize (VariableName));
-        ASSERT (Entry->Next->Name != NULL);
-        StrCpyS (Entry->Next->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName);
-        Entry->Next->Volatile = Volatile;
-      }
-
-    }
-  }
-}
-
-
-/**
-
-  This code checks if variable header is valid or not.
-
-  @param Variable           Pointer to the Variable Header.
-  @param VariableStoreEnd   Pointer to the Variable Store End.
-
-  @retval TRUE              Variable header is valid.
-  @retval FALSE             Variable header is not valid.
-
-**/
-BOOLEAN
-IsValidVariableHeader (
-  IN  VARIABLE_HEADER       *Variable,
-  IN  VARIABLE_HEADER       *VariableStoreEnd
-  )
-{
-  if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) {
-    //
-    // Variable is NULL or has reached the end of variable store,
-    // or the StartId is not correct.
-    //
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-
 /**
 
   This function writes data to the FWH at the correct LBA even if the LBAs
@@ -376,345 +253,6 @@ UpdateVariableStore (
   return EFI_SUCCESS;
 }
 
-
-/**
-
-  This code gets the current status of Variable Store.
-
-  @param VarStoreHeader  Pointer to the Variable Store Header.
-
-  @retval EfiRaw         Variable store status is raw.
-  @retval EfiValid       Variable store status is valid.
-  @retval EfiInvalid     Variable store status is invalid.
-
-**/
-VARIABLE_STORE_STATUS
-GetVariableStoreStatus (
-  IN VARIABLE_STORE_HEADER *VarStoreHeader
-  )
-{
-  if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||
-       CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
-      VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
-      VarStoreHeader->State == VARIABLE_STORE_HEALTHY
-      ) {
-
-    return EfiValid;
-  } else if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
-             ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
-             ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
-             ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
-             VarStoreHeader->Size == 0xffffffff &&
-             VarStoreHeader->Format == 0xff &&
-             VarStoreHeader->State == 0xff
-          ) {
-
-    return EfiRaw;
-  } else {
-    return EfiInvalid;
-  }
-}
-
-/**
-  This code gets the size of variable header.
-
-  @return Size of variable header in bytes in type UINTN.
-
-**/
-UINTN
-GetVariableHeaderSize (
-  VOID
-  )
-{
-  UINTN Value;
-
-  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
-    Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);
-  } else {
-    Value = sizeof (VARIABLE_HEADER);
-  }
-
-  return Value;
-}
-
-/**
-
-  This code gets the size of name of variable.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return UINTN          Size of variable in bytes.
-
-**/
-UINTN
-NameSizeOfVariable (
-  IN  VARIABLE_HEADER   *Variable
-  )
-{
-  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
-
-  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
-  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
-    if (AuthVariable->State == (UINT8) (-1) ||
-       AuthVariable->DataSize == (UINT32) (-1) ||
-       AuthVariable->NameSize == (UINT32) (-1) ||
-       AuthVariable->Attributes == (UINT32) (-1)) {
-      return 0;
-    }
-    return (UINTN) AuthVariable->NameSize;
-  } else {
-    if (Variable->State == (UINT8) (-1) ||
-        Variable->DataSize == (UINT32) (-1) ||
-        Variable->NameSize == (UINT32) (-1) ||
-        Variable->Attributes == (UINT32) (-1)) {
-      return 0;
-    }
-    return (UINTN) Variable->NameSize;
-  }
-}
-
-/**
-  This code sets the size of name of variable.
-
-  @param[in] Variable   Pointer to the Variable Header.
-  @param[in] NameSize   Name size to set.
-
-**/
-VOID
-SetNameSizeOfVariable (
-  IN VARIABLE_HEADER    *Variable,
-  IN UINTN              NameSize
-  )
-{
-  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
-
-  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
-  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
-    AuthVariable->NameSize = (UINT32) NameSize;
-  } else {
-    Variable->NameSize = (UINT32) NameSize;
-  }
-}
-
-/**
-
-  This code gets the size of variable data.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Size of variable in bytes.
-
-**/
-UINTN
-DataSizeOfVariable (
-  IN  VARIABLE_HEADER   *Variable
-  )
-{
-  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
-
-  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
-  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
-    if (AuthVariable->State == (UINT8) (-1) ||
-       AuthVariable->DataSize == (UINT32) (-1) ||
-       AuthVariable->NameSize == (UINT32) (-1) ||
-       AuthVariable->Attributes == (UINT32) (-1)) {
-      return 0;
-    }
-    return (UINTN) AuthVariable->DataSize;
-  } else {
-    if (Variable->State == (UINT8) (-1) ||
-        Variable->DataSize == (UINT32) (-1) ||
-        Variable->NameSize == (UINT32) (-1) ||
-        Variable->Attributes == (UINT32) (-1)) {
-      return 0;
-    }
-    return (UINTN) Variable->DataSize;
-  }
-}
-
-/**
-  This code sets the size of variable data.
-
-  @param[in] Variable   Pointer to the Variable Header.
-  @param[in] DataSize   Data size to set.
-
-**/
-VOID
-SetDataSizeOfVariable (
-  IN VARIABLE_HEADER    *Variable,
-  IN UINTN              DataSize
-  )
-{
-  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
-
-  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
-  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
-    AuthVariable->DataSize = (UINT32) DataSize;
-  } else {
-    Variable->DataSize = (UINT32) DataSize;
-  }
-}
-
-/**
-
-  This code gets the pointer to the variable name.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Pointer to Variable Name which is Unicode encoding.
-
-**/
-CHAR16 *
-GetVariableNamePtr (
-  IN  VARIABLE_HEADER   *Variable
-  )
-{
-  return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize ());
-}
-
-/**
-  This code gets the pointer to the variable guid.
-
-  @param Variable   Pointer to the Variable Header.
-
-  @return A EFI_GUID* pointer to Vendor Guid.
-
-**/
-EFI_GUID *
-GetVendorGuidPtr (
-  IN VARIABLE_HEADER    *Variable
-  )
-{
-  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
-
-  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
-  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
-    return &AuthVariable->VendorGuid;
-  } else {
-    return &Variable->VendorGuid;
-  }
-}
-
-/**
-
-  This code gets the pointer to the variable data.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Pointer to Variable Data.
-
-**/
-UINT8 *
-GetVariableDataPtr (
-  IN  VARIABLE_HEADER   *Variable
-  )
-{
-  UINTN Value;
-
-  //
-  // Be careful about pad size for alignment.
-  //
-  Value =  (UINTN) GetVariableNamePtr (Variable);
-  Value += NameSizeOfVariable (Variable);
-  Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
-
-  return (UINT8 *) Value;
-}
-
-/**
-  This code gets the variable data offset related to variable header.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Variable Data offset.
-
-**/
-UINTN
-GetVariableDataOffset (
-  IN  VARIABLE_HEADER   *Variable
-  )
-{
-  UINTN Value;
-
-  //
-  // Be careful about pad size for alignment
-  //
-  Value = GetVariableHeaderSize ();
-  Value += NameSizeOfVariable (Variable);
-  Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
-
-  return Value;
-}
-
-/**
-
-  This code gets the pointer to the next variable header.
-
-  @param Variable        Pointer to the Variable Header.
-
-  @return Pointer to next variable header.
-
-**/
-VARIABLE_HEADER *
-GetNextVariablePtr (
-  IN  VARIABLE_HEADER   *Variable
-  )
-{
-  UINTN Value;
-
-  Value =  (UINTN) GetVariableDataPtr (Variable);
-  Value += DataSizeOfVariable (Variable);
-  Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
-
-  //
-  // Be careful about pad size for alignment.
-  //
-  return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
-}
-
-/**
-
-  Gets the pointer to the first variable header in given variable store area.
-
-  @param VarStoreHeader  Pointer to the Variable Store Header.
-
-  @return Pointer to the first variable header.
-
-**/
-VARIABLE_HEADER *
-GetStartPointer (
-  IN VARIABLE_STORE_HEADER       *VarStoreHeader
-  )
-{
-  //
-  // The start of variable store.
-  //
-  return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
-}
-
-/**
-
-  Gets the pointer to the end of the variable storage area.
-
-  This function gets pointer to the end of the variable storage
-  area, according to the input variable store header.
-
-  @param VarStoreHeader  Pointer to the Variable Store Header.
-
-  @return Pointer to the end of the variable storage area.
-
-**/
-VARIABLE_HEADER *
-GetEndPointer (
-  IN VARIABLE_STORE_HEADER       *VarStoreHeader
-  )
-{
-  //
-  // The end of variable store
-  //
-  return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
-}
-
 /**
   Record variable error flag.
 
@@ -1228,75 +766,6 @@ Done:
   return Status;
 }
 
-/**
-  Find the variable in the specified variable store.
-
-  @param[in]       VariableName        Name of the variable to be found
-  @param[in]       VendorGuid          Vendor GUID to be found.
-  @param[in]       IgnoreRtCheck       Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
-                                       check at runtime when searching variable.
-  @param[in, out]  PtrTrack            Variable Track Pointer structure that contains Variable Information.
-
-  @retval          EFI_SUCCESS         Variable found successfully
-  @retval          EFI_NOT_FOUND       Variable not found
-**/
-EFI_STATUS
-FindVariableEx (
-  IN     CHAR16                  *VariableName,
-  IN     EFI_GUID                *VendorGuid,
-  IN     BOOLEAN                 IgnoreRtCheck,
-  IN OUT VARIABLE_POINTER_TRACK  *PtrTrack
-  )
-{
-  VARIABLE_HEADER                *InDeletedVariable;
-  VOID                           *Point;
-
-  PtrTrack->InDeletedTransitionPtr = NULL;
-
-  //
-  // Find the variable by walk through HOB, volatile and non-volatile variable store.
-  //
-  InDeletedVariable  = NULL;
-
-  for ( PtrTrack->CurrPtr = PtrTrack->StartPtr
-      ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr)
-      ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)
-      ) {
-    if (PtrTrack->CurrPtr->State == VAR_ADDED ||
-        PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
-       ) {
-      if (IgnoreRtCheck || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
-        if (VariableName[0] == 0) {
-          if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
-            InDeletedVariable   = PtrTrack->CurrPtr;
-          } else {
-            PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
-            return EFI_SUCCESS;
-          }
-        } else {
-          if (CompareGuid (VendorGuid, GetVendorGuidPtr (PtrTrack->CurrPtr))) {
-            Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr);
-
-            ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0);
-            if (CompareMem (VariableName, Point, NameSizeOfVariable (PtrTrack->CurrPtr)) == 0) {
-              if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
-                InDeletedVariable     = PtrTrack->CurrPtr;
-              } else {
-                PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
-                return EFI_SUCCESS;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  PtrTrack->CurrPtr = InDeletedVariable;
-  return (PtrTrack->CurrPtr  == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
-}
-
-
 /**
   Finds variable in storage blocks of volatile and non-volatile storage areas.
 
@@ -2078,38 +1547,6 @@ AutoUpdateLangVariable (
   }
 }
 
-/**
-  Compare two EFI_TIME data.
-
-
-  @param FirstTime           A pointer to the first EFI_TIME data.
-  @param SecondTime          A pointer to the second EFI_TIME data.
-
-  @retval  TRUE              The FirstTime is not later than the SecondTime.
-  @retval  FALSE             The FirstTime is later than the SecondTime.
-
-**/
-BOOLEAN
-VariableCompareTimeStampInternal (
-  IN EFI_TIME               *FirstTime,
-  IN EFI_TIME               *SecondTime
-  )
-{
-  if (FirstTime->Year != SecondTime->Year) {
-    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
-  } else if (FirstTime->Month != SecondTime->Month) {
-    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
-  } else if (FirstTime->Day != SecondTime->Day) {
-    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
-  } else if (FirstTime->Hour != SecondTime->Hour) {
-    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
-  } else if (FirstTime->Minute != SecondTime->Minute) {
-    return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);
-  }
-
-  return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);
-}
-
 /**
   Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set,
   index of associated public key is needed.
@@ -2205,7 +1642,7 @@ UpdateVariable (
         // go to delete this variable in variable HOB and
         // try to flush other variables from HOB to flash.
         //
-        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALSE, TRUE, FALSE);
+        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, FALSE, TRUE, FALSE, &gVariableInfo);
         FlushHobVariableToFlash (VariableName, VendorGuid);
         return EFI_SUCCESS;
       }
@@ -2322,7 +1759,7 @@ UpdateVariable (
                  &State
                  );
       if (!EFI_ERROR (Status)) {
-        UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);
+        UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE, &gVariableInfo);
         if (!Variable->Volatile) {
           CacheVariable->CurrPtr->State = State;
           FlushHobVariableToFlash (VariableName, VendorGuid);
@@ -2341,7 +1778,7 @@ UpdateVariable (
       //
       // Variable content unchanged and no need to update timestamp, just return.
       //
-      UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);
+      UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
       Status = EFI_SUCCESS;
       goto Done;
     } else if ((CacheVariable->CurrPtr->State == VAR_ADDED) ||
@@ -2570,7 +2007,7 @@ UpdateVariable (
           CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
           CacheVariable->InDeletedTransitionPtr = NULL;
         }
-        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE);
+        UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
         FlushHobVariableToFlash (VariableName, VendorGuid);
       } else {
         if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)) {
@@ -2720,7 +2157,7 @@ UpdateVariable (
           CacheVariable->CurrPtr = (VARIABLE_HEADER *)((UINTN) CacheVariable->StartPtr + ((UINTN) Variable->CurrPtr - (UINTN) Variable->StartPtr));
           CacheVariable->InDeletedTransitionPtr = NULL;
         }
-        UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE);
+        UpdateVariableInfo (VariableName, VendorGuid, TRUE, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
       }
       goto Done;
     }
@@ -2791,7 +2228,7 @@ UpdateVariable (
   }
 
   if (!EFI_ERROR (Status)) {
-    UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE);
+    UpdateVariableInfo (VariableName, VendorGuid, Volatile, FALSE, TRUE, FALSE, FALSE, &gVariableInfo);
     if (!Volatile) {
       FlushHobVariableToFlash (VariableName, VendorGuid);
     }
@@ -2870,7 +2307,7 @@ VariableServiceGetVariable (
     }
 
     *DataSize = VarDataSize;
-    UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);
+    UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE, &gVariableInfo);
 
     Status = EFI_SUCCESS;
     goto Done;
@@ -2885,166 +2322,6 @@ Done:
   return Status;
 }
 
-/**
-  This code Finds the Next available variable.
-
-  Caution: This function may receive untrusted input.
-  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
-
-  @param[in]  VariableName  Pointer to variable name.
-  @param[in]  VendorGuid    Variable Vendor Guid.
-  @param[out] VariablePtr   Pointer to variable header address.
-
-  @retval EFI_SUCCESS           The function completed successfully.
-  @retval EFI_NOT_FOUND         The next variable was not found.
-  @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL.
-  @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and
-                                GUID of an existing variable.
-
-**/
-EFI_STATUS
-EFIAPI
-VariableServiceGetNextVariableInternal (
-  IN  CHAR16                *VariableName,
-  IN  EFI_GUID              *VendorGuid,
-  OUT VARIABLE_HEADER       **VariablePtr
-  )
-{
-  VARIABLE_STORE_TYPE     Type;
-  VARIABLE_POINTER_TRACK  Variable;
-  VARIABLE_POINTER_TRACK  VariableInHob;
-  VARIABLE_POINTER_TRACK  VariablePtrTrack;
-  EFI_STATUS              Status;
-  VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];
-
-  Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);
-  if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
-    //
-    // For VariableName is an empty string, FindVariable() will try to find and return
-    // the first qualified variable, and if FindVariable() returns error (EFI_NOT_FOUND)
-    // as no any variable is found, still go to return the error (EFI_NOT_FOUND).
-    //
-    if (VariableName[0] != 0) {
-      //
-      // For VariableName is not an empty string, and FindVariable() returns error as
-      // VariableName and VendorGuid are not a name and GUID of an existing variable,
-      // there is no way to get next variable, follow spec to return EFI_INVALID_PARAMETER.
-      //
-      Status = EFI_INVALID_PARAMETER;
-    }
-    goto Done;
-  }
-
-  if (VariableName[0] != 0) {
-    //
-    // If variable name is not NULL, get next variable.
-    //
-    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
-  }
-
-  //
-  // 0: Volatile, 1: HOB, 2: Non-Volatile.
-  // The index and attributes mapping must be kept in this order as FindVariable
-  // makes use of this mapping to implement search algorithm.
-  //
-  VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
-  VariableStoreHeader[VariableStoreTypeHob]      = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
-  VariableStoreHeader[VariableStoreTypeNv]       = mNvVariableCache;
-
-  while (TRUE) {
-    //
-    // Switch from Volatile to HOB, to Non-Volatile.
-    //
-    while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) {
-      //
-      // Find current storage index
-      //
-      for (Type = (VARIABLE_STORE_TYPE) 0; Type < VariableStoreTypeMax; Type++) {
-        if ((VariableStoreHeader[Type] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreHeader[Type]))) {
-          break;
-        }
-      }
-      ASSERT (Type < VariableStoreTypeMax);
-      //
-      // Switch to next storage
-      //
-      for (Type++; Type < VariableStoreTypeMax; Type++) {
-        if (VariableStoreHeader[Type] != NULL) {
-          break;
-        }
-      }
-      //
-      // Capture the case that
-      // 1. current storage is the last one, or
-      // 2. no further storage
-      //
-      if (Type == VariableStoreTypeMax) {
-        Status = EFI_NOT_FOUND;
-        goto Done;
-      }
-      Variable.StartPtr = GetStartPointer (VariableStoreHeader[Type]);
-      Variable.EndPtr   = GetEndPointer   (VariableStoreHeader[Type]);
-      Variable.CurrPtr  = Variable.StartPtr;
-    }
-
-    //
-    // Variable is found
-    //
-    if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
-      if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
-        if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
-          //
-          // If it is a IN_DELETED_TRANSITION variable,
-          // and there is also a same ADDED one at the same time,
-          // don't return it.
-          //
-          VariablePtrTrack.StartPtr = Variable.StartPtr;
-          VariablePtrTrack.EndPtr = Variable.EndPtr;
-          Status = FindVariableEx (
-                     GetVariableNamePtr (Variable.CurrPtr),
-                     GetVendorGuidPtr (Variable.CurrPtr),
-                     FALSE,
-                     &VariablePtrTrack
-                     );
-          if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
-            Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
-            continue;
-          }
-        }
-
-        //
-        // Don't return NV variable when HOB overrides it
-        //
-        if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&
-            (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))
-           ) {
-          VariableInHob.StartPtr = GetStartPointer (VariableStoreHeader[VariableStoreTypeHob]);
-          VariableInHob.EndPtr   = GetEndPointer   (VariableStoreHeader[VariableStoreTypeHob]);
-          Status = FindVariableEx (
-                     GetVariableNamePtr (Variable.CurrPtr),
-                     GetVendorGuidPtr (Variable.CurrPtr),
-                     FALSE,
-                     &VariableInHob
-                     );
-          if (!EFI_ERROR (Status)) {
-            Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
-            continue;
-          }
-        }
-
-        *VariablePtr = Variable.CurrPtr;
-        Status = EFI_SUCCESS;
-        goto Done;
-      }
-    }
-
-    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
-  }
-
-Done:
-  return Status;
-}
-
 /**
 
   This code Finds the Next available variable.
@@ -3082,6 +2359,7 @@ VariableServiceGetNextVariableName (
   UINTN                   MaxLen;
   UINTN                   VarNameSize;
   VARIABLE_HEADER         *VariablePtr;
+  VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];
 
   if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {
     return EFI_INVALID_PARAMETER;
@@ -3101,7 +2379,16 @@ VariableServiceGetNextVariableName (
 
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
 
-  Status = VariableServiceGetNextVariableInternal (VariableName, VendorGuid, &VariablePtr);
+  //
+  // 0: Volatile, 1: HOB, 2: Non-Volatile.
+  // The index and attributes mapping must be kept in this order as FindVariable
+  // makes use of this mapping to implement search algorithm.
+  //
+  VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
+  VariableStoreHeader[VariableStoreTypeHob]      = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+  VariableStoreHeader[VariableStoreTypeNv]       = mNvVariableCache;
+
+  Status = GetNextVariableEx (VariableName, VendorGuid, VariableStoreHeader, &VariablePtr);
   if (!EFI_ERROR (Status)) {
     VarNameSize = NameSizeOfVariable (VariablePtr);
     ASSERT (VarNameSize != 0);
@@ -3720,25 +3007,6 @@ ReclaimForOS(
   }
 }
 
-/**
-  Get non-volatile maximum variable size.
-
-  @return Non-volatile maximum variable size.
-
-**/
-UINTN
-GetNonVolatileMaxVariableSize (
-  VOID
-  )
-{
-  if (PcdGet32 (PcdHwErrStorageSize) != 0) {
-    return MAX (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)),
-                PcdGet32 (PcdMaxHardwareErrorVariableSize));
-  } else {
-    return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize));
-  }
-}
-
 /**
   Get maximum variable size, covering both non-volatile and volatile variables.
 
@@ -4024,7 +3292,7 @@ InitNonVolatileVariableStore (
       return Status;
     }
     mVariableModuleGlobal->VariableGlobal.EmuNvMode = TRUE;
-    DEBUG ((DEBUG_INFO, "Variable driver will work at emulated non-volatile variable mode!\n"));
+    DEBUG ((DEBUG_INFO, "Variable driver will work in emulated non-volatile variable mode!\n"));
   } else {
     Status = InitRealNonVolatileVariableStore (&VariableStoreBase);
     if (EFI_ERROR (Status)) {
@@ -4040,6 +3308,9 @@ InitNonVolatileVariableStore (
   mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);
   mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);
 
+  Status = InitVariableHelpers (mVariableModuleGlobal->VariableGlobal.AuthFormat);
+  ASSERT_EFI_ERROR (Status);
+
   //
   // Parse non-volatile variable data and get last variable offset.
   //
@@ -4470,18 +3741,13 @@ VariableCommonInitialize (
 
   //
   // mVariableModuleGlobal->VariableGlobal.AuthFormat
-  // has been initialized in InitNonVolatileVariableStore().
+  // is initialized in InitNonVolatileVariableStore().
   //
   if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {
     DEBUG ((EFI_D_INFO, "Variable driver will work with auth variable format!\n"));
-    //
-    // Set AuthSupport to FALSE first, VariableWriteServiceInitialize() will initialize it.
-    //
-    mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;
     VariableGuid = &gEfiAuthenticatedVariableGuid;
   } else {
     DEBUG ((EFI_D_INFO, "Variable driver will work without auth variable support!\n"));
-    mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;
     VariableGuid = &gEfiVariableGuid;
   }
 
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c
index cb6fcebe2d..232d9ffe25 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c
@@ -1,12 +1,13 @@
 /** @file
   Provides variable driver extended services.
 
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include "Variable.h"
+#include "VariableParsing.h"
 
 /**
   Finds variable in storage blocks of volatile and non-volatile storage areas.
@@ -97,10 +98,16 @@ VariableExLibFindNextVariable (
   EFI_STATUS                    Status;
   VARIABLE_HEADER               *VariablePtr;
   AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr;
+  VARIABLE_STORE_HEADER         *VariableStoreHeader[VariableStoreTypeMax];
 
-  Status = VariableServiceGetNextVariableInternal (
+  VariableStoreHeader[VariableStoreTypeVolatile] = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase;
+  VariableStoreHeader[VariableStoreTypeHob]      = (VARIABLE_STORE_HEADER *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase;
+  VariableStoreHeader[VariableStoreTypeNv]       = mNvVariableCache;
+
+  Status = GetNextVariableEx (
              VariableName,
              VendorGuid,
+             VariableStoreHeader,
              &VariablePtr
              );
   if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
new file mode 100644
index 0000000000..b1b6d8282f
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableNonVolatile.c
@@ -0,0 +1,28 @@
+/** @file
+  Common variable non-volatile store routines.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VariableNonVolatile.h"
+
+/**
+  Get non-volatile maximum variable size.
+
+  @return Non-volatile maximum variable size.
+
+**/
+UINTN
+GetNonVolatileMaxVariableSize (
+  VOID
+  )
+{
+  if (PcdGet32 (PcdHwErrStorageSize) != 0) {
+    return MAX (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)),
+                PcdGet32 (PcdMaxHardwareErrorVariableSize));
+  } else {
+    return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize));
+  }
+}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c
new file mode 100644
index 0000000000..d448e5a264
--- /dev/null
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableParsing.c
@@ -0,0 +1,816 @@
+/** @file
+  The common variable helper routines shared by the DXE_RUNTIME variable
+  module and the DXE_SMM variable module.
+
+  Caution: This module requires additional review when modified.
+  This driver will have external input - variable data. They may be input in SMM mode.
+  This external input must be validated carefully to avoid security issue like
+  buffer overflow, integer overflow.
+
+Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VariableParsing.h"
+
+typedef struct {
+  CONST CHAR16       *VariableName;
+  EFI_GUID           *VendorGuid;
+} VARIABLE_TYPE;
+
+VARIABLE_TYPE mAlwaysAuthenticatedVariables[] = {
+  {EFI_SECURE_BOOT_MODE_NAME,    &gEfiGlobalVariableGuid},
+  {EFI_PLATFORM_KEY_NAME,        &gEfiGlobalVariableGuid},
+  {EFI_KEY_EXCHANGE_KEY_NAME,    &gEfiGlobalVariableGuid},
+  {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},
+  {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},
+  {EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid},
+};
+
+STATIC  BOOLEAN   mAuthFormat;
+
+/**
+
+  This code checks if variable header is valid or not.
+
+  @param Variable           Pointer to the Variable Header.
+  @param VariableStoreEnd   Pointer to the Variable Store End.
+
+  @retval TRUE              Variable header is valid.
+  @retval FALSE             Variable header is not valid.
+
+**/
+BOOLEAN
+IsValidVariableHeader (
+  IN  VARIABLE_HEADER       *Variable,
+  IN  VARIABLE_HEADER       *VariableStoreEnd
+  )
+{
+  if ((Variable == NULL) || (Variable >= VariableStoreEnd) || (Variable->StartId != VARIABLE_DATA)) {
+    //
+    // Variable is NULL or has reached the end of variable store,
+    // or the StartId is not correct.
+    //
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+
+  This code gets the current status of Variable Store.
+
+  @param VarStoreHeader  Pointer to the Variable Store Header.
+
+  @retval EfiRaw         Variable store status is raw.
+  @retval EfiValid       Variable store status is valid.
+  @retval EfiInvalid     Variable store status is invalid.
+
+**/
+VARIABLE_STORE_STATUS
+GetVariableStoreStatus (
+  IN VARIABLE_STORE_HEADER *VarStoreHeader
+  )
+{
+  if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||
+       CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&
+      VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&
+      VarStoreHeader->State == VARIABLE_STORE_HEALTHY
+      ) {
+
+    return EfiValid;
+  } else if (((UINT32 *)(&VarStoreHeader->Signature))[0] == 0xffffffff &&
+             ((UINT32 *)(&VarStoreHeader->Signature))[1] == 0xffffffff &&
+             ((UINT32 *)(&VarStoreHeader->Signature))[2] == 0xffffffff &&
+             ((UINT32 *)(&VarStoreHeader->Signature))[3] == 0xffffffff &&
+             VarStoreHeader->Size == 0xffffffff &&
+             VarStoreHeader->Format == 0xff &&
+             VarStoreHeader->State == 0xff
+          ) {
+
+    return EfiRaw;
+  } else {
+    return EfiInvalid;
+  }
+}
+
+/**
+  This code gets the size of variable header.
+
+  @return Size of variable header in bytes in type UINTN.
+
+**/
+UINTN
+GetVariableHeaderSize (
+  VOID
+  )
+{
+  UINTN Value;
+
+  if (mAuthFormat) {
+    Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);
+  } else {
+    Value = sizeof (VARIABLE_HEADER);
+  }
+
+  return Value;
+}
+
+/**
+
+  This code gets the size of name of variable.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return UINTN          Size of variable in bytes.
+
+**/
+UINTN
+NameSizeOfVariable (
+  IN  VARIABLE_HEADER   *Variable
+  )
+{
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
+
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
+  if (mAuthFormat) {
+    if (AuthVariable->State == (UINT8) (-1) ||
+       AuthVariable->DataSize == (UINT32) (-1) ||
+       AuthVariable->NameSize == (UINT32) (-1) ||
+       AuthVariable->Attributes == (UINT32) (-1)) {
+      return 0;
+    }
+    return (UINTN) AuthVariable->NameSize;
+  } else {
+    if (Variable->State == (UINT8) (-1) ||
+        Variable->DataSize == (UINT32) (-1) ||
+        Variable->NameSize == (UINT32) (-1) ||
+        Variable->Attributes == (UINT32) (-1)) {
+      return 0;
+    }
+    return (UINTN) Variable->NameSize;
+  }
+}
+
+/**
+  This code sets the size of name of variable.
+
+  @param[in] Variable   Pointer to the Variable Header.
+  @param[in] NameSize   Name size to set.
+
+**/
+VOID
+SetNameSizeOfVariable (
+  IN VARIABLE_HEADER    *Variable,
+  IN UINTN              NameSize
+  )
+{
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
+
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
+  if (mAuthFormat) {
+    AuthVariable->NameSize = (UINT32) NameSize;
+  } else {
+    Variable->NameSize = (UINT32) NameSize;
+  }
+}
+
+/**
+
+  This code gets the size of variable data.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Size of variable in bytes.
+
+**/
+UINTN
+DataSizeOfVariable (
+  IN  VARIABLE_HEADER   *Variable
+  )
+{
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
+
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
+  if (mAuthFormat) {
+    if (AuthVariable->State == (UINT8) (-1) ||
+       AuthVariable->DataSize == (UINT32) (-1) ||
+       AuthVariable->NameSize == (UINT32) (-1) ||
+       AuthVariable->Attributes == (UINT32) (-1)) {
+      return 0;
+    }
+    return (UINTN) AuthVariable->DataSize;
+  } else {
+    if (Variable->State == (UINT8) (-1) ||
+        Variable->DataSize == (UINT32) (-1) ||
+        Variable->NameSize == (UINT32) (-1) ||
+        Variable->Attributes == (UINT32) (-1)) {
+      return 0;
+    }
+    return (UINTN) Variable->DataSize;
+  }
+}
+
+/**
+  This code sets the size of variable data.
+
+  @param[in] Variable   Pointer to the Variable Header.
+  @param[in] DataSize   Data size to set.
+
+**/
+VOID
+SetDataSizeOfVariable (
+  IN VARIABLE_HEADER    *Variable,
+  IN UINTN              DataSize
+  )
+{
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
+
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
+  if (mAuthFormat) {
+    AuthVariable->DataSize = (UINT32) DataSize;
+  } else {
+    Variable->DataSize = (UINT32) DataSize;
+  }
+}
+
+/**
+
+  This code gets the pointer to the variable name.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Pointer to Variable Name which is Unicode encoding.
+
+**/
+CHAR16 *
+GetVariableNamePtr (
+  IN  VARIABLE_HEADER   *Variable
+  )
+{
+  return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize ());
+}
+
+/**
+  This code gets the pointer to the variable guid.
+
+  @param Variable   Pointer to the Variable Header.
+
+  @return A EFI_GUID* pointer to Vendor Guid.
+
+**/
+EFI_GUID *
+GetVendorGuidPtr (
+  IN VARIABLE_HEADER    *Variable
+  )
+{
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;
+
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;
+  if (mAuthFormat) {
+    return &AuthVariable->VendorGuid;
+  } else {
+    return &Variable->VendorGuid;
+  }
+}
+
+/**
+
+  This code gets the pointer to the variable data.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Pointer to Variable Data.
+
+**/
+UINT8 *
+GetVariableDataPtr (
+  IN  VARIABLE_HEADER   *Variable
+  )
+{
+  UINTN Value;
+
+  //
+  // Be careful about pad size for alignment.
+  //
+  Value =  (UINTN) GetVariableNamePtr (Variable);
+  Value += NameSizeOfVariable (Variable);
+  Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
+
+  return (UINT8 *) Value;
+}
+
+/**
+  This code gets the variable data offset related to variable header.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Variable Data offset.
+
+**/
+UINTN
+GetVariableDataOffset (
+  IN  VARIABLE_HEADER   *Variable
+  )
+{
+  UINTN Value;
+
+  //
+  // Be careful about pad size for alignment
+  //
+  Value = GetVariableHeaderSize ();
+  Value += NameSizeOfVariable (Variable);
+  Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));
+
+  return Value;
+}
+
+/**
+
+  This code gets the pointer to the next variable header.
+
+  @param Variable        Pointer to the Variable Header.
+
+  @return Pointer to next variable header.
+
+**/
+VARIABLE_HEADER *
+GetNextVariablePtr (
+  IN  VARIABLE_HEADER   *Variable
+  )
+{
+  UINTN Value;
+
+  Value =  (UINTN) GetVariableDataPtr (Variable);
+  Value += DataSizeOfVariable (Variable);
+  Value += GET_PAD_SIZE (DataSizeOfVariable (Variable));
+
+  //
+  // Be careful about pad size for alignment.
+  //
+  return (VARIABLE_HEADER *) HEADER_ALIGN (Value);
+}
+
+/**
+
+  Gets the pointer to the first variable header in given variable store area.
+
+  @param VarStoreHeader  Pointer to the Variable Store Header.
+
+  @return Pointer to the first variable header.
+
+**/
+VARIABLE_HEADER *
+GetStartPointer (
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader
+  )
+{
+  //
+  // The end of variable store.
+  //
+  return (VARIABLE_HEADER *) HEADER_ALIGN (VarStoreHeader + 1);
+}
+
+/**
+
+  Gets the pointer to the end of the variable storage area.
+
+  This function gets pointer to the end of the variable storage
+  area, according to the input variable store header.
+
+  @param VarStoreHeader  Pointer to the Variable Store Header.
+
+  @return Pointer to the end of the variable storage area.
+
+**/
+VARIABLE_HEADER *
+GetEndPointer (
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader
+  )
+{
+  //
+  // The end of variable store
+  //
+  return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
+}
+
+/**
+  Returns if this is a variable that always requires authenticated writes.
+  There may be other scenarios that result in a variable not identified by the
+  function to also require authentication.
+
+  @param[in]  VariableName       Name of variable.
+  @param[in]  VendorGuid         Guid of variable.
+
+  @retval  TRUE            The variable always requires authenticated writes
+  @retval  FALSE           The variable may or may not require authenticated writes
+**/
+BOOLEAN
+IsAuthenticatedVariable (
+  IN CHAR16                   *VariableName,
+  IN EFI_GUID                 *VendorGuid
+  )
+{
+  UINTN   Index;
+
+  for (Index = 0; Index < sizeof (mAlwaysAuthenticatedVariables) / sizeof (mAlwaysAuthenticatedVariables[0]); Index++) {
+    if ((StrCmp (VariableName, mAlwaysAuthenticatedVariables[Index].VariableName) == 0) &&
+        (CompareGuid (VendorGuid, mAlwaysAuthenticatedVariables[Index].VendorGuid))) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Compare two EFI_TIME data.
+
+
+  @param FirstTime           A pointer to the first EFI_TIME data.
+  @param SecondTime          A pointer to the second EFI_TIME data.
+
+  @retval  TRUE              The FirstTime is not later than the SecondTime.
+  @retval  FALSE             The FirstTime is later than the SecondTime.
+
+**/
+BOOLEAN
+VariableCompareTimeStampInternal (
+  IN EFI_TIME               *FirstTime,
+  IN EFI_TIME               *SecondTime
+  )
+{
+  if (FirstTime->Year != SecondTime->Year) {
+    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);
+  } else if (FirstTime->Month != SecondTime->Month) {
+    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);
+  } else if (FirstTime->Day != SecondTime->Day) {
+    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);
+  } else if (FirstTime->Hour != SecondTime->Hour) {
+    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);
+  } else if (FirstTime->Minute != SecondTime->Minute) {
+    return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);
+  }
+
+  return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);
+}
+
+/**
+  Find the variable in the specified variable store.
+
+  @param[in]       VariableName        Name of the variable to be found
+  @param[in]       VendorGuid          Vendor GUID to be found.
+  @param[in]       IgnoreRtCheck       Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute
+                                       check at runtime when searching variable.
+  @param[in, out]  PtrTrack            Variable Track Pointer structure that contains Variable Information.
+
+  @retval          EFI_SUCCESS         Variable found successfully
+  @retval          EFI_NOT_FOUND       Variable not found
+**/
+EFI_STATUS
+FindVariableEx (
+  IN     CHAR16                  *VariableName,
+  IN     EFI_GUID                *VendorGuid,
+  IN     BOOLEAN                 IgnoreRtCheck,
+  IN OUT VARIABLE_POINTER_TRACK  *PtrTrack
+  )
+{
+  VARIABLE_HEADER                *InDeletedVariable;
+  VOID                           *Point;
+
+  PtrTrack->InDeletedTransitionPtr = NULL;
+
+  //
+  // Find the variable by walk through HOB, volatile and non-volatile variable store.
+  //
+  InDeletedVariable  = NULL;
+
+  for ( PtrTrack->CurrPtr = PtrTrack->StartPtr
+      ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr)
+      ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)
+      ) {
+    if (PtrTrack->CurrPtr->State == VAR_ADDED ||
+        PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)
+       ) {
+      if (IgnoreRtCheck || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
+        if (VariableName[0] == 0) {
+          if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+            InDeletedVariable   = PtrTrack->CurrPtr;
+          } else {
+            PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
+            return EFI_SUCCESS;
+          }
+        } else {
+          if (CompareGuid (VendorGuid, GetVendorGuidPtr (PtrTrack->CurrPtr))) {
+            Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr);
+
+            ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0);
+            if (CompareMem (VariableName, Point, NameSizeOfVariable (PtrTrack->CurrPtr)) == 0) {
+              if (PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+                InDeletedVariable     = PtrTrack->CurrPtr;
+              } else {
+                PtrTrack->InDeletedTransitionPtr = InDeletedVariable;
+                return EFI_SUCCESS;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  PtrTrack->CurrPtr = InDeletedVariable;
+  return (PtrTrack->CurrPtr  == NULL) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
+/**
+  This code finds the next available variable.
+
+  Caution: This function may receive untrusted input.
+  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.
+
+  @param[in]  VariableName      Pointer to variable name.
+  @param[in]  VendorGuid        Variable Vendor Guid.
+  @param[in]  VariableStoreList A list of variable stores that should be used to get the next variable.
+                                The maximum number of entries is the max value of VARIABLE_STORE_TYPE.
+  @param[out] VariablePtr       Pointer to variable header address.
+
+  @retval EFI_SUCCESS           The function completed successfully.
+  @retval EFI_NOT_FOUND         The next variable was not found.
+  @retval EFI_INVALID_PARAMETER If VariableName is not an empty string, while VendorGuid is NULL.
+  @retval EFI_INVALID_PARAMETER The input values of VariableName and VendorGuid are not a name and
+                                GUID of an existing variable.
+
+**/
+EFI_STATUS
+EFIAPI
+GetNextVariableEx (
+  IN  CHAR16                *VariableName,
+  IN  EFI_GUID              *VendorGuid,
+  IN  VARIABLE_STORE_HEADER **VariableStoreList,
+  OUT VARIABLE_HEADER       **VariablePtr
+  )
+{
+  EFI_STATUS              Status;
+  VARIABLE_STORE_TYPE     StoreType;
+  VARIABLE_POINTER_TRACK  Variable;
+  VARIABLE_POINTER_TRACK  VariableInHob;
+  VARIABLE_POINTER_TRACK  VariablePtrTrack;
+
+  Status = EFI_NOT_FOUND;
+
+  if (VariableStoreList == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Check if the variable exists in the given variable store list
+  for (StoreType = (VARIABLE_STORE_TYPE) 0; StoreType < VariableStoreTypeMax; StoreType++) {
+    if (VariableStoreList[StoreType] == NULL) {
+      continue;
+    }
+
+    Variable.StartPtr = GetStartPointer (VariableStoreList[StoreType]);
+    Variable.EndPtr   = GetEndPointer   (VariableStoreList[StoreType]);
+    Variable.Volatile = (BOOLEAN) (StoreType == VariableStoreTypeVolatile);
+
+    Status = FindVariableEx (VariableName, VendorGuid, FALSE, &Variable);
+    if (!EFI_ERROR (Status)) {
+      break;
+    }
+  }
+
+  if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {
+    //
+    // For VariableName is an empty string, FindVariable() will try to find and return
+    // the first qualified variable, and if FindVariable() returns error (EFI_NOT_FOUND)
+    // as no any variable is found, still go to return the error (EFI_NOT_FOUND).
+    //
+    if (VariableName[0] != 0) {
+      //
+      // For VariableName is not an empty string, and FindVariable() returns error as
+      // VariableName and VendorGuid are not a name and GUID of an existing variable,
+      // there is no way to get next variable, follow spec to return EFI_INVALID_PARAMETER.
+      //
+      Status = EFI_INVALID_PARAMETER;
+    }
+    goto Done;
+  }
+
+  if (VariableName[0] != 0) {
+    //
+    // If variable name is not empty, get next variable.
+    //
+    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+  }
+
+  while (TRUE) {
+    //
+    // Switch to the next variable store if needed
+    //
+    while (!IsValidVariableHeader (Variable.CurrPtr, Variable.EndPtr)) {
+      //
+      // Find current storage index
+      //
+      for (StoreType = (VARIABLE_STORE_TYPE) 0; StoreType < VariableStoreTypeMax; StoreType++) {
+        if ((VariableStoreList[StoreType] != NULL) && (Variable.StartPtr == GetStartPointer (VariableStoreList[StoreType]))) {
+          break;
+        }
+      }
+      ASSERT (StoreType < VariableStoreTypeMax);
+      //
+      // Switch to next storage
+      //
+      for (StoreType++; StoreType < VariableStoreTypeMax; StoreType++) {
+        if (VariableStoreList[StoreType] != NULL) {
+          break;
+        }
+      }
+      //
+      // Capture the case that
+      // 1. current storage is the last one, or
+      // 2. no further storage
+      //
+      if (StoreType == VariableStoreTypeMax) {
+        Status = EFI_NOT_FOUND;
+        goto Done;
+      }
+      Variable.StartPtr = GetStartPointer (VariableStoreList[StoreType]);
+      Variable.EndPtr   = GetEndPointer   (VariableStoreList[StoreType]);
+      Variable.CurrPtr  = Variable.StartPtr;
+    }
+
+    //
+    // Variable is found
+    //
+    if (Variable.CurrPtr->State == VAR_ADDED || Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+      if (!AtRuntime () || ((Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {
+        if (Variable.CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {
+          //
+          // If it is a IN_DELETED_TRANSITION variable,
+          // and there is also a same ADDED one at the same time,
+          // don't return it.
+          //
+          VariablePtrTrack.StartPtr = Variable.StartPtr;
+          VariablePtrTrack.EndPtr = Variable.EndPtr;
+          Status = FindVariableEx (
+                     GetVariableNamePtr (Variable.CurrPtr),
+                     GetVendorGuidPtr (Variable.CurrPtr),
+                     FALSE,
+                     &VariablePtrTrack
+                     );
+          if (!EFI_ERROR (Status) && VariablePtrTrack.CurrPtr->State == VAR_ADDED) {
+            Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+            continue;
+          }
+        }
+
+        //
+        // Don't return NV variable when HOB overrides it
+        //
+        if ((VariableStoreList[VariableStoreTypeHob] != NULL) && (VariableStoreList[VariableStoreTypeNv] != NULL) &&
+            (Variable.StartPtr == GetStartPointer (VariableStoreList[VariableStoreTypeNv]))
+           ) {
+          VariableInHob.StartPtr = GetStartPointer (VariableStoreList[VariableStoreTypeHob]);
+          VariableInHob.EndPtr   = GetEndPointer   (VariableStoreList[VariableStoreTypeHob]);
+          Status = FindVariableEx (
+                     GetVariableNamePtr (Variable.CurrPtr),
+                     GetVendorGuidPtr (Variable.CurrPtr),
+                     FALSE,
+                     &VariableInHob
+                     );
+          if (!EFI_ERROR (Status)) {
+            Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+            continue;
+          }
+        }
+
+        *VariablePtr = Variable.CurrPtr;
+        Status = EFI_SUCCESS;
+        goto Done;
+      }
+    }
+
+    Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr);
+  }
+
+Done:
+  return Status;
+}
+
+/**
+  Routine used to track statistical information about variable usage.
+  The data is stored in the EFI system table so it can be accessed later.
+  VariableInfo.efi can dump out the table. Only Boot Services variable
+  accesses are tracked by this code. The PcdVariableCollectStatistics
+  build flag controls if this feature is enabled.
+
+  A read that hits in the cache will have Read and Cache true for
+  the transaction. Data is allocated by this routine, but never
+  freed.
+
+  @param[in]      VariableName   Name of the Variable to track.
+  @param[in]      VendorGuid     Guid of the Variable to track.
+  @param[in]      Volatile       TRUE if volatile FALSE if non-volatile.
+  @param[in]      Read           TRUE if GetVariable() was called.
+  @param[in]      Write          TRUE if SetVariable() was called.
+  @param[in]      Delete         TRUE if deleted via SetVariable().
+  @param[in]      Cache          TRUE for a cache hit.
+  @param[in,out]  VariableInfo   Pointer to a pointer of VARIABLE_INFO_ENTRY structures.
+
+**/
+VOID
+UpdateVariableInfo (
+  IN  CHAR16                  *VariableName,
+  IN  EFI_GUID                *VendorGuid,
+  IN  BOOLEAN                 Volatile,
+  IN  BOOLEAN                 Read,
+  IN  BOOLEAN                 Write,
+  IN  BOOLEAN                 Delete,
+  IN  BOOLEAN                 Cache,
+  IN OUT VARIABLE_INFO_ENTRY  **VariableInfo
+  )
+{
+  VARIABLE_INFO_ENTRY   *Entry;
+
+  if (FeaturePcdGet (PcdVariableCollectStatistics)) {
+    if (VariableName == NULL || VendorGuid == NULL || VariableInfo == NULL) {
+      return;
+    }
+    if (AtRuntime ()) {
+      // Don't collect statistics at runtime.
+      return;
+    }
+
+    if (*VariableInfo == NULL) {
+      //
+      // On the first call allocate a entry and place a pointer to it in
+      // the EFI System Table.
+      //
+      *VariableInfo = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
+      ASSERT (*VariableInfo != NULL);
+
+      CopyGuid (&(*VariableInfo)->VendorGuid, VendorGuid);
+      (*VariableInfo)->Name = AllocateZeroPool (StrSize (VariableName));
+      ASSERT ((*VariableInfo)->Name != NULL);
+      StrCpyS ((*VariableInfo)->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName);
+      (*VariableInfo)->Volatile = Volatile;
+    }
+
+
+    for (Entry = (*VariableInfo); Entry != NULL; Entry = Entry->Next) {
+      if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {
+        if (StrCmp (VariableName, Entry->Name) == 0) {
+          if (Read) {
+            Entry->ReadCount++;
+          }
+          if (Write) {
+            Entry->WriteCount++;
+          }
+          if (Delete) {
+            Entry->DeleteCount++;
+          }
+          if (Cache) {
+            Entry->CacheCount++;
+          }
+
+          return;
+        }
+      }
+
+      if (Entry->Next == NULL) {
+        //
+        // If the entry is not in the table add it.
+        // Next iteration of the loop will fill in the data.
+        //
+        Entry->Next = AllocateZeroPool (sizeof (VARIABLE_INFO_ENTRY));
+        ASSERT (Entry->Next != NULL);
+
+        CopyGuid (&Entry->Next->VendorGuid, VendorGuid);
+        Entry->Next->Name = AllocateZeroPool (StrSize (VariableName));
+        ASSERT (Entry->Next->Name != NULL);
+        StrCpyS (Entry->Next->Name, StrSize(VariableName)/sizeof(CHAR16), VariableName);
+        Entry->Next->Volatile = Volatile;
+      }
+    }
+  }
+}
+
+/**
+  Initializes context needed for variable helpers.
+
+  @param[in]       AuthFormat          If true then indicates authenticated variables are supported
+
+  @retval          EFI_SUCCESS         Initialized successfully
+  @retval          Others              An error occurred during initialization
+**/
+EFI_STATUS
+EFIAPI
+InitVariableHelpers (
+  IN  BOOLEAN   AuthFormat
+  )
+{
+  mAuthFormat = AuthFormat;
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
index ec463d063e..bda531d104 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
@@ -30,6 +30,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #include <Guid/SmmVariableCommon.h>
 #include "Variable.h"
+#include "VariableNonVolatile.h"
+#include "VariableParsing.h"
 
 BOOLEAN                                              mAtRuntime              = FALSE;
 UINT8                                                *mVariableBufferPayload = NULL;
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 0a1888e5ef..5bf90039d6 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -13,7 +13,7 @@
 
   InitCommunicateBuffer() is really function to check the variable data size.
 
-Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -39,6 +39,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Guid/SmmVariableCommon.h>
 
 #include "PrivilegePolymorphic.h"
+#include "VariableParsing.h"
 
 EFI_HANDLE                       mHandle                    = NULL;
 EFI_SMM_VARIABLE_PROTOCOL       *mSmmVariable               = NULL;
-- 
2.16.2.windows.1


  reply	other threads:[~2019-09-26  4:51 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-26  4:50 [PATCH V1 0/5] UEFI Variable SMI Reduction Kubacki, Michael A
2019-09-26  4:50 ` Kubacki, Michael A [this message]
2019-09-27  8:17   ` [edk2-devel] [PATCH V1 1/5] MdeModulePkg/Variable: Consolidate common parsing functions Wu, Hao A
2019-09-27 17:31     ` Kubacki, Michael A
2019-09-26  4:50 ` [PATCH V1 2/5] MdeModulePkg VariableInfo: Always consider RT DXE and SMM stats Kubacki, Michael A
2019-09-26  4:50 ` [PATCH V1 3/5] MdeModulePkg/Variable: Add RT GetVariable() cache support Kubacki, Michael A
2019-09-26  4:50 ` [PATCH V1 4/5] MdeModulePkg/Variable: Add RT GetNextVariableName() " Kubacki, Michael A
2019-09-26  4:50 ` [PATCH V1 5/5] MdeModulePkg/VariableSmm: Remove unused SMI handler functions Kubacki, Michael A
2019-09-26 18:23 ` [PATCH V1 0/5] UEFI Variable SMI Reduction Laszlo Ersek
2019-09-26 20:29   ` Kubacki, Michael A
2019-09-26 22:35     ` Kubacki, Michael A
2019-09-30 22:43       ` Laszlo Ersek
2019-09-30 22:47         ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190926045046.34592-2-michael.a.kubacki@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox