]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools: add new command line option to support override PCD value
authorYonghong Zhu <yonghong.zhu@intel.com>
Thu, 25 Feb 2016 08:13:31 +0000 (16:13 +0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Wed, 16 Mar 2016 02:35:52 +0000 (10:35 +0800)
this patch add new feature to support override PCD value on the command
line. The value from the command line is the highest priority.
1.Add option(--pcd) to support both PcdName and TokenSpaceGuild.PcdName
2.For void* type PCD, use following format:
  cstring PCD: --pcd PcdName="string"
  unicodestring PCD: --pcd PcdName=L"string"
  CArray PCD: --pcd PcdName=B"{0x1, 0x2}"
3.Build Report, use *B to show the PCD value was overridden in the
command line.
4.Error Condition:
Report error if the PCD is not found
Report error if the PcdName is found under multiple different TokenSpaceGuid
Report error if PCD value syntax is incorrect
Report error if void* type PCD value exceed its max size

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools/Source/Python/AutoGen/GenC.py
BaseTools/Source/Python/AutoGen/GenPcdDb.py
BaseTools/Source/Python/Common/GlobalData.py
BaseTools/Source/Python/build/BuildReport.py
BaseTools/Source/Python/build/build.py

index 7106a7c54c64211d90bf6a74eb22c67c237560c2..c7aa84fb342e02e47a5694a0758e35f58ff76754 100644 (file)
@@ -350,6 +350,67 @@ class WorkspaceAutoGen(AutoGen):
             DecPcds = {}\r
             DecPcdsKey = set()\r
             PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
+            if GlobalData.BuildOptionPcd:\r
+                for i, pcd in enumerate(GlobalData.BuildOptionPcd):\r
+                    (pcdname, pcdvalue) = pcd.split('=')\r
+                    if not pcdvalue:\r
+                        EdkLogger.error('build', AUTOGEN_ERROR, "No Value specified for the PCD %s." % (pcdname))\r
+                    if '.' in pcdname:\r
+                        (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')\r
+                        HasTokenSpace = True\r
+                    else:\r
+                        TokenCName = pcdname\r
+                        TokenSpaceGuidCName = ''\r
+                        HasTokenSpace = False\r
+                    TokenSpaceGuidCNameList = []\r
+                    FoundFlag = False\r
+                    PcdDatumType = ''\r
+                    NewValue = ''\r
+                    for package in PGen.PackageList:\r
+                        for key in package.Pcds:\r
+                            PcdItem = package.Pcds[key]\r
+                            if HasTokenSpace:\r
+                                if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):\r
+                                    PcdDatumType = PcdItem.DatumType\r
+                                    NewValue = self._BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)\r
+                                    FoundFlag = True\r
+                            else:\r
+                                if PcdItem.TokenCName == TokenCName:\r
+                                    if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:\r
+                                        if len (TokenSpaceGuidCNameList) < 1:\r
+                                            TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)\r
+                                            PcdDatumType = PcdItem.DatumType\r
+                                            TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName\r
+                                            NewValue = self._BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)\r
+                                            FoundFlag = True\r
+                                        else:\r
+                                            EdkLogger.error(\r
+                                                    'build',\r
+                                                     AUTOGEN_ERROR,\r
+                                                    "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])\r
+                                                    )\r
+\r
+                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue)\r
+\r
+                    if not FoundFlag:\r
+                        if HasTokenSpace:\r
+                            EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, TokenCName))\r
+                        else:\r
+                            EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (TokenCName))\r
+\r
+                    for BuildData in PGen.BuildDatabase._CACHE_.values():\r
+                        if BuildData.Arch != Arch:\r
+                            continue\r
+                        if BuildData.MetaFile.Ext == '.dec':\r
+                            continue\r
+                        for key in BuildData.Pcds:\r
+                            PcdItem = BuildData.Pcds[key]\r
+                            if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName):\r
+                                PcdItem.DefaultValue = NewValue\r
+\r
+                    if (TokenCName, TokenSpaceGuidCName) in PcdSet:\r
+                        PcdSet[(TokenCName, TokenSpaceGuidCName)] = NewValue\r
+\r
             #Collect package set information from INF of FDF\r
             PkgSet = set()\r
             for Inf in ModuleList:\r
@@ -418,6 +479,32 @@ class WorkspaceAutoGen(AutoGen):
 \r
         return True\r
 \r
+    def _BuildOptionPcdValueFormat(self, TokenSpaceGuidCName, TokenCName, PcdDatumType, Value):\r
+        if PcdDatumType == 'VOID*':\r
+            if Value.startswith('L'):\r
+                if not Value[1]:\r
+                    EdkLogger.error('build', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')\r
+                Value = Value[0] + '"' + Value[1:] + '"'\r
+            elif Value.startswith('B'):\r
+                if not Value[1]:\r
+                    EdkLogger.error('build', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')\r
+                Value = Value[1:]\r
+            else:\r
+                if not Value[0]:\r
+                    EdkLogger.error('build', OPTION_VALUE_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", B"{...}"')\r
+                Value = '"' + Value + '"'\r
+\r
+        IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)\r
+        if not IsValid:\r
+            EdkLogger.error('build', FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))\r
+        if PcdDatumType == 'BOOLEAN':\r
+            Value = Value.upper()\r
+            if Value == 'TRUE' or Value == '1':\r
+                Value = '1'\r
+            elif Value == 'FALSE' or Value == '0':\r
+                Value = '0'\r
+        return  Value\r
+\r
     ## _CheckDuplicateInFV() method\r
     #\r
     # Check whether there is duplicate modules/files exist in FV section. \r
@@ -953,6 +1040,18 @@ class PlatformAutoGen(AutoGen):
     #  This interface should be invoked explicitly when platform action is created.\r
     #\r
     def CollectPlatformDynamicPcds(self):\r
+        # Override the platform Pcd's value by build option\r
+        if GlobalData.BuildOptionPcd:\r
+            for key in self.Platform.Pcds:\r
+                PlatformPcd = self.Platform.Pcds[key]\r
+                for PcdItem in GlobalData.BuildOptionPcd:\r
+                    if (PlatformPcd.TokenSpaceGuidCName, PlatformPcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
+                        PlatformPcd.DefaultValue = PcdItem[2]\r
+                        if PlatformPcd.SkuInfoList:\r
+                            Sku = PlatformPcd.SkuInfoList[PlatformPcd.SkuInfoList.keys()[0]]\r
+                            Sku.DefaultValue = PcdItem[2]\r
+                        break\r
+\r
         # for gathering error information\r
         NoDatumTypePcdList = set()\r
         PcdNotInDb = []\r
index 3f0dfd90d9e2fcadcab83331125e0b7d4b2121a7..842d8bd6663a8ad7f6bdc1929dd4ff10e21e9d6d 100644 (file)
@@ -766,6 +766,13 @@ def GetPcdSize(Pcd):
 def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):\r
     TokenSpaceGuidValue = Pcd.TokenSpaceGuidValue   #Info.GuidList[Pcd.TokenSpaceGuidCName]\r
     PcdTokenNumber = Info.PlatformInfo.PcdTokenNumber\r
+\r
+    if GlobalData.BuildOptionPcd:\r
+        for PcdItem in GlobalData.BuildOptionPcd:\r
+            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
+                Pcd.DefaultValue = PcdItem[2]\r
+                break\r
+\r
     #\r
     # Write PCDs\r
     #\r
@@ -1054,7 +1061,13 @@ def CreateLibraryPcdCode(Info, AutoGenC, AutoGenH, Pcd):
     FixPcdSizeTokenName = '_PCD_SIZE_' + Pcd.TokenCName\r
     PatchPcdSizeTokenName = '_PCD_PATCHABLE_' + Pcd.TokenCName +'_SIZE'\r
     PatchPcdSizeVariableName = '_gPcd_BinaryPatch_Size_' + Pcd.TokenCName\r
-    \r
+\r
+    if GlobalData.BuildOptionPcd:\r
+        for PcdItem in GlobalData.BuildOptionPcd:\r
+            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
+                Pcd.DefaultValue = PcdItem[2]\r
+                break\r
+\r
     #\r
     # Write PCDs\r
     #\r
index 23865254d791b2c6531ca46aa79d68bf65f3a8ac..76d1254e72ed5d50dcdab50bff677c57f16b7c90 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # Routines for generating Pcd Database\r
 #\r
-# Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2013 - 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
@@ -1141,6 +1141,12 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
         CName = Pcd.TokenCName\r
         TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName\r
 \r
+        if GlobalData.BuildOptionPcd:\r
+            for PcdItem in GlobalData.BuildOptionPcd:\r
+                if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
+                    Pcd.DefaultValue = PcdItem[2]\r
+                    break\r
+\r
         EdkLogger.debug(EdkLogger.DEBUG_3, "PCD: %s %s (%s : %s)" % (CName, TokenSpaceGuidCName, Pcd.Phase, Phase))\r
 \r
         if Pcd.Phase == 'PEI':\r
@@ -1455,6 +1461,11 @@ def CreatePcdDatabasePhaseSpecificAutoGen (Platform, Phase):
         TokenSpaceGuidCName = Pcd.TokenSpaceGuidCName\r
         if Pcd.Phase != Phase:\r
             continue\r
+        if GlobalData.BuildOptionPcd:\r
+            for PcdItem in GlobalData.BuildOptionPcd:\r
+                if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (PcdItem[0], PcdItem[1]):\r
+                    Pcd.DefaultValue = PcdItem[2]\r
+                    break\r
 \r
         TokenSpaceGuid = GuidStructureStringToGuidValueName(Pcd.TokenSpaceGuidValue) #(Platform.PackageList, TokenSpaceGuidCName))\r
         GeneratedTokenNumber = Platform.PcdTokenNumber[CName, TokenSpaceGuidCName] - 1\r
index 218034ba33b39acb3913908c9f38e46f140a310f..4234bf5f955ff9154a6305e7f7e941ed77349a25 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # This file is used to define common static strings used by INF/DEC/DSC files\r
 #\r
-# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 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
@@ -77,3 +77,4 @@ gFdfParser = None
 #\r
 gTempInfs = []\r
 \r
+BuildOptionPcd = []\r
index 04a4d7dbd5b6d4de333a82dc7fc3b93abf9654ad..2dc02c2c4e056ecf792e3c0dbd0573440aa40c32 100644 (file)
@@ -42,6 +42,7 @@ from Common.DataType import TAB_BRG_LIBRARY
 from Common.DataType import TAB_BACK_SLASH\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
+import Common.GlobalData as GlobalData\r
 \r
 ## Pattern to extract contents in EDK DXS files\r
 gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)\r
@@ -727,6 +728,7 @@ class PcdReport(object):
             #\r
             FileWrite(File, gSectionStart)\r
             FileWrite(File, "Platform Configuration Database Report")\r
+            FileWrite(File, "  *B  - PCD override in the build option")\r
             FileWrite(File, "  *P  - Platform scoped PCD override in DSC file")\r
             FileWrite(File, "  *F  - Platform scoped PCD override in FDF file")\r
             FileWrite(File, "  *M  - Module scoped PCD override")\r
@@ -767,6 +769,15 @@ class PcdReport(object):
                         InfDefault, PcdValue = ModulePcdSet[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type]\r
                         if InfDefault == "":\r
                             InfDefault = None\r
+\r
+                    BuildOptionMatch = False\r
+                    if GlobalData.BuildOptionPcd:\r
+                        for pcd in GlobalData.BuildOptionPcd:\r
+                            if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (pcd[0], pcd[1]):\r
+                                PcdValue = pcd[2]\r
+                                BuildOptionMatch = True\r
+                                break\r
+\r
                     if First:\r
                         if ModulePcdSet == None:\r
                             FileWrite(File, "")\r
@@ -812,7 +823,9 @@ class PcdReport(object):
                     #\r
                     # Report PCD item according to their override relationship\r
                     #\r
-                    if DecMatch and InfMatch:\r
+                    if BuildOptionMatch:\r
+                        FileWrite(File, ' *B %-*s: %6s %10s = %-22s' % (self.MaxLen, Pcd.TokenCName, TypeName, '(' + Pcd.DatumType + ')', PcdValue.strip()))\r
+                    elif DecMatch and InfMatch:\r
                         FileWrite(File, '    %-*s: %6s %10s = %-22s' % (self.MaxLen, Pcd.TokenCName, TypeName, '(' + Pcd.DatumType + ')', PcdValue.strip()))\r
                     else:\r
                         if DscMatch:\r
@@ -840,17 +853,18 @@ class PcdReport(object):
                         FileWrite(File, '    %*s = %s' % (self.MaxLen + 19, 'DEC DEFAULT', DecDefaultValue.strip()))\r
 \r
                     if ModulePcdSet == None:\r
-                        ModuleOverride = self.ModulePcdOverride.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName), {})\r
-                        for ModulePath in ModuleOverride:\r
-                            ModuleDefault = ModuleOverride[ModulePath]\r
-                            if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):\r
-                                ModulePcdDefaultValueNumber = int(ModuleDefault.strip(), 0)\r
-                                Match = (ModulePcdDefaultValueNumber == PcdValueNumber)\r
-                            else:\r
-                                Match = (ModuleDefault.strip() == PcdValue.strip())\r
-                            if Match:\r
-                                continue\r
-                            FileWrite(File, ' *M %-*s = %s' % (self.MaxLen + 19, ModulePath, ModuleDefault.strip()))\r
+                        if not BuildOptionMatch:\r
+                            ModuleOverride = self.ModulePcdOverride.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName), {})\r
+                            for ModulePath in ModuleOverride:\r
+                                ModuleDefault = ModuleOverride[ModulePath]\r
+                                if Pcd.DatumType in ('UINT8', 'UINT16', 'UINT32', 'UINT64'):\r
+                                    ModulePcdDefaultValueNumber = int(ModuleDefault.strip(), 0)\r
+                                    Match = (ModulePcdDefaultValueNumber == PcdValueNumber)\r
+                                else:\r
+                                    Match = (ModuleDefault.strip() == PcdValue.strip())\r
+                                if Match:\r
+                                    continue\r
+                                FileWrite(File, ' *M %-*s = %s' % (self.MaxLen + 19, ModulePath, ModuleDefault.strip()))\r
 \r
         if ModulePcdSet == None:\r
             FileWrite(File, gSectionEnd)\r
index 23ca76e82c121777c7455bb35c0ba7e4abc160ca..5619638bd846ff56427bffc83530a81adefe3db4 100644 (file)
@@ -53,7 +53,7 @@ import Common.GlobalData as GlobalData
 # Version and Copyright\r
 VersionNumber = "0.60" + ' ' + gBUILD_VERSION\r
 __version__ = "%prog Version " + VersionNumber\r
-__copyright__ = "Copyright (c) 2007 - 2014, Intel Corporation  All rights reserved."\r
+__copyright__ = "Copyright (c) 2007 - 2016, Intel Corporation  All rights reserved."\r
 \r
 ## standard targets of build command\r
 gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'clean', 'cleanall', 'cleanlib', 'run']\r
@@ -747,6 +747,7 @@ class Build():
         self.BuildReport    = BuildReport(BuildOptions.ReportFile, BuildOptions.ReportType)\r
         self.TargetTxt      = TargetTxtClassObject()\r
         self.ToolDef        = ToolDefClassObject()\r
+        GlobalData.BuildOptionPcd     = BuildOptions.OptionPcd\r
         #Set global flag for build mode\r
         GlobalData.gIgnoreSource = BuildOptions.IgnoreSources\r
 \r
@@ -1929,6 +1930,7 @@ def MyOptionParser():
     Parser.add_option("--conf", action="store", type="string", dest="ConfDirectory", help="Specify the customized Conf directory.")\r
     Parser.add_option("--check-usage", action="store_true", dest="CheckUsage", default=False, help="Check usage content of entries listed in INF file.")\r
     Parser.add_option("--ignore-sources", action="store_true", dest="IgnoreSources", default=False, help="Focus to a binary build and ignore all source files")\r
+    Parser.add_option("--pcd", action="append", dest="OptionPcd", help="Set PCD value by command line. Format: 'PcdName=Value' ")\r
 \r
     (Opt, Args) = Parser.parse_args()\r
     return (Opt, Args)\r