]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
MdeModulePkg Variable: Implement variable quota management.
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VarCheck.c
index f8173308cf40c82ad20188e89aab3b886b6bf901..01ca55a1780fecedc47afba2f79b611f666910d4 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
@@ -602,6 +594,26 @@ UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
   },\r
 };\r
 \r
+typedef struct {\r
+  EFI_GUID                      *Guid;\r
+  CHAR16                        *Name;\r
+  VAR_CHECK_VARIABLE_PROPERTY   VariableProperty;\r
+} VARIABLE_DRIVER_VARIABLE_ENTRY;\r
+\r
+VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {\r
+  {\r
+    &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
 /**\r
   Get UEFI defined global variable property.\r
   The code will check if variable guid is global variable guid first.\r
@@ -661,14 +673,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
@@ -684,6 +695,32 @@ GetUefiDefinedVariableProperty (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Get variable property for variables managed by Varaible driver.\r
+\r
+  @param[in]  VariableName      Pointer to variable name.\r
+  @param[in]  VendorGuid        Variable Vendor Guid.\r
+\r
+  @return Pointer to variable property.\r
+\r
+**/\r
+VAR_CHECK_VARIABLE_PROPERTY *\r
+GetVariableDriverVariableProperty (\r
+  IN CHAR16                         *VariableName,\r
+  IN EFI_GUID                       *VendorGuid\r
+  )\r
+{\r
+  UINTN     Index;\r
+\r
+  for (Index = 0; Index < sizeof (mVariableDriverVariableList)/sizeof (mVariableDriverVariableList[0]); Index++) {\r
+    if ((CompareGuid (mVariableDriverVariableList[Index].Guid, VendorGuid)) && (StrCmp (mVariableDriverVariableList[Index].Name, VariableName) == 0)) {\r
+      return &mVariableDriverVariableList[Index].VariableProperty;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
 /**\r
   Internal SetVariable check.\r
 \r
@@ -694,7 +731,7 @@ GetUefiDefinedVariableProperty (
   @param[in] Data               Data pointer.\r
 \r
   @retval EFI_SUCCESS           The SetVariable check result was success.\r
-  @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID were supplied,\r
+  @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied,\r
                                 or the DataSize exceeds the minimum or maximum allowed,\r
                                 or the Data value is not following UEFI spec for UEFI defined variables.\r
   @retval EFI_WRITE_PROTECTED   The variable in question is read-only.\r
@@ -727,23 +764,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
-    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
+    Property = GetVariableDriverVariableProperty (VariableName, VendorGuid);\r
+  }\r
+  if (Property == NULL) {\r
+    Status = GetUefiDefinedVariableProperty (VariableName, VendorGuid, TRUE, &Property, &VarCheckFunction);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_INFO, "[Variable]: Var Check UEFI defined variable fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
+      return Status;\r
     }\r
   }\r
   if (Property != NULL) {\r
@@ -751,29 +792,28 @@ InternalVarCheckSetVariableCheck (
       DEBUG ((EFI_D_INFO, "[Variable]: Var Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));\r
       return EFI_WRITE_PROTECTED;\r
     }\r
-    if ((DataSize == 0) || (Attributes == 0)) {\r
+    if (!((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 != 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 < 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
-      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 (Attributes != Property->Attributes) {\r
+        DEBUG ((EFI_D_INFO, "[Variable]: Var Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {\r
+        DEBUG ((EFI_D_INFO, "[Variable]: Var Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      if (VarCheckFunction != NULL) {\r
+        Status = VarCheckFunction (\r
+                   Property,\r
+                   DataSize,\r
+                   Data\r
+                   );\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((EFI_D_INFO, "[Variable]: Internal Var Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));\r
+          return Status;\r
+        }\r
       }\r
     }\r
   }\r
@@ -888,18 +928,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
@@ -907,24 +949,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
-    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
@@ -975,7 +1016,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
@@ -998,20 +1039,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
@@ -1023,19 +1063,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
@@ -1056,8 +1086,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