]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg Variable: Merge from Auth Variable driver in SecurityPkg
authorStar Zeng <star.zeng@intel.com>
Wed, 1 Jul 2015 03:08:29 +0000 (03:08 +0000)
committerlzeng14 <lzeng14@Edk2>
Wed, 1 Jul 2015 03:08:29 +0000 (03:08 +0000)
What to do:
1. Merge from Auth Variable driver in SecurityPkg to Variable drive in
MdeModulePkg. Then the merged Variable driver in MdeModulePkg will
link to AuthVariableLib and TpmMeasurementLib.
AuthVariableLibNull and TpmMeasurementLibNull in MdeModulePkg
could be used for non auth variable support.
AuthVariableLib and DxeTpmMeasurementLib in SecurityPkg
may be used for auth variable support.

Why to do:
1. Remove code duplication and reduce maintenance effort.
After auth variable service separated from Auth Variable driver in SecurityPkg
to AuthVariableLib. The remaining code logic of Auth Variable driver in SecurityPkg
will be almost same with Variable driver in MdeModulePkg. Now it is to
merge them.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17765 6f19259b-4bc3-4df7-8a09-765794883524

16 files changed:
MdeModulePkg/Include/Guid/SmmVariableCommon.h
MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c [new file with mode: 0644]
MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c
MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.h
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c [new file with mode: 0644]
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.uni
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.uni
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmExtra.uni
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf

index e92ab7fe79a6f8c18c8678a4672a4d91798e081f..734eb19681e14e7be758a9cca7d5f0210a89d5cd 100644 (file)
@@ -2,12 +2,12 @@
   The file defined some common structures used for communicating between SMM variable module and SMM variable wrapper module.\r
 \r
 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials are licensed and made available under \r
-the terms and conditions of the BSD License that accompanies this distribution.  \r
+This program and the accompanying materials are licensed and made available under\r
+the terms and conditions of the BSD License that accompanies this distribution.\r
 The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php.                                            \r
+http://opensource.org/licenses/bsd-license.php.\r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \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
@@ -23,8 +23,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 extern EFI_GUID gSmmVariableWriteGuid;\r
 \r
 //\r
-// This structure is used for SMM variable. the collected statistics data is saved in SMRAM. It can be got from \r
-// SMI handler. The communication buffer should be: \r
+// This structure is used for SMM variable. the collected statistics data is saved in SMRAM. It can be got from\r
+// SMI handler. The communication buffer should be:\r
 // EFI_SMM_COMMUNICATE_HEADER + SMM_VARIABLE_COMMUNICATE_HEADER + payload.\r
 //\r
 typedef struct {\r
@@ -39,26 +39,26 @@ typedef struct {
 #define SMM_VARIABLE_FUNCTION_GET_VARIABLE            1\r
 //\r
 // The payload for this function is SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME.\r
-// \r
+//\r
 #define SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME  2\r
 //\r
 // The payload for this function is SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE.\r
-// \r
+//\r
 #define SMM_VARIABLE_FUNCTION_SET_VARIABLE            3\r
 //\r
 // The payload for this function is SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO.\r
-// \r
+//\r
 #define SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO     4\r
 //\r
 // It is a notify event, no extra payload for this function.\r
-// \r
+//\r
 #define SMM_VARIABLE_FUNCTION_READY_TO_BOOT           5\r
 //\r
 // It is a notify event, no extra payload for this function.\r
-// \r
+//\r
 #define SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE       6\r
 //\r
-// The payload for this function is VARIABLE_INFO_ENTRY. The GUID in EFI_SMM_COMMUNICATE_HEADER \r
+// The payload for this function is VARIABLE_INFO_ENTRY. The GUID in EFI_SMM_COMMUNICATE_HEADER\r
 // is gEfiSmmVariableProtocolGuid.\r
 //\r
 #define SMM_VARIABLE_FUNCTION_GET_STATISTICS          7\r
@@ -71,6 +71,8 @@ typedef struct {
 \r
 #define SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET  10\r
 \r
+#define SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE        11\r
+\r
 ///\r
 /// Size of SMM communicate header, without including the payload.\r
 ///\r
@@ -88,7 +90,7 @@ typedef struct {
   EFI_GUID    Guid;\r
   UINTN       DataSize;\r
   UINTN       NameSize;\r
-  UINT32      Attributes;  \r
+  UINT32      Attributes;\r
   CHAR16      Name[1];\r
 } SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE;\r
 \r
@@ -108,7 +110,7 @@ typedef struct {
   UINT64          MaximumVariableStorageSize;\r
   UINT64          RemainingVariableStorageSize;\r
   UINT64          MaximumVariableSize;\r
-  UINT32          Attributes; \r
+  UINT32          Attributes;\r
 } SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO;\r
 \r
 typedef SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE;\r
@@ -120,4 +122,8 @@ typedef struct {
   CHAR16                        Name[1];\r
 } SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY;\r
 \r
-#endif // _SMM_VARIABLE_COMMON_H_
\ No newline at end of file
+typedef struct {\r
+  UINTN                         VariablePayloadSize;\r
+} SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE;\r
+\r
+#endif // _SMM_VARIABLE_COMMON_H_\r
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c
new file mode 100644 (file)
index 0000000..2f92fae
--- /dev/null
@@ -0,0 +1,255 @@
+/** @file\r
+  Measure TrEE required variable.\r
+\r
+Copyright (c) 2013 - 2014, 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 <PiDxe.h>\r
+#include <Guid/ImageAuthentication.h>\r
+#include <IndustryStandard/UefiTcgPlatform.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/TpmMeasurementLib.h>\r
+\r
+typedef struct {\r
+  CHAR16                                 *VariableName;\r
+  EFI_GUID                               *VendorGuid;\r
+} VARIABLE_TYPE;\r
+\r
+VARIABLE_TYPE  mVariableType[] = {\r
+  {EFI_SECURE_BOOT_MODE_NAME,    &gEfiGlobalVariableGuid},\r
+  {EFI_PLATFORM_KEY_NAME,        &gEfiGlobalVariableGuid},\r
+  {EFI_KEY_EXCHANGE_KEY_NAME,    &gEfiGlobalVariableGuid},\r
+  {EFI_IMAGE_SECURITY_DATABASE,  &gEfiImageSecurityDatabaseGuid},\r
+  {EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid},\r
+};\r
+\r
+/**\r
+  This function will return if this variable is SecureBootPolicy Variable.\r
+\r
+  @param[in]  VariableName      A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+\r
+  @retval TRUE  This is SecureBootPolicy Variable\r
+  @retval FALSE This is not SecureBootPolicy Variable\r
+**/\r
+BOOLEAN\r
+IsSecureBootPolicyVariable (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  UINTN   Index;\r
+\r
+  for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) {\r
+    if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&\r
+        (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+/**\r
+  Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
+\r
+  @param[in]  VarName           A Null-terminated string that is the name of the vendor's variable.\r
+  @param[in]  VendorGuid        A unique identifier for the vendor.\r
+  @param[in]  VarData           The content of the variable data.\r
+  @param[in]  VarSize           The size of the variable data.\r
+\r
+  @retval EFI_SUCCESS           Operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Out of memory.\r
+  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+MeasureVariable (\r
+  IN      CHAR16                    *VarName,\r
+  IN      EFI_GUID                  *VendorGuid,\r
+  IN      VOID                      *VarData,\r
+  IN      UINTN                     VarSize\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             VarNameLength;\r
+  EFI_VARIABLE_DATA_TREE            *VarLog;\r
+  UINT32                            VarLogSize;\r
+\r
+  ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));\r
+\r
+  VarNameLength      = StrLen (VarName);\r
+  VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
+                        - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
+\r
+  VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize);\r
+  if (VarLog == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName));\r
+  VarLog->UnicodeNameLength  = VarNameLength;\r
+  VarLog->VariableDataLength = VarSize;\r
+  CopyMem (\r
+     VarLog->UnicodeName,\r
+     VarName,\r
+     VarNameLength * sizeof (*VarName)\r
+     );\r
+  if (VarSize != 0) {\r
+    CopyMem (\r
+       (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
+       VarData,\r
+       VarSize\r
+       );\r
+  }\r
+\r
+  DEBUG ((EFI_D_INFO, "AuthVariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY));\r
+  DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
+\r
+  Status = TpmMeasureAndLogData (\r
+             7,\r
+             EV_EFI_VARIABLE_DRIVER_CONFIG,\r
+             VarLog,\r
+             VarLogSize,\r
+             VarLog,\r
+             VarLogSize\r
+             );\r
+  FreePool (VarLog);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Returns the status whether get the variable success. The function retrieves\r
+  variable  through the UEFI Runtime Service GetVariable().  The\r
+  returned buffer is allocated using AllocatePool().  The caller is responsible\r
+  for freeing this buffer with FreePool().\r
+\r
+  This API is only invoked in boot time. It may NOT be invoked at runtime.\r
+\r
+  @param[in]  Name  The pointer to a Null-terminated Unicode string.\r
+  @param[in]  Guid  The pointer to an EFI_GUID structure\r
+  @param[out] Value The buffer point saved the variable info.\r
+  @param[out] Size  The buffer size of the variable.\r
+\r
+  @return EFI_OUT_OF_RESOURCES      Allocate buffer failed.\r
+  @return EFI_SUCCESS               Find the specified variable.\r
+  @return Others Errors             Return errors from call to gRT->GetVariable.\r
+\r
+**/\r
+EFI_STATUS\r
+InternalGetVariable (\r
+  IN CONST CHAR16    *Name,\r
+  IN CONST EFI_GUID  *Guid,\r
+  OUT VOID           **Value,\r
+  OUT UINTN          *Size\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       BufferSize;\r
+\r
+  //\r
+  // Try to get the variable size.\r
+  //\r
+  BufferSize = 0;\r
+  *Value     = NULL;\r
+  if (Size != NULL) {\r
+    *Size  = 0;\r
+  }\r
+\r
+  Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Allocate buffer to get the variable.\r
+  //\r
+  *Value = AllocatePool (BufferSize);\r
+  ASSERT (*Value != NULL);\r
+  if (*Value == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Get the variable data.\r
+  //\r
+  Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &BufferSize, *Value);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool(*Value);\r
+    *Value = NULL;\r
+  }\r
+\r
+  if (Size != NULL) {\r
+    *Size = BufferSize;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  SecureBoot Hook for SetVariable.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             VariableDataSize;\r
+  VOID                              *VariableData;\r
+\r
+  if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) {\r
+    return ;\r
+  }\r
+\r
+  //\r
+  // We should NOT use Data and DataSize here,because it may include signature,\r
+  // or is just partial with append attributes, or is deleted.\r
+  // We should GetVariable again, to get full variable content.\r
+  //\r
+  Status = InternalGetVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             &VariableData,\r
+             &VariableDataSize\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    VariableData     = NULL;\r
+    VariableDataSize = 0;\r
+  }\r
+\r
+  Status = MeasureVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             VariableData,\r
+             VariableDataSize\r
+             );\r
+  DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status));\r
+\r
+  if (VariableData != NULL) {\r
+    FreePool (VariableData);\r
+  }\r
+\r
+  return ;\r
+}\r
index 44c56e232f891dadeb73f5cb619b0d1d1d46afb8..616812ccd8d8f9ddcbdd6f9882545c30ba8c0a8a 100644 (file)
@@ -1,9 +1,8 @@
 /** @file\r
-  \r
   Handles non-volatile variable store garbage collection, using FTW\r
   (Fault Tolerant Write) protocol.\r
 \r
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2015, 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
@@ -50,7 +49,7 @@ GetLbaAndOffsetByAddress (
   Fvb     = NULL;\r
   *Lba    = (EFI_LBA) (-1);\r
   *Offset = 0;\r
-  \r
+\r
   //\r
   // Get the proper FVB protocol.\r
   //\r
index b2f557232765b7fe1b7f9f410a42e5e18c337c61..ab0c1d6324a0da0f1d32cfdf480773d12a458461 100644 (file)
@@ -2,12 +2,12 @@
   Implementation functions and structures for var check protocol.\r
 \r
 Copyright (c) 2015, 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
+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
+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
@@ -616,30 +616,49 @@ UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
   },\r
 };\r
 \r
-typedef struct {\r
-  EFI_GUID                      *Guid;\r
-  CHAR16                        *Name;\r
-  VAR_CHECK_VARIABLE_PROPERTY   VariableProperty;\r
-} VARIABLE_DRIVER_VARIABLE_ENTRY;\r
-\r
-VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {\r
+//\r
+// EFI_IMAGE_SECURITY_DATABASE_GUID\r
+//\r
+UEFI_DEFINED_VARIABLE_ENTRY mImageSecurityVariableList[] = {\r
   {\r
-    &gEdkiiVarErrorFlagGuid,\r
-    VAR_ERROR_FLAG_NAME,\r
+    EFI_IMAGE_SECURITY_DATABASE,\r
     {\r
       VAR_CHECK_VARIABLE_PROPERTY_REVISION,\r
-      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,\r
-      VARIABLE_ATTRIBUTE_NV_BS_RT,\r
-      sizeof (VAR_ERROR_FLAG),\r
-      sizeof (VAR_ERROR_FLAG),\r
-    }\r
+      0,\r
+      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,\r
+      1,\r
+      MAX_UINTN\r
+    },\r
+    NULL\r
+  },\r
+  {\r
+    EFI_IMAGE_SECURITY_DATABASE1,\r
+    {\r
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,\r
+      0,\r
+      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,\r
+      1,\r
+      MAX_UINTN\r
+    },\r
+    NULL\r
+  },\r
+  {\r
+    EFI_IMAGE_SECURITY_DATABASE2,\r
+    {\r
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,\r
+      0,\r
+      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,\r
+      1,\r
+      MAX_UINTN\r
+    },\r
+    NULL\r
   },\r
 };\r
 \r
 /**\r
-  Get UEFI defined global variable property.\r
-  The code will check if variable guid is global variable guid first.\r
-  If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2.\r
+  Get UEFI defined global variable or image security database variable property.\r
+  The code will check if variable guid is global variable or image security database guid first.\r
+  If yes, further check if variable name is in mGlobalVariableList, mGlobalVariableList2 or mImageSecurityVariableList.\r
 \r
   @param[in]  VariableName      Pointer to variable name.\r
   @param[in]  VendorGuid        Variable Vendor Guid.\r
@@ -647,8 +666,8 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
   @param[out] VariableProperty  Pointer to variable property.\r
   @param[out] VarCheckFunction  Pointer to check function.\r
 \r
-  @retval EFI_SUCCESS           Variable is not global variable.\r
-  @retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists.\r
+  @retval EFI_SUCCESS           Variable is not global variable or image security database variable.\r
+  @retval EFI_INVALID_PARAMETER Variable is global variable or image security database variable, but variable name is not in the lists.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -711,36 +730,24 @@ GetUefiDefinedVariableProperty (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  //\r
-  // It is not global variable.\r
-  //\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Get variable property for variables managed by Varaible driver.\r
-\r
-  @param[in]  VariableName      Pointer to variable name.\r
-  @param[in]  VendorGuid        Variable Vendor Guid.\r
-\r
-  @return Pointer to variable property.\r
-\r
-**/\r
-VAR_CHECK_VARIABLE_PROPERTY *\r
-GetVariableDriverVariableProperty (\r
-  IN CHAR16                         *VariableName,\r
-  IN EFI_GUID                       *VendorGuid\r
-  )\r
-{\r
-  UINTN     Index;\r
-\r
-  for (Index = 0; Index < sizeof (mVariableDriverVariableList)/sizeof (mVariableDriverVariableList[0]); Index++) {\r
-    if ((CompareGuid (mVariableDriverVariableList[Index].Guid, VendorGuid)) && (StrCmp (mVariableDriverVariableList[Index].Name, VariableName) == 0)) {\r
-      return &mVariableDriverVariableList[Index].VariableProperty;\r
+  if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid)) {\r
+    for (Index = 0; Index < sizeof (mImageSecurityVariableList)/sizeof (mImageSecurityVariableList[0]); Index++) {\r
+      if (StrCmp (mImageSecurityVariableList[Index].Name, VariableName) == 0) {\r
+        if (VarCheckFunction != NULL) {\r
+          *VarCheckFunction = mImageSecurityVariableList[Index].CheckFunction;\r
+        }\r
+        *VariableProperty = &mImageSecurityVariableList[Index].VariableProperty;\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
+\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  return NULL;\r
+  //\r
+  // It is not global variable, image security database variable.\r
+  //\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -799,13 +806,18 @@ InternalVarCheckSetVariableCheck (
       break;\r
     }\r
   }\r
-  if (Property == NULL) {\r
-    Property = GetVariableDriverVariableProperty (VariableName, VendorGuid);\r
-  }\r
   if (Property == NULL) {\r
     Status = GetUefiDefinedVariableProperty (VariableName, VendorGuid, TRUE, &Property, &VarCheckFunction);\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_INFO, "[Variable]: Var Check UEFI defined variable fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
+    //\r
+    // To prevent name collisions with possible future globally defined variables,\r
+    // other internal firmware data variables that are not defined here must be\r
+    // saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or\r
+    // any other GUID defined by the UEFI Specification. Implementations must\r
+    // only permit the creation of variables with a UEFI Specification-defined\r
+    // VendorGuid when these variables are documented in the UEFI Specification.\r
+    //\r
+      DEBUG ((EFI_D_INFO, "Variable Check UEFI defined variable fail %r - %s not in %g namespace\n", Status, VariableName, VendorGuid));\r
       return Status;\r
     }\r
   }\r
@@ -814,27 +826,29 @@ InternalVarCheckSetVariableCheck (
       DEBUG ((EFI_D_INFO, "[Variable]: Var Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));\r
       return EFI_WRITE_PROTECTED;\r
     }\r
-    if (!((DataSize == 0) || (Attributes == 0))) {\r
+    if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {\r
       //\r
       // Not to delete variable.\r
       //\r
-      if (Attributes != Property->Attributes) {\r
-        DEBUG ((EFI_D_INFO, "[Variable]: Var Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));\r
+      if ((Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes)) {\r
+        DEBUG ((EFI_D_INFO, "Variable Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));\r
         return EFI_INVALID_PARAMETER;\r
       }\r
-      if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {\r
-        DEBUG ((EFI_D_INFO, "[Variable]: Var Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-      if (VarCheckFunction != NULL) {\r
-        Status = VarCheckFunction (\r
-                   Property,\r
-                   DataSize,\r
-                   Data\r
-                   );\r
-        if (EFI_ERROR (Status)) {\r
-          DEBUG ((EFI_D_INFO, "[Variable]: Internal Var Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
-          return Status;\r
+      if (DataSize != 0) {\r
+        if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {\r
+          DEBUG ((EFI_D_INFO, "Variable Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+        if (VarCheckFunction != NULL) {\r
+          Status = VarCheckFunction (\r
+                     Property,\r
+                     DataSize,\r
+                     Data\r
+                     );\r
+          if (EFI_ERROR (Status)) {\r
+            DEBUG ((EFI_D_INFO, "Internal Variable Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
+            return Status;\r
+          }\r
         }\r
       }\r
     }\r
@@ -849,7 +863,7 @@ InternalVarCheckSetVariableCheck (
                Data\r
                );\r
     if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_INFO, "[Variable]: Var Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
+      DEBUG ((EFI_D_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
       return Status;\r
     }\r
   }\r
@@ -875,8 +889,8 @@ ReallocateHandlerTable (
   // Reallocate memory for check handler table.\r
   //\r
   HandlerTable = ReallocateRuntimePool (\r
-                     mMaxNumberOfHandler * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER), \r
-                     (mMaxNumberOfHandler + VAR_CHECK_HANDLER_TABLE_SIZE) * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER), \r
+                     mMaxNumberOfHandler * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),\r
+                     (mMaxNumberOfHandler + VAR_CHECK_HANDLER_TABLE_SIZE) * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),\r
                      mHandlerTable\r
                      );\r
 \r
@@ -927,6 +941,10 @@ VarCheckRegisterSetVariableCheckHandler (
 \r
   DEBUG ((EFI_D_INFO, "RegisterSetVariableCheckHandler - 0x%x\n", Handler));\r
 \r
+  Status = EFI_SUCCESS;\r
+\r
+  AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
   //\r
   // Check whether the handler list is enough to store new handler.\r
   //\r
@@ -936,7 +954,7 @@ VarCheckRegisterSetVariableCheckHandler (
     //\r
     Status = ReallocateHandlerTable();\r
     if (EFI_ERROR (Status)) {\r
-      return Status;\r
+      goto Done;\r
     }\r
   }\r
 \r
@@ -946,7 +964,10 @@ VarCheckRegisterSetVariableCheckHandler (
   mHandlerTable[mNumberOfHandler] = Handler;\r
   mNumberOfHandler++;\r
 \r
-  return EFI_SUCCESS;\r
+Done:\r
+  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
@@ -971,6 +992,8 @@ VariablePropertyGetFunction (
   CHAR16                        *VariableName;\r
   VAR_CHECK_VARIABLE_PROPERTY   *Property;\r
 \r
+  Property = NULL;\r
+\r
   for ( Link = GetFirstNode (&mVarCheckVariableList)\r
       ; !IsNull (&mVarCheckVariableList, Link)\r
       ; Link = GetNextNode (&mVarCheckVariableList, Link)\r
@@ -982,14 +1005,57 @@ VariablePropertyGetFunction (
     }\r
   }\r
 \r
-  Property = GetVariableDriverVariableProperty (Name, Guid);\r
-  if (Property == NULL) {\r
-    GetUefiDefinedVariableProperty (Name, Guid, WildcardMatch, &Property, NULL);\r
-  }\r
+  GetUefiDefinedVariableProperty (Name, Guid, WildcardMatch, &Property, NULL);\r
 \r
   return Property;\r
 }\r
 \r
+/**\r
+  Internal variable property set.\r
+\r
+  @param[in] Name               Pointer to the variable name.\r
+  @param[in] Guid               Pointer to the vendor GUID.\r
+  @param[in] VariableProperty   Pointer to the input variable property.\r
+\r
+  @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was set successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the variable property set request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalVarCheckVariablePropertySet (\r
+  IN CHAR16                         *Name,\r
+  IN EFI_GUID                       *Guid,\r
+  IN VAR_CHECK_VARIABLE_PROPERTY    *VariableProperty\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  VAR_CHECK_VARIABLE_ENTRY      *Entry;\r
+  CHAR16                        *VariableName;\r
+  VAR_CHECK_VARIABLE_PROPERTY   *Property;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  Property = VariablePropertyGetFunction (Name, Guid, FALSE);\r
+  if (Property != NULL) {\r
+    CopyMem (Property, VariableProperty, sizeof (*VariableProperty));\r
+  } else {\r
+    Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));\r
+    if (Entry == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+    VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));\r
+    StrnCpy (VariableName, Name, StrLen (Name));\r
+    CopyGuid (&Entry->Guid, Guid);\r
+    CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));\r
+    InsertTailList (&mVarCheckVariableList, &Entry->Link);\r
+  }\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
 /**\r
   Variable property set.\r
 \r
@@ -1014,9 +1080,6 @@ VarCheckVariablePropertySet (
   )\r
 {\r
   EFI_STATUS                    Status;\r
-  VAR_CHECK_VARIABLE_ENTRY      *Entry;\r
-  CHAR16                        *VariableName;\r
-  VAR_CHECK_VARIABLE_PROPERTY   *Property;\r
 \r
   if (Name == NULL || Name[0] == 0 || Guid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1034,27 +1097,10 @@ VarCheckVariablePropertySet (
     return EFI_ACCESS_DENIED;\r
   }\r
 \r
-  Status = EFI_SUCCESS;\r
-\r
   AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
-  Property = VariablePropertyGetFunction (Name, Guid, FALSE);\r
-  if (Property != NULL) {\r
-    CopyMem (Property, VariableProperty, sizeof (*VariableProperty));\r
-  } else {\r
-    Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));\r
-    if (Entry == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto Done;\r
-    }\r
-    VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));\r
-    StrnCpy (VariableName, Name, StrLen (Name));\r
-    CopyGuid (&Entry->Guid, Guid);\r
-    CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));\r
-    InsertTailList (&mVarCheckVariableList, &Entry->Link);\r
-  }\r
+  Status = InternalVarCheckVariablePropertySet (Name, Guid, VariableProperty);\r
 \r
-Done:\r
   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
   return Status;\r
index a4104cc228770738cd7056b722bb65fd85e4a6c6..70be71e7c76237dd6e454c66e777271e76d3f7dd 100644 (file)
@@ -1,8 +1,7 @@
 /** @file\r
-\r
-  The common variable operation routines shared by DXE_RUNTIME variable \r
+  The common variable operation routines shared by DXE_RUNTIME variable\r
   module and DXE_SMM variable module.\r
-  \r
+\r
   Caution: This module requires additional review when modified.\r
   This driver will have external input - variable data. They may be input in SMM mode.\r
   This external input must be validated carefully to avoid security issue like\r
   VariableServiceGetVariable() and VariableServiceSetVariable() are external API\r
   to receive datasize and data buffer. The size should be checked carefully.\r
 \r
+  VariableServiceSetVariable() should also check authenticate data to avoid buffer overflow,\r
+  integer overflow. It should also check attribute to avoid authentication bypass.\r
+\r
 Copyright (c) 2006 - 2015, 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
+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
+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
@@ -60,14 +62,59 @@ BOOLEAN                mEnableLocking         = TRUE;
 //\r
 VAR_ERROR_FLAG         mCurrentBootVarErrFlag = VAR_ERROR_FLAG_NO_ERROR;\r
 \r
+VARIABLE_ENTRY_PROPERTY mVariableEntryProperty[] = {\r
+  {\r
+    &gEdkiiVarErrorFlagGuid,\r
+    VAR_ERROR_FLAG_NAME,\r
+    {\r
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,\r
+      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,\r
+      VARIABLE_ATTRIBUTE_NV_BS_RT,\r
+      sizeof (VAR_ERROR_FLAG),\r
+      sizeof (VAR_ERROR_FLAG)\r
+    }\r
+  },\r
+};\r
+\r
+AUTH_VAR_LIB_CONTEXT_IN mContextIn = {\r
+  AUTH_VAR_LIB_CONTEXT_IN_STRUCT_VERSION,\r
+  sizeof (AUTH_VAR_LIB_CONTEXT_IN),\r
+  //\r
+  // MaxAuthVariableSize, TO BE FILLED\r
+  //\r
+  0,\r
+  VariableExLibFindVariable,\r
+  VariableExLibFindNextVariable,\r
+  VariableExLibUpdateVariable,\r
+  VariableExLibGetScratchBuffer,\r
+  VariableExLibCheckRemainingSpaceForConsistency,\r
+  VariableExLibAtRuntime,\r
+};\r
+\r
+AUTH_VAR_LIB_CONTEXT_OUT mContextOut;\r
+\r
 /**\r
-  Routine used to track statistical information about variable usage. \r
+\r
+  SecureBoot Hook for auth variable update.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  );\r
+\r
+/**\r
+  Routine used to track statistical information about variable usage.\r
   The data is stored in the EFI system table so it can be accessed later.\r
-  VariableInfo.efi can dump out the table. Only Boot Services variable \r
+  VariableInfo.efi can dump out the table. Only Boot Services variable\r
   accesses are tracked by this code. The PcdVariableCollectStatistics\r
-  build flag controls if this feature is enabled. \r
+  build flag controls if this feature is enabled.\r
 \r
-  A read that hits in the cache will have Read and Cache true for \r
+  A read that hits in the cache will have Read and Cache true for\r
   the transaction. Data is allocated by this routine, but never\r
   freed.\r
 \r
@@ -115,7 +162,7 @@ UpdateVariableInfo (
       gVariableInfo->Volatile = Volatile;\r
     }\r
 \r
-    \r
+\r
     for (Entry = gVariableInfo; Entry != NULL; Entry = Entry->Next) {\r
       if (CompareGuid (VendorGuid, &Entry->VendorGuid)) {\r
         if (StrCmp (VariableName, Entry->Name) == 0) {\r
@@ -236,7 +283,9 @@ UpdateVariableStore (
   // Check if the Data is Volatile.\r
   //\r
   if (!Volatile) {\r
-    ASSERT (Fvb != NULL);\r
+    if (Fvb == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
     Status = Fvb->GetPhysicalAddress(Fvb, &FvVolHdr);\r
     ASSERT_EFI_ERROR (Status);\r
 \r
@@ -265,14 +314,14 @@ UpdateVariableStore (
     if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
-    \r
+\r
     //\r
     // If Volatile Variable just do a simple mem copy.\r
-    //    \r
+    //\r
     CopyMem ((UINT8 *)(UINTN)DataPtr, Buffer, DataSize);\r
     return EFI_SUCCESS;\r
   }\r
-  \r
+\r
   //\r
   // If we are here we are dealing with Non-Volatile Variables.\r
   //\r
@@ -346,7 +395,8 @@ GetVariableStoreStatus (
   IN VARIABLE_STORE_HEADER *VarStoreHeader\r
   )\r
 {\r
-  if (CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid) &&\r
+  if ((CompareGuid (&VarStoreHeader->Signature, &gEfiAuthenticatedVariableGuid) ||\r
+       CompareGuid (&VarStoreHeader->Signature, &gEfiVariableGuid)) &&\r
       VarStoreHeader->Format == VARIABLE_STORE_FORMATTED &&\r
       VarStoreHeader->State == VARIABLE_STORE_HEALTHY\r
       ) {\r
@@ -367,6 +417,27 @@ GetVariableStoreStatus (
   }\r
 }\r
 \r
+/**\r
+  This code gets the size of variable header.\r
+\r
+  @return Size of variable header in bytes in type UINTN.\r
+\r
+**/\r
+UINTN\r
+GetVariableHeaderSize (\r
+  VOID\r
+  )\r
+{\r
+  UINTN Value;\r
+\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    Value = sizeof (AUTHENTICATED_VARIABLE_HEADER);\r
+  } else {\r
+    Value = sizeof (VARIABLE_HEADER);\r
+  }\r
+\r
+  return Value;\r
+}\r
 \r
 /**\r
 \r
@@ -382,13 +453,49 @@ NameSizeOfVariable (
   IN  VARIABLE_HEADER   *Variable\r
   )\r
 {\r
-  if (Variable->State    == (UINT8) (-1) ||\r
-      Variable->DataSize == (UINT32) (-1) ||\r
-      Variable->NameSize == (UINT32) (-1) ||\r
-      Variable->Attributes == (UINT32) (-1)) {\r
-    return 0;\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;\r
+\r
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    if (AuthVariable->State == (UINT8) (-1) ||\r
+       AuthVariable->DataSize == (UINT32) (-1) ||\r
+       AuthVariable->NameSize == (UINT32) (-1) ||\r
+       AuthVariable->Attributes == (UINT32) (-1)) {\r
+      return 0;\r
+    }\r
+    return (UINTN) AuthVariable->NameSize;\r
+  } else {\r
+    if (Variable->State == (UINT8) (-1) ||\r
+        Variable->DataSize == (UINT32) (-1) ||\r
+        Variable->NameSize == (UINT32) (-1) ||\r
+        Variable->Attributes == (UINT32) (-1)) {\r
+      return 0;\r
+    }\r
+    return (UINTN) Variable->NameSize;\r
+  }\r
+}\r
+\r
+/**\r
+  This code sets the size of name of variable.\r
+\r
+  @param[in] Variable   Pointer to the Variable Header.\r
+  @param[in] NameSize   Name size to set.\r
+\r
+**/\r
+VOID\r
+SetNameSizeOfVariable (\r
+  IN VARIABLE_HEADER    *Variable,\r
+  IN UINTN              NameSize\r
+  )\r
+{\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;\r
+\r
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    AuthVariable->NameSize = (UINT32) NameSize;\r
+  } else {\r
+    Variable->NameSize = (UINT32) NameSize;\r
   }\r
-  return (UINTN) Variable->NameSize;\r
 }\r
 \r
 /**\r
@@ -405,13 +512,49 @@ DataSizeOfVariable (
   IN  VARIABLE_HEADER   *Variable\r
   )\r
 {\r
-  if (Variable->State    == (UINT8)  (-1) ||\r
-      Variable->DataSize == (UINT32) (-1) ||\r
-      Variable->NameSize == (UINT32) (-1) ||\r
-      Variable->Attributes == (UINT32) (-1)) {\r
-    return 0;\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;\r
+\r
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    if (AuthVariable->State == (UINT8) (-1) ||\r
+       AuthVariable->DataSize == (UINT32) (-1) ||\r
+       AuthVariable->NameSize == (UINT32) (-1) ||\r
+       AuthVariable->Attributes == (UINT32) (-1)) {\r
+      return 0;\r
+    }\r
+    return (UINTN) AuthVariable->DataSize;\r
+  } else {\r
+    if (Variable->State == (UINT8) (-1) ||\r
+        Variable->DataSize == (UINT32) (-1) ||\r
+        Variable->NameSize == (UINT32) (-1) ||\r
+        Variable->Attributes == (UINT32) (-1)) {\r
+      return 0;\r
+    }\r
+    return (UINTN) Variable->DataSize;\r
+  }\r
+}\r
+\r
+/**\r
+  This code sets the size of variable data.\r
+\r
+  @param[in] Variable   Pointer to the Variable Header.\r
+  @param[in] DataSize   Data size to set.\r
+\r
+**/\r
+VOID\r
+SetDataSizeOfVariable (\r
+  IN VARIABLE_HEADER    *Variable,\r
+  IN UINTN              DataSize\r
+  )\r
+{\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;\r
+\r
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    AuthVariable->DataSize = (UINT32) DataSize;\r
+  } else {\r
+    Variable->DataSize = (UINT32) DataSize;\r
   }\r
-  return (UINTN) Variable->DataSize;\r
 }\r
 \r
 /**\r
@@ -428,8 +571,30 @@ GetVariableNamePtr (
   IN  VARIABLE_HEADER   *Variable\r
   )\r
 {\r
+  return (CHAR16 *) ((UINTN) Variable + GetVariableHeaderSize ());\r
+}\r
 \r
-  return (CHAR16 *) (Variable + 1);\r
+/**\r
+  This code gets the pointer to the variable guid.\r
+\r
+  @param Variable   Pointer to the Variable Header.\r
+\r
+  @return A EFI_GUID* pointer to Vendor Guid.\r
+\r
+**/\r
+EFI_GUID *\r
+GetVendorGuidPtr (\r
+  IN VARIABLE_HEADER    *Variable\r
+  )\r
+{\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;\r
+\r
+  AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    return &AuthVariable->VendorGuid;\r
+  } else {\r
+    return &Variable->VendorGuid;\r
+  }\r
 }\r
 \r
 /**\r
@@ -447,7 +612,7 @@ GetVariableDataPtr (
   )\r
 {\r
   UINTN Value;\r
-  \r
+\r
   //\r
   // Be careful about pad size for alignment.\r
   //\r
@@ -458,6 +623,30 @@ GetVariableDataPtr (
   return (UINT8 *) Value;\r
 }\r
 \r
+/**\r
+  This code gets the variable data offset related to variable header.\r
+\r
+  @param Variable        Pointer to the Variable Header.\r
+\r
+  @return Variable Data offset.\r
+\r
+**/\r
+UINTN\r
+GetVariableDataOffset (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  )\r
+{\r
+  UINTN Value;\r
+\r
+  //\r
+  // Be careful about pad size for alignment\r
+  //\r
+  Value = GetVariableHeaderSize ();\r
+  Value += NameSizeOfVariable (Variable);\r
+  Value += GET_PAD_SIZE (NameSizeOfVariable (Variable));\r
+\r
+  return Value;\r
+}\r
 \r
 /**\r
 \r
@@ -514,7 +703,7 @@ GetStartPointer (
 \r
   @param VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
-  @return Pointer to the end of the variable storage area. \r
+  @return Pointer to the end of the variable storage area.\r
 \r
 **/\r
 VARIABLE_HEADER *\r
@@ -657,7 +846,10 @@ InitializeVarErrorFlag (
     &Flag,\r
     sizeof (Flag),\r
     VARIABLE_ATTRIBUTE_NV_BS_RT,\r
-    &Variable\r
+    0,\r
+    0,\r
+    &Variable,\r
+    NULL\r
     );\r
 }\r
 \r
@@ -683,7 +875,7 @@ IsUserVariable (
   // then no need to check if the variable is user variable or not specially.\r
   //\r
   if (mEndOfDxe && (mVariableModuleGlobal->CommonMaxUserVariableSpace != mVariableModuleGlobal->CommonVariableSpace)) {\r
-    if (InternalVarCheckVariablePropertyGet (GetVariableNamePtr (Variable), &Variable->VendorGuid, &Property) == EFI_NOT_FOUND) {\r
+    if (InternalVarCheckVariablePropertyGet (GetVariableNamePtr (Variable), GetVendorGuidPtr (Variable), &Property) == EFI_NOT_FOUND) {\r
       return TRUE;\r
     }\r
   }\r
@@ -715,7 +907,7 @@ CalculateCommonUserVariableTotalSize (
       NextVariable = GetNextVariablePtr (Variable);\r
       VariableSize = (UINTN) NextVariable - (UINTN) Variable;\r
       if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
-        if (InternalVarCheckVariablePropertyGet (GetVariableNamePtr (Variable), &Variable->VendorGuid, &Property) == EFI_NOT_FOUND) {\r
+        if (InternalVarCheckVariablePropertyGet (GetVariableNamePtr (Variable), GetVendorGuidPtr (Variable), &Property) == EFI_NOT_FOUND) {\r
           //\r
           // No property, it is user variable.\r
           //\r
@@ -752,27 +944,27 @@ InitializeVariableQuota (
 \r
   Variable store garbage collection and reclaim operation.\r
 \r
-  @param VariableBase            Base address of variable store.\r
-  @param LastVariableOffset      Offset of last variable.\r
-  @param IsVolatile              The variable store is volatile or not;\r
-                                 if it is non-volatile, need FTW.\r
-  @param UpdatingPtrTrack        Pointer to updating variable pointer track structure.\r
-  @param NewVariable             Pointer to new variable.\r
-  @param NewVariableSize         New variable size.\r
+  @param[in]      VariableBase            Base address of variable store.\r
+  @param[out]     LastVariableOffset      Offset of last variable.\r
+  @param[in]      IsVolatile              The variable store is volatile or not;\r
+                                          if it is non-volatile, need FTW.\r
+  @param[in, out] UpdatingPtrTrack        Pointer to updating variable pointer track structure.\r
+  @param[in]      NewVariable             Pointer to new variable.\r
+  @param[in]      NewVariableSize         New variable size.\r
 \r
-  @return EFI_OUT_OF_RESOURCES\r
-  @return EFI_SUCCESS\r
-  @return Others\r
+  @return EFI_SUCCESS                  Reclaim operation has finished successfully.\r
+  @return EFI_OUT_OF_RESOURCES         No enough memory resources or variable space.\r
+  @return Others                       Unexpect error happened during reclaim operation.\r
 \r
 **/\r
 EFI_STATUS\r
 Reclaim (\r
-  IN  EFI_PHYSICAL_ADDRESS  VariableBase,\r
-  OUT UINTN                 *LastVariableOffset,\r
-  IN  BOOLEAN               IsVolatile,\r
-  IN OUT VARIABLE_POINTER_TRACK *UpdatingPtrTrack,\r
-  IN  VARIABLE_HEADER       *NewVariable,\r
-  IN  UINTN                 NewVariableSize\r
+  IN     EFI_PHYSICAL_ADDRESS         VariableBase,\r
+  OUT    UINTN                        *LastVariableOffset,\r
+  IN     BOOLEAN                      IsVolatile,\r
+  IN OUT VARIABLE_POINTER_TRACK       *UpdatingPtrTrack,\r
+  IN     VARIABLE_HEADER              *NewVariable,\r
+  IN     UINTN                        NewVariableSize\r
   )\r
 {\r
   VARIABLE_HEADER       *Variable;\r
@@ -863,7 +1055,7 @@ Reclaim (
 \r
   //\r
   // Reinstall all ADDED variables as long as they are not identical to Updating Variable.\r
-  // \r
+  //\r
   Variable = GetStartPointer (VariableStoreHeader);\r
   while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {\r
     NextVariable = GetNextVariablePtr (Variable);\r
@@ -885,24 +1077,24 @@ Reclaim (
 \r
   //\r
   // Reinstall all in delete transition variables.\r
-  // \r
+  //\r
   Variable = GetStartPointer (VariableStoreHeader);\r
   while (IsValidVariableHeader (Variable, GetEndPointer (VariableStoreHeader))) {\r
     NextVariable = GetNextVariablePtr (Variable);\r
     if (Variable != UpdatingVariable && Variable != UpdatingInDeletedTransition && Variable->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)) {\r
 \r
       //\r
-      // Buffer has cached all ADDED variable. \r
+      // Buffer has cached all ADDED variable.\r
       // Per IN_DELETED variable, we have to guarantee that\r
-      // no ADDED one in previous buffer. \r
-      // \r
-     \r
+      // no ADDED one in previous buffer.\r
+      //\r
+\r
       FoundAdded = FALSE;\r
       AddedVariable = GetStartPointer ((VARIABLE_STORE_HEADER *) ValidBuffer);\r
       while (IsValidVariableHeader (AddedVariable, GetEndPointer ((VARIABLE_STORE_HEADER *) ValidBuffer))) {\r
         NextAddedVariable = GetNextVariablePtr (AddedVariable);\r
         NameSize = NameSizeOfVariable (AddedVariable);\r
-        if (CompareGuid (&AddedVariable->VendorGuid, &Variable->VendorGuid) &&\r
+        if (CompareGuid (GetVendorGuidPtr (AddedVariable), GetVendorGuidPtr (Variable)) &&\r
             NameSize == NameSizeOfVariable (Variable)\r
            ) {\r
           Point0 = (VOID *) GetVariableNamePtr (AddedVariable);\r
@@ -1033,14 +1225,14 @@ Done:
 /**\r
   Find the variable in the specified variable store.\r
 \r
-  @param  VariableName        Name of the variable to be found\r
-  @param  VendorGuid          Vendor GUID to be found.\r
-  @param  IgnoreRtCheck       Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute\r
-                              check at runtime when searching variable.\r
-  @param  PtrTrack            Variable Track Pointer structure that contains Variable Information.\r
+  @param[in]       VariableName        Name of the variable to be found\r
+  @param[in]       VendorGuid          Vendor GUID to be found.\r
+  @param[in]       IgnoreRtCheck       Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute\r
+                                       check at runtime when searching variable.\r
+  @param[in, out]  PtrTrack            Variable Track Pointer structure that contains Variable Information.\r
 \r
-  @retval  EFI_SUCCESS            Variable found successfully\r
-  @retval  EFI_NOT_FOUND          Variable not found\r
+  @retval          EFI_SUCCESS         Variable found successfully\r
+  @retval          EFI_NOT_FOUND       Variable not found\r
 **/\r
 EFI_STATUS\r
 FindVariableEx (\r
@@ -1064,7 +1256,7 @@ FindVariableEx (
       ; IsValidVariableHeader (PtrTrack->CurrPtr, PtrTrack->EndPtr)\r
       ; PtrTrack->CurrPtr = GetNextVariablePtr (PtrTrack->CurrPtr)\r
       ) {\r
-    if (PtrTrack->CurrPtr->State == VAR_ADDED || \r
+    if (PtrTrack->CurrPtr->State == VAR_ADDED ||\r
         PtrTrack->CurrPtr->State == (VAR_IN_DELETED_TRANSITION & VAR_ADDED)\r
        ) {\r
       if (IgnoreRtCheck || !AtRuntime () || ((PtrTrack->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) != 0)) {\r
@@ -1076,7 +1268,7 @@ FindVariableEx (
             return EFI_SUCCESS;\r
           }\r
         } else {\r
-          if (CompareGuid (VendorGuid, &PtrTrack->CurrPtr->VendorGuid)) {\r
+          if (CompareGuid (VendorGuid, GetVendorGuidPtr (PtrTrack->CurrPtr))) {\r
             Point = (VOID *) GetVariableNamePtr (PtrTrack->CurrPtr);\r
 \r
             ASSERT (NameSizeOfVariable (PtrTrack->CurrPtr) != 0);\r
@@ -1109,14 +1301,14 @@ FindVariableEx (
   at runtime when searching existing variable, only VariableName and VendorGuid are compared.\r
   Otherwise, variables without EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.\r
 \r
-  @param  VariableName                Name of the variable to be found.\r
-  @param  VendorGuid                  Vendor GUID to be found.\r
-  @param  PtrTrack                    VARIABLE_POINTER_TRACK structure for output,\r
+  @param[in]   VariableName           Name of the variable to be found.\r
+  @param[in]   VendorGuid             Vendor GUID to be found.\r
+  @param[out]  PtrTrack               VARIABLE_POINTER_TRACK structure for output,\r
                                       including the range searched and the target position.\r
-  @param  Global                      Pointer to VARIABLE_GLOBAL structure, including\r
+  @param[in]   Global                 Pointer to VARIABLE_GLOBAL structure, including\r
                                       base of volatile variable storage area, base of\r
                                       NV variable storage area, and a lock.\r
-  @param  IgnoreRtCheck               Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute\r
+  @param[in]   IgnoreRtCheck          Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute\r
                                       check at runtime when searching variable.\r
 \r
   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
@@ -1202,7 +1394,7 @@ GetIndexFromSupportedLangCodes(
   IN  CHAR8            *SupportedLang,\r
   IN  CHAR8            *Lang,\r
   IN  BOOLEAN          Iso639Language\r
-  ) \r
+  )\r
 {\r
   UINTN    Index;\r
   UINTN    CompareLength;\r
@@ -1237,8 +1429,8 @@ GetIndexFromSupportedLangCodes(
       // Determine the length of the next language code in SupportedLang\r
       //\r
       for (CompareLength = 0; SupportedLang[CompareLength] != '\0' && SupportedLang[CompareLength] != ';'; CompareLength++);\r
-      \r
-      if ((CompareLength == LanguageLength) && \r
+\r
+      if ((CompareLength == LanguageLength) &&\r
           (AsciiStrnCmp (Lang, SupportedLang, CompareLength) == 0)) {\r
         //\r
         // Successfully find the index of Lang string in SupportedLang string.\r
@@ -1336,10 +1528,10 @@ GetLangFromSupportedLangCodes (
 }\r
 \r
 /**\r
-  Returns a pointer to an allocated buffer that contains the best matching language \r
-  from a set of supported languages.  \r
-  \r
-  This function supports both ISO 639-2 and RFC 4646 language codes, but language \r
+  Returns a pointer to an allocated buffer that contains the best matching language\r
+  from a set of supported languages.\r
+\r
+  This function supports both ISO 639-2 and RFC 4646 language codes, but language\r
   code types may not be mixed in a single call to this function. This function\r
   supports a variable argument list that allows the caller to pass in a prioritized\r
   list of language codes to test against all the language codes in SupportedLanguages.\r
@@ -1347,37 +1539,37 @@ GetLangFromSupportedLangCodes (
   If SupportedLanguages is NULL, then ASSERT().\r
 \r
   @param[in]  SupportedLanguages  A pointer to a Null-terminated ASCII string that\r
-                                  contains a set of language codes in the format \r
+                                  contains a set of language codes in the format\r
                                   specified by Iso639Language.\r
   @param[in]  Iso639Language      If TRUE, then all language codes are assumed to be\r
                                   in ISO 639-2 format.  If FALSE, then all language\r
                                   codes are assumed to be in RFC 4646 language format\r
-  @param[in]  ...                 A variable argument list that contains pointers to \r
+  @param[in]  ...                 A variable argument list that contains pointers to\r
                                   Null-terminated ASCII strings that contain one or more\r
                                   language codes in the format specified by Iso639Language.\r
                                   The first language code from each of these language\r
                                   code lists is used to determine if it is an exact or\r
-                                  close match to any of the language codes in \r
+                                  close match to any of the language codes in\r
                                   SupportedLanguages.  Close matches only apply to RFC 4646\r
                                   language codes, and the matching algorithm from RFC 4647\r
-                                  is used to determine if a close match is present.  If \r
+                                  is used to determine if a close match is present.  If\r
                                   an exact or close match is found, then the matching\r
                                   language code from SupportedLanguages is returned.  If\r
                                   no matches are found, then the next variable argument\r
-                                  parameter is evaluated.  The variable argument list \r
+                                  parameter is evaluated.  The variable argument list\r
                                   is terminated by a NULL.\r
 \r
   @retval NULL   The best matching language could not be found in SupportedLanguages.\r
-  @retval NULL   There are not enough resources available to return the best matching \r
+  @retval NULL   There are not enough resources available to return the best matching\r
                  language.\r
-  @retval Other  A pointer to a Null-terminated ASCII string that is the best matching \r
+  @retval Other  A pointer to a Null-terminated ASCII string that is the best matching\r
                  language in SupportedLanguages.\r
 \r
 **/\r
 CHAR8 *\r
 EFIAPI\r
 VariableGetBestLanguage (\r
-  IN CONST CHAR8  *SupportedLanguages, \r
+  IN CONST CHAR8  *SupportedLanguages,\r
   IN BOOLEAN      Iso639Language,\r
   ...\r
   )\r
@@ -1389,7 +1581,9 @@ VariableGetBestLanguage (
   CONST CHAR8  *Supported;\r
   CHAR8        *Buffer;\r
 \r
-  ASSERT (SupportedLanguages != NULL);\r
+  if (SupportedLanguages == NULL) {\r
+    return NULL;\r
+  }\r
 \r
   VA_START (Args, Iso639Language);\r
   while ((Language = VA_ARG (Args, CHAR8 *)) != NULL) {\r
@@ -1452,7 +1646,7 @@ VariableGetBestLanguage (
         LanguageLength = 0;\r
       } else {\r
         //\r
-        // If RFC 4646 mode, then trim Language from the right to the next '-' character \r
+        // If RFC 4646 mode, then trim Language from the right to the next '-' character\r
         //\r
         for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--);\r
       }\r
@@ -1461,7 +1655,7 @@ VariableGetBestLanguage (
   VA_END (Args);\r
 \r
   //\r
-  // No matches were found \r
+  // No matches were found\r
   //\r
   return NULL;\r
 }\r
@@ -1476,8 +1670,9 @@ VariableGetBestLanguage (
   so follow the argument sequence to check the Variables.\r
 \r
   @param[in] Attributes         Variable attributes for Variable entries.\r
-  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
-                                A NULL terminates the list. The VariableSize of \r
+  @param[in] Marker             VA_LIST style variable argument list.\r
+                                The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
+                                A NULL terminates the list. The VariableSize of\r
                                 VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.\r
                                 It will be changed to variable total size as output.\r
 \r
@@ -1487,9 +1682,9 @@ VariableGetBestLanguage (
 **/\r
 BOOLEAN\r
 EFIAPI\r
-CheckRemainingSpaceForConsistency (\r
+CheckRemainingSpaceForConsistencyInternal (\r
   IN UINT32                     Attributes,\r
-  ...\r
+  IN VA_LIST                    Marker\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -1520,7 +1715,7 @@ CheckRemainingSpaceForConsistency (
   ASSERT_EFI_ERROR (Status);\r
 \r
   TotalNeededSize = 0;\r
-  VA_START (Args, Attributes);\r
+  Args = Marker;\r
   VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   while (VariableEntry != NULL) {\r
     //\r
@@ -1530,12 +1725,11 @@ CheckRemainingSpaceForConsistency (
     VarNameSize += GET_PAD_SIZE (VarNameSize);\r
     VarDataSize  = VariableEntry->VariableSize;\r
     VarDataSize += GET_PAD_SIZE (VarDataSize);\r
-    VariableEntry->VariableSize = HEADER_ALIGN (sizeof (VARIABLE_HEADER) + VarNameSize + VarDataSize);\r
+    VariableEntry->VariableSize = HEADER_ALIGN (GetVariableHeaderSize () + VarNameSize + VarDataSize);\r
 \r
     TotalNeededSize += VariableEntry->VariableSize;\r
     VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   }\r
-  VA_END (Args);\r
 \r
   if (RemainingVariableStorageSize >= TotalNeededSize) {\r
     //\r
@@ -1550,7 +1744,7 @@ CheckRemainingSpaceForConsistency (
     return FALSE;\r
   }\r
 \r
-  VA_START (Args, Attributes);\r
+  Args = Marker;\r
   VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   while (VariableEntry != NULL) {\r
     //\r
@@ -1580,7 +1774,6 @@ CheckRemainingSpaceForConsistency (
       //\r
       // No enough space for Variable[Index].\r
       //\r
-      VA_END (Args);\r
       return FALSE;\r
     }\r
     //\r
@@ -1589,11 +1782,48 @@ CheckRemainingSpaceForConsistency (
     RemainingVariableStorageSize -= VariableEntry->VariableSize;\r
     VariableEntry = VA_ARG (Args, VARIABLE_ENTRY_CONSISTENCY *);\r
   }\r
-  VA_END (Args);\r
 \r
   return TRUE;\r
 }\r
 \r
+/**\r
+  This function is to check if the remaining variable space is enough to set\r
+  all Variables from argument list successfully. The purpose of the check\r
+  is to keep the consistency of the Variables to be in variable storage.\r
+\r
+  Note: Variables are assumed to be in same storage.\r
+  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,\r
+  so follow the argument sequence to check the Variables.\r
+\r
+  @param[in] Attributes         Variable attributes for Variable entries.\r
+  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
+                                A NULL terminates the list. The VariableSize of\r
+                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.\r
+                                It will be changed to variable total size as output.\r
+\r
+  @retval TRUE                  Have enough variable space to set the Variables successfully.\r
+  @retval FALSE                 No enough variable space to set the Variables successfully.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CheckRemainingSpaceForConsistency (\r
+  IN UINT32                     Attributes,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST Marker;\r
+  BOOLEAN Return;\r
+\r
+  VA_START (Marker, Attributes);\r
+\r
+  Return = CheckRemainingSpaceForConsistencyInternal (Attributes, Marker);\r
+\r
+  VA_END (Marker);\r
+\r
+  return Return;\r
+}\r
+\r
 /**\r
   Hook the operations in PlatformLangCodes, LangCodes, PlatformLang and Lang.\r
 \r
@@ -1660,7 +1890,7 @@ AutoUpdateLangVariable (
     ASSERT (mVariableModuleGlobal->PlatformLangCodes != NULL);\r
 \r
     //\r
-    // PlatformLang holds a single language from PlatformLangCodes, \r
+    // PlatformLang holds a single language from PlatformLangCodes,\r
     // so the size of PlatformLangCodes is enough for the PlatformLang.\r
     //\r
     if (mVariableModuleGlobal->PlatformLang != NULL) {\r
@@ -1690,7 +1920,7 @@ AutoUpdateLangVariable (
     ASSERT (mVariableModuleGlobal->LangCodes != NULL);\r
   }\r
 \r
-  if (SetLanguageCodes \r
+  if (SetLanguageCodes\r
       && (mVariableModuleGlobal->PlatformLangCodes != NULL)\r
       && (mVariableModuleGlobal->LangCodes != NULL)) {\r
     //\r
@@ -1704,7 +1934,7 @@ AutoUpdateLangVariable (
       //\r
       VariableName = EFI_PLATFORM_LANG_VARIABLE_NAME;\r
       Data         = GetVariableDataPtr (Variable.CurrPtr);\r
-      DataSize     = Variable.CurrPtr->DataSize;\r
+      DataSize     = DataSizeOfVariable (Variable.CurrPtr);\r
     } else {\r
       Status = FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
       if (!EFI_ERROR (Status)) {\r
@@ -1713,7 +1943,7 @@ AutoUpdateLangVariable (
         //\r
         VariableName = EFI_LANG_VARIABLE_NAME;\r
         Data         = GetVariableDataPtr (Variable.CurrPtr);\r
-        DataSize     = Variable.CurrPtr->DataSize;\r
+        DataSize     = DataSizeOfVariable (Variable.CurrPtr);\r
       } else {\r
         //\r
         // Neither PlatformLang nor Lang is set, directly return\r
@@ -1756,7 +1986,7 @@ AutoUpdateLangVariable (
         VariableEntry[0].VariableSize = ISO_639_2_ENTRY_SIZE + 1;\r
         VariableEntry[0].Guid = &gEfiGlobalVariableGuid;\r
         VariableEntry[0].Name = EFI_LANG_VARIABLE_NAME;\r
-        \r
+\r
         VariableEntry[1].VariableSize = AsciiStrSize (BestPlatformLang);\r
         VariableEntry[1].Guid = &gEfiGlobalVariableGuid;\r
         VariableEntry[1].Name = EFI_PLATFORM_LANG_VARIABLE_NAME;\r
@@ -1772,7 +2002,7 @@ AutoUpdateLangVariable (
           FindVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
 \r
           Status = UpdateVariable (EFI_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestLang,\r
-                                   ISO_639_2_ENTRY_SIZE + 1, Attributes, &Variable);\r
+                                   ISO_639_2_ENTRY_SIZE + 1, Attributes, 0, 0, &Variable, NULL);\r
         }\r
 \r
         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update PlatformLang, PlatformLang:%a, Lang:%a Status: %r\n", BestPlatformLang, BestLang, Status));\r
@@ -1820,8 +2050,8 @@ AutoUpdateLangVariable (
           //\r
           FindVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
 \r
-          Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang, \r
-                                   AsciiStrSize (BestPlatformLang), Attributes, &Variable);\r
+          Status = UpdateVariable (EFI_PLATFORM_LANG_VARIABLE_NAME, &gEfiGlobalVariableGuid, BestPlatformLang,\r
+                                   AsciiStrSize (BestPlatformLang), Attributes, 0, 0, &Variable, NULL);\r
         }\r
 \r
         DEBUG ((EFI_D_INFO, "Variable Driver Auto Update Lang, Lang:%a, PlatformLang:%a Status: %r\n", BestLang, BestPlatformLang, Status));\r
@@ -1840,16 +2070,51 @@ AutoUpdateLangVariable (
 }\r
 \r
 /**\r
-  Update the variable region with Variable information. These are the same \r
-  arguments as the EFI Variable services.\r
+  Compare two EFI_TIME data.\r
+\r
+\r
+  @param FirstTime           A pointer to the first EFI_TIME data.\r
+  @param SecondTime          A pointer to the second EFI_TIME data.\r
+\r
+  @retval  TRUE              The FirstTime is not later than the SecondTime.\r
+  @retval  FALSE             The FirstTime is later than the SecondTime.\r
+\r
+**/\r
+BOOLEAN\r
+VariableCompareTimeStampInternal (\r
+  IN EFI_TIME               *FirstTime,\r
+  IN EFI_TIME               *SecondTime\r
+  )\r
+{\r
+  if (FirstTime->Year != SecondTime->Year) {\r
+    return (BOOLEAN) (FirstTime->Year < SecondTime->Year);\r
+  } else if (FirstTime->Month != SecondTime->Month) {\r
+    return (BOOLEAN) (FirstTime->Month < SecondTime->Month);\r
+  } else if (FirstTime->Day != SecondTime->Day) {\r
+    return (BOOLEAN) (FirstTime->Day < SecondTime->Day);\r
+  } else if (FirstTime->Hour != SecondTime->Hour) {\r
+    return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour);\r
+  } else if (FirstTime->Minute != SecondTime->Minute) {\r
+    return (BOOLEAN) (FirstTime->Minute < SecondTime->Minute);\r
+  }\r
+\r
+  return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);\r
+}\r
+\r
+/**\r
+  Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set,\r
+  index of associated public key is needed.\r
 \r
   @param[in] VariableName       Name of variable.\r
   @param[in] VendorGuid         Guid of variable.\r
   @param[in] Data               Variable data.\r
   @param[in] DataSize           Size of data. 0 means delete.\r
-  @param[in] Attributes         Attribues of the variable.\r
+  @param[in] Attributes         Attributes of the variable.\r
+  @param[in] KeyIndex           Index of associated public key.\r
+  @param[in] MonotonicCount     Value of associated monotonic count.\r
   @param[in, out] CacheVariable The variable information which is used to keep track of variable usage.\r
-  \r
+  @param[in] TimeStamp          Value of associated TimeStamp.\r
+\r
   @retval EFI_SUCCESS           The update operation is success.\r
   @retval EFI_OUT_OF_RESOURCES  Variable region is full, can not write other data into this region.\r
 \r
@@ -1861,12 +2126,16 @@ UpdateVariable (
   IN      VOID                        *Data,\r
   IN      UINTN                       DataSize,\r
   IN      UINT32                      Attributes      OPTIONAL,\r
-  IN OUT  VARIABLE_POINTER_TRACK      *CacheVariable\r
+  IN      UINT32                      KeyIndex        OPTIONAL,\r
+  IN      UINT64                      MonotonicCount  OPTIONAL,\r
+  IN OUT  VARIABLE_POINTER_TRACK      *CacheVariable,\r
+  IN      EFI_TIME                    *TimeStamp      OPTIONAL\r
   )\r
 {\r
   EFI_STATUS                          Status;\r
   VARIABLE_HEADER                     *NextVariable;\r
   UINTN                               ScratchSize;\r
+  UINTN                               MaxDataSize;\r
   UINTN                               VarNameOffset;\r
   UINTN                               VarDataOffset;\r
   UINTN                               VarNameSize;\r
@@ -1878,15 +2147,32 @@ UpdateVariable (
   VARIABLE_POINTER_TRACK              NvVariable;\r
   VARIABLE_STORE_HEADER               *VariableStoreHeader;\r
   UINTN                               CacheOffset;\r
+  UINT8                               *BufferForMerge;\r
+  UINTN                               MergedBufSize;\r
+  BOOLEAN                             DataReady;\r
+  UINTN                               DataOffset;\r
   BOOLEAN                             IsCommonVariable;\r
   BOOLEAN                             IsCommonUserVariable;\r
+  AUTHENTICATED_VARIABLE_HEADER       *AuthVariable;\r
 \r
-  if ((mVariableModuleGlobal->FvbInstance == NULL) && ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {\r
+  if (mVariableModuleGlobal->FvbInstance == NULL) {\r
     //\r
-    // The FVB protocol is not ready. Trying to update NV variable prior to the installation\r
-    // of EFI_VARIABLE_WRITE_ARCH_PROTOCOL.\r
+    // The FVB protocol is not ready, so the EFI_VARIABLE_WRITE_ARCH_PROTOCOL is not installed.\r
     //\r
-    return EFI_NOT_AVAILABLE_YET;     \r
+    if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
+      //\r
+      // Trying to update NV variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Update NV variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r\n", EFI_NOT_AVAILABLE_YET));\r
+      return EFI_NOT_AVAILABLE_YET;\r
+    } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
+      //\r
+      // Trying to update volatile authenticated variable prior to the installation of EFI_VARIABLE_WRITE_ARCH_PROTOCOL\r
+      // The authenticated variable perhaps is not initialized, just return here.\r
+      //\r
+      DEBUG ((EFI_D_ERROR, "Update AUTH variable before EFI_VARIABLE_WRITE_ARCH_PROTOCOL ready - %r\n", EFI_NOT_AVAILABLE_YET));\r
+      return EFI_NOT_AVAILABLE_YET;\r
+    }\r
   }\r
 \r
   if ((CacheVariable->CurrPtr == NULL) || CacheVariable->Volatile) {\r
@@ -1898,7 +2184,7 @@ UpdateVariable (
     // Now let Variable points to the same variable in Flash area.\r
     //\r
     VariableStoreHeader  = (VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase);\r
-    Variable = &NvVariable;    \r
+    Variable = &NvVariable;\r
     Variable->StartPtr = GetStartPointer (VariableStoreHeader);\r
     Variable->EndPtr   = GetEndPointer (VariableStoreHeader);\r
     Variable->CurrPtr  = (VARIABLE_HEADER *)((UINTN)Variable->StartPtr + ((UINTN)CacheVariable->CurrPtr - (UINTN)CacheVariable->StartPtr));\r
@@ -1908,18 +2194,27 @@ UpdateVariable (
       Variable->InDeletedTransitionPtr = NULL;\r
     }\r
     Variable->Volatile = FALSE;\r
-  } \r
+  }\r
 \r
   Fvb       = mVariableModuleGlobal->FvbInstance;\r
 \r
+  //\r
+  // Tricky part: Use scratch data area at the end of volatile variable store\r
+  // as a temporary storage.\r
+  //\r
+  NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));\r
+  ScratchSize = mVariableModuleGlobal->ScratchBufferSize;\r
+  SetMem (NextVariable, ScratchSize, 0xff);\r
+  DataReady = FALSE;\r
+\r
   if (Variable->CurrPtr != NULL) {\r
     //\r
     // Update/Delete existing variable.\r
     //\r
-    if (AtRuntime ()) {        \r
+    if (AtRuntime ()) {\r
       //\r
-      // If AtRuntime and the variable is Volatile and Runtime Access,  \r
-      // the volatile is ReadOnly, and SetVariable should be aborted and \r
+      // If AtRuntime and the variable is Volatile and Runtime Access,\r
+      // the volatile is ReadOnly, and SetVariable should be aborted and\r
       // return EFI_WRITE_PROTECTED.\r
       //\r
       if (Variable->Volatile) {\r
@@ -1927,19 +2222,29 @@ UpdateVariable (
         goto Done;\r
       }\r
       //\r
-      // Only variable that have NV|RT attributes can be updated/deleted in Runtime.\r
+      // Only variable that have NV attributes can be updated/deleted in Runtime.\r
+      //\r
+      if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {\r
+        Status = EFI_INVALID_PARAMETER;\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Only variable that have RT attributes can be updated/deleted in Runtime.\r
       //\r
-      if (((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Variable->CurrPtr->Attributes & EFI_VARIABLE_NON_VOLATILE) == 0)) {\r
+      if ((Variable->CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {\r
         Status = EFI_INVALID_PARAMETER;\r
-        goto Done;      \r
+        goto Done;\r
       }\r
     }\r
 \r
     //\r
     // Setting a data variable with no access, or zero DataSize attributes\r
     // causes it to be deleted.\r
+    // When the EFI_VARIABLE_APPEND_WRITE attribute is set, DataSize of zero will\r
+    // not delete the variable.\r
     //\r
-    if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {    \r
+    if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0))|| ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0)) {\r
       if (Variable->InDeletedTransitionPtr != NULL) {\r
         //\r
         // Both ADDED and IN_DELETED_TRANSITION variable are present,\r
@@ -1977,7 +2282,7 @@ UpdateVariable (
                  (UINTN) &Variable->CurrPtr->State,\r
                  sizeof (UINT8),\r
                  &State\r
-                 ); \r
+                 );\r
       if (!EFI_ERROR (Status)) {\r
         UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, FALSE, TRUE, FALSE);\r
         if (!Variable->Volatile) {\r
@@ -1985,21 +2290,72 @@ UpdateVariable (
           FlushHobVariableToFlash (VariableName, VendorGuid);\r
         }\r
       }\r
-      goto Done;     \r
+      goto Done;\r
     }\r
     //\r
     // If the variable is marked valid, and the same data has been passed in,\r
     // then return to the caller immediately.\r
     //\r
     if (DataSizeOfVariable (Variable->CurrPtr) == DataSize &&\r
-        (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0)) {\r
-      \r
+        (CompareMem (Data, GetVariableDataPtr (Variable->CurrPtr), DataSize) == 0) &&\r
+        ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) &&\r
+        (TimeStamp == NULL)) {\r
+      //\r
+      // Variable content unchanged and no need to update timestamp, just return.\r
+      //\r
       UpdateVariableInfo (VariableName, VendorGuid, Variable->Volatile, FALSE, TRUE, FALSE, FALSE);\r
       Status = EFI_SUCCESS;\r
       goto Done;\r
     } else if ((Variable->CurrPtr->State == VAR_ADDED) ||\r
                (Variable->CurrPtr->State == (VAR_ADDED & VAR_IN_DELETED_TRANSITION))) {\r
 \r
+      //\r
+      // EFI_VARIABLE_APPEND_WRITE attribute only effects for existing variable.\r
+      //\r
+      if ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0) {\r
+        //\r
+        // NOTE: From 0 to DataOffset of NextVariable is reserved for Variable Header and Name.\r
+        // From DataOffset of NextVariable is to save the existing variable data.\r
+        //\r
+        DataOffset = GetVariableDataOffset (Variable->CurrPtr);\r
+        BufferForMerge = (UINT8 *) ((UINTN) NextVariable + DataOffset);\r
+        CopyMem (BufferForMerge, (UINT8 *) ((UINTN) Variable->CurrPtr + DataOffset), DataSizeOfVariable (Variable->CurrPtr));\r
+\r
+        //\r
+        // Set Max Common/Auth Variable Data Size as default MaxDataSize.\r
+        //\r
+        if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
+          MaxDataSize = mVariableModuleGlobal->MaxAuthVariableSize - DataOffset;\r
+        } else {\r
+          MaxDataSize = mVariableModuleGlobal->MaxVariableSize - DataOffset;\r
+        }\r
+\r
+        //\r
+        // Append the new data to the end of existing data.\r
+        // Max Harware error record variable data size is different from common/auth variable.\r
+        //\r
+        if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
+          MaxDataSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - DataOffset;\r
+        }\r
+\r
+        if (DataSizeOfVariable (Variable->CurrPtr) + DataSize > MaxDataSize) {\r
+          //\r
+          // Existing data size + new data size exceed maximum variable size limitation.\r
+          //\r
+          Status = EFI_INVALID_PARAMETER;\r
+          goto Done;\r
+        }\r
+        CopyMem ((UINT8*) ((UINTN) BufferForMerge + DataSizeOfVariable (Variable->CurrPtr)), Data, DataSize);\r
+        MergedBufSize = DataSizeOfVariable (Variable->CurrPtr) + DataSize;\r
+\r
+        //\r
+        // BufferForMerge(from DataOffset of NextVariable) has included the merged existing and new data.\r
+        //\r
+        Data      = BufferForMerge;\r
+        DataSize  = MergedBufSize;\r
+        DataReady = TRUE;\r
+      }\r
+\r
       //\r
       // Mark the old variable as in delete transition.\r
       //\r
@@ -2014,28 +2370,33 @@ UpdateVariable (
                  (UINTN) &Variable->CurrPtr->State,\r
                  sizeof (UINT8),\r
                  &State\r
-                 );      \r
+                 );\r
       if (EFI_ERROR (Status)) {\r
-        goto Done;  \r
-      } \r
+        goto Done;\r
+      }\r
       if (!Variable->Volatile) {\r
         CacheVariable->CurrPtr->State = State;\r
       }\r
-    }    \r
+    }\r
   } else {\r
     //\r
     // Not found existing variable. Create a new variable.\r
-    //  \r
-    \r
+    //\r
+\r
+    if ((DataSize == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) != 0)) {\r
+      Status = EFI_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
     //\r
     // Make sure we are trying to create a new variable.\r
-    // Setting a data variable with zero DataSize or no access attributes means to delete it.    \r
+    // Setting a data variable with zero DataSize or no access attributes means to delete it.\r
     //\r
     if (DataSize == 0 || (Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == 0) {\r
       Status = EFI_NOT_FOUND;\r
       goto Done;\r
     }\r
-        \r
+\r
     //\r
     // Only variable have NV|RT attribute can be created in Runtime.\r
     //\r
@@ -2043,29 +2404,50 @@ UpdateVariable (
         (((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) || ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0))) {\r
       Status = EFI_INVALID_PARAMETER;\r
       goto Done;\r
-    }         \r
+    }\r
   }\r
 \r
   //\r
   // Function part - create a new variable and copy the data.\r
   // Both update a variable and create a variable will come here.\r
-\r
-  //\r
-  // Tricky part: Use scratch data area at the end of volatile variable store\r
-  // as a temporary storage.\r
   //\r
-  NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));\r
-  ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
-\r
-  SetMem (NextVariable, ScratchSize, 0xff);\r
-\r
   NextVariable->StartId     = VARIABLE_DATA;\r
-  NextVariable->Attributes  = Attributes;\r
   //\r
   // NextVariable->State = VAR_ADDED;\r
   //\r
   NextVariable->Reserved        = 0;\r
-  VarNameOffset                 = sizeof (VARIABLE_HEADER);\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) NextVariable;\r
+    AuthVariable->PubKeyIndex    = KeyIndex;\r
+    AuthVariable->MonotonicCount = MonotonicCount;\r
+    ZeroMem (&AuthVariable->TimeStamp, sizeof (EFI_TIME));\r
+\r
+    if (((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) &&\r
+        (TimeStamp != NULL)) {\r
+      if ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) {\r
+        CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));\r
+      } else {\r
+        //\r
+        // In the case when the EFI_VARIABLE_APPEND_WRITE attribute is set, only\r
+        // when the new TimeStamp value is later than the current timestamp associated\r
+        // with the variable, we need associate the new timestamp with the updated value.\r
+        //\r
+        if (Variable->CurrPtr != NULL) {\r
+          if (VariableCompareTimeStampInternal (&(((AUTHENTICATED_VARIABLE_HEADER *) Variable->CurrPtr)->TimeStamp), TimeStamp)) {\r
+            CopyMem (&AuthVariable->TimeStamp, TimeStamp, sizeof (EFI_TIME));\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // The EFI_VARIABLE_APPEND_WRITE attribute will never be set in the returned\r
+  // Attributes bitmask parameter of a GetVariable() call.\r
+  //\r
+  NextVariable->Attributes  = Attributes & (~EFI_VARIABLE_APPEND_WRITE);\r
+\r
+  VarNameOffset                 = GetVariableHeaderSize ();\r
   VarNameSize                   = StrSize (VariableName);\r
   CopyMem (\r
     (UINT8 *) ((UINTN) NextVariable + VarNameOffset),\r
@@ -2073,19 +2455,27 @@ UpdateVariable (
     VarNameSize\r
     );\r
   VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize);\r
-  CopyMem (\r
-    (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
-    Data,\r
-    DataSize\r
-    );\r
-  CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // If DataReady is TRUE, it means the variable data has been saved into\r
+  // NextVariable during EFI_VARIABLE_APPEND_WRITE operation preparation.\r
+  //\r
+  if (!DataReady) {\r
+    CopyMem (\r
+      (UINT8 *) ((UINTN) NextVariable + VarDataOffset),\r
+      Data,\r
+      DataSize\r
+      );\r
+  }\r
+\r
+  CopyMem (GetVendorGuidPtr (NextVariable), VendorGuid, sizeof (EFI_GUID));\r
   //\r
   // There will be pad bytes after Data, the NextVariable->NameSize and\r
   // NextVariable->DataSize should not include pad size so that variable\r
   // service can get actual size in GetVariable.\r
   //\r
-  NextVariable->NameSize  = (UINT32)VarNameSize;\r
-  NextVariable->DataSize  = (UINT32)DataSize;\r
+  SetNameSizeOfVariable (NextVariable, VarNameSize);\r
+  SetDataSizeOfVariable (NextVariable, DataSize);\r
 \r
   //\r
   // The actual size of the variable that stores in storage should\r
@@ -2122,8 +2512,14 @@ UpdateVariable (
       //\r
       // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.\r
       //\r
-      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase, \r
-                        &mVariableModuleGlobal->NonVolatileLastVariableOffset, FALSE, Variable, NextVariable, HEADER_ALIGN (VarSize));\r
+      Status = Reclaim (\r
+                 mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
+                 &mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
+                 FALSE,\r
+                 Variable,\r
+                 NextVariable,\r
+                 HEADER_ALIGN (VarSize)\r
+                 );\r
       if (!EFI_ERROR (Status)) {\r
         //\r
         // The new variable has been integrated successfully during reclaiming.\r
@@ -2147,7 +2543,7 @@ UpdateVariable (
     //\r
     // Four steps\r
     // 1. Write variable header\r
-    // 2. Set variable state to header valid  \r
+    // 2. Set variable state to header valid\r
     // 3. Write variable data\r
     // 4. Set variable state to valid\r
     //\r
@@ -2161,7 +2557,7 @@ UpdateVariable (
                TRUE,\r
                Fvb,\r
                mVariableModuleGlobal->NonVolatileLastVariableOffset,\r
-               sizeof (VARIABLE_HEADER),\r
+               (UINT32) GetVariableHeaderSize (),\r
                (UINT8 *) NextVariable\r
                );\r
 \r
@@ -2194,9 +2590,9 @@ UpdateVariable (
                FALSE,\r
                TRUE,\r
                Fvb,\r
-               mVariableModuleGlobal->NonVolatileLastVariableOffset + sizeof (VARIABLE_HEADER),\r
-               (UINT32) VarSize - sizeof (VARIABLE_HEADER),\r
-               (UINT8 *) NextVariable + sizeof (VARIABLE_HEADER)\r
+               mVariableModuleGlobal->NonVolatileLastVariableOffset + GetVariableHeaderSize (),\r
+               (UINT32) (VarSize - GetVariableHeaderSize ()),\r
+               (UINT8 *) NextVariable + GetVariableHeaderSize ()\r
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
@@ -2237,7 +2633,7 @@ UpdateVariable (
   } else {\r
     //\r
     // Create a volatile variable.\r
-    //      \r
+    //\r
     Volatile = TRUE;\r
 \r
     if ((UINT32) (VarSize + mVariableModuleGlobal->VolatileLastVariableOffset) >\r
@@ -2245,8 +2641,14 @@ UpdateVariable (
       //\r
       // Perform garbage collection & reclaim operation, and integrate the new variable at the same time.\r
       //\r
-      Status = Reclaim (mVariableModuleGlobal->VariableGlobal.VolatileVariableBase, \r
-                          &mVariableModuleGlobal->VolatileLastVariableOffset, TRUE, Variable, NextVariable, HEADER_ALIGN (VarSize));\r
+      Status = Reclaim (\r
+                 mVariableModuleGlobal->VariableGlobal.VolatileVariableBase,\r
+                 &mVariableModuleGlobal->VolatileLastVariableOffset,\r
+                 TRUE,\r
+                 Variable,\r
+                 NextVariable,\r
+                 HEADER_ALIGN (VarSize)\r
+                 );\r
       if (!EFI_ERROR (Status)) {\r
         //\r
         // The new variable has been integrated successfully during reclaiming.\r
@@ -2320,7 +2722,7 @@ UpdateVariable (
              sizeof (UINT8),\r
              &State\r
              );\r
-    if (!EFI_ERROR (Status) && !Variable->Volatile) {         \r
+    if (!EFI_ERROR (Status) && !Variable->Volatile) {\r
       CacheVariable->CurrPtr->State = State;\r
     }\r
   }\r
@@ -2339,8 +2741,8 @@ Done:
 /**\r
   Check if a Unicode character is a hexadecimal character.\r
 \r
-  This function checks if a Unicode character is a \r
-  hexadecimal character.  The valid hexadecimal character is \r
+  This function checks if a Unicode character is a\r
+  hexadecimal character.  The valid hexadecimal character is\r
   L'0' to L'9', L'a' to L'f', or L'A' to L'F'.\r
 \r
 \r
@@ -2396,6 +2798,7 @@ IsHwErrRecVariable (
 /**\r
   Mark a variable that will become read-only after leaving the DXE phase of execution.\r
 \r
+\r
   @param[in] This          The VARIABLE_LOCK_PROTOCOL instance.\r
   @param[in] VariableName  A pointer to the variable name that will be made read-only subsequently.\r
   @param[in] VendorGuid    A pointer to the vendor GUID that will be made read-only subsequently.\r
@@ -2474,7 +2877,7 @@ Done:
   @param DataSize                   Size of Data found. If size is less than the\r
                                     data, this value contains the required size.\r
   @param Data                       Data pointer.\r
-                      \r
+\r
   @return EFI_INVALID_PARAMETER     Invalid parameter.\r
   @return EFI_SUCCESS               Find the specified variable.\r
   @return EFI_NOT_FOUND             Not found.\r
@@ -2500,7 +2903,7 @@ VariableServiceGetVariable (
   }\r
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
-  \r
+\r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
@@ -2525,7 +2928,7 @@ VariableServiceGetVariable (
 \r
     *DataSize = VarDataSize;\r
     UpdateVariableInfo (VariableName, VendorGuid, Variable.Volatile, TRUE, FALSE, FALSE, FALSE);\r
\r
+\r
     Status = EFI_SUCCESS;\r
     goto Done;\r
   } else {\r
@@ -2539,47 +2942,35 @@ Done:
   return Status;\r
 }\r
 \r
-\r
-\r
 /**\r
-\r
   This code Finds the Next available variable.\r
 \r
   Caution: This function may receive untrusted input.\r
   This function may be invoked in SMM mode. This function will do basic validation, before parse the data.\r
 \r
-  @param VariableNameSize           Size of the variable name.\r
-  @param VariableName               Pointer to variable name.\r
-  @param VendorGuid                 Variable Vendor Guid.\r
+  @param[in]  VariableName  Pointer to variable name.\r
+  @param[in]  VendorGuid    Variable Vendor Guid.\r
+  @param[out] VariablePtr   Pointer to variable header address.\r
 \r
-  @return EFI_INVALID_PARAMETER     Invalid parameter.\r
-  @return EFI_SUCCESS               Find the specified variable.\r
-  @return EFI_NOT_FOUND             Not found.\r
-  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.\r
+  @return EFI_SUCCESS       Find the specified variable.\r
+  @return EFI_NOT_FOUND     Not found.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-VariableServiceGetNextVariableName (\r
-  IN OUT  UINTN             *VariableNameSize,\r
-  IN OUT  CHAR16            *VariableName,\r
-  IN OUT  EFI_GUID          *VendorGuid\r
+VariableServiceGetNextVariableInternal (\r
+  IN  CHAR16                *VariableName,\r
+  IN  EFI_GUID              *VendorGuid,\r
+  OUT VARIABLE_HEADER       **VariablePtr\r
   )\r
 {\r
   VARIABLE_STORE_TYPE     Type;\r
   VARIABLE_POINTER_TRACK  Variable;\r
   VARIABLE_POINTER_TRACK  VariableInHob;\r
   VARIABLE_POINTER_TRACK  VariablePtrTrack;\r
-  UINTN                   VarNameSize;\r
   EFI_STATUS              Status;\r
   VARIABLE_STORE_HEADER   *VariableStoreHeader[VariableStoreTypeMax];\r
 \r
-  if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
-\r
   Status = FindVariable (VariableName, VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
   if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) {\r
     goto Done;\r
@@ -2624,7 +3015,7 @@ VariableServiceGetNextVariableName (
         }\r
       }\r
       //\r
-      // Capture the case that \r
+      // Capture the case that\r
       // 1. current storage is the last one, or\r
       // 2. no further storage\r
       //\r
@@ -2652,7 +3043,7 @@ VariableServiceGetNextVariableName (
           VariablePtrTrack.EndPtr = Variable.EndPtr;\r
           Status = FindVariableEx (\r
                      GetVariableNamePtr (Variable.CurrPtr),\r
-                     &Variable.CurrPtr->VendorGuid,\r
+                     GetVendorGuidPtr (Variable.CurrPtr),\r
                      FALSE,\r
                      &VariablePtrTrack\r
                      );\r
@@ -2665,14 +3056,14 @@ VariableServiceGetNextVariableName (
         //\r
         // Don't return NV variable when HOB overrides it\r
         //\r
-        if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) && \r
+        if ((VariableStoreHeader[VariableStoreTypeHob] != NULL) && (VariableStoreHeader[VariableStoreTypeNv] != NULL) &&\r
             (Variable.StartPtr == GetStartPointer (VariableStoreHeader[VariableStoreTypeNv]))\r
            ) {\r
           VariableInHob.StartPtr = GetStartPointer (VariableStoreHeader[VariableStoreTypeHob]);\r
           VariableInHob.EndPtr   = GetEndPointer   (VariableStoreHeader[VariableStoreTypeHob]);\r
           Status = FindVariableEx (\r
                      GetVariableNamePtr (Variable.CurrPtr),\r
-                     &Variable.CurrPtr->VendorGuid,\r
+                     GetVendorGuidPtr (Variable.CurrPtr),\r
                      FALSE,\r
                      &VariableInHob\r
                      );\r
@@ -2682,18 +3073,8 @@ VariableServiceGetNextVariableName (
           }\r
         }\r
 \r
-        VarNameSize = NameSizeOfVariable (Variable.CurrPtr);\r
-        ASSERT (VarNameSize != 0);\r
-\r
-        if (VarNameSize <= *VariableNameSize) {\r
-          CopyMem (VariableName, GetVariableNamePtr (Variable.CurrPtr), VarNameSize);\r
-          CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID));\r
-          Status = EFI_SUCCESS;\r
-        } else {\r
-          Status = EFI_BUFFER_TOO_SMALL;\r
-        }\r
-\r
-        *VariableNameSize = VarNameSize;\r
+        *VariablePtr = Variable.CurrPtr;\r
+        Status = EFI_SUCCESS;\r
         goto Done;\r
       }\r
     }\r
@@ -2702,6 +3083,59 @@ VariableServiceGetNextVariableName (
   }\r
 \r
 Done:\r
+  return Status;\r
+}\r
+\r
+/**\r
+\r
+  This code Finds the Next available variable.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.\r
+\r
+  @param VariableNameSize           Size of the variable name.\r
+  @param VariableName               Pointer to variable name.\r
+  @param VendorGuid                 Variable Vendor Guid.\r
+\r
+  @return EFI_INVALID_PARAMETER     Invalid parameter.\r
+  @return EFI_SUCCESS               Find the specified variable.\r
+  @return EFI_NOT_FOUND             Not found.\r
+  @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceGetNextVariableName (\r
+  IN OUT  UINTN             *VariableNameSize,\r
+  IN OUT  CHAR16            *VariableName,\r
+  IN OUT  EFI_GUID          *VendorGuid\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  UINTN                   VarNameSize;\r
+  VARIABLE_HEADER         *VariablePtr;\r
+\r
+  if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
+\r
+  Status = VariableServiceGetNextVariableInternal (VariableName, VendorGuid, &VariablePtr);\r
+  if (!EFI_ERROR (Status)) {\r
+    VarNameSize = NameSizeOfVariable (VariablePtr);\r
+    ASSERT (VarNameSize != 0);\r
+    if (VarNameSize <= *VariableNameSize) {\r
+      CopyMem (VariableName, GetVariableNamePtr (VariablePtr), VarNameSize);\r
+      CopyMem (VendorGuid, GetVendorGuidPtr (VariablePtr), sizeof (EFI_GUID));\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+    }\r
+\r
+    *VariableNameSize = VarNameSize;\r
+  }\r
+\r
   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
   return Status;\r
 }\r
@@ -2713,6 +3147,9 @@ Done:
   Caution: This function may receive untrusted input.\r
   This function may be invoked in SMM mode, and datasize and data are external input.\r
   This function will do basic validation, before parse the data.\r
+  This function will parse the authentication carefully to avoid security issues, like\r
+  buffer overflow, integer overflow.\r
+  This function will check attribute carefully to avoid authentication bypass.\r
 \r
   @param VariableName                     Name of Variable to be found.\r
   @param VendorGuid                       Variable vendor GUID.\r
@@ -2742,6 +3179,7 @@ VariableServiceSetVariable (
   EFI_STATUS                          Status;\r
   VARIABLE_HEADER                     *NextVariable;\r
   EFI_PHYSICAL_ADDRESS                Point;\r
+  UINTN                               PayloadSize;\r
   LIST_ENTRY                          *Link;\r
   VARIABLE_ENTRY                      *Entry;\r
   CHAR16                              *Name;\r
@@ -2751,16 +3189,16 @@ VariableServiceSetVariable (
   //\r
   if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
-  } \r
+  }\r
 \r
   if (DataSize != 0 && Data == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
-  // Not support authenticated or append variable write yet.\r
+  // Check for reserverd bit in variable attribute.\r
   //\r
-  if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) {\r
+  if ((Attributes & (~EFI_VARIABLE_ATTRIBUTES_MASK)) != 0) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -2769,22 +3207,67 @@ VariableServiceSetVariable (
   //\r
   if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS) {\r
     return EFI_INVALID_PARAMETER;\r
+  } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
+    if (!mVariableModuleGlobal->VariableGlobal.AuthSupport) {\r
+      //\r
+      // Not support authenticated variable write.\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  } else if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {\r
+    if (PcdGet32 (PcdHwErrStorageSize) == 0) {\r
+      //\r
+      // Not support harware error record variable variable.\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  //\r
+  // EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS and EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute\r
+  // cannot be set both.\r
+  //\r
+  if (((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)\r
+     && ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if ((UINTN)(~0) - DataSize < StrSize(VariableName)){\r
+  if ((Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {\r
+    if (DataSize < AUTHINFO_SIZE) {\r
+      //\r
+      // Try to write Authenticated Variable without AuthInfo.\r
+      //\r
+      return EFI_SECURITY_VIOLATION;\r
+    }\r
+    PayloadSize = DataSize - AUTHINFO_SIZE;\r
+  } else if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) == EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {\r
+    //\r
+    // Sanity check for EFI_VARIABLE_AUTHENTICATION_2 descriptor.\r
+    //\r
+    if (DataSize < OFFSET_OF_AUTHINFO2_CERT_DATA ||\r
+      ((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->AuthInfo.Hdr.dwLength > DataSize - (OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo)) ||\r
+      ((EFI_VARIABLE_AUTHENTICATION_2 *) Data)->AuthInfo.Hdr.dwLength < OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData)) {\r
+      return EFI_SECURITY_VIOLATION;\r
+    }\r
+    PayloadSize = DataSize - AUTHINFO2_SIZE (Data);\r
+  } else {\r
+    PayloadSize = DataSize;\r
+  }\r
+\r
+  if ((UINTN)(~0) - PayloadSize < StrSize(VariableName)){\r
+    //\r
+    // Prevent whole variable size overflow\r
     //\r
-    // Prevent whole variable size overflow \r
-    // \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   //\r
   //  The size of the VariableName, including the Unicode Null in bytes plus\r
   //  the DataSize is limited to maximum size of PcdGet32 (PcdMaxHardwareErrorVariableSize)\r
-  //  bytes for HwErrRec, and PcdGet32 (PcdMaxVariableSize) bytes for the others.\r
+  //  bytes for HwErrRec#### variable.\r
   //\r
   if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {\r
-    if ( StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER)) {\r
+    if (StrSize (VariableName) + PayloadSize > PcdGet32 (PcdMaxHardwareErrorVariableSize) - GetVariableHeaderSize ()) {\r
       return EFI_INVALID_PARAMETER;\r
     }\r
     if (!IsHwErrRecVariable(VariableName, VendorGuid)) {\r
@@ -2793,13 +3276,24 @@ VariableServiceSetVariable (
   } else {\r
     //\r
     //  The size of the VariableName, including the Unicode Null in bytes plus\r
-    //  the DataSize is limited to maximum size of PcdGet32 (PcdMaxVariableSize) bytes.\r
+    //  the DataSize is limited to maximum size of Max(Auth)VariableSize bytes.\r
     //\r
-    if (StrSize (VariableName) + DataSize > PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER)) {\r
-      return EFI_INVALID_PARAMETER;\r
+    if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
+      if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxAuthVariableSize - GetVariableHeaderSize ()) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    } else {\r
+      if (StrSize (VariableName) + PayloadSize > mVariableModuleGlobal->MaxVariableSize - GetVariableHeaderSize ()) {\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
     }\r
   }\r
 \r
+  Status = InternalVarCheckSetVariableCheck (VariableName, VendorGuid, Attributes, PayloadSize, (VOID *) ((UINTN) Data + DataSize - PayloadSize));\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
   //\r
@@ -2835,11 +3329,6 @@ VariableServiceSetVariable (
     }\r
   }\r
 \r
-  Status = InternalVarCheckSetVariableCheck (VariableName, VendorGuid, Attributes, DataSize, Data);\r
-  if (EFI_ERROR (Status)) {\r
-    goto Done;\r
-  }\r
-\r
   //\r
   // Check whether the input variable is already existed.\r
   //\r
@@ -2849,7 +3338,7 @@ VariableServiceSetVariable (
       Status = EFI_WRITE_PROTECTED;\r
       goto Done;\r
     }\r
-    if (Attributes != 0 && Attributes != Variable.CurrPtr->Attributes) {\r
+    if (Attributes != 0 && (Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Variable.CurrPtr->Attributes) {\r
       //\r
       // If a preexisting variable is rewritten with different attributes, SetVariable() shall not\r
       // modify the variable and shall return EFI_INVALID_PARAMETER. Two exceptions to this rule:\r
@@ -2875,12 +3364,25 @@ VariableServiceSetVariable (
     }\r
   }\r
 \r
-  Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, &Variable);\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthSupport) {\r
+    Status = AuthVariableLibProcessVariable (VariableName, VendorGuid, Data, DataSize, Attributes);\r
+  } else {\r
+    Status = UpdateVariable (VariableName, VendorGuid, Data, DataSize, Attributes, 0, 0, &Variable, NULL);\r
+  }\r
 \r
 Done:\r
   InterlockedDecrement (&mVariableModuleGlobal->VariableGlobal.ReentrantState);\r
   ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
 \r
+  if (!AtRuntime ()) {\r
+    if (!EFI_ERROR (Status)) {\r
+      SecureBootHook (\r
+        VariableName,\r
+        VendorGuid\r
+        );\r
+    }\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
@@ -2947,7 +3449,7 @@ VariableServiceQueryVariableInfoInternal (
   //\r
   if ((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {\r
     *MaximumVariableStorageSize = PcdGet32 (PcdHwErrStorageSize);\r
-    *MaximumVariableSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);\r
+    *MaximumVariableSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - GetVariableHeaderSize ();\r
   } else {\r
     if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {\r
       if (AtRuntime ()) {\r
@@ -2958,9 +3460,13 @@ VariableServiceQueryVariableInfoInternal (
     }\r
 \r
     //\r
-    // Let *MaximumVariableSize be PcdGet32 (PcdMaxVariableSize) with the exception of the variable header size.\r
+    // Let *MaximumVariableSize be Max(Auth)VariableSize with the exception of the variable header size.\r
     //\r
-    *MaximumVariableSize = PcdGet32 (PcdMaxVariableSize) - sizeof (VARIABLE_HEADER);\r
+    if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
+      *MaximumVariableSize = mVariableModuleGlobal->MaxAuthVariableSize - GetVariableHeaderSize ();\r
+    } else {\r
+      *MaximumVariableSize = mVariableModuleGlobal->MaxVariableSize - GetVariableHeaderSize ();\r
+    }\r
   }\r
 \r
   //\r
@@ -3008,7 +3514,7 @@ VariableServiceQueryVariableInfoInternal (
         VariablePtrTrack.EndPtr   = GetEndPointer   (VariableStoreHeader);\r
         Status = FindVariableEx (\r
                    GetVariableNamePtr (Variable),\r
-                   &Variable->VendorGuid,\r
+                   GetVendorGuidPtr (Variable),\r
                    FALSE,\r
                    &VariablePtrTrack\r
                    );\r
@@ -3038,10 +3544,10 @@ VariableServiceQueryVariableInfoInternal (
     }\r
   }\r
 \r
-  if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {\r
+  if (*RemainingVariableStorageSize < GetVariableHeaderSize ()) {\r
     *MaximumVariableSize = 0;\r
-  } else if ((*RemainingVariableStorageSize - sizeof (VARIABLE_HEADER)) < *MaximumVariableSize) {\r
-    *MaximumVariableSize = *RemainingVariableStorageSize - sizeof (VARIABLE_HEADER);\r
+  } else if ((*RemainingVariableStorageSize - GetVariableHeaderSize ()) < *MaximumVariableSize) {\r
+    *MaximumVariableSize = *RemainingVariableStorageSize - GetVariableHeaderSize ();\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -3083,7 +3589,7 @@ VariableServiceQueryVariableInfo (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {\r
+  if ((Attributes & EFI_VARIABLE_ATTRIBUTES_MASK) == 0) {\r
     //\r
     // Make sure the Attributes combination is supported by the platform.\r
     //\r
@@ -3103,11 +3609,20 @@ VariableServiceQueryVariableInfo (
     // Make sure Hw Attribute is set with NV.\r
     //\r
     return EFI_INVALID_PARAMETER;\r
-  } else if ((Attributes & (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE)) != 0) {\r
-    //\r
-    // Not support authenticated or append variable write yet.\r
-    //\r
-    return EFI_UNSUPPORTED;\r
+  } else if ((Attributes & VARIABLE_ATTRIBUTE_AT_AW) != 0) {\r
+    if (!mVariableModuleGlobal->VariableGlobal.AuthSupport) {\r
+      //\r
+      // Not support authenticated variable write.\r
+      //\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+  } else if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {\r
+    if (PcdGet32 (PcdHwErrStorageSize) == 0) {\r
+      //\r
+      // Not support harware error record variable variable.\r
+      //\r
+      return EFI_UNSUPPORTED;\r
+    }\r
   }\r
 \r
   AcquireLockOnlyAtBootTime(&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);\r
@@ -3157,11 +3672,13 @@ ReclaimForOS(
   }\r
 \r
   RemainingHwErrVariableSpace = PcdGet32 (PcdHwErrStorageSize) - mVariableModuleGlobal->HwErrVariableTotalSize;\r
+\r
   //\r
   // Check if the free area is below a threshold.\r
   //\r
-  if ((RemainingCommonRuntimeVariableSpace < PcdGet32 (PcdMaxVariableSize))\r
-    || ((PcdGet32 (PcdHwErrStorageSize) != 0) &&\r
+  if (((RemainingCommonRuntimeVariableSpace < mVariableModuleGlobal->MaxVariableSize) ||\r
+       (RemainingCommonRuntimeVariableSpace < mVariableModuleGlobal->MaxAuthVariableSize)) ||\r
+      ((PcdGet32 (PcdHwErrStorageSize) != 0) &&\r
        (RemainingHwErrVariableSpace < PcdGet32 (PcdMaxHardwareErrorVariableSize)))){\r
     Status = Reclaim (\r
             mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,\r
@@ -3175,9 +3692,30 @@ ReclaimForOS(
   }\r
 }\r
 \r
+/**\r
+  Get non-volatile maximum variable size.\r
+\r
+  @return Non-volatile maximum variable size.\r
+\r
+**/\r
+UINTN\r
+GetNonVolatileMaxVariableSize (\r
+  VOID\r
+  )\r
+{\r
+  if (PcdGet32 (PcdHwErrStorageSize) != 0) {\r
+    return MAX (MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize)),\r
+                PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
+  } else {\r
+    return MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxAuthVariableSize));\r
+  }\r
+}\r
+\r
 /**\r
   Init non-volatile variable store.\r
 \r
+  @param[out] NvFvHeader        Output pointer to non-volatile FV header address.\r
+\r
   @retval EFI_SUCCESS           Function successfully executed.\r
   @retval EFI_OUT_OF_RESOURCES  Fail to allocate enough memory resource.\r
   @retval EFI_VOLUME_CORRUPTED  Variable Store or Firmware Volume for Variable Store is corrupted.\r
@@ -3185,7 +3723,7 @@ ReclaimForOS(
 **/\r
 EFI_STATUS\r
 InitNonVolatileVariableStore (\r
-  VOID\r
+  OUT EFI_FIRMWARE_VOLUME_HEADER    **NvFvHeader\r
   )\r
 {\r
   EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;\r
@@ -3241,7 +3779,7 @@ InitNonVolatileVariableStore (
     } else if ((FtwLastWriteData->TargetAddress > NvStorageBase) &&\r
                (FtwLastWriteData->TargetAddress < (NvStorageBase + NvStorageSize))) {\r
       //\r
-      // Flash NV storage from the offset is backed up in spare block.\r
+      // Flash NV storage from the Offset is backed up in spare block.\r
       //\r
       BackUpOffset = (UINT32) (FtwLastWriteData->TargetAddress - NvStorageBase);\r
       BackUpSize = NvStorageSize - BackUpOffset;\r
@@ -3276,9 +3814,10 @@ InitNonVolatileVariableStore (
   }\r
   ASSERT(mNvVariableCache->Size == VariableStoreLength);\r
 \r
-\r
   ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);\r
 \r
+  mVariableModuleGlobal->VariableGlobal.AuthFormat = (BOOLEAN)(CompareGuid (&mNvVariableCache->Signature, &gEfiAuthenticatedVariableGuid));\r
+\r
   HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);\r
   MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);\r
   BoottimeReservedNvVariableSpaceSize = PcdGet32 (PcdBoottimeReservedNvVariableSpaceSize);\r
@@ -3287,17 +3826,17 @@ InitNonVolatileVariableStore (
   // Note that in EdkII variable driver implementation, Hardware Error Record type variable\r
   // is stored with common variable in the same NV region. So the platform integrator should\r
   // ensure that the value of PcdHwErrStorageSize is less than the value of\r
-  // VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).\r
+  // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).\r
   //\r
   ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));\r
   //\r
   // Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of\r
-  // VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).\r
+  // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).\r
   //\r
   ASSERT (MaxUserNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));\r
   //\r
   // Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of\r
-  // VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).\r
+  // (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).\r
   //\r
   ASSERT (BoottimeReservedNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));\r
 \r
@@ -3308,9 +3847,12 @@ InitNonVolatileVariableStore (
   DEBUG ((EFI_D_INFO, "Variable driver common space: 0x%x 0x%x 0x%x\n", mVariableModuleGlobal->CommonVariableSpace, mVariableModuleGlobal->CommonMaxUserVariableSpace, mVariableModuleGlobal->CommonRuntimeVariableSpace));\r
 \r
   //\r
-  // The max variable or hardware error variable size should be < variable store size.\r
+  // The max NV variable size should be < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).\r
   //\r
-  ASSERT(MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) < VariableStoreLength);\r
+  ASSERT (GetNonVolatileMaxVariableSize () < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));\r
+\r
+  mVariableModuleGlobal->MaxVariableSize = PcdGet32 (PcdMaxVariableSize);\r
+  mVariableModuleGlobal->MaxAuthVariableSize = ((PcdGet32 (PcdMaxAuthVariableSize) != 0) ? PcdGet32 (PcdMaxAuthVariableSize) : mVariableModuleGlobal->MaxVariableSize);\r
 \r
   //\r
   // Parse non-volatile variable data and get last variable offset.\r
@@ -3329,6 +3871,7 @@ InitNonVolatileVariableStore (
   }\r
   mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) Variable - (UINTN) VariableStoreBase;\r
 \r
+  *NvFvHeader = FvHeader;\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -3374,17 +3917,17 @@ FlushHobVariableToFlash (
       }\r
       ASSERT ((Variable->Attributes & EFI_VARIABLE_NON_VOLATILE) != 0);\r
       if (VendorGuid == NULL || VariableName == NULL ||\r
-          !CompareGuid (VendorGuid, &Variable->VendorGuid) ||\r
+          !CompareGuid (VendorGuid, GetVendorGuidPtr (Variable)) ||\r
           StrCmp (VariableName, GetVariableNamePtr (Variable)) != 0) {\r
         VariableData = GetVariableDataPtr (Variable);\r
         Status = VariableServiceSetVariable (\r
                    GetVariableNamePtr (Variable),\r
-                   &Variable->VendorGuid,\r
+                   GetVendorGuidPtr (Variable),\r
                    Variable->Attributes,\r
-                   Variable->DataSize,\r
+                   DataSizeOfVariable (Variable),\r
                    VariableData\r
                    );\r
-        DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", &Variable->VendorGuid, GetVariableNamePtr (Variable), Status));\r
+        DEBUG ((EFI_D_INFO, "Variable driver flush the HOB variable to flash: %g %s %r\n", GetVendorGuidPtr (Variable), GetVariableNamePtr (Variable), Status));\r
       } else {\r
         //\r
         // The updated or deleted variable is matched with the HOB variable.\r
@@ -3398,7 +3941,7 @@ FlushHobVariableToFlash (
         // If set variable successful, or the updated or deleted variable is matched with the HOB variable,\r
         // set the HOB variable to DELETED state in local.\r
         //\r
-        DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", &Variable->VendorGuid, GetVariableNamePtr (Variable)));\r
+        DEBUG ((EFI_D_INFO, "Variable driver set the HOB variable to DELETED state in local: %g %s\n", GetVendorGuidPtr (Variable), GetVariableNamePtr (Variable)));\r
         Variable->State &= VAR_DELETED;\r
       } else {\r
         ErrorFlag = TRUE;\r
@@ -3440,6 +3983,7 @@ VariableWriteServiceInitialize (
   UINT8                           Data;\r
   EFI_PHYSICAL_ADDRESS            VariableStoreBase;\r
   EFI_PHYSICAL_ADDRESS            NvStorageBase;\r
+  VARIABLE_ENTRY_PROPERTY         *VariableEntry;\r
 \r
   NvStorageBase = (EFI_PHYSICAL_ADDRESS) PcdGet64 (PcdFlashNvStorageVariableBase64);\r
   if (NvStorageBase == 0) {\r
@@ -3452,7 +3996,7 @@ VariableWriteServiceInitialize (
   //\r
   mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase = VariableStoreBase;\r
   VariableStoreHeader = (VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase;\r
\r
+\r
   //\r
   // Check if the free area is really free.\r
   //\r
@@ -3479,7 +4023,45 @@ VariableWriteServiceInitialize (
 \r
   FlushHobVariableToFlash (NULL, NULL);\r
 \r
-  return EFI_SUCCESS;\r
+  Status = EFI_SUCCESS;\r
+  ZeroMem (&mContextOut, sizeof (mContextOut));\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    //\r
+    // Authenticated variable initialize.\r
+    //\r
+    mContextIn.MaxAuthVariableSize = mVariableModuleGlobal->MaxAuthVariableSize - GetVariableHeaderSize ();\r
+    Status = AuthVariableLibInitialize (&mContextIn, &mContextOut);\r
+    if (!EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_INFO, "Variable driver will work with auth variable support!\n"));\r
+      mVariableModuleGlobal->VariableGlobal.AuthSupport = TRUE;\r
+      if (mContextOut.AuthVarEntry != NULL) {\r
+        for (Index = 0; Index < mContextOut.AuthVarEntryCount; Index++) {\r
+          VariableEntry = &mContextOut.AuthVarEntry[Index];\r
+          Status = InternalVarCheckVariablePropertySet (\r
+                     VariableEntry->Name,\r
+                     VariableEntry->Guid,\r
+                     &VariableEntry->VariableProperty\r
+                     );\r
+          ASSERT_EFI_ERROR (Status);\r
+        }\r
+      }\r
+    } else if (Status == EFI_UNSUPPORTED) {\r
+      DEBUG ((EFI_D_INFO, "NOTICE - AuthVariableLibInitialize() returns %r!\n", Status));\r
+      DEBUG ((EFI_D_INFO, "Variable driver will continue to work without auth variable support!\n"));\r
+      mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    for (Index = 0; Index < sizeof (mVariableEntryProperty) / sizeof (mVariableEntryProperty[0]); Index++) {\r
+      VariableEntry = &mVariableEntryProperty[Index];\r
+      Status = InternalVarCheckVariablePropertySet (VariableEntry->Name, VariableEntry->Guid, &VariableEntry->VariableProperty);\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
+  }\r
+\r
+  return Status;\r
 }\r
 \r
 \r
@@ -3501,6 +4083,8 @@ VariableCommonInitialize (
   UINT64                          VariableStoreLength;\r
   UINTN                           ScratchSize;\r
   EFI_HOB_GUID_TYPE               *GuidHob;\r
+  EFI_GUID                        *VariableGuid;\r
+  EFI_FIRMWARE_VOLUME_HEADER      *NvFvHeader;\r
 \r
   //\r
   // Allocate runtime memory for variable driver global structure.\r
@@ -3512,16 +4096,43 @@ VariableCommonInitialize (
 \r
   InitializeLock (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock, TPL_NOTIFY);\r
 \r
+  //\r
+  // Init non-volatile variable store.\r
+  //\r
+  Status = InitNonVolatileVariableStore (&NvFvHeader);\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (mVariableModuleGlobal);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // mVariableModuleGlobal->VariableGlobal.AuthFormat\r
+  // has been initialized in InitNonVolatileVariableStore().\r
+  //\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    DEBUG ((EFI_D_INFO, "Variable driver will work with auth variable format!\n"));\r
+    //\r
+    // Set AuthSupport to FALSE first, VariableWriteServiceInitialize() will initialize it.\r
+    //\r
+    mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;\r
+    VariableGuid = &gEfiAuthenticatedVariableGuid;\r
+  } else {\r
+    DEBUG ((EFI_D_INFO, "Variable driver will work without auth variable support!\n"));\r
+    mVariableModuleGlobal->VariableGlobal.AuthSupport = FALSE;\r
+    VariableGuid = &gEfiVariableGuid;\r
+  }\r
+\r
   //\r
   // Get HOB variable store.\r
   //\r
-  GuidHob = GetFirstGuidHob (&gEfiVariableGuid);\r
+  GuidHob = GetFirstGuidHob (VariableGuid);\r
   if (GuidHob != NULL) {\r
     VariableStoreHeader = GET_GUID_HOB_DATA (GuidHob);\r
     VariableStoreLength = (UINT64) (GuidHob->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE));\r
     if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) {\r
       mVariableModuleGlobal->VariableGlobal.HobVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocateRuntimeCopyPool ((UINTN) VariableStoreLength, (VOID *) VariableStoreHeader);\r
       if (mVariableModuleGlobal->VariableGlobal.HobVariableBase == 0) {\r
+        FreePool (NvFvHeader);\r
         FreePool (mVariableModuleGlobal);\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
@@ -3533,12 +4144,14 @@ VariableCommonInitialize (
   //\r
   // Allocate memory for volatile variable store, note that there is a scratch space to store scratch data.\r
   //\r
-  ScratchSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize));\r
+  ScratchSize = GetNonVolatileMaxVariableSize ();\r
+  mVariableModuleGlobal->ScratchBufferSize = ScratchSize;\r
   VolatileVariableStore = AllocateRuntimePool (PcdGet32 (PcdVariableStoreSize) + ScratchSize);\r
   if (VolatileVariableStore == NULL) {\r
     if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
       FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
     }\r
+    FreePool (NvFvHeader);\r
     FreePool (mVariableModuleGlobal);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -3551,33 +4164,21 @@ VariableCommonInitialize (
   mVariableModuleGlobal->VariableGlobal.VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore;\r
   mVariableModuleGlobal->VolatileLastVariableOffset = (UINTN) GetStartPointer (VolatileVariableStore) - (UINTN) VolatileVariableStore;\r
 \r
-  CopyGuid (&VolatileVariableStore->Signature, &gEfiVariableGuid);\r
+  CopyGuid (&VolatileVariableStore->Signature, VariableGuid);\r
   VolatileVariableStore->Size        = PcdGet32 (PcdVariableStoreSize);\r
   VolatileVariableStore->Format      = VARIABLE_STORE_FORMATTED;\r
   VolatileVariableStore->State       = VARIABLE_STORE_HEALTHY;\r
   VolatileVariableStore->Reserved    = 0;\r
   VolatileVariableStore->Reserved1   = 0;\r
 \r
-  //\r
-  // Init non-volatile variable store.\r
-  //\r
-  Status = InitNonVolatileVariableStore ();\r
-  if (EFI_ERROR (Status)) {\r
-    if (mVariableModuleGlobal->VariableGlobal.HobVariableBase != 0) {\r
-      FreePool ((VOID *) (UINTN) mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
-    }\r
-    FreePool (mVariableModuleGlobal);\r
-    FreePool (VolatileVariableStore);\r
-  }\r
-\r
-  return Status;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 /**\r
   Get the proper fvb handle and/or fvb protocol by the given Flash address.\r
 \r
-  @param[in] Address        The Flash address.\r
+  @param[in]  Address       The Flash address.\r
   @param[out] FvbHandle     In output, if it is not NULL, it points to the proper FVB handle.\r
   @param[out] FvbProtocol   In output, if it is not NULL, it points to the proper FVB protocol.\r
 \r
@@ -3600,7 +4201,6 @@ GetFvbInfoByAddress (
   UINTN                                   NumberOfBlocks;\r
 \r
   HandleBuffer = NULL;\r
-\r
   //\r
   // Get all FVB handles.\r
   //\r
@@ -3660,7 +4260,7 @@ GetFvbInfoByAddress (
   if (Fvb == NULL) {\r
     Status = EFI_NOT_FOUND;\r
   }\r
-  \r
-  return Status;  \r
+\r
+  return Status;\r
 }\r
 \r
index f5ba4865735554e71e7c918be27f304492059fc6..9928837fd834523b47e83213a7069897925b1161 100644 (file)
@@ -1,5 +1,4 @@
 /** @file\r
-\r
   The internal header file includes the common header files, defines\r
   internal structure and functions used by Variable modules.\r
 \r
@@ -36,14 +35,24 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/BaseLib.h>\r
 #include <Library/SynchronizationLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/AuthVariableLib.h>\r
 #include <Guid/GlobalVariable.h>\r
 #include <Guid/EventGroup.h>\r
 #include <Guid/VariableFormat.h>\r
+#include <Guid/ImageAuthentication.h>\r
 #include <Guid/SystemNvDataGuid.h>\r
 #include <Guid/FaultTolerantWrite.h>\r
 #include <Guid/HardwareErrorVariable.h>\r
 #include <Guid/VarErrorFlag.h>\r
 \r
+#define EFI_VARIABLE_ATTRIBUTES_MASK (EFI_VARIABLE_NON_VOLATILE | \\r
+                                      EFI_VARIABLE_BOOTSERVICE_ACCESS | \\r
+                                      EFI_VARIABLE_RUNTIME_ACCESS | \\r
+                                      EFI_VARIABLE_HARDWARE_ERROR_RECORD | \\r
+                                      EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \\r
+                                      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \\r
+                                      EFI_VARIABLE_APPEND_WRITE)\r
+\r
 ///\r
 /// The size of a 3 character ISO639 language code.\r
 ///\r
@@ -76,6 +85,8 @@ typedef struct {
   EFI_PHYSICAL_ADDRESS  NonVolatileVariableBase;\r
   EFI_LOCK              VariableServicesLock;\r
   UINT32                ReentrantState;\r
+  BOOLEAN               AuthFormat;\r
+  BOOLEAN               AuthSupport;\r
 } VARIABLE_GLOBAL;\r
 \r
 typedef struct {\r
@@ -88,6 +99,9 @@ typedef struct {
   UINTN           CommonVariableTotalSize;\r
   UINTN           CommonUserVariableTotalSize;\r
   UINTN           HwErrVariableTotalSize;\r
+  UINTN           MaxVariableSize;\r
+  UINTN           MaxAuthVariableSize;\r
+  UINTN           ScratchBufferSize;\r
   CHAR8           *PlatformLangCodes;\r
   CHAR8           *LangCodes;\r
   CHAR8           *PlatformLang;\r
@@ -135,25 +149,167 @@ FtwVariableSpace (
   IN VARIABLE_STORE_HEADER  *VariableBuffer\r
   );\r
 \r
+/**\r
+  Finds variable in storage blocks of volatile and non-volatile storage areas.\r
+\r
+  This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
+  If VariableName is an empty string, then we just return the first\r
+  qualified variable without comparing VariableName and VendorGuid.\r
+  If IgnoreRtCheck is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS attribute check\r
+  at runtime when searching existing variable, only VariableName and VendorGuid are compared.\r
+  Otherwise, variables without EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.\r
+\r
+  @param[in]   VariableName           Name of the variable to be found.\r
+  @param[in]   VendorGuid             Vendor GUID to be found.\r
+  @param[out]  PtrTrack               VARIABLE_POINTER_TRACK structure for output,\r
+                                      including the range searched and the target position.\r
+  @param[in]   Global                 Pointer to VARIABLE_GLOBAL structure, including\r
+                                      base of volatile variable storage area, base of\r
+                                      NV variable storage area, and a lock.\r
+  @param[in]   IgnoreRtCheck          Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute\r
+                                      check at runtime when searching variable.\r
+\r
+  @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
+                                      VendorGuid is NULL.\r
+  @retval EFI_SUCCESS                 Variable successfully found.\r
+  @retval EFI_NOT_FOUND               Variable not found\r
+\r
+**/\r
+EFI_STATUS\r
+FindVariable (\r
+  IN  CHAR16                  *VariableName,\r
+  IN  EFI_GUID                *VendorGuid,\r
+  OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
+  IN  VARIABLE_GLOBAL         *Global,\r
+  IN  BOOLEAN                 IgnoreRtCheck\r
+  );\r
 \r
 /**\r
-  Update the variable region with Variable information. These are the same \r
-  arguments as the EFI Variable services.\r
 \r
-  @param[in] VariableName       Name of variable.\r
+  Gets the pointer to the end of the variable storage area.\r
 \r
-  @param[in] VendorGuid         Guid of variable.\r
+  This function gets pointer to the end of the variable storage\r
+  area, according to the input variable store header.\r
 \r
-  @param[in] Data               Variable data.\r
+  @param VarStoreHeader  Pointer to the Variable Store Header.\r
 \r
-  @param[in] DataSize           Size of data. 0 means delete.\r
+  @return Pointer to the end of the variable storage area.\r
+\r
+**/\r
+VARIABLE_HEADER *\r
+GetEndPointer (\r
+  IN VARIABLE_STORE_HEADER       *VarStoreHeader\r
+  );\r
+\r
+/**\r
+  This code gets the size of variable header.\r
+\r
+  @return Size of variable header in bytes in type UINTN.\r
+\r
+**/\r
+UINTN\r
+GetVariableHeaderSize (\r
+  VOID\r
+  );\r
+\r
+/**\r
+\r
+  This code gets the pointer to the variable name.\r
+\r
+  @param Variable        Pointer to the Variable Header.\r
+\r
+  @return Pointer to Variable Name which is Unicode encoding.\r
+\r
+**/\r
+CHAR16 *\r
+GetVariableNamePtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  );\r
+\r
+/**\r
+  This code gets the pointer to the variable guid.\r
+\r
+  @param Variable   Pointer to the Variable Header.\r
+\r
+  @return A EFI_GUID* pointer to Vendor Guid.\r
+\r
+**/\r
+EFI_GUID *\r
+GetVendorGuidPtr (\r
+  IN VARIABLE_HEADER    *Variable\r
+  );\r
+\r
+/**\r
+\r
+  This code gets the pointer to the variable data.\r
+\r
+  @param Variable        Pointer to the Variable Header.\r
+\r
+  @return Pointer to Variable Data.\r
+\r
+**/\r
+UINT8 *\r
+GetVariableDataPtr (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  );\r
+\r
+/**\r
+\r
+  This code gets the size of variable data.\r
+\r
+  @param Variable        Pointer to the Variable Header.\r
+\r
+  @return Size of variable in bytes.\r
+\r
+**/\r
+UINTN\r
+DataSizeOfVariable (\r
+  IN  VARIABLE_HEADER   *Variable\r
+  );\r
+\r
+/**\r
+  This function is to check if the remaining variable space is enough to set\r
+  all Variables from argument list successfully. The purpose of the check\r
+  is to keep the consistency of the Variables to be in variable storage.\r
 \r
-  @param[in] Attributes         Attribues of the variable.\r
+  Note: Variables are assumed to be in same storage.\r
+  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,\r
+  so follow the argument sequence to check the Variables.\r
+\r
+  @param[in] Attributes         Variable attributes for Variable entries.\r
+  @param[in] Marker             VA_LIST style variable argument list.\r
+                                The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
+                                A NULL terminates the list. The VariableSize of\r
+                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.\r
+                                It will be changed to variable total size as output.\r
+\r
+  @retval TRUE                  Have enough variable space to set the Variables successfully.\r
+  @retval FALSE                 No enough variable space to set the Variables successfully.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CheckRemainingSpaceForConsistencyInternal (\r
+  IN UINT32                     Attributes,\r
+  IN VA_LIST                    Marker\r
+  );\r
+\r
+/**\r
+  Update the variable region with Variable information. If EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS is set,\r
+  index of associated public key is needed.\r
 \r
+  @param[in] VariableName       Name of variable.\r
+  @param[in] VendorGuid         Guid of variable.\r
+  @param[in] Data               Variable data.\r
+  @param[in] DataSize           Size of data. 0 means delete.\r
+  @param[in] Attributes         Attributes of the variable.\r
+  @param[in] KeyIndex           Index of associated public key.\r
+  @param[in] MonotonicCount     Value of associated monotonic count.\r
   @param[in, out] Variable      The variable information that is used to keep track of variable usage.\r
 \r
-  @retval EFI_SUCCESS           The update operation is success.\r
+  @param[in] TimeStamp          Value of associated TimeStamp.\r
 \r
+  @retval EFI_SUCCESS           The update operation is success.\r
   @retval EFI_OUT_OF_RESOURCES  Variable region is full, cannot write other data into this region.\r
 \r
 **/\r
@@ -164,13 +320,16 @@ UpdateVariable (
   IN      VOID            *Data,\r
   IN      UINTN           DataSize,\r
   IN      UINT32          Attributes OPTIONAL,\r
-  IN OUT  VARIABLE_POINTER_TRACK *Variable\r
+  IN      UINT32          KeyIndex  OPTIONAL,\r
+  IN      UINT64          MonotonicCount  OPTIONAL,\r
+  IN OUT  VARIABLE_POINTER_TRACK *Variable,\r
+  IN      EFI_TIME        *TimeStamp  OPTIONAL\r
   );\r
 \r
 \r
 /**\r
   Return TRUE if ExitBootServices () has been called.\r
-  \r
+\r
   @retval TRUE If ExitBootServices () has been called.\r
 **/\r
 BOOLEAN\r
@@ -181,8 +340,8 @@ AtRuntime (
 /**\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
+  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
@@ -200,7 +359,7 @@ InitializeLock (
   IN EFI_TPL        Priority\r
   );\r
 \r
-  \r
+\r
 /**\r
   Acquires lock only at boot time. Simply returns at runtime.\r
 \r
@@ -234,7 +393,7 @@ AcquireLockOnlyAtBootTime (
 VOID\r
 ReleaseLockOnlyAtBootTime (\r
   IN EFI_LOCK  *Lock\r
-  );  \r
+  );\r
 \r
 /**\r
   Retrive the FVB protocol interface by HANDLE.\r
@@ -246,7 +405,7 @@ ReleaseLockOnlyAtBootTime (
   @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
 **/\r
 EFI_STATUS\r
 GetFvbByHandle (\r
@@ -254,25 +413,9 @@ GetFvbByHandle (
   OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvBlock\r
   );\r
 \r
-\r
-/**\r
-  Retrive the Swap Address Range protocol interface.\r
-\r
-  @param[out] SarProtocol       The interface of SAR protocol\r
-\r
-  @retval EFI_SUCCESS           The SAR protocol instance was found and returned in SarProtocol.\r
-  @retval EFI_NOT_FOUND         The SAR protocol instance was not found.\r
-  @retval EFI_INVALID_PARAMETER SarProtocol is NULL.\r
-\r
-**/\r
-EFI_STATUS\r
-GetSarProtocol (\r
-  OUT VOID                                **SarProtocol\r
-  );\r
-\r
 /**\r
   Function returns an array of handles that support the FVB protocol\r
-  in a buffer allocated from pool. \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
@@ -283,7 +426,7 @@ GetSarProtocol (
   @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
 **/\r
 EFI_STATUS\r
 GetFvbCountAndBuffer (\r
@@ -305,13 +448,23 @@ VariableCommonInitialize (
 \r
 /**\r
   This function reclaims variable storage if free size is below the threshold.\r
-  \r
+\r
 **/\r
 VOID\r
 ReclaimForOS(\r
   VOID\r
-  );  \r
+  );\r
+\r
+/**\r
+  Get non-volatile maximum variable size.\r
 \r
+  @return Non-volatile maximum variable size.\r
+\r
+**/\r
+UINTN\r
+GetNonVolatileMaxVariableSize (\r
+  VOID\r
+  );\r
 \r
 /**\r
   Initializes variable write service after FVB was ready.\r
@@ -324,7 +477,7 @@ EFI_STATUS
 VariableWriteServiceInitialize (\r
   VOID\r
   );\r
-  \r
+\r
 /**\r
   Retrive the SMM Fault Tolerent Write protocol interface.\r
 \r
@@ -355,52 +508,21 @@ GetFvbInfoByAddress (
   OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  **FvbProtocol OPTIONAL\r
   );\r
 \r
-/**\r
-  Finds variable in storage blocks of volatile and non-volatile storage areas.\r
-\r
-  This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
-  If VariableName is an empty string, then we just return the first\r
-  qualified variable without comparing VariableName and VendorGuid.\r
-  If IgnoreRtCheck is TRUE, then we ignore the EFI_VARIABLE_RUNTIME_ACCESS attribute check\r
-  at runtime when searching existing variable, only VariableName and VendorGuid are compared.\r
-  Otherwise, variables without EFI_VARIABLE_RUNTIME_ACCESS are not visible at runtime.\r
-\r
-  @param  VariableName                Name of the variable to be found.\r
-  @param  VendorGuid                  Vendor GUID to be found.\r
-  @param  PtrTrack                    VARIABLE_POINTER_TRACK structure for output,\r
-                                      including the range searched and the target position.\r
-  @param  Global                      Pointer to VARIABLE_GLOBAL structure, including\r
-                                      base of volatile variable storage area, base of\r
-                                      NV variable storage area, and a lock.\r
-  @param  IgnoreRtCheck               Ignore EFI_VARIABLE_RUNTIME_ACCESS attribute\r
-                                      check at runtime when searching variable.\r
-\r
-  @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while\r
-                                      VendorGuid is NULL.\r
-  @retval EFI_SUCCESS                 Variable successfully found.\r
-  @retval EFI_NOT_FOUND               Variable not found\r
-\r
-**/\r
-EFI_STATUS\r
-FindVariable (\r
-  IN  CHAR16                  *VariableName,\r
-  IN  EFI_GUID                *VendorGuid,\r
-  OUT VARIABLE_POINTER_TRACK  *PtrTrack,\r
-  IN  VARIABLE_GLOBAL         *Global,\r
-  IN  BOOLEAN                 IgnoreRtCheck\r
-  );\r
-\r
 /**\r
 \r
   This code finds variable in storage blocks (Volatile or Non-Volatile).\r
 \r
+  Caution: This function may receive untrusted input.\r
+  This function may be invoked in SMM mode, and datasize and data are external input.\r
+  This function will do basic validation, before parse the data.\r
+\r
   @param VariableName               Name of Variable to be found.\r
   @param VendorGuid                 Variable vendor GUID.\r
   @param Attributes                 Attribute value of the variable found.\r
   @param DataSize                   Size of Data found. If size is less than the\r
                                     data, this value contains the required size.\r
   @param Data                       Data pointer.\r
-                      \r
+\r
   @return EFI_INVALID_PARAMETER     Invalid parameter.\r
   @return EFI_SUCCESS               Find the specified variable.\r
   @return EFI_NOT_FOUND             Not found.\r
@@ -417,6 +539,28 @@ VariableServiceGetVariable (
   OUT     VOID              *Data\r
   );\r
 \r
+/**\r
+  This code Finds the Next available variable.\r
+\r
+  Caution: This function may receive untrusted input.\r
+  This function may be invoked in SMM mode. This function will do basic validation, before parse the data.\r
+\r
+  @param[in] VariableName   Pointer to variable name.\r
+  @param[in] VendorGuid     Variable Vendor Guid.\r
+  @param[out] VariablePtr   Pointer to variable header address.\r
+\r
+  @return EFI_SUCCESS       Find the specified variable.\r
+  @return EFI_NOT_FOUND     Not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableServiceGetNextVariableInternal (\r
+  IN  CHAR16                *VariableName,\r
+  IN  EFI_GUID              *VendorGuid,\r
+  OUT VARIABLE_HEADER       **VariablePtr\r
+  );\r
+\r
 /**\r
 \r
   This code Finds the Next available variable.\r
@@ -449,6 +593,9 @@ VariableServiceGetNextVariableName (
   Caution: This function may receive untrusted input.\r
   This function may be invoked in SMM mode, and datasize and data are external input.\r
   This function will do basic validation, before parse the data.\r
+  This function will parse the authentication carefully to avoid security issues, like\r
+  buffer overflow, integer overflow.\r
+  This function will check attribute carefully to avoid authentication bypass.\r
 \r
   @param VariableName                     Name of Variable to be found.\r
   @param VendorGuid                       Variable vendor GUID.\r
@@ -530,7 +677,7 @@ VariableServiceQueryVariableInfo (
   OUT UINT64                 *MaximumVariableStorageSize,\r
   OUT UINT64                 *RemainingVariableStorageSize,\r
   OUT UINT64                 *MaximumVariableSize\r
-  );  \r
+  );\r
 \r
 /**\r
   Mark a variable that will become read-only after leaving the DXE phase of execution.\r
@@ -623,45 +770,65 @@ VarCheckRegisterSetVariableCheckHandler (
   );\r
 \r
 /**\r
-  Variable property set.\r
+  Internal variable property get.\r
+\r
+  @param[in]  Name              Pointer to the variable name.\r
+  @param[in]  Guid              Pointer to the vendor GUID.\r
+  @param[out] VariableProperty  Pointer to the output variable property.\r
+\r
+  @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was got successfully.\r
+  @retval EFI_NOT_FOUND         The property of variable specified by the Name and Guid was not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalVarCheckVariablePropertyGet (\r
+  IN CHAR16                         *Name,\r
+  IN EFI_GUID                       *Guid,\r
+  OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty\r
+  );\r
+\r
+/**\r
+  Internal variable property set.\r
 \r
   @param[in] Name               Pointer to the variable name.\r
   @param[in] Guid               Pointer to the vendor GUID.\r
   @param[in] VariableProperty   Pointer to the input variable property.\r
 \r
   @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was set successfully.\r
-  @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,\r
-                                or the fields of VariableProperty are not valid.\r
-  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
-                                already been signaled.\r
   @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the variable property set request.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-VarCheckVariablePropertySet (\r
+InternalVarCheckVariablePropertySet (\r
   IN CHAR16                         *Name,\r
   IN EFI_GUID                       *Guid,\r
   IN VAR_CHECK_VARIABLE_PROPERTY    *VariableProperty\r
   );\r
 \r
+\r
 /**\r
-  Internal variable property get.\r
+  Variable property set.\r
 \r
-  @param[in]  Name              Pointer to the variable name.\r
-  @param[in]  Guid              Pointer to the vendor GUID.\r
-  @param[out] VariableProperty  Pointer to the output variable property.\r
+  @param[in] Name               Pointer to the variable name.\r
+  @param[in] Guid               Pointer to the vendor GUID.\r
+  @param[in] VariableProperty   Pointer to the input variable property.\r
 \r
-  @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was got successfully.\r
-  @retval EFI_NOT_FOUND         The property of variable specified by the Name and Guid was not found.\r
+  @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was set successfully.\r
+  @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,\r
+                                or the fields of VariableProperty are not valid.\r
+  @retval EFI_ACCESS_DENIED     EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has\r
+                                already been signaled.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough resource for the variable property set request.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-InternalVarCheckVariablePropertyGet (\r
+VarCheckVariablePropertySet (\r
   IN CHAR16                         *Name,\r
   IN EFI_GUID                       *Guid,\r
-  OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty\r
+  IN VAR_CHECK_VARIABLE_PROPERTY    *VariableProperty\r
   );\r
 \r
 /**\r
@@ -695,4 +862,134 @@ InitializeVariableQuota (
 \r
 extern VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;\r
 \r
+extern AUTH_VAR_LIB_CONTEXT_OUT mContextOut;\r
+\r
+/**\r
+  Finds variable in storage blocks of volatile and non-volatile storage areas.\r
+\r
+  This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
+  If VariableName is an empty string, then we just return the first\r
+  qualified variable without comparing VariableName and VendorGuid.\r
+\r
+  @param[in]  VariableName          Name of the variable to be found.\r
+  @param[in]  VendorGuid            Variable vendor GUID to be found.\r
+  @param[out] AuthVariableInfo      Pointer to AUTH_VARIABLE_INFO structure for\r
+                                    output of the variable found.\r
+\r
+  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,\r
+                                    while VendorGuid is NULL.\r
+  @retval EFI_SUCCESS               Variable successfully found.\r
+  @retval EFI_NOT_FOUND             Variable not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibFindVariable (\r
+  IN  CHAR16                *VariableName,\r
+  IN  EFI_GUID              *VendorGuid,\r
+  OUT AUTH_VARIABLE_INFO    *AuthVariableInfo\r
+  );\r
+\r
+/**\r
+  Finds next variable in storage blocks of volatile and non-volatile storage areas.\r
+\r
+  This code finds next variable in storage blocks of volatile and non-volatile storage areas.\r
+  If VariableName is an empty string, then we just return the first\r
+  qualified variable without comparing VariableName and VendorGuid.\r
+\r
+  @param[in]  VariableName          Name of the variable to be found.\r
+  @param[in]  VendorGuid            Variable vendor GUID to be found.\r
+  @param[out] AuthVariableInfo      Pointer to AUTH_VARIABLE_INFO structure for\r
+                                    output of the next variable.\r
+\r
+  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,\r
+                                    while VendorGuid is NULL.\r
+  @retval EFI_SUCCESS               Variable successfully found.\r
+  @retval EFI_NOT_FOUND             Variable not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibFindNextVariable (\r
+  IN  CHAR16                *VariableName,\r
+  IN  EFI_GUID              *VendorGuid,\r
+  OUT AUTH_VARIABLE_INFO    *AuthVariableInfo\r
+  );\r
+\r
+/**\r
+  Update the variable region with Variable information.\r
+\r
+  @param[in] AuthVariableInfo       Pointer AUTH_VARIABLE_INFO structure for\r
+                                    input of the variable.\r
+\r
+  @retval EFI_SUCCESS               The update operation is success.\r
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.\r
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibUpdateVariable (\r
+  IN AUTH_VARIABLE_INFO     *AuthVariableInfo\r
+  );\r
+\r
+/**\r
+  Get scratch buffer.\r
+\r
+  @param[in, out] ScratchBufferSize Scratch buffer size. If input size is greater than\r
+                                    the maximum supported buffer size, this value contains\r
+                                    the maximum supported buffer size as output.\r
+  @param[out]     ScratchBuffer     Pointer to scratch buffer address.\r
+\r
+  @retval EFI_SUCCESS       Get scratch buffer successfully.\r
+  @retval EFI_UNSUPPORTED   If input size is greater than the maximum supported buffer size.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibGetScratchBuffer (\r
+  IN OUT UINTN      *ScratchBufferSize,\r
+  OUT    VOID       **ScratchBuffer\r
+  );\r
+\r
+/**\r
+  This function is to check if the remaining variable space is enough to set\r
+  all Variables from argument list successfully. The purpose of the check\r
+  is to keep the consistency of the Variables to be in variable storage.\r
+\r
+  Note: Variables are assumed to be in same storage.\r
+  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,\r
+  so follow the argument sequence to check the Variables.\r
+\r
+  @param[in] Attributes         Variable attributes for Variable entries.\r
+  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
+                                A NULL terminates the list. The VariableSize of\r
+                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.\r
+                                It will be changed to variable total size as output.\r
+\r
+  @retval TRUE                  Have enough variable space to set the Variables successfully.\r
+  @retval FALSE                 No enough variable space to set the Variables successfully.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VariableExLibCheckRemainingSpaceForConsistency (\r
+  IN UINT32                     Attributes,\r
+  ...\r
+  );\r
+\r
+/**\r
+  Return TRUE if at OS runtime.\r
+\r
+  @retval TRUE If at OS runtime.\r
+  @retval FALSE If at boot time.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VariableExLibAtRuntime (\r
+  VOID\r
+  );\r
+\r
 #endif\r
index c5cef3194492ed73298e96e89cd66e0973f4c5b9..a95846a934e84681d81246c09dca909d8702007d 100644 (file)
@@ -1,17 +1,16 @@
 /** @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
+\r
 Copyright (C) 2013, Red Hat, Inc.\r
 Copyright (c) 2006 - 2015, 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
+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
+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
@@ -34,7 +33,7 @@ EDKII_VAR_CHECK_PROTOCOL       mVarCheck                  = { VarCheckRegisterSe
 \r
 /**\r
   Return TRUE if ExitBootServices () has been called.\r
-  \r
+\r
   @retval TRUE If ExitBootServices () has been called.\r
 **/\r
 BOOLEAN\r
@@ -49,8 +48,8 @@ AtRuntime (
 /**\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
+  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
@@ -141,7 +140,7 @@ GetFtwProtocol (
                   &gEfiFaultTolerantWriteProtocolGuid,\r
                   NULL,\r
                   FtwProtocol\r
-                  );                    \r
+                  );\r
   return Status;\r
 }\r
 \r
@@ -155,7 +154,7 @@ GetFtwProtocol (
   @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
 **/\r
 EFI_STATUS\r
 GetFvbByHandle (\r
@@ -176,7 +175,7 @@ GetFvbByHandle (
 \r
 /**\r
   Function returns an array of handles that support the FVB protocol\r
-  in a buffer allocated from pool. \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
@@ -187,7 +186,7 @@ GetFvbByHandle (
   @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
 **/\r
 EFI_STATUS\r
 GetFvbCountAndBuffer (\r
@@ -246,7 +245,7 @@ VariableClassAddressChangeEvent (
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.VolatileVariableBase);\r
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->VariableGlobal.HobVariableBase);\r
   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);\r
-  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);  \r
+  EfiConvertPointer (0x0, (VOID **) &mNvVariableCache);\r
   EfiConvertPointer (0x0, (VOID **) &mHandlerTable);\r
   for (Index = 0; Index < mNumberOfHandler; Index++) {\r
     EfiConvertPointer (0x0, (VOID **) &mHandlerTable[Index]);\r
@@ -257,6 +256,12 @@ VariableClassAddressChangeEvent (
 \r
   Status = EfiConvertList (0x0, &mVarCheckVariableList);\r
   ASSERT_EFI_ERROR (Status);\r
+\r
+  if (mContextOut.AddressPointer != NULL) {\r
+    for (Index = 0; Index < mContextOut.AddressPointerCount; Index++) {\r
+      EfiConvertPointer (0x0, (VOID **) &mContextOut.AddressPointer[Index]);\r
+    }\r
+  }\r
 }\r
 \r
 \r
@@ -288,8 +293,14 @@ OnReadyToBoot (
   InitializeVariableQuota ();\r
   ReclaimForOS ();\r
   if (FeaturePcdGet (PcdVariableCollectStatistics)) {\r
-    gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);\r
+    if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+      gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);\r
+    } else {\r
+      gBS->InstallConfigurationTable (&gEfiVariableGuid, gVariableInfo);\r
+    }\r
   }\r
+\r
+  gBS->CloseEvent (Event);\r
 }\r
 \r
 /**\r
@@ -316,17 +327,19 @@ OnEndOfDxe (
   if (PcdGetBool (PcdReclaimVariableSpaceAtEndOfDxe)) {\r
     ReclaimForOS ();\r
   }\r
+\r
+  gBS->CloseEvent (Event);\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
+  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
 **/\r
 VOID\r
 EFIAPI\r
@@ -394,21 +407,23 @@ FtwNotificationEvent (
       DEBUG ((DEBUG_WARN, "Variable driver failed to add EFI_MEMORY_RUNTIME attribute to Flash.\n"));\r
     }\r
   }\r
-  \r
+\r
   Status = VariableWriteServiceInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
+  }\r
+\r
   //\r
   // Install the Variable Write Architectural protocol.\r
   //\r
   Status = gBS->InstallProtocolInterface (\r
                   &mHandle,\r
-                  &gEfiVariableWriteArchProtocolGuid, \r
+                  &gEfiVariableWriteArchProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
                   NULL\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
-  \r
+\r
   //\r
   // Close the notify event to avoid install gEfiVariableWriteArchProtocolGuid again.\r
   //\r
@@ -419,13 +434,13 @@ FtwNotificationEvent (
 \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
+  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] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       Variable service successfully initialized.\r
 \r
 **/\r
@@ -463,13 +478,13 @@ VariableServiceInitialize (
   SystemTable->RuntimeServices->GetNextVariableName = VariableServiceGetNextVariableName;\r
   SystemTable->RuntimeServices->SetVariable         = VariableServiceSetVariable;\r
   SystemTable->RuntimeServices->QueryVariableInfo   = VariableServiceQueryVariableInfo;\r
-    \r
+\r
   //\r
   // Now install the Variable Runtime Architectural protocol on a new handle.\r
   //\r
   Status = gBS->InstallProtocolInterface (\r
                   &mHandle,\r
-                  &gEfiVariableArchProtocolGuid, \r
+                  &gEfiVariableArchProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
                   NULL\r
                   );\r
@@ -477,7 +492,7 @@ VariableServiceInitialize (
 \r
   //\r
   // Register FtwNotificationEvent () notify function.\r
-  // \r
+  //\r
   EfiCreateProtocolNotifyEvent (\r
     &gEfiFaultTolerantWriteProtocolGuid,\r
     TPL_CALLBACK,\r
@@ -500,9 +515,9 @@ VariableServiceInitialize (
   // Register the event handling function to reclaim variable for OS usage.\r
   //\r
   Status = EfiCreateEventReadyToBootEx (\r
-             TPL_NOTIFY, \r
-             OnReadyToBoot, \r
-             NULL, \r
+             TPL_NOTIFY,\r
+             OnReadyToBoot,\r
+             NULL,\r
              &ReadyToBootEvent\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableExLib.c
new file mode 100644 (file)
index 0000000..9067f64
--- /dev/null
@@ -0,0 +1,256 @@
+/** @file\r
+  Provides variable driver extended services.\r
+\r
+Copyright (c) 2015, 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
+/**\r
+  Finds variable in storage blocks of volatile and non-volatile storage areas.\r
+\r
+  This code finds variable in storage blocks of volatile and non-volatile storage areas.\r
+  If VariableName is an empty string, then we just return the first\r
+  qualified variable without comparing VariableName and VendorGuid.\r
+\r
+  @param[in]  VariableName          Name of the variable to be found.\r
+  @param[in]  VendorGuid            Variable vendor GUID to be found.\r
+  @param[out] AuthVariableInfo      Pointer to AUTH_VARIABLE_INFO structure for\r
+                                    output of the variable found.\r
+\r
+  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,\r
+                                    while VendorGuid is NULL.\r
+  @retval EFI_SUCCESS               Variable successfully found.\r
+  @retval EFI_NOT_FOUND             Variable not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibFindVariable (\r
+  IN  CHAR16                *VariableName,\r
+  IN  EFI_GUID              *VendorGuid,\r
+  OUT AUTH_VARIABLE_INFO    *AuthVariableInfo\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  VARIABLE_POINTER_TRACK        Variable;\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariable;\r
+\r
+  Status = FindVariable (\r
+             VariableName,\r
+             VendorGuid,\r
+             &Variable,\r
+             &mVariableModuleGlobal->VariableGlobal,\r
+             FALSE\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    AuthVariableInfo->Data = NULL;\r
+    AuthVariableInfo->DataSize = 0;\r
+    AuthVariableInfo->Attributes = 0;\r
+    AuthVariableInfo->PubKeyIndex = 0;\r
+    AuthVariableInfo->MonotonicCount = 0;\r
+    AuthVariableInfo->TimeStamp = NULL;\r
+    return Status;\r
+  }\r
+\r
+  AuthVariableInfo->DataSize        = DataSizeOfVariable (Variable.CurrPtr);\r
+  AuthVariableInfo->Data            = GetVariableDataPtr (Variable.CurrPtr);\r
+  AuthVariableInfo->Attributes      = Variable.CurrPtr->Attributes;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    AuthVariable = (AUTHENTICATED_VARIABLE_HEADER *) Variable.CurrPtr;\r
+    AuthVariableInfo->PubKeyIndex     = AuthVariable->PubKeyIndex;\r
+    AuthVariableInfo->MonotonicCount  = AuthVariable->MonotonicCount;\r
+    AuthVariableInfo->TimeStamp       = &AuthVariable->TimeStamp;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Finds next variable in storage blocks of volatile and non-volatile storage areas.\r
+\r
+  This code finds next variable in storage blocks of volatile and non-volatile storage areas.\r
+  If VariableName is an empty string, then we just return the first\r
+  qualified variable without comparing VariableName and VendorGuid.\r
+\r
+  @param[in]  VariableName          Name of the variable to be found.\r
+  @param[in]  VendorGuid            Variable vendor GUID to be found.\r
+  @param[out] AuthVariableInfo      Pointer to AUTH_VARIABLE_INFO structure for\r
+                                    output of the next variable.\r
+\r
+  @retval EFI_INVALID_PARAMETER     If VariableName is not an empty string,\r
+                                    while VendorGuid is NULL.\r
+  @retval EFI_SUCCESS               Variable successfully found.\r
+  @retval EFI_NOT_FOUND             Variable not found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibFindNextVariable (\r
+  IN  CHAR16                *VariableName,\r
+  IN  EFI_GUID              *VendorGuid,\r
+  OUT AUTH_VARIABLE_INFO    *AuthVariableInfo\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  VARIABLE_HEADER               *VariablePtr;\r
+  AUTHENTICATED_VARIABLE_HEADER *AuthVariablePtr;\r
+\r
+  Status = VariableServiceGetNextVariableInternal (\r
+             VariableName,\r
+             VendorGuid,\r
+             &VariablePtr\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    AuthVariableInfo->VariableName = NULL;\r
+    AuthVariableInfo->VendorGuid = NULL;\r
+    AuthVariableInfo->Data = NULL;\r
+    AuthVariableInfo->DataSize = 0;\r
+    AuthVariableInfo->Attributes = 0;\r
+    AuthVariableInfo->PubKeyIndex = 0;\r
+    AuthVariableInfo->MonotonicCount = 0;\r
+    AuthVariableInfo->TimeStamp = NULL;\r
+    return Status;\r
+  }\r
+\r
+  AuthVariableInfo->VariableName    = GetVariableNamePtr (VariablePtr);\r
+  AuthVariableInfo->VendorGuid      = GetVendorGuidPtr (VariablePtr);\r
+  AuthVariableInfo->DataSize        = DataSizeOfVariable (VariablePtr);\r
+  AuthVariableInfo->Data            = GetVariableDataPtr (VariablePtr);\r
+  AuthVariableInfo->Attributes      = VariablePtr->Attributes;\r
+  if (mVariableModuleGlobal->VariableGlobal.AuthFormat) {\r
+    AuthVariablePtr = (AUTHENTICATED_VARIABLE_HEADER *) VariablePtr;\r
+    AuthVariableInfo->PubKeyIndex     = AuthVariablePtr->PubKeyIndex;\r
+    AuthVariableInfo->MonotonicCount  = AuthVariablePtr->MonotonicCount;\r
+    AuthVariableInfo->TimeStamp       = &AuthVariablePtr->TimeStamp;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Update the variable region with Variable information.\r
+\r
+  @param[in] AuthVariableInfo       Pointer AUTH_VARIABLE_INFO structure for\r
+                                    input of the variable.\r
+\r
+  @retval EFI_SUCCESS               The update operation is success.\r
+  @retval EFI_INVALID_PARAMETER     Invalid parameter.\r
+  @retval EFI_WRITE_PROTECTED       Variable is write-protected.\r
+  @retval EFI_OUT_OF_RESOURCES      There is not enough resource.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibUpdateVariable (\r
+  IN AUTH_VARIABLE_INFO     *AuthVariableInfo\r
+  )\r
+{\r
+  VARIABLE_POINTER_TRACK    Variable;\r
+\r
+  FindVariable (AuthVariableInfo->VariableName, AuthVariableInfo->VendorGuid, &Variable, &mVariableModuleGlobal->VariableGlobal, FALSE);\r
+  return UpdateVariable (\r
+           AuthVariableInfo->VariableName,\r
+           AuthVariableInfo->VendorGuid,\r
+           AuthVariableInfo->Data,\r
+           AuthVariableInfo->DataSize,\r
+           AuthVariableInfo->Attributes,\r
+           AuthVariableInfo->PubKeyIndex,\r
+           AuthVariableInfo->MonotonicCount,\r
+           &Variable,\r
+           AuthVariableInfo->TimeStamp\r
+           );\r
+}\r
+\r
+/**\r
+  Get scratch buffer.\r
+\r
+  @param[in, out] ScratchBufferSize Scratch buffer size. If input size is greater than\r
+                                    the maximum supported buffer size, this value contains\r
+                                    the maximum supported buffer size as output.\r
+  @param[out]     ScratchBuffer     Pointer to scratch buffer address.\r
+\r
+  @retval EFI_SUCCESS       Get scratch buffer successfully.\r
+  @retval EFI_UNSUPPORTED   If input size is greater than the maximum supported buffer size.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+VariableExLibGetScratchBuffer (\r
+  IN OUT UINTN      *ScratchBufferSize,\r
+  OUT    VOID       **ScratchBuffer\r
+  )\r
+{\r
+  UINTN MaxBufferSize;\r
+\r
+  MaxBufferSize = mVariableModuleGlobal->ScratchBufferSize;\r
+  if (*ScratchBufferSize > MaxBufferSize) {\r
+    *ScratchBufferSize = MaxBufferSize;\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  *ScratchBuffer = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) mVariableModuleGlobal->VariableGlobal.VolatileVariableBase));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This function is to check if the remaining variable space is enough to set\r
+  all Variables from argument list successfully. The purpose of the check\r
+  is to keep the consistency of the Variables to be in variable storage.\r
+\r
+  Note: Variables are assumed to be in same storage.\r
+  The set sequence of Variables will be same with the sequence of VariableEntry from argument list,\r
+  so follow the argument sequence to check the Variables.\r
+\r
+  @param[in] Attributes         Variable attributes for Variable entries.\r
+  @param ...                    The variable argument list with type VARIABLE_ENTRY_CONSISTENCY *.\r
+                                A NULL terminates the list. The VariableSize of\r
+                                VARIABLE_ENTRY_CONSISTENCY is the variable data size as input.\r
+                                It will be changed to variable total size as output.\r
+\r
+  @retval TRUE                  Have enough variable space to set the Variables successfully.\r
+  @retval FALSE                 No enough variable space to set the Variables successfully.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VariableExLibCheckRemainingSpaceForConsistency (\r
+  IN UINT32                     Attributes,\r
+  ...\r
+  )\r
+{\r
+  VA_LIST Marker;\r
+  BOOLEAN Return;\r
+\r
+  VA_START (Marker, Attributes);\r
+\r
+  Return = CheckRemainingSpaceForConsistencyInternal (Attributes, Marker);\r
+\r
+  VA_END (Marker);\r
+\r
+  return Return;\r
+}\r
+\r
+/**\r
+  Return TRUE if at OS runtime.\r
+\r
+  @retval TRUE If at OS runtime.\r
+  @retval FALSE If at boot time.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+VariableExLibAtRuntime (\r
+  VOID\r
+  )\r
+{\r
+  return AtRuntime ();\r
+}\r
index 05d276590cbe5ff7a4a3c62269ce08b7d896ee54..6a523b8d76b4350a42b55a39985e593373144ebe 100644 (file)
@@ -1,7 +1,8 @@
 ## @file\r
-# This module installs variable arch protocol and variable write arch protocol.\r
+#  Provides variable service.\r
 #\r
-# It provides four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.\r
+#  This module installs variable arch protocol and variable write arch protocol to provide\r
+#  variable services: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo.\r
 #\r
 #  Caution: This module requires additional review when modified.\r
 #  This driver will have external input - variable data.\r
 #  buffer overflow or integer overflow.\r
 #\r
 # Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
-#\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
-#  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
+# 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
+# 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
@@ -42,7 +41,9 @@
   Variable.c\r
   VariableDxe.c\r
   Variable.h\r
+  Measurement.c\r
   VarCheck.c\r
+  VariableExLib.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -62,6 +63,8 @@
   PcdLib\r
   HobLib\r
   DevicePathLib\r
+  TpmMeasurementLib\r
+  AuthVariableLib\r
 \r
 [Protocols]\r
   gEfiFirmwareVolumeBlockProtocolGuid           ## CONSUMES\r
   gEdkiiVarCheckProtocolGuid                    ## PRODUCES\r
 \r
 [Guids]\r
+  ## PRODUCES             ## GUID # Signature of Variable store header\r
+  ## CONSUMES             ## GUID # Signature of Variable store header\r
+  ## SOMETIMES_CONSUMES   ## HOB\r
+  ## SOMETIMES_PRODUCES   ## SystemTable\r
+  gEfiAuthenticatedVariableGuid\r
+\r
   ## PRODUCES             ## GUID # Signature of Variable store header\r
   ## CONSUMES             ## GUID # Signature of Variable store header\r
   ## SOMETIMES_CONSUMES   ## HOB\r
   ## SOMETIMES_PRODUCES   ## SystemTable\r
   gEfiVariableGuid\r
+\r
   ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"\r
   ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"\r
   ## SOMETIMES_CONSUMES   ## Variable:L"Lang"\r
   ## SOMETIMES_PRODUCES   ## Variable:L"Lang"\r
   ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRecSupport"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SetupMode"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"PK"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"KEK"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SecureBoot"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SignatureSupport"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"VendorKeys"\r
   gEfiGlobalVariableGuid\r
+\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DB"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DBT"\r
+  gEfiImageSecurityDatabaseGuid\r
+\r
   gEfiEventVirtualAddressChangeGuid             ## CONSUMES             ## Event\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES             ## GUID\r
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRec####"\r
   gEfiEndOfDxeEventGroupGuid                    ## CONSUMES             ## Event\r
-  ## SOMETIMES_CONSUMES   ## HOB\r
-  gEdkiiFaultTolerantWriteGuid\r
+  gEdkiiFaultTolerantWriteGuid                  ## SOMETIMES_CONSUMES   ## HOB\r
   gEdkiiVarErrorFlagGuid                        ## CONSUMES             ## GUID\r
 \r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## SOMETIMES_CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64    ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize             ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize               ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                ## CONSUMES\r
 \r
 [FeaturePcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics  ## CONSUMES # statistic the information of variable.\r
-  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate ## CONSUMES # Auto update PlatformLang/Lang\r
 \r
 [Depex]\r
   TRUE\r
index ee8acd0ad15e03ec5b02d459b7e2b24fda6f14c1..48745b62f5dced96f8a0e908b2bc1bb50e37af57 100644 (file)
Binary files a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.uni and b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.uni differ
index 590840878281e000be92f78b6b89a9c9febeb572..1cf288cb989dcb926d053dc9cf2aac3826d582ad 100644 (file)
@@ -1,7 +1,6 @@
 /** @file\r
-\r
-  The sample implementation for SMM variable protocol. And this driver \r
-  implements  an SMI handler to communicate with the DXE runtime driver \r
+  The sample implementation for SMM variable protocol. And this driver\r
+  implements an SMI handler to communicate with the DXE runtime driver\r
   to provide variable services.\r
 \r
   Caution: This module requires additional review when modified.\r
 \r
   SmmVariableHandler() will receive untrusted input and do basic validation.\r
 \r
-  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(), \r
-  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), \r
+  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),\r
+  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
   SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
 \r
 Copyright (c) 2010 - 2015, 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
+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
+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 <Protocol/SmmVariable.h>\r
 #include <Protocol/SmmFirmwareVolumeBlock.h>\r
 #include <Protocol/SmmFaultTolerantWrite.h>\r
@@ -34,7 +34,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/SmmServicesTableLib.h>\r
 #include <Library/SmmMemLib.h>\r
 \r
-#include <Guid/VariableFormat.h>\r
 #include <Guid/SmmVariableCommon.h>\r
 #include "Variable.h"\r
 \r
@@ -48,6 +47,23 @@ UINTN                                                mVariableBufferPayloadSize;
 extern BOOLEAN                                       mEndOfDxe;\r
 extern BOOLEAN                                       mEnableLocking;\r
 \r
+/**\r
+  SecureBoot Hook for SetVariable.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  )\r
+{\r
+  return ;\r
+}\r
+\r
 /**\r
 \r
   This code sets variable in storage blocks (Volatile or Non-Volatile).\r
@@ -106,7 +122,7 @@ EDKII_SMM_VAR_CHECK_PROTOCOL mSmmVarCheck = { VarCheckRegisterSetVariableCheckHa
 \r
 /**\r
   Return TRUE if ExitBootServices () has been called.\r
-  \r
+\r
   @retval TRUE If ExitBootServices () has been called.\r
 **/\r
 BOOLEAN\r
@@ -120,8 +136,8 @@ AtRuntime (
 /**\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
+  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
@@ -204,8 +220,8 @@ GetFtwProtocol (
   // Locate Smm Fault Tolerent Write protocol\r
   //\r
   Status = gSmst->SmmLocateProtocol (\r
-                    &gEfiSmmFaultTolerantWriteProtocolGuid, \r
-                    NULL, \r
+                    &gEfiSmmFaultTolerantWriteProtocolGuid,\r
+                    NULL,\r
                     FtwProtocol\r
                     );\r
   return Status;\r
@@ -243,7 +259,7 @@ GetFvbByHandle (
 \r
 /**\r
   Function returns an array of handles that support the SMM FVB protocol\r
-  in a buffer allocated from pool. \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
@@ -314,16 +330,17 @@ GetFvbCountAndBuffer (
   InfoEntry and InfoSize are external input. Care must be taken to make sure not security issue at runtime.\r
 \r
   @param[in, out]  InfoEntry    A pointer to the buffer of variable information entry.\r
-                                On input, point to the variable information returned last time. if \r
+                                On input, point to the variable information returned last time. if\r
                                 InfoEntry->VendorGuid is zero, return the first information.\r
                                 On output, point to the next variable information.\r
   @param[in, out]  InfoSize     On input, the size of the variable information buffer.\r
                                 On output, the returned variable information size.\r
 \r
-  @retval EFI_SUCCESS          The variable information is found and returned successfully.\r
-  @retval EFI_UNSUPPORTED      No variable inoformation exists in variable driver. The \r
-                               PcdVariableCollectStatistics should be set TRUE to support it.\r
-  @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the next variable information.\r
+  @retval EFI_SUCCESS           The variable information is found and returned successfully.\r
+  @retval EFI_UNSUPPORTED       No variable inoformation exists in variable driver. The\r
+                                PcdVariableCollectStatistics should be set TRUE to support it.\r
+  @retval EFI_BUFFER_TOO_SMALL  The buffer is too small to hold the next variable information.\r
+  @retval EFI_INVALID_PARAMETER Input parameter is invalid.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -338,8 +355,11 @@ SmmVariableGetStatistics (
   CHAR16                                               *InfoName;\r
   EFI_GUID                                             VendorGuid;\r
 \r
-  ASSERT (InfoEntry != NULL);\r
-  VariableInfo = gVariableInfo; \r
+  if (InfoEntry == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  VariableInfo = gVariableInfo;\r
   if (VariableInfo == NULL) {\r
     return EFI_UNSUPPORTED;\r
   }\r
@@ -381,7 +401,7 @@ SmmVariableGetStatistics (
     }\r
     VariableInfo = VariableInfo->Next;\r
   };\r
-    \r
+\r
   if (VariableInfo == NULL) {\r
     *InfoSize = 0;\r
     return EFI_SUCCESS;\r
@@ -399,7 +419,7 @@ SmmVariableGetStatistics (
   CopyMem (InfoEntry, VariableInfo, sizeof (VARIABLE_INFO_ENTRY));\r
   CopyMem (InfoName, VariableInfo->Name, StrSize (VariableInfo->Name));\r
   *InfoSize = StatisticsInfoSize;\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -411,8 +431,8 @@ SmmVariableGetStatistics (
 \r
   Caution: This function may receive untrusted input.\r
   This variable data and communicate buffer are external input, so this function will do basic validation.\r
-  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(), \r
-  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(), \r
+  Each sub function VariableServiceGetVariable(), VariableServiceGetNextVariableName(),\r
+  VariableServiceSetVariable(), VariableServiceQueryVariableInfo(), ReclaimForOS(),\r
   SmmVariableGetStatistics() should also do validation based on its own knowledge.\r
 \r
   @param[in]     DispatchHandle  The unique handle assigned to this handler by SmiHandlerRegister().\r
@@ -422,11 +442,11 @@ SmmVariableGetStatistics (
                                  be conveyed from a non-SMM environment into an SMM environment.\r
   @param[in, out] CommBufferSize The size of the CommBuffer.\r
 \r
-  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers \r
+  @retval EFI_SUCCESS                         The interrupt was handled and quiesced. No other handlers\r
                                               should still be called.\r
-  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should \r
+  @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED  The interrupt has been quiesced but other handlers should\r
                                               still be called.\r
-  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still \r
+  @retval EFI_WARN_INTERRUPT_SOURCE_PENDING   The interrupt is still pending and other handlers should still\r
                                               be called.\r
   @retval EFI_INTERRUPT_PENDING               The interrupt could not be quiesced.\r
 **/\r
@@ -444,6 +464,7 @@ SmmVariableHandler (
   SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE         *SmmVariableHeader;\r
   SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME  *GetNextVariableName;\r
   SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO     *QueryVariableInfo;\r
+  SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE        *GetPayloadSize;\r
   VARIABLE_INFO_ENTRY                              *VariableInfo;\r
   SMM_VARIABLE_COMMUNICATE_LOCK_VARIABLE           *VariableToLock;\r
   SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *CommVariableProperty;\r
@@ -496,7 +517,7 @@ SmmVariableHandler (
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
       }\r
-      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name) \r
+      InfoSize = OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)\r
                  + SmmVariableHeader->DataSize + SmmVariableHeader->NameSize;\r
 \r
       //\r
@@ -525,7 +546,7 @@ SmmVariableHandler (
                  );\r
       CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
       break;\r
-      \r
+\r
     case SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME:\r
       if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name)) {\r
         DEBUG ((EFI_D_ERROR, "GetNextVariableName: SMM communication buffer size invalid!\n"));\r
@@ -570,7 +591,7 @@ SmmVariableHandler (
                  );\r
       CopyMem (SmmVariableFunctionHeader->Data, mVariableBufferPayload, CommBufferPayloadSize);\r
       break;\r
-      \r
+\r
     case SMM_VARIABLE_FUNCTION_SET_VARIABLE:\r
       if (CommBufferPayloadSize < OFFSET_OF(SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE, Name)) {\r
         DEBUG ((EFI_D_ERROR, "SetVariable: SMM communication buffer size invalid!\n"));\r
@@ -618,7 +639,7 @@ SmmVariableHandler (
                  (UINT8 *)SmmVariableHeader->Name + SmmVariableHeader->NameSize\r
                  );\r
       break;\r
-      \r
+\r
     case SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO:\r
       if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {\r
         DEBUG ((EFI_D_ERROR, "QueryVariableInfo: SMM communication buffer size invalid!\n"));\r
@@ -634,6 +655,16 @@ SmmVariableHandler (
                  );\r
       break;\r
 \r
+    case SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE:\r
+      if (CommBufferPayloadSize < sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE)) {\r
+        DEBUG ((EFI_D_ERROR, "GetPayloadSize: SMM communication buffer size invalid!\n"));\r
+        return EFI_SUCCESS;\r
+      }\r
+      GetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
+      GetPayloadSize->VariablePayloadSize = mVariableBufferPayloadSize;\r
+      Status = EFI_SUCCESS;\r
+      break;\r
+\r
     case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:\r
       mEndOfDxe = TRUE;\r
       //\r
@@ -647,7 +678,7 @@ SmmVariableHandler (
       ReclaimForOS ();\r
       Status = EFI_SUCCESS;\r
       break;\r
-  \r
+\r
     case SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE:\r
       mAtRuntime = TRUE;\r
       Status = EFI_SUCCESS;\r
@@ -658,15 +689,15 @@ SmmVariableHandler (
       InfoSize = TempCommBufferSize - SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
 \r
       //\r
-      // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here. \r
-      // It is covered by previous CommBuffer check \r
+      // Do not need to check SmmVariableFunctionHeader->Data in SMRAM here.\r
+      // It is covered by previous CommBuffer check\r
       //\r
-     \r
+\r
       if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)CommBufferSize, sizeof(UINTN))) {\r
         DEBUG ((EFI_D_ERROR, "GetStatistics: SMM communication buffer in SMRAM!\n"));\r
         Status = EFI_ACCESS_DENIED;\r
         goto EXIT;\r
-      }  \r
+      }\r
 \r
       Status = SmmVariableGetStatistics (VariableInfo, &InfoSize);\r
       *CommBufferSize = InfoSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
@@ -784,16 +815,16 @@ SmmEndOfDxeCallback (
 /**\r
   SMM Fault Tolerant Write protocol notification event handler.\r
 \r
-  Non-Volatile variable write may needs FTW protocol to reclaim when \r
+  Non-Volatile variable write may needs FTW protocol to reclaim when\r
   writting variable.\r
-  \r
+\r
   @param  Protocol   Points to the protocol's unique identifier\r
   @param  Interface  Points to the interface instance\r
   @param  Handle     The handle on which the interface was installed\r
 \r
   @retval EFI_SUCCESS   SmmEventCallback runs successfully\r
   @retval EFI_NOT_FOUND The Fvb protocol for variable is not found.\r
-  \r
+\r
  **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -808,7 +839,7 @@ SmmFtwNotificationEvent (
   EFI_SMM_FAULT_TOLERANT_WRITE_PROTOCOL   *FtwProtocol;\r
   EFI_PHYSICAL_ADDRESS                    NvStorageVariableBase;\r
   UINTN                                   FtwMaxBlockSize;\r
-  \r
+\r
   if (mVariableModuleGlobal->FvbInstance != NULL) {\r
     return EFI_SUCCESS;\r
   }\r
@@ -839,10 +870,12 @@ SmmFtwNotificationEvent (
   }\r
 \r
   mVariableModuleGlobal->FvbInstance = FvbProtocol;\r
-  \r
+\r
   Status = VariableWriteServiceInitialize ();\r
-  ASSERT_EFI_ERROR (Status);\r
\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Variable write service initialization failed. Status = %r\n", Status));\r
+  }\r
+\r
   //\r
   // Notify the variable wrapper driver the variable write service is ready\r
   //\r
@@ -853,20 +886,20 @@ SmmFtwNotificationEvent (
                   NULL\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
-  \r
+\r
   return EFI_SUCCESS;\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
+  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] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       Variable service successfully initialized.\r
 \r
 **/\r
@@ -908,8 +941,8 @@ VariableServiceInitialize (
                     );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +\r
-                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - sizeof (VARIABLE_HEADER);\r
+  mVariableBufferPayloadSize = GetNonVolatileMaxVariableSize () +\r
+                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - GetVariableHeaderSize ();\r
 \r
   Status = gSmst->SmmAllocatePool (\r
                     EfiRuntimeServicesData,\r
@@ -924,7 +957,7 @@ VariableServiceInitialize (
   VariableHandle = NULL;\r
   Status = gSmst->SmiHandlerRegister (SmmVariableHandler, &gEfiSmmVariableProtocolGuid, &VariableHandle);\r
   ASSERT_EFI_ERROR (Status);\r
-  \r
+\r
   //\r
   // Notify the variable wrapper driver the variable service is ready\r
   //\r
@@ -935,7 +968,7 @@ VariableServiceInitialize (
                                         &gSmmVariable\r
                                         );\r
   ASSERT_EFI_ERROR (Status);\r
\r
+\r
   //\r
   // Register EFI_SMM_END_OF_DXE_PROTOCOL_GUID notify function.\r
   //\r
@@ -948,7 +981,7 @@ VariableServiceInitialize (
 \r
   //\r
   // Register FtwNotificationEvent () notify function.\r
-  // \r
+  //\r
   Status = gSmst->SmmRegisterProtocolNotify (\r
                     &gEfiSmmFaultTolerantWriteProtocolGuid,\r
                     SmmFtwNotificationEvent,\r
@@ -957,7 +990,7 @@ VariableServiceInitialize (
   ASSERT_EFI_ERROR (Status);\r
 \r
   SmmFtwNotificationEvent (NULL, NULL, NULL);\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
index 9b8675b631add1246015fe4eaa7694ee94d11991..47b7f3a2c2d7c6be4e2a7e7cdb3cdb0dfb860725 100644 (file)
@@ -1,16 +1,22 @@
 ## @file\r
+#  Provides SMM variable service.\r
+#\r
 #  This module installs SMM variable protocol into SMM protocol database,\r
-#  which can be used by SMM driver, and installs SMM variable protocol \r
+#  which can be used by SMM driver, and installs SMM variable protocol\r
 #  into BS protocol database, which can be used to notify the SMM Runtime\r
 #  Dxe driver that the SMM variable service is ready.\r
-#  This module should be used with SMM Runtime DXE module together. The \r
-#  SMM Runtime DXE module would install variable arch protocol and variable \r
+#  This module should be used with SMM Runtime DXE module together. The\r
+#  SMM Runtime DXE module would install variable arch protocol and variable\r
 #  write arch protocol based on SMM variable module.\r
 #\r
 #  Caution: This module requires additional review when modified.\r
 #  This driver will have external input - variable data and communicate buffer in SMM mode.\r
-#  This external input must be validated carefully to avoid security issue like\r
-#  buffer overflow, integer overflow.\r
+#  This external input must be validated carefully to avoid security issues such as\r
+#  buffer overflow or integer overflow.\r
+#    The whole SMM authentication variable design relies on the integrity of flash part and SMM.\r
+#  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory\r
+#  may not be modified without authorization. If platform fails to protect these resources,\r
+#  the authentication service provided in this driver will be broken, and the behavior is undefined.\r
 #\r
 # Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
@@ -20,7 +26,6 @@
 # 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
 \r
 [Defines]\r
@@ -46,6 +51,7 @@
   VariableSmm.c\r
   VarCheck.c\r
   Variable.h\r
+  VariableExLib.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
@@ -65,6 +71,7 @@
   PcdLib\r
   DevicePathLib\r
   SmmMemLib\r
+  AuthVariableLib\r
 \r
 [Protocols]\r
   gEfiSmmFirmwareVolumeBlockProtocolGuid        ## CONSUMES\r
   ## PRODUCES             ## GUID # Signature of Variable store header\r
   ## CONSUMES             ## GUID # Signature of Variable store header\r
   ## SOMETIMES_CONSUMES   ## HOB\r
+  ## SOMETIMES_PRODUCES   ## SystemTable\r
+  gEfiAuthenticatedVariableGuid\r
+\r
+  ## PRODUCES             ## GUID # Signature of Variable store header\r
+  ## CONSUMES             ## GUID # Signature of Variable store header\r
+  ## SOMETIMES_CONSUMES   ## HOB\r
+  ## SOMETIMES_PRODUCES   ## SystemTable\r
   gEfiVariableGuid\r
+\r
   ## SOMETIMES_CONSUMES   ## Variable:L"PlatformLang"\r
   ## SOMETIMES_PRODUCES   ## Variable:L"PlatformLang"\r
   ## SOMETIMES_CONSUMES   ## Variable:L"Lang"\r
   ## SOMETIMES_PRODUCES   ## Variable:L"Lang"\r
   ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRecSupport"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SetupMode"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"PK"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"KEK"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SecureBoot"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SignatureSupport"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"VendorKeys"\r
   gEfiGlobalVariableGuid\r
-  gSmmVariableWriteGuid                         ## PRODUCES             ## UNDEFINED # Install protocol\r
+\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DB"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DBT"\r
+  gEfiImageSecurityDatabaseGuid\r
+\r
+  gSmmVariableWriteGuid                         ## PRODUCES             ## GUID # Install protocol\r
   gEfiSystemNvDataFvGuid                        ## CONSUMES             ## GUID\r
   gEfiHardwareErrorVariableGuid                 ## SOMETIMES_CONSUMES   ## Variable:L"HwErrRec####"\r
-  ## SOMETIMES_CONSUMES   ## HOB\r
-  gEdkiiFaultTolerantWriteGuid\r
+  gEdkiiFaultTolerantWriteGuid                  ## SOMETIMES_CONSUMES   ## HOB\r
   gEdkiiVarErrorFlagGuid                        ## CONSUMES             ## GUID\r
 \r
 [Pcd]\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize      ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase      ## SOMETIMES_CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64    ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize               ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize       ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase       ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64     ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                  ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize              ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize     ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                 ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxUserNvVariableSpaceSize           ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdBoottimeReservedNvVariableSpaceSize  ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe  ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe   ## CONSUMES\r
 \r
 [FeaturePcd]\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics   ## CONSUMES # statistic the information of variable.\r
-  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate  ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics        ## CONSUMES  # statistic the information of variable.\r
+  gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate       ## CONSUMES  # Auto update PlatformLang/Lang\r
 \r
 [Depex]\r
   TRUE\r
index 3e72476e6479820c62b0c68f2e581a2be40917d1..60502d0451b40b40de52e1339e7666801b1b5409 100644 (file)
Binary files a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.uni and b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.uni differ
index e42cc12b4de70d9e51476aa891469a7d1a84cea5..46f984c809f21e48ed023ea68e685ba74d3f854e 100644 (file)
Binary files a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmExtra.uni and b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmExtra.uni differ
index 30fb5df6c0c0a136cda4434f67c231055dec1013..0a076ae4675ad6167869fff58aca7c51bcbb66d4 100644 (file)
@@ -1,5 +1,4 @@
 /** @file\r
-\r
   Implement all four UEFI Runtime Variable services for the nonvolatile\r
   and volatile storage space and install variable architecture protocol\r
   based on SMM variable module.\r
   InitCommunicateBuffer() is really function to check the variable data size.\r
 \r
 Copyright (c) 2010 - 2015, 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
+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
+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
 #include <PiDxe.h>\r
@@ -39,15 +38,13 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/UefiRuntimeLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
-#include <Library/PcdLib.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/BaseLib.h>\r
 \r
 #include <Guid/EventGroup.h>\r
-#include <Guid/VariableFormat.h>\r
 #include <Guid/SmmVariableCommon.h>\r
 \r
-EFI_HANDLE                       mHandle                    = NULL; \r
+EFI_HANDLE                       mHandle                    = NULL;\r
 EFI_SMM_VARIABLE_PROTOCOL       *mSmmVariable               = NULL;\r
 EFI_EVENT                        mVirtualAddressChangeEvent = NULL;\r
 EFI_SMM_COMMUNICATION_PROTOCOL  *mSmmCommunication          = NULL;\r
@@ -59,6 +56,20 @@ EFI_LOCK                         mVariableServicesLock;
 EDKII_VARIABLE_LOCK_PROTOCOL     mVariableLock;\r
 EDKII_VAR_CHECK_PROTOCOL         mVarCheck;\r
 \r
+/**\r
+  SecureBoot Hook for SetVariable.\r
+\r
+  @param[in] VariableName                 Name of Variable to be found.\r
+  @param[in] VendorGuid                   Variable vendor GUID.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+SecureBootHook (\r
+  IN CHAR16                                 *VariableName,\r
+  IN EFI_GUID                               *VendorGuid\r
+  );\r
+\r
 /**\r
   Acquires lock only at boot time. Simply returns at runtime.\r
 \r
@@ -115,7 +126,7 @@ ReleaseLockOnlyAtBootTime (
   @param[out]      DataPtr          Points to the data in the communicate buffer.\r
   @param[in]       DataSize         The data size to send to SMM.\r
   @param[in]       Function         The function number to initialize the communicate header.\r
-                      \r
+\r
   @retval EFI_INVALID_PARAMETER     The data size is too big.\r
   @retval EFI_SUCCESS               Find the specified variable.\r
 \r
@@ -127,10 +138,10 @@ InitCommunicateBuffer (
   IN      UINTN                             Function\r
   )\r
 {\r
-  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;  \r
-  SMM_VARIABLE_COMMUNICATE_HEADER           *SmmVariableFunctionHeader; \r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;\r
+  SMM_VARIABLE_COMMUNICATE_HEADER           *SmmVariableFunctionHeader;\r
+\r
 \r
\r
   if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
@@ -138,7 +149,7 @@ InitCommunicateBuffer (
   SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) mVariableBuffer;\r
   CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
   SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
-   \r
+\r
   SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
   SmmVariableFunctionHeader->Function = Function;\r
   if (DataPtr != NULL) {\r
@@ -155,8 +166,8 @@ InitCommunicateBuffer (
   @param[in]   DataSize               This size of the function header and the data.\r
 \r
   @retval      EFI_SUCCESS            Success is returned from the functin in SMM.\r
-  @retval      Others                 Failure is returned from the function in SMM. \r
-  \r
+  @retval      Others                 Failure is returned from the function in SMM.\r
+\r
 **/\r
 EFI_STATUS\r
 SendCommunicateBuffer (\r
@@ -165,9 +176,9 @@ SendCommunicateBuffer (
 {\r
   EFI_STATUS                                Status;\r
   UINTN                                     CommSize;\r
-  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;  \r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;\r
   SMM_VARIABLE_COMMUNICATE_HEADER           *SmmVariableFunctionHeader;\r
-  \r
+\r
   CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;\r
   Status = mSmmCommunication->Communicate (mSmmCommunication, mVariableBufferPhysical, &CommSize);\r
   ASSERT_EFI_ERROR (Status);\r
@@ -432,7 +443,7 @@ Done:
   @param[in, out] DataSize           Size of Data found. If size is less than the\r
                                      data, this value contains the required size.\r
   @param[out]     Data               Data pointer.\r
-                      \r
+\r
   @retval EFI_INVALID_PARAMETER      Invalid parameter.\r
   @retval EFI_SUCCESS                Find the specified variable.\r
   @retval EFI_NOT_FOUND              Not found.\r
@@ -594,7 +605,6 @@ RuntimeServiceGetNextVariableName (
   //\r
   PayloadSize = OFFSET_OF (SMM_VARIABLE_COMMUNICATE_GET_NEXT_VARIABLE_NAME, Name) + MAX (OutVariableNameSize, InVariableNameSize);\r
 \r
-\r
   Status = InitCommunicateBuffer ((VOID **)&SmmGetNextVariableName, PayloadSize, SMM_VARIABLE_FUNCTION_GET_NEXT_VARIABLE_NAME);\r
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
@@ -633,9 +643,9 @@ RuntimeServiceGetNextVariableName (
   if (EFI_ERROR (Status)) {\r
     goto Done;\r
   }\r
-  \r
+\r
   CopyGuid (VendorGuid, &SmmGetNextVariableName->Guid);\r
-  CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);  \r
+  CopyMem (VariableName, SmmGetNextVariableName->Name, SmmGetNextVariableName->NameSize);\r
 \r
 Done:\r
   ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
@@ -673,16 +683,16 @@ RuntimeServiceSetVariable (
   )\r
 {\r
   EFI_STATUS                                Status;\r
-  UINTN                                     PayloadSize; \r
+  UINTN                                     PayloadSize;\r
   SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE  *SmmVariableHeader;\r
   UINTN                                     VariableNameSize;\r
-    \r
+\r
   //\r
   // Check input parameters.\r
   //\r
   if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
-  } \r
+  }\r
 \r
   if (DataSize != 0 && Data == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -700,7 +710,7 @@ RuntimeServiceSetVariable (
   }\r
 \r
   AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
\r
+\r
   //\r
   // Init the communicate buffer. The buffer data size is:\r
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + PayloadSize.\r
@@ -726,6 +736,15 @@ RuntimeServiceSetVariable (
 \r
 Done:\r
   ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+\r
+  if (!EfiAtRuntime ()) {\r
+    if (!EFI_ERROR (Status)) {\r
+      SecureBootHook (\r
+        VariableName,\r
+        VendorGuid\r
+        );\r
+    }\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -794,7 +813,7 @@ RuntimeServiceQueryVariableInfo (
   //\r
   *MaximumVariableSize          = SmmQueryVariableInfo->MaximumVariableSize;\r
   *MaximumVariableStorageSize   = SmmQueryVariableInfo->MaximumVariableStorageSize;\r
-  *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize; \r
+  *RemainingVariableStorageSize = SmmQueryVariableInfo->RemainingVariableStorageSize;\r
 \r
 Done:\r
   ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
@@ -822,7 +841,7 @@ OnExitBootServices (
   // Init the communicate buffer. The buffer data size is:\r
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
   //\r
-  InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE); \r
+  InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_EXIT_BOOT_SERVICE);\r
 \r
   //\r
   // Send data to SMM.\r
@@ -852,11 +871,13 @@ OnReadyToBoot (
   // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE.\r
   //\r
   InitCommunicateBuffer (NULL, 0, SMM_VARIABLE_FUNCTION_READY_TO_BOOT);\r
-  \r
+\r
   //\r
   // Send data to SMM.\r
   //\r
   SendCommunicateBuffer (0);\r
+\r
+  gBS->CloseEvent (Event);\r
 }\r
 \r
 \r
@@ -881,13 +902,86 @@ VariableAddressChangeEvent (
   EfiConvertPointer (0x0, (VOID **) &mSmmCommunication);\r
 }\r
 \r
+/**\r
+  This code gets variable payload size.\r
+\r
+  @param[out] VariablePayloadSize   Output pointer to variable payload size.\r
+\r
+  @retval EFI_SUCCESS               Get successfully.\r
+  @retval Others                    Get unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetVariablePayloadSize (\r
+  OUT UINTN                         *VariablePayloadSize\r
+  )\r
+{\r
+  EFI_STATUS                                Status;\r
+  SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *SmmGetPayloadSize;\r
+  EFI_SMM_COMMUNICATE_HEADER                *SmmCommunicateHeader;\r
+  SMM_VARIABLE_COMMUNICATE_HEADER           *SmmVariableFunctionHeader;\r
+  UINTN                                     CommSize;\r
+  UINT8                                     *CommBuffer;\r
+\r
+  SmmGetPayloadSize = NULL;\r
+  CommBuffer = NULL;\r
+\r
+  if(VariablePayloadSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  AcquireLockOnlyAtBootTime(&mVariableServicesLock);\r
+\r
+  //\r
+  // Init the communicate buffer. The buffer data size is:\r
+  // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
+  //\r
+  CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
+  CommBuffer = AllocateZeroPool (CommSize);\r
+  if (CommBuffer == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommBuffer;\r
+  CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);\r
+  SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);\r
+\r
+  SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;\r
+  SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;\r
+  SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *) SmmVariableFunctionHeader->Data;\r
+\r
+  //\r
+  // Send data to SMM.\r
+  //\r
+  Status = mSmmCommunication->Communicate (mSmmCommunication, CommBuffer, &CommSize);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = SmmVariableFunctionHeader->ReturnStatus;\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Get data from SMM.\r
+  //\r
+  *VariablePayloadSize = SmmGetPayloadSize->VariablePayloadSize;\r
+\r
+Done:\r
+  if (CommBuffer != NULL) {\r
+    FreePool (CommBuffer);\r
+  }\r
+  ReleaseLockOnlyAtBootTime (&mVariableServicesLock);\r
+  return Status;\r
+}\r
 \r
 /**\r
   Initialize variable service and install Variable Architectural protocol.\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
 **/\r
 VOID\r
 EFIAPI\r
@@ -902,15 +996,15 @@ SmmVariableReady (
   if (EFI_ERROR (Status)) {\r
     return;\r
   }\r
-  \r
+\r
   Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &mSmmCommunication);\r
   ASSERT_EFI_ERROR (Status);\r
-  \r
+\r
   //\r
   // Allocate memory for variable communicate buffer.\r
   //\r
-  mVariableBufferPayloadSize = MAX (PcdGet32 (PcdMaxVariableSize), PcdGet32 (PcdMaxHardwareErrorVariableSize)) +\r
-                               OFFSET_OF (SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY, Name) - sizeof (VARIABLE_HEADER);\r
+  Status = GetVariablePayloadSize (&mVariableBufferPayloadSize);\r
+  ASSERT_EFI_ERROR (Status);\r
   mVariableBufferSize  = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + mVariableBufferPayloadSize;\r
   mVariableBuffer      = AllocateRuntimePool (mVariableBufferSize);\r
   ASSERT (mVariableBuffer != NULL);\r
@@ -924,13 +1018,13 @@ SmmVariableReady (
   gRT->GetNextVariableName = RuntimeServiceGetNextVariableName;\r
   gRT->SetVariable         = RuntimeServiceSetVariable;\r
   gRT->QueryVariableInfo   = RuntimeServiceQueryVariableInfo;\r
\r
+\r
   //\r
   // Install the Variable Architectural Protocol on a new handle.\r
   //\r
   Status = gBS->InstallProtocolInterface (\r
                   &mHandle,\r
-                  &gEfiVariableArchProtocolGuid, \r
+                  &gEfiVariableArchProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
                   NULL\r
                   );\r
@@ -955,6 +1049,8 @@ SmmVariableReady (
                   NULL\r
                   );\r
   ASSERT_EFI_ERROR (Status);\r
+\r
+  gBS->CloseEvent (Event);\r
 }\r
 \r
 \r
@@ -963,7 +1059,7 @@ SmmVariableReady (
 \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
 **/\r
 VOID\r
 EFIAPI\r
@@ -982,26 +1078,28 @@ SmmVariableWriteReady (
   if (EFI_ERROR (Status)) {\r
     return;\r
   }\r
\r
+\r
   Status = gBS->InstallProtocolInterface (\r
                   &mHandle,\r
-                  &gEfiVariableWriteArchProtocolGuid, \r
+                  &gEfiVariableWriteArchProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
                   NULL\r
                   );\r
-  ASSERT_EFI_ERROR (Status);  \r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  gBS->CloseEvent (Event);\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
+  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] ImageHandle    The firmware allocated handle for the EFI image.\r
   @param[in] SystemTable    A pointer to the EFI System Table.\r
-  \r
+\r
   @retval EFI_SUCCESS       Variable service successfully initialized.\r
 \r
 **/\r
@@ -1024,10 +1122,10 @@ VariableSmmRuntimeInitialize (
   // Smm variable service is ready\r
   //\r
   EfiCreateProtocolNotifyEvent (\r
-    &gEfiSmmVariableProtocolGuid, \r
-    TPL_CALLBACK, \r
-    SmmVariableReady, \r
-    NULL, \r
+    &gEfiSmmVariableProtocolGuid,\r
+    TPL_CALLBACK,\r
+    SmmVariableReady,\r
+    NULL,\r
     &SmmVariableRegistration\r
     );\r
 \r
@@ -1035,10 +1133,10 @@ VariableSmmRuntimeInitialize (
   // Smm Non-Volatile variable write service is ready\r
   //\r
   EfiCreateProtocolNotifyEvent (\r
-    &gSmmVariableWriteGuid, \r
-    TPL_CALLBACK, \r
-    SmmVariableWriteReady, \r
-    NULL, \r
+    &gSmmVariableWriteGuid,\r
+    TPL_CALLBACK,\r
+    SmmVariableWriteReady,\r
+    NULL,\r
     &SmmVariableWriteRegistration\r
     );\r
 \r
@@ -1046,11 +1144,11 @@ VariableSmmRuntimeInitialize (
   // Register the event to reclaim variable for OS usage.\r
   //\r
   EfiCreateEventReadyToBootEx (\r
-    TPL_NOTIFY, \r
-    OnReadyToBoot, \r
-    NULL, \r
+    TPL_NOTIFY,\r
+    OnReadyToBoot,\r
+    NULL,\r
     &OnReadyToBootEvent\r
-    );             \r
+    );\r
 \r
   //\r
   // Register the event to inform SMM variable that it is at runtime.\r
@@ -1062,7 +1160,7 @@ VariableSmmRuntimeInitialize (
          NULL,\r
          &gEfiEventExitBootServicesGuid,\r
          &ExitBootServiceEvent\r
-         ); \r
+         );\r
 \r
   //\r
   // Register the event to inform SMM variable that it is at runtime for legacy boot.\r
@@ -1086,7 +1184,7 @@ VariableSmmRuntimeInitialize (
          &gEfiEventVirtualAddressChangeGuid,\r
          &mVirtualAddressChangeEvent\r
          );\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
index a72619e002ec57aa6ada6e5b7922d24664e841d3..82ddb00a19c17918b407f82196216501cfbd3668 100644 (file)
@@ -1,24 +1,25 @@
 ## @file\r
-#  This module is the Runtime DXE part correspond to SMM variable module.\r
+#  Runtime DXE part corresponding to SMM authenticated variable module.\r
 #\r
-#  It installs variable arch protocol and variable write arch protocol to provide\r
-#  four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo\r
-#  and works with SMM variable module together.\r
+#  This module installs variable arch protocol and variable write arch protocol to provide\r
+#  variable service. This module need work together with SMM authenticated variable module.\r
 #\r
 #  Caution: This module requires additional review when modified.\r
 #  This driver will have external input - variable data.\r
 #  This external input must be validated carefully to avoid security issues such as\r
 #  buffer overflow or integer overflow.\r
+#    The whole SMM authentication variable design relies on the integrity of flash part and SMM.\r
+#  which is assumed to be protected by platform.  All variable code and metadata in flash/SMM Memory\r
+#  may not be modified without authorization. If platform fails to protect these resources,\r
+#  the authentication service provided in this driver will be broken, and the behavior is undefined.\r
 #\r
 # Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>\r
-#\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
-#  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
+# 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
+# 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
@@ -41,6 +42,7 @@
 \r
 [Sources]\r
   VariableSmmRuntimeDxe.c\r
+  Measurement.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
 \r
 [LibraryClasses]\r
   MemoryAllocationLib\r
-  BaseLib  \r
+  BaseLib\r
   UefiBootServicesTableLib\r
   DebugLib\r
   UefiRuntimeLib\r
   DxeServicesTableLib\r
   UefiDriverEntryPoint\r
-  PcdLib  \r
+  TpmMeasurementLib\r
 \r
 [Protocols]\r
   gEfiVariableWriteArchProtocolGuid             ## PRODUCES\r
   ## CONSUMES ## GUID # Protocol notify\r
   gSmmVariableWriteGuid\r
 \r
-[Pcd]\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize                 ## CONSUMES\r
-  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize    ## CONSUMES\r
-  \r
+  ## SOMETIMES_CONSUMES   ## Variable:L"PK"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"KEK"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"SecureBoot"\r
+  gEfiGlobalVariableGuid\r
+\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DB"\r
+  ## SOMETIMES_CONSUMES   ## Variable:L"DBX"\r
+  gEfiImageSecurityDatabaseGuid\r
+\r
 [Depex]\r
   gEfiSmmCommunicationProtocolGuid\r
 \r