]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg PCD: Avoid DynamicHii PCD set to override other values
authorStar Zeng <star.zeng@intel.com>
Thu, 19 May 2016 03:23:41 +0000 (11:23 +0800)
committerStar Zeng <star.zeng@intel.com>
Mon, 20 Jun 2016 09:27:58 +0000 (17:27 +0800)
When Hii variable is not present and if we try to update a variable offset
with some value, we are creating a new variable by Zeroing all the variable
offsets except the one which we are trying to update.
This will override all the other variable default values which are
programmed as a part of initial PCD definition.

DXE PCD driver could be enhanced to combine the DynamicHii
PCDs(related to same variable) default values and only update the offset
PcdSetXXX want to set, then set the combined values to variable.

Cc: Liming Gao <liming.gao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
MdeModulePkg/Universal/PCD/Dxe/Service.c

index eb1e1cef0bea17e87509b6d03395701d96f87c5b..9ab456624fc7086427c6a446d58d71acc28ab48d 100644 (file)
@@ -2,7 +2,7 @@
     Help functions used by PCD DXE driver.\r
 \r
 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>\r
-Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -1369,6 +1369,84 @@ ExSetWorker (
 \r
 }\r
 \r
+/**\r
+  Get variable size and data from HII-type PCDs.\r
+\r
+  @param[in]  VariableGuid   Guid of variable which stored value of a HII-type PCD.\r
+  @param[in]  VariableName   Unicode name of variable which stored value of a HII-type PCD.\r
+  @param[out] VariableSize   Pointer to variable size got from HII-type PCDs.\r
+  @param[out] VariableData   Pointer to variable data got from HII-type PCDs.\r
+\r
+**/\r
+VOID\r
+GetVariableSizeAndDataFromHiiPcd (\r
+  IN EFI_GUID               *VariableGuid,\r
+  IN UINT16                 *VariableName,\r
+  OUT UINTN                 *VariableSize,\r
+  OUT VOID                  *VariableData OPTIONAL\r
+  )\r
+{\r
+  BOOLEAN                   IsPeiDb;\r
+  PCD_DATABASE_INIT         *Database;\r
+  UINTN                     TokenNumber;\r
+  UINT32                    LocalTokenNumber;\r
+  UINTN                     Offset;\r
+  EFI_GUID                  *GuidTable;\r
+  UINT8                     *StringTable;\r
+  VARIABLE_HEAD             *VariableHead;\r
+  EFI_GUID                  *Guid;\r
+  UINT16                    *Name;\r
+  UINTN                     PcdDataSize;\r
+  UINTN                     Size;\r
+  UINT8                     *VaraiableDefaultBuffer;\r
+  STRING_HEAD               StringTableIdx;\r
+\r
+  *VariableSize = 0;\r
+\r
+  //\r
+  // Go through PCD database to find out DynamicHii PCDs.\r
+  //\r
+  for (TokenNumber = 1; TokenNumber <= mPcdTotalTokenCount; TokenNumber++) {\r
+    IsPeiDb = (BOOLEAN) ((TokenNumber + 1 < mPeiLocalTokenCount + 1) ? TRUE : FALSE);\r
+    Database = IsPeiDb ? mPcdDatabase.PeiDb: mPcdDatabase.DxeDb;\r
+    LocalTokenNumber = GetLocalTokenNumber (IsPeiDb, TokenNumber);\r
+    if ((LocalTokenNumber & PCD_TYPE_HII) != 0) {\r
+      //\r
+      // Get the Variable Guid and Name pointer.\r
+      //\r
+      Offset = LocalTokenNumber & PCD_DATABASE_OFFSET_MASK;\r
+      VariableHead = (VARIABLE_HEAD *) ((UINT8 *) Database + Offset);\r
+      StringTable = (UINT8 *) ((UINT8 *) Database + Database->StringTableOffset);\r
+      GuidTable = (EFI_GUID *) ((UINT8 *) Database + Database->GuidTableOffset);\r
+      Guid = GuidTable + VariableHead->GuidTableIndex;\r
+      Name = (UINT16*) (StringTable + VariableHead->StringIndex);\r
+      if (CompareGuid (VariableGuid, Guid) && (StrCmp (VariableName, Name) == 0)) {\r
+        //\r
+        // It is the matched DynamicHii PCD.\r
+        //\r
+        PcdDataSize = DxePcdGetSize (TokenNumber);\r
+        Size = VariableHead->Offset + PcdDataSize;\r
+        if (Size > *VariableSize) {\r
+          *VariableSize = Size;\r
+        }\r
+        if (VariableData != NULL) {\r
+          if ((LocalTokenNumber & PCD_TYPE_ALL_SET) == (PCD_TYPE_HII|PCD_TYPE_STRING)) {\r
+            //\r
+            // If a HII type PCD's datum type is VOID*, the DefaultValueOffset is the index of\r
+            // string array in string table.\r
+            //\r
+            StringTableIdx = *(STRING_HEAD *) ((UINT8 *) Database + VariableHead->DefaultValueOffset);\r
+            VaraiableDefaultBuffer = (UINT8 *) (StringTable + StringTableIdx);\r
+          } else {\r
+            VaraiableDefaultBuffer = (UINT8 *) Database + VariableHead->DefaultValueOffset;\r
+          }\r
+          CopyMem ((UINT8 *) VariableData + VariableHead->Offset, VaraiableDefaultBuffer, PcdDataSize);\r
+        }\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Set value for HII-type PCD.\r
 \r
@@ -1457,12 +1535,18 @@ SetHiiVariable (
     //\r
     // If variable does not exist, a new variable need to be created.\r
     //\r
-    \r
-    Size = Offset + DataSize;\r
-    \r
+\r
+    //\r
+    // Get size, allocate buffer and get data.\r
+    //\r
+    GetVariableSizeAndDataFromHiiPcd (VariableGuid, VariableName, &Size, NULL);\r
     Buffer = AllocateZeroPool (Size);\r
     ASSERT (Buffer != NULL);\r
-    \r
+    GetVariableSizeAndDataFromHiiPcd (VariableGuid, VariableName, &Size, Buffer);\r
+\r
+    //\r
+    // Update buffer.\r
+    //\r
     CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize);\r
 \r
     if (SetAttributes == 0) {\r