diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VarCheck.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VarCheck.c
index 76bd7b4d90..3f4beb07f0 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VarCheck.c
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VarCheck.c
@@ -48,14 +48,6 @@ typedef struct {
   INTERNAL_VAR_CHECK_FUNCTION   CheckFunction;
 } UEFI_DEFINED_VARIABLE_ENTRY;
 
-typedef struct _EFI_LOAD_OPTION {
-  UINT32                   Attributes;
-  UINT16                   FilePathListLength;
-//CHAR16                   Description[];
-//EFI_DEVICE_PATH_PROTOCOL FilePathList[];
-//UINT8                    OptionalData[];
-} EFI_LOAD_OPTION;
-
 /**
   Internal check for load option.
 
@@ -75,16 +67,16 @@ InternalVarCheckLoadOption (
   IN VOID                           *Data
   )
 {
-  EFI_LOAD_OPTION           *LoadOption;
+  UINT16                    FilePathListLength;
   CHAR16                    *Description;
   EFI_DEVICE_PATH_PROTOCOL  *FilePathList;
 
-  LoadOption = (EFI_LOAD_OPTION *) Data;
+  FilePathListLength = *((UINT16 *) ((UINTN) Data + sizeof (UINT32)));
 
   //
   // Check Description
   //
-  Description = (CHAR16 *) ((UINTN) Data + sizeof (EFI_LOAD_OPTION));
+  Description = (CHAR16 *) ((UINTN) Data + sizeof (UINT32) + sizeof (UINT16));
   while (Description < (CHAR16 *) ((UINTN) Data + DataSize)) {
     if (*Description == L'\0') {
       break;
@@ -100,16 +92,16 @@ InternalVarCheckLoadOption (
   // Check FilePathList
   //
   FilePathList = (EFI_DEVICE_PATH_PROTOCOL *) Description;
-  if ((UINTN) FilePathList > (MAX_ADDRESS - LoadOption->FilePathListLength)) {
+  if ((UINTN) FilePathList > (MAX_ADDRESS - FilePathListLength)) {
     return EFI_INVALID_PARAMETER;
   }
-  if (((UINTN) FilePathList + LoadOption->FilePathListLength) > ((UINTN) Data + DataSize)) {
+  if (((UINTN) FilePathList + FilePathListLength) > ((UINTN) Data + DataSize)) {
     return EFI_INVALID_PARAMETER;
   }
-  if (LoadOption->FilePathListLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
+  if (FilePathListLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
     return EFI_INVALID_PARAMETER;
   }
-  if (!IsDevicePathValid (FilePathList, LoadOption->FilePathListLength)) {
+  if (!IsDevicePathValid (FilePathList, FilePathListLength)) {
     return EFI_INVALID_PARAMETER;
   }
 
@@ -573,7 +565,7 @@ UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
       0,
       VARIABLE_ATTRIBUTE_NV_BS_RT,
-      sizeof (EFI_LOAD_OPTION),
+      sizeof (UINT32) + sizeof (UINT16),
       MAX_UINTN
     },
     InternalVarCheckLoadOption
@@ -584,7 +576,7 @@ UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
       0,
       VARIABLE_ATTRIBUTE_NV_BS_RT,
-      sizeof (EFI_LOAD_OPTION),
+      sizeof (UINT32) + sizeof (UINT16),
       MAX_UINTN
     },
     InternalVarCheckLoadOption
@@ -658,8 +650,7 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
       VARIABLE_ATTRIBUTE_NV_BS,
       sizeof (UINT8),
       sizeof (UINT8)
-    },
-    NULL
+    }
   },
   {
     &gEfiCustomModeEnableGuid,
@@ -670,8 +661,7 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
       VARIABLE_ATTRIBUTE_NV_BS,
       sizeof (UINT8),
       sizeof (UINT8)
-    },
-    NULL
+    }
   },
   {
     &gEfiVendorKeysNvGuid,
@@ -682,8 +672,7 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
       VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
       sizeof (UINT8),
       sizeof (UINT8)
-    },
-    NULL
+    }
   },
   {
     &gEfiAuthenticatedVariableGuid,
@@ -694,8 +683,7 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
       VARIABLE_ATTRIBUTE_NV_BS_RT_AW,
       sizeof (UINT8),
       MAX_UINTN
-    },
-    NULL
+    }
   },
   {
     &gEfiCertDbGuid,
@@ -706,8 +694,18 @@ VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
       VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
       sizeof (UINT32),
       MAX_UINTN
-    },
-    NULL
+    }
+  },
+  {
+    &gEdkiiVarErrorFlagGuid,
+    VAR_ERROR_FLAG_NAME,
+    {
+      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+      VARIABLE_ATTRIBUTE_NV_BS_RT,
+      sizeof (VAR_ERROR_FLAG),
+      sizeof (VAR_ERROR_FLAG)
+    }
   },
 };
 
@@ -738,7 +736,7 @@ GetUefiDefinedVariableProperty (
   UINTN     Index;
   UINTN     NameLength;
 
-  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)){
+  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
     //
     // Try list 1, exactly match.
     //
@@ -770,14 +768,13 @@ GetUefiDefinedVariableProperty (
           *VariableProperty = &mGlobalVariableList2[Index].VariableProperty;
           return EFI_SUCCESS;
         }
-      } else {
-        if (StrCmp (mGlobalVariableList2[Index].Name, VariableName) == 0) {
-          if (VarCheckFunction != NULL) {
-            *VarCheckFunction = mGlobalVariableList2[Index].CheckFunction;
-          }
-          *VariableProperty = &mGlobalVariableList2[Index].VariableProperty;
-          return EFI_SUCCESS;
+      }
+      if (StrCmp (mGlobalVariableList2[Index].Name, VariableName) == 0) {
+        if (VarCheckFunction != NULL) {
+          *VarCheckFunction = mGlobalVariableList2[Index].CheckFunction;
         }
+        *VariableProperty = &mGlobalVariableList2[Index].VariableProperty;
+        return EFI_SUCCESS;
       }
     }
 
@@ -812,7 +809,6 @@ GetUefiDefinedVariableProperty (
 
   @param[in]  VariableName      Pointer to variable name.
   @param[in]  VendorGuid        Variable Vendor Guid.
-  @param[out] VarCheckFunction  Pointer to check function.
 
   @return Pointer to variable property.
 
@@ -820,17 +816,13 @@ GetUefiDefinedVariableProperty (
 VAR_CHECK_VARIABLE_PROPERTY *
 GetVariableDriverVariableProperty (
   IN CHAR16                         *VariableName,
-  IN EFI_GUID                       *VendorGuid,
-  OUT INTERNAL_VAR_CHECK_FUNCTION   *VarCheckFunction OPTIONAL
+  IN EFI_GUID                       *VendorGuid
   )
 {
   UINTN     Index;
 
   for (Index = 0; Index < sizeof (mVariableDriverVariableList)/sizeof (mVariableDriverVariableList[0]); Index++) {
     if ((CompareGuid (mVariableDriverVariableList[Index].Guid, VendorGuid)) && (StrCmp (mVariableDriverVariableList[Index].Name, VariableName) == 0)) {
-      if (VarCheckFunction != NULL) {
-        *VarCheckFunction = mVariableDriverVariableList[Index].CheckFunction;
-      }
       return &mVariableDriverVariableList[Index].VariableProperty;
     }
   }
@@ -881,26 +873,27 @@ InternalVarCheckSetVariableCheck (
   }
 
   Property = NULL;
-  Status = GetUefiDefinedVariableProperty (VariableName, VendorGuid, TRUE, &Property, &VarCheckFunction);
-  if (EFI_ERROR (Status)) {
-    DEBUG ((EFI_D_INFO, "[Variable]: Var Check UEFI defined variable fail %r - %g:%s\n", Status, VendorGuid, VariableName));
-    return Status;
+  VarCheckFunction = NULL;
+
+  for ( Link = GetFirstNode (&mVarCheckVariableList)
+      ; !IsNull (&mVarCheckVariableList, Link)
+      ; Link = GetNextNode (&mVarCheckVariableList, Link)
+      ) {
+    Entry = BASE_CR (Link, VAR_CHECK_VARIABLE_ENTRY, Link);
+    Name = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
+    if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Name, VariableName) == 0)) {
+      Property = &Entry->VariableProperty;
+      break;
+    }
   }
   if (Property == NULL) {
-    Property = GetVariableDriverVariableProperty (VariableName, VendorGuid, &VarCheckFunction);
+    Property = GetVariableDriverVariableProperty (VariableName, VendorGuid);
   }
   if (Property == NULL) {
-    VarCheckFunction = NULL;
-    for ( Link = GetFirstNode (&mVarCheckVariableList)
-        ; !IsNull (&mVarCheckVariableList, Link)
-        ; Link = GetNextNode (&mVarCheckVariableList, Link)
-        ) {
-      Entry = BASE_CR (Link, VAR_CHECK_VARIABLE_ENTRY, Link);
-      Name = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
-      if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Name, VariableName) == 0)) {
-        Property = &Entry->VariableProperty;
-        break;
-      }
+    Status = GetUefiDefinedVariableProperty (VariableName, VendorGuid, TRUE, &Property, &VarCheckFunction);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_INFO, "[Variable]: Var Check UEFI defined variable fail %r - %g:%s\n", Status, VendorGuid, VariableName));
+      return Status;
     }
   }
   if (Property != NULL) {
@@ -908,30 +901,29 @@ InternalVarCheckSetVariableCheck (
       DEBUG ((EFI_D_INFO, "[Variable]: Var Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));
       return EFI_WRITE_PROTECTED;
     }
-    if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
+    if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {
       //
-      // Do not check delete variable.
+      // Not to delete variable.
       //
-      return EFI_SUCCESS;
-    }
-    if ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes) {
-      DEBUG ((EFI_D_INFO, "[Variable]: Var Check Attributes fail %r - %g:%s\n", EFI_INVALID_PARAMETER, VendorGuid, VariableName));
-      return EFI_INVALID_PARAMETER;
-    }
-    if (DataSize != 0) {
-      if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
-        DEBUG ((EFI_D_INFO, "[Variable]: Var Check DataSize fail %r - %g:%s\n", EFI_INVALID_PARAMETER, VendorGuid, VariableName));
+      if ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes) {
+        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));
         return EFI_INVALID_PARAMETER;
       }
-      if (VarCheckFunction != NULL) {
-        Status = VarCheckFunction (
-                   Property,
-                   DataSize,
-                   Data
-                   );
-        if (EFI_ERROR (Status)) {
-          DEBUG ((EFI_D_INFO, "[Variable]: Internal Var Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
-          return Status;
+      if (DataSize != 0) {
+        if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
+          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));
+          return EFI_INVALID_PARAMETER;
+        }
+        if (VarCheckFunction != NULL) {
+          Status = VarCheckFunction (
+                     Property,
+                     DataSize,
+                     Data
+                     );
+          if (EFI_ERROR (Status)) {
+            DEBUG ((EFI_D_INFO, "[Variable]: Internal Var Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
+            return Status;
+          }
         }
       }
     }
@@ -1047,18 +1039,20 @@ VarCheckRegisterSetVariableCheckHandler (
 }
 
 /**
-  Internal variable property get.
+  Variable property get function.
 
-  @param[in] Name   Pointer to the variable name.
-  @param[in] Guid   Pointer to the vendor GUID.
+  @param[in] Name           Pointer to the variable name.
+  @param[in] Guid           Pointer to the vendor GUID.
+  @param[in] WildcardMatch  Try wildcard match or not.
 
   @return Pointer to the property of variable specified by the Name and Guid.
 
 **/
 VAR_CHECK_VARIABLE_PROPERTY *
