SecurityPkg Variable: Implement variable quota management.
authorStar Zeng <star.zeng@intel.com>
Tue, 27 Jan 2015 08:44:10 +0000 (08:44 +0000)
committerlzeng14 <lzeng14@Edk2>
Tue, 27 Jan 2015 08:44:10 +0000 (08:44 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16670 6f19259b-4bc3-4df7-8a09-765794883524

SecurityPkg/VariableAuthenticated/RuntimeDxe/VarCheck.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/Variable.h
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableDxe.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.c
SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableSmm.inf

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