-InternalVarCheckVariablePropertyGet (
-  IN CHAR16                         *Name,
-  IN EFI_GUID                       *Guid
+VariablePropertyGetFunction (
+  IN CHAR16                 *Name,
+  IN EFI_GUID               *Guid,
+  IN BOOLEAN                WildcardMatch
   )
 {
   LIST_ENTRY                    *Link;
@@ -1066,27 +1060,23 @@ InternalVarCheckVariablePropertyGet (
   CHAR16                        *VariableName;
   VAR_CHECK_VARIABLE_PROPERTY   *Property;
 
-  Property = NULL;
-  GetUefiDefinedVariableProperty (Name, Guid, FALSE, &Property, NULL);
-  if (Property == NULL) {
-    Property = GetVariableDriverVariableProperty (Name, Guid, NULL);
-  }
-  if (Property != NULL) {
-    return Property;
-  } else {
-    for ( Link = GetFirstNode (&mVarCheckVariableList)
-        ; !IsNull (&mVarCheckVariableList, Link)
-        ; Link = GetNextNode (&mVarCheckVariableList, Link)
-        ) {
-      Entry = BASE_CR (Link, VAR_CHECK_VARIABLE_ENTRY, Link);
-      VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
-      if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
-        return &Entry->VariableProperty;
-      }
+  for ( Link = GetFirstNode (&mVarCheckVariableList)
+      ; !IsNull (&mVarCheckVariableList, Link)
+      ; Link = GetNextNode (&mVarCheckVariableList, Link)
+      ) {
+    Entry = BASE_CR (Link, VAR_CHECK_VARIABLE_ENTRY, Link);
+    VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
+    if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
+      return &Entry->VariableProperty;
     }
   }
 
-  return NULL;
+  Property = GetVariableDriverVariableProperty (Name, Guid);
+  if (Property == NULL) {
+    GetUefiDefinedVariableProperty (Name, Guid, WildcardMatch, &Property, NULL);
+  }
+
+  return Property;
 }
 
 /**
@@ -1137,7 +1127,7 @@ VarCheckVariablePropertySet (
 
   AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
 
-  Property = InternalVarCheckVariablePropertyGet (Name, Guid);
+  Property = VariablePropertyGetFunction (Name, Guid, FALSE);
   if (Property != NULL) {
     CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
   } else {
@@ -1160,20 +1150,19 @@ Done:
 }
 
 /**
-  Variable property get.
+  Internal variable property get.
 
   @param[in]  Name              Pointer to the variable name.
   @param[in]  Guid              Pointer to the vendor GUID.
   @param[out] VariableProperty  Pointer to the output variable property.
 
   @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was got successfully.
-  @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.
   @retval EFI_NOT_FOUND         The property of variable specified by the Name and Guid was not found.
 
 **/
 EFI_STATUS
 EFIAPI
-VarCheckVariablePropertyGet (
+InternalVarCheckVariablePropertyGet (
   IN CHAR16                         *Name,
   IN EFI_GUID                       *Guid,
   OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty
@@ -1185,19 +1174,9 @@ VarCheckVariablePropertyGet (
   BOOLEAN                       Found;
   VAR_CHECK_VARIABLE_PROPERTY   *Property;
 
-  if (Name == NULL || Name[0] == 0 || Guid == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
-  if (VariableProperty == NULL) {
-    return EFI_INVALID_PARAMETER;
-  }
-
   Found = FALSE;
 
-  AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
-  Property = InternalVarCheckVariablePropertyGet (Name, Guid);
+  Property = VariablePropertyGetFunction (Name, Guid, TRUE);
   if (Property != NULL) {
     CopyMem (VariableProperty, Property, sizeof (*VariableProperty));
     Found = TRUE;
@@ -1218,8 +1197,45 @@ VarCheckVariablePropertyGet (
     }
   }
 
-  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
   return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
 }
 
+/**
+  Variable property get.
+
+  @param[in]  Name              Pointer to the variable name.
+  @param[in]  Guid              Pointer to the vendor GUID.
+  @param[out] VariableProperty  Pointer to the output variable property.
+
+  @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was got successfully.
+  @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.
+  @retval EFI_NOT_FOUND         The property of variable specified by the Name and Guid was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckVariablePropertyGet (
+  IN CHAR16                         *Name,
+  IN EFI_GUID                       *Guid,
+  OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty
+  )
+{
+  EFI_STATUS    Status;
+
+  if (Name == NULL || Name[0] == 0 || Guid == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (VariableProperty == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+  Status = InternalVarCheckVariablePropertyGet (Name, Guid, VariableProperty);
+
+  ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
+
+  return Status;
+}
+
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
index 86e3616e30..7a42d971e0 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
@@ -542,6 +542,218 @@ GetEndPointer (
   return (VARIABLE_HEADER *) HEADER_ALIGN ((UINTN) VarStoreHeader + VarStoreHeader->Size);
 }
 
+/**
+  Record variable error flag.
+
+  @param[in] Flag               Variable error flag to record.
+  @param[in] VariableName       Name of variable.
+  @param[in] VendorGuid         Guid of variable.
+  @param[in] Attributes         Attributes of the variable.
+  @param[in] VariableSize       Size of the variable.
+
+**/
+VOID
+RecordVarErrorFlag (
+  IN VAR_ERROR_FLAG         Flag,
+  IN CHAR16                 *VariableName,
+  IN EFI_GUID               *VendorGuid,
+  IN UINT32                 Attributes,
+  IN UINTN                  VariableSize
+  )
+{
+  EFI_STATUS                Status;
+  VARIABLE_POINTER_TRACK    Variable;
+  VAR_ERROR_FLAG            *VarErrFlag;
+  VAR_ERROR_FLAG            TempFlag;
+
+  DEBUG_CODE (
+    DEBUG ((EFI_D_ERROR, "RecordVarErrorFlag (0x%02x) %s:%g - 0x%08x - 0x%x\n", Flag, VariableName, VendorGuid, Attributes, VariableSize));
+    if (Flag == VAR_ERROR_FLAG_SYSTEM_ERROR) {
+      if (AtRuntime ()) {
+        DEBUG ((EFI_D_ERROR, "CommonRuntimeVariableSpace = 0x%x - CommonVariableTotalSize = 0x%x\n", mVariableModuleGlobal->CommonRuntimeVariableSpace, mVariableModuleGlobal->CommonVariableTotalSize));
+      } else {
+        DEBUG ((EFI_D_ERROR, "CommonVariableSpace = 0x%x - CommonVariableTotalSize = 0x%x\n", mVariableModuleGlobal->CommonVariableSpace, mVariableModuleGlobal->CommonVariableTotalSize));
+      }
+    } else {
+      DEBUG ((EFI_D_ERROR, "CommonMaxUserVariableSpace = 0x%x - CommonUserVariableTotalSize = 0x%x\n", mVariableModuleGlobal->CommonMaxUserVariableSpace, mVariableModuleGlobal->CommonUserVariableTotalSize));
+    }
+  );
+
+  //
+  // Record error flag (it should have be initialized).
+  //
+  Status = FindVariable (
+             VAR_ERROR_FLAG_NAME,
+             &gEdkiiVarErrorFlagGuid,
+             &Variable,
+             &mVariableModuleGlobal->VariableGlobal,
+             FALSE
+             );
+  if (!EFI_ERROR (Status)) {
+    VarErrFlag = (VAR_ERROR_FLAG *) GetVariableDataPtr (Variable.CurrPtr);
+    TempFlag = *VarErrFlag;
+    TempFlag &= Flag;
+    if (TempFlag == *VarErrFlag) {
+      return;
+    }
+    Status = UpdateVariableStore (
+               &mVariableModuleGlobal->VariableGlobal,
+               FALSE,
+               FALSE,
+               mVariableModuleGlobal->FvbInstance,
+               (UINTN) VarErrFlag - (UINTN) mNvVariableCache + (UINTN) mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase,
+               sizeof (TempFlag),
+               &TempFlag
+               );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Update the data in NV cache.
+      //
+      *VarErrFlag = Flag;
+    }
+  }
+}
+
+/**
+  Initialize variable error flag.
+
+  Before EndOfDxe, the variable indicates the last boot variable error flag,
+  then it means the last boot variable error flag must be got before EndOfDxe.
+  After EndOfDxe, the variable indicates the current boot variable error flag,
+  then it means the current boot variable error flag must be got after EndOfDxe.
+
+**/
+VOID
+InitializeVarErrorFlag (
+  VOID
+  )
+{
+  EFI_STATUS                Status;
+  VARIABLE_POINTER_TRACK    Variable;
+  VAR_ERROR_FLAG            Flag;
+  VAR_ERROR_FLAG            VarErrFlag;
+
+  if (!mEndOfDxe) {
+    return;
+  }
+
+  Flag = VAR_ERROR_FLAG_NO_ERROR;
+  DEBUG ((EFI_D_INFO, "Initialize variable error flag (%02x)\n", Flag));
+
+  Status = FindVariable (
+             VAR_ERROR_FLAG_NAME,
+             &gEdkiiVarErrorFlagGuid,
+             &Variable,
+             &mVariableModuleGlobal->VariableGlobal,
+             FALSE
+             );
+  if (!EFI_ERROR (Status)) {
+    VarErrFlag = *((VAR_ERROR_FLAG *) GetVariableDataPtr (Variable.CurrPtr));
+    if (VarErrFlag == Flag) {
+      return;
+    }
+  }
+
+  UpdateVariable (
+    VAR_ERROR_FLAG_NAME,
+    &gEdkiiVarErrorFlagGuid,
+    &Flag,
+    sizeof (Flag),
+    VARIABLE_ATTRIBUTE_NV_BS_RT,
+    0,
+    0,
+    &Variable,
+    NULL
+    );
+}
+
+/**
+  Is user variable?
+
+  @param[in] Variable   Pointer to variable header.
+
+  @retval TRUE          User variable.
+  @retval FALSE         System variable.
+
+**/
+BOOLEAN
+IsUserVariable (
+  IN VARIABLE_HEADER    *Variable
+  )
+{
+  VAR_CHECK_VARIABLE_PROPERTY   Property;
+
+  //
+  // Only after End Of Dxe, the variables belong to system variable are fixed.
+  // If PcdMaxUserNvStorageVariableSize is 0, it means user variable share the same NV storage with system variable,
+  // then no need to check if the variable is user variable or not specially.
+  //
+  if (mEndOfDxe && (mVariableModuleGlobal->CommonMaxUserVariableSpace != mVariableModuleGlobal->CommonVariableSpace)) {
+    if (InternalVarCheckVariablePropertyGet (GetVariableNamePtr (Variable), &Variable->VendorGuid, &Property) == EFI_NOT_FOUND) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Calculate common user variable total size.
+
+**/
+VOID
+CalculateCommonUserVariableTotalSize (
+  VOID
+  )
+{
+  VARIABLE_HEADER               *Variable;
+  VARIABLE_HEADER               *NextVariable;
+  UINTN                         VariableSize;
+  VAR_CHECK_VARIABLE_PROPERTY   Property;
+
+  //
+  // Only after End Of Dxe, the variables belong to system variable are fixed.
+  // If PcdMaxUserNvStorageVariableSize is 0, it means user variable share the same NV storage with system variable,
+  // then no need to calculate the common user variable total size specially.
+  //
+  if (mEndOfDxe && (mVariableModuleGlobal->CommonMaxUserVariableSpace != mVariableModuleGlobal->CommonVariableSpace)) {
+    Variable = GetStartPointer (mNvVariableCache);
+    while (IsValidVariableHeader (Variable, GetEndPointer (mNvVariableCache))) {
+      NextVariable = GetNextVariablePtr (Variable);
+      VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+      if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
+        if (InternalVarCheckVariablePropertyGet (GetVariableNamePtr (Variable), &Variable->VendorGuid, &Property) == EFI_NOT_FOUND) {
+          //
+          // No property, it is user variable.
+          //
+          mVariableModuleGlobal->CommonUserVariableTotalSize += VariableSize;
+        }
+      }
+
+      Variable = NextVariable;
+    }
+  }
+}
+
+/**
+  Initialize variable quota.
+
+**/
+VOID
+InitializeVariableQuota (
+  VOID
+  )
+{
+  STATIC BOOLEAN    Initialized;
+
+  if (!mEndOfDxe || Initialized) {
+    return;
+  }
+  Initialized = TRUE;
+
+  InitializeVarErrorFlag ();
+  CalculateCommonUserVariableTotalSize ();
+}
+
 /**
 
   Check the PubKeyIndex is a valid key or not.
@@ -726,6 +938,7 @@ Reclaim (
   BOOLEAN               FoundAdded;
   EFI_STATUS            Status;
   UINTN                 CommonVariableTotalSize;
+  UINTN                 CommonUserVariableTotalSize;
   UINTN                 HwErrVariableTotalSize;
   UINT32                *NewPubKeyIndex;
   UINT8                 *NewPubKeyStore;
@@ -744,6 +957,7 @@ Reclaim (
   VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase);
 
   CommonVariableTotalSize = 0;
+  CommonUserVariableTotalSize = 0;
   HwErrVariableTotalSize  = 0;
   NewPubKeyIndex = NULL;
   NewPubKeyStore = NULL;
@@ -845,8 +1059,11 @@ Reclaim (
           HwErrVariableTotalSize += VariableSize;
         } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
           CommonVariableTotalSize += VariableSize;
+          if (IsUserVariable (Variable)) {
+            CommonUserVariableTotalSize += VariableSize;
           }
         }
+      }
       Variable = NextVariable;
     }
 
@@ -865,6 +1082,9 @@ Reclaim (
     CopyMem (GetVariableDataPtr (Variable), NewPubKeyStore, NewPubKeySize);
     CurrPtr = (UINT8*) GetNextVariablePtr (Variable);
     CommonVariableTotalSize += (UINTN) CurrPtr - (UINTN) Variable;
+    if (IsUserVariable (Variable)) {
+      CommonUserVariableTotalSize += (UINTN) CurrPtr - (UINTN) Variable;
+    }
   } else {
     //
     // Reinstall all ADDED variables as long as they are not identical to Updating Variable.
@@ -880,8 +1100,11 @@ Reclaim (
           HwErrVariableTotalSize += VariableSize;
         } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
           CommonVariableTotalSize += VariableSize;
+          if (IsUserVariable (Variable)) {
+            CommonUserVariableTotalSize += VariableSize;
           }
         }
+      }
       Variable = NextVariable;
     }
 
@@ -928,9 +1151,12 @@ Reclaim (
             HwErrVariableTotalSize += VariableSize;
           } else if ((!IsVolatile) && ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
             CommonVariableTotalSize += VariableSize;
+            if (IsUserVariable (Variable)) {
+              CommonUserVariableTotalSize += VariableSize;
             }
           }
         }
+      }
 
       Variable = NextVariable;
     }
@@ -951,9 +1177,13 @@ Reclaim (
           HwErrVariableTotalSize += NewVariableSize;
         } else if ((NewVariable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
           CommonVariableTotalSize += NewVariableSize;
+          if (IsUserVariable (NewVariable)) {
+            CommonUserVariableTotalSize += NewVariableSize;
           }
+        }
         if ((HwErrVariableTotalSize > PcdGet32 (PcdHwErrStorageSize)) ||
-            (CommonVariableTotalSize > VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize))) {
+            (CommonVariableTotalSize > mVariableModuleGlobal->CommonVariableSpace) ||
+            (CommonUserVariableTotalSize > mVariableModuleGlobal->CommonMaxUserVariableSpace)) {
           //
           // No enough space to store the new variable by NV or NV+HR attribute.
           //
@@ -992,19 +1222,24 @@ Reclaim (
       *LastVariableOffset = (UINTN) (CurrPtr - ValidBuffer);
       mVariableModuleGlobal->HwErrVariableTotalSize = HwErrVariableTotalSize;
       mVariableModuleGlobal->CommonVariableTotalSize = CommonVariableTotalSize;
+      mVariableModuleGlobal->CommonUserVariableTotalSize = CommonUserVariableTotalSize;
     } else {
-      NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);
-      while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) {
-        VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
+      Variable = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase);
+      while (IsValidVariableHeader (Variable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableBase))) {
+        NextVariable = GetNextVariablePtr (Variable);
+        VariableSize = (UINTN) NextVariable - (UINTN) Variable;
         if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
-          mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
+          mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
         } else if ((Variable->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
-          mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
+          mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
+          if (IsUserVariable (Variable)) {
+            mVariableModuleGlobal->CommonUserVariableTotalSize += VariableSize;
           }
+        }
 
-        NextVariable = GetNextVariablePtr (NextVariable);
+        Variable = NextVariable;
       }
-      *LastVariableOffset = (UINTN) NextVariable - (UINTN) VariableBase;
+      *LastVariableOffset = (UINTN) Variable - (UINTN) VariableBase;
     }
   }
 
@@ -1875,7 +2110,6 @@ UpdateVariable (
   VARIABLE_HEADER                     *NextVariable;
   UINTN                               ScratchSize;
   UINTN                               MaxDataSize;
-  UINTN                               NonVolatileVarableStoreSize;
   UINTN                               VarNameOffset;
   UINTN                               VarDataOffset;
   UINTN                               VarNameSize;
@@ -1891,6 +2125,8 @@ UpdateVariable (
   UINTN                               MergedBufSize;
   BOOLEAN                             DataReady;
   UINTN                               DataOffset;
+  BOOLEAN                             IsCommonVariable;
+  BOOLEAN                             IsCommonUserVariable;
 
   if (mVariableModuleGlobal->FvbInstance == NULL) {
     //
@@ -2252,12 +2488,25 @@ UpdateVariable (
     // Create a nonvolatile variable.
     //
     Volatile = FALSE;
-    NonVolatileVarableStoreSize = ((VARIABLE_STORE_HEADER *)(UINTN)(mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase))->Size;
+
+    IsCommonVariable = FALSE;
+    IsCommonUserVariable = FALSE;
+    if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0) {
+      IsCommonVariable = TRUE;
+      IsCommonUserVariable = IsUserVariable (NextVariable);
+    }
     if ((((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0)
       && ((VarSize + mVariableModuleGlobal->HwErrVariableTotalSize) > PcdGet32 (PcdHwErrStorageSize)))
-      || (((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == 0)
-      && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > NonVolatileVarableStoreSize - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize)))) {
+      || (IsCommonVariable && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonVariableSpace))
+      || (IsCommonVariable && AtRuntime () && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonRuntimeVariableSpace))
+      || (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace))) {
       if (AtRuntime ()) {
+        if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)) {
+          RecordVarErrorFlag (VAR_ERROR_FLAG_USER_ERROR, VariableName, VendorGuid, Attributes, VarSize);
+        }
+        if (IsCommonVariable && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonRuntimeVariableSpace)) {
+          RecordVarErrorFlag (VAR_ERROR_FLAG_SYSTEM_ERROR, VariableName, VendorGuid, Attributes, VarSize);
+        }
         Status = EFI_OUT_OF_RESOURCES;
         goto Done;
       }
@@ -2283,7 +2532,14 @@ UpdateVariable (
         }
         UpdateVariableInfo (VariableName, VendorGuid, FALSE, FALSE, TRUE, FALSE, FALSE);
         FlushHobVariableToFlash (VariableName, VendorGuid);
+      } else {
+        if (IsCommonUserVariable && ((VarSize + mVariableModuleGlobal->CommonUserVariableTotalSize) > mVariableModuleGlobal->CommonMaxUserVariableSpace)) {
+          RecordVarErrorFlag (VAR_ERROR_FLAG_USER_ERROR, VariableName, VendorGuid, Attributes, VarSize);
         }
+        if (IsCommonVariable && ((VarSize + mVariableModuleGlobal->CommonVariableTotalSize) > mVariableModuleGlobal->CommonVariableSpace)) {
+          RecordVarErrorFlag (VAR_ERROR_FLAG_SYSTEM_ERROR, VariableName, VendorGuid, Attributes, VarSize);
+        }
+      }
       goto Done;
     }
     //
@@ -2368,7 +2624,10 @@ UpdateVariable (
       mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VarSize);
     } else {
       mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VarSize);
+      if (IsCommonUserVariable) {
+        mVariableModuleGlobal->CommonUserVariableTotalSize += HEADER_ALIGN (VarSize);
       }
+    }
     //
     // update the memory copy of Flash region.
     //
@@ -3024,7 +3283,7 @@ VariableServiceSetVariable (
       // 2. The only attribute differing is EFI_VARIABLE_APPEND_WRITE
       //
       Status = EFI_INVALID_PARAMETER;
-      DEBUG ((EFI_D_INFO, "[Variable]: Rewritten a preexisting variable with different attributes - %g:%s\n", VendorGuid, VariableName));
+      DEBUG ((EFI_D_INFO, "[Variable]: Rewritten a preexisting variable(0x%08x) with different attributes(0x%08x) - %g:%s\n", Variable.CurrPtr->Attributes, Attributes, VendorGuid, VariableName));
       goto Done;
     }
   }
@@ -3145,8 +3404,11 @@ VariableServiceQueryVariableInfoInternal (
     *MaximumVariableSize = PcdGet32 (PcdMaxHardwareErrorVariableSize) - sizeof (VARIABLE_HEADER);
   } else {
     if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
-      ASSERT (PcdGet32 (PcdHwErrStorageSize) < VariableStoreHeader->Size);
-      *MaximumVariableStorageSize = VariableStoreHeader->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32 (PcdHwErrStorageSize);
+      if (AtRuntime ()) {
+        *MaximumVariableStorageSize = mVariableModuleGlobal->CommonRuntimeVariableSpace;
+      } else {
+        *MaximumVariableStorageSize = mVariableModuleGlobal->CommonVariableSpace;
+      }
     }
 
     //
@@ -3222,8 +3484,12 @@ VariableServiceQueryVariableInfoInternal (
 
   if ((Attributes  & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD){
     *RemainingVariableStorageSize = *MaximumVariableStorageSize - HwErrVariableTotalSize;
-  }else {
-    *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;
+  } else {
+    if (*MaximumVariableStorageSize < CommonVariableTotalSize) {
+      *RemainingVariableStorageSize = 0;
+    } else {
+      *RemainingVariableStorageSize = *MaximumVariableStorageSize - CommonVariableTotalSize;
+    }
   }
 
   if (*RemainingVariableStorageSize < sizeof (VARIABLE_HEADER)) {
@@ -3271,7 +3537,7 @@ VariableServiceQueryVariableInfo (
     return EFI_INVALID_PARAMETER;
   }
 
-  if((Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == 0) {
+  if ((Attributes & VARIABLE_ATTRIBUTE_NV_BS_RT_AT_HR_AW) == 0) {
     //
     // Make sure the Attributes combination is supported by the platform.
     //
@@ -3319,21 +3585,22 @@ ReclaimForOS(
   )
 {
   EFI_STATUS                     Status;
-  UINTN                          CommonVariableSpace;
-  UINTN                          RemainingCommonVariableSpace;
+  UINTN                          RemainingCommonRuntimeVariableSpace;
   UINTN                          RemainingHwErrVariableSpace;
 
   Status  = EFI_SUCCESS;
 
-  CommonVariableSpace = ((VARIABLE_STORE_HEADER *) ((UINTN) (mVariableModuleGlobal->VariableGlobal.NonVolatileVariableBase)))->Size - sizeof (VARIABLE_STORE_HEADER) - PcdGet32(PcdHwErrStorageSize); //Allowable max size of common variable storage space
-
-  RemainingCommonVariableSpace = CommonVariableSpace - mVariableModuleGlobal->CommonVariableTotalSize;
+  if (mVariableModuleGlobal->CommonRuntimeVariableSpace < mVariableModuleGlobal->CommonVariableTotalSize) {
+    RemainingCommonRuntimeVariableSpace = 0;
+  } else {
+    RemainingCommonRuntimeVariableSpace = mVariableModuleGlobal->CommonRuntimeVariableSpace - mVariableModuleGlobal->CommonVariableTotalSize;
+  }
 
   RemainingHwErrVariableSpace = PcdGet32 (PcdHwErrStorageSize) - mVariableModuleGlobal->HwErrVariableTotalSize;
   //
-  // Check if the free area is blow a threshold.
+  // Check if the free area is below a threshold.
   //
-  if ((RemainingCommonVariableSpace < PcdGet32 (PcdMaxVariableSize))
+  if ((RemainingCommonRuntimeVariableSpace < PcdGet32 (PcdMaxVariableSize))
     || ((PcdGet32 (PcdHwErrStorageSize) != 0) &&
        (RemainingHwErrVariableSpace < PcdGet32 (PcdMaxHardwareErrorVariableSize)))){
     Status = Reclaim (
@@ -3363,6 +3630,7 @@ InitNonVolatileVariableStore (
   )
 {
   EFI_FIRMWARE_VOLUME_HEADER            *FvHeader;
+  VARIABLE_HEADER                       *Variable;
   VARIABLE_HEADER                       *NextVariable;
   EFI_PHYSICAL_ADDRESS                  VariableStoreBase;
   UINT64                                VariableStoreLength;
@@ -3374,17 +3642,12 @@ InitNonVolatileVariableStore (
   FAULT_TOLERANT_WRITE_LAST_WRITE_DATA  *FtwLastWriteData;
   UINT32                                BackUpOffset;
   UINT32                                BackUpSize;
+  UINT32                                HwErrStorageSize;
+  UINT32                                MaxUserNvVariableSpaceSize;
+  UINT32                                BoottimeReservedNvVariableSpaceSize;
 
   mVariableModuleGlobal->FvbInstance = NULL;
 
-  //
-  // Note that in EdkII variable driver implementation, Hardware Error Record type variable
-  // is stored with common variable in the same NV region. So the platform integrator should
-  // ensure that the value of PcdHwErrStorageSize is less than or equal to the value of
-  // PcdFlashNvStorageVariableSize.
-  //
-  ASSERT (PcdGet32 (PcdHwErrStorageSize) <= PcdGet32 (PcdFlashNvStorageVariableSize));
-
   //
   // Allocate runtime memory used for a memory copy of the FLASH region.
   // Keep the memory and the FLASH in sync as updates occur.
@@ -3454,6 +3717,37 @@ InitNonVolatileVariableStore (
   }
   ASSERT(mNvVariableCache->Size == VariableStoreLength);
 
+
+  ASSERT (sizeof (VARIABLE_STORE_HEADER) <= VariableStoreLength);
+
+  HwErrStorageSize = PcdGet32 (PcdHwErrStorageSize);
+  MaxUserNvVariableSpaceSize = PcdGet32 (PcdMaxUserNvVariableSpaceSize);
+  BoottimeReservedNvVariableSpaceSize = PcdGet32 (PcdBoottimeReservedNvVariableSpaceSize);
+
+  //
+  // Note that in EdkII variable driver implementation, Hardware Error Record type variable
+  // is stored with common variable in the same NV region. So the platform integrator should
+  // ensure that the value of PcdHwErrStorageSize is less than the value of
+  // VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)).
+  //
+  ASSERT (HwErrStorageSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)));
+  //
+  // Ensure that the value of PcdMaxUserNvVariableSpaceSize is less than the value of
+  // VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
+  //
+  ASSERT (MaxUserNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
+  //
+  // Ensure that the value of PcdBoottimeReservedNvVariableSpaceSize is less than the value of
+  // VariableStoreLength - sizeof (VARIABLE_STORE_HEADER)) - PcdGet32 (PcdHwErrStorageSize).
+  //
+  ASSERT (BoottimeReservedNvVariableSpaceSize < (VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize));
+
+  mVariableModuleGlobal->CommonVariableSpace = ((UINTN) VariableStoreLength - sizeof (VARIABLE_STORE_HEADER) - HwErrStorageSize);
+  mVariableModuleGlobal->CommonMaxUserVariableSpace = ((MaxUserNvVariableSpaceSize != 0) ? MaxUserNvVariableSpaceSize : mVariableModuleGlobal->CommonVariableSpace);
+  mVariableModuleGlobal->CommonRuntimeVariableSpace = mVariableModuleGlobal->CommonVariableSpace - BoottimeReservedNvVariableSpaceSize;
+
+  DEBUG ((EFI_D_INFO, "Variable driver common space: 0x%x 0x%x 0x%x\n", mVariableModuleGlobal->CommonVariableSpace, mVariableModuleGlobal->CommonMaxUserVariableSpace, mVariableModuleGlobal->CommonRuntimeVariableSpace));
+
   //
   // The max variable or hardware error variable size should be < variable store size.
   //
@@ -3462,18 +3756,19 @@ InitNonVolatileVariableStore (
   //
   // Parse non-volatile variable data and get last variable offset.
   //
-  NextVariable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
-  while (IsValidVariableHeader (NextVariable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) {
-    VariableSize = NextVariable->NameSize + NextVariable->DataSize + sizeof (VARIABLE_HEADER);
-    if ((NextVariable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
-      mVariableModuleGlobal->HwErrVariableTotalSize += HEADER_ALIGN (VariableSize);
+  Variable  = GetStartPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase);
+  while (IsValidVariableHeader (Variable, GetEndPointer ((VARIABLE_STORE_HEADER *)(UINTN)VariableStoreBase))) {
+    NextVariable = GetNextVariablePtr (Variable);
+    VariableSize = (UINTN) NextVariable - (UINTN) Variable;
+    if ((Variable->Attributes & (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) == (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_HARDWARE_ERROR_RECORD)) {
+      mVariableModuleGlobal->HwErrVariableTotalSize += VariableSize;
     } else {
-      mVariableModuleGlobal->CommonVariableTotalSize += HEADER_ALIGN (VariableSize);
+      mVariableModuleGlobal->CommonVariableTotalSize += VariableSize;
     }
 
-    NextVariable = GetNextVariablePtr (NextVariable);
+    Variable = NextVariable;
   }
-  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) VariableStoreBase;
+  mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) Variable - (UINTN) VariableStoreBase;
 
   return EFI_SUCCESS;
 }
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
index 8591001f8b..f86b202fda 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
@@ -44,6 +44,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Guid/SystemNvDataGuid.h>
 #include <Guid/FaultTolerantWrite.h>
 #include <Guid/HardwareErrorVariable.h>
+#include <Guid/VarErrorFlag.h>
 
 #define EFI_VARIABLE_ATTRIBUTES_MASK (EFI_VARIABLE_NON_VOLATILE | \
                                       EFI_VARIABLE_BOOTSERVICE_ACCESS | \
@@ -59,7 +60,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define VARIABLE_ATTRIBUTE_NV_BS_RT_AT  (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
 #define VARIABLE_ATTRIBUTE_NV_BS_RT_HR  (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_HARDWARE_ERROR_RECORD)
 #define VARIABLE_ATTRIBUTE_NV_BS_RT_AW  (VARIABLE_ATTRIBUTE_NV_BS_RT | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
- 
+#define VARIABLE_ATTRIBUTE_NV_BS_RT_AT_HR_AW  (VARIABLE_ATTRIBUTE_NV_BS_RT_AT | EFI_VARIABLE_HARDWARE_ERROR_RECORD | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
+
 ///
 /// The size of a 3 character ISO639 language code.
 ///
@@ -98,7 +100,11 @@ typedef struct {
   VARIABLE_GLOBAL VariableGlobal;
   UINTN           VolatileLastVariableOffset;
   UINTN           NonVolatileLastVariableOffset;
+  UINTN           CommonVariableSpace;
+  UINTN           CommonMaxUserVariableSpace;
+  UINTN           CommonRuntimeVariableSpace;
   UINTN           CommonVariableTotalSize;
+  UINTN           CommonUserVariableTotalSize;
   UINTN           HwErrVariableTotalSize;
   CHAR8           *PlatformLangCodes;
   CHAR8           *LangCodes;
@@ -735,6 +741,25 @@ VarCheckRegisterSetVariableCheckHandler (
   IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER   Handler
   );
 
+/**
+  Internal variable property get.
+
+  @param[in]  Name              Pointer to the variable name.
+  @param[in]  Guid              Pointer to the vendor GUID.
+  @param[out] VariableProperty  Pointer to the output variable property.
+
+  @retval EFI_SUCCESS           The property of variable specified by the Name and Guid was got successfully.
+  @retval EFI_NOT_FOUND         The property of variable specified by the Name and Guid was not found.
+
+**/
+EFI_STATUS
+EFIAPI
+InternalVarCheckVariablePropertyGet (
+  IN CHAR16                         *Name,
+  IN EFI_GUID                       *Guid,
+  OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty
+  );
+
 /**
   Variable property set.
 
@@ -778,6 +803,15 @@ VarCheckVariablePropertyGet (
   OUT VAR_CHECK_VARIABLE_PROPERTY   *VariableProperty
   );
 
+/**
+  Initialize variable quota.
+
+**/
+VOID
+InitializeVariableQuota (
+  VOID
+  );
+
 extern VARIABLE_MODULE_GLOBAL  *mVariableModuleGlobal;
 
 #endif
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
index a1352510eb..375a604df2 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
@@ -286,6 +286,10 @@ OnReadyToBoot (
   // Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
   //
   mEndOfDxe = TRUE;
+  //
+  // The initialization for variable quota.
+  //
+  InitializeVariableQuota ();
   ReclaimForOS ();
   if (FeaturePcdGet (PcdVariableCollectStatistics)) {
     gBS->InstallConfigurationTable (&gEfiAuthenticatedVariableGuid, gVariableInfo);
@@ -309,6 +313,10 @@ OnEndOfDxe (
   )
 {
   mEndOfDxe = TRUE;
+  //
+  // The initialization for variable quota.
+  //
+  InitializeVariableQuota ();
 }
 
 /**
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
index 8a8d4adef5..4e31178e16 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
@@ -132,6 +132,7 @@
   gEfiSystemNvDataFvGuid                   ## CONSUMES               ## GUID
   gEfiHardwareErrorVariableGuid            ## SOMETIMES_CONSUMES     ## Variable:L"HwErrRec####"
   gEdkiiFaultTolerantWriteGuid             ## SOMETIMES_CONSUMES     ## HOB
+  gEdkiiVarErrorFlagGuid                   ## CONSUMES               ## GUID
 
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize       ## CONSUMES
@@ -141,6 +142,8 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize     ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                 ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxUserNvVariableSpaceSize           ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBoottimeReservedNvVariableSpaceSize  ## CONSUMES
 
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics        ## CONSUMES  # statistic the information of variable.
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
index dd1f794cff..9af9eafe14 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
@@ -716,6 +716,10 @@ SmmVariableHandler (
 
     case SMM_VARIABLE_FUNCTION_READY_TO_BOOT:
       mEndOfDxe = TRUE;
+      //
+      // The initialization for variable quota.
+      //
+      InitializeVariableQuota ();
       if (AtRuntime()) {
         Status = EFI_UNSUPPORTED;
         break;
@@ -846,6 +850,10 @@ SmmEndOfDxeCallback (
 {
   DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
   mEndOfDxe = TRUE;
+  //
+  // The initialization for variable quota.
+  //
+  InitializeVariableQuota ();
   return EFI_SUCCESS;
 }
 
diff --git a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
index a7d0505e21..ec4249a95f 100644
--- a/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
+++ b/SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf
@@ -139,7 +139,8 @@
   gEfiSystemNvDataFvGuid                   ## CONSUMES               ## GUID
   gEfiHardwareErrorVariableGuid            ## SOMETIMES_CONSUMES     ## Variable:L"HwErrRec####"
   gEdkiiFaultTolerantWriteGuid             ## SOMETIMES_CONSUMES     ## HOB
-  
+  gEdkiiVarErrorFlagGuid                   ## CONSUMES               ## GUID
+
 [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize       ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase       ## SOMETIMES_CONSUMES
@@ -148,7 +149,9 @@
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize     ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize                ## CONSUMES
   gEfiMdeModulePkgTokenSpaceGuid.PcdHwErrStorageSize                 ## CONSUMES
-  
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxUserNvVariableSpaceSize           ## CONSUMES
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBoottimeReservedNvVariableSpaceSize  ## CONSUMES
+
 [FeaturePcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics        ## CONSUMES  # statistic the information of variable.
   gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangDeprecate       ## CONSUMES  # Auto update PlatformLang/Lang