[edk2] [Patch V2] BaseTools: Update --pcd parser to support flexible pcd format

Yonghong Zhu posted 1 patch 6 years, 1 month ago
Failed in applying to current master (apply log)
BaseTools/Source/Python/Common/Expression.py       |  21 +-
BaseTools/Source/Python/Common/Misc.py             |  41 ++-
BaseTools/Source/Python/GenFds/FdfParser.py        |   1 +
BaseTools/Source/Python/GenFds/FfsInfStatement.py  |  18 +-
BaseTools/Source/Python/GenFds/GenFds.py           |  49 ----
BaseTools/Source/Python/Workspace/DscBuildData.py  | 292 ++++++++-------------
.../Source/Python/Workspace/MetaFileParser.py      |   1 +
BaseTools/Source/Python/build/BuildReport.py       |   4 +-
8 files changed, 159 insertions(+), 268 deletions(-)
[edk2] [Patch V2] BaseTools: Update --pcd parser to support flexible pcd format
Posted by Yonghong Zhu 6 years, 1 month ago
This patch update --pcd parser to support flexible pcd format.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
---
 BaseTools/Source/Python/Common/Expression.py       |  21 +-
 BaseTools/Source/Python/Common/Misc.py             |  41 ++-
 BaseTools/Source/Python/GenFds/FdfParser.py        |   1 +
 BaseTools/Source/Python/GenFds/FfsInfStatement.py  |  18 +-
 BaseTools/Source/Python/GenFds/GenFds.py           |  49 ----
 BaseTools/Source/Python/Workspace/DscBuildData.py  | 292 ++++++++-------------
 .../Source/Python/Workspace/MetaFileParser.py      |   1 +
 BaseTools/Source/Python/build/BuildReport.py       |   4 +-
 8 files changed, 159 insertions(+), 268 deletions(-)

diff --git a/BaseTools/Source/Python/Common/Expression.py b/BaseTools/Source/Python/Common/Expression.py
index 5a0ade9..79dc83e 100644
--- a/BaseTools/Source/Python/Common/Expression.py
+++ b/BaseTools/Source/Python/Common/Expression.py
@@ -13,11 +13,11 @@
 ## Import Modules
 #
 from Common.GlobalData import *
 from CommonDataClass.Exceptions import BadExpression
 from CommonDataClass.Exceptions import WrnExpression
-from Misc import GuidStringToGuidStructureString, ParseFieldValue
+from Misc import GuidStringToGuidStructureString, ParseFieldValue, IsFieldValueAnArray
 import Common.EdkLogger as EdkLogger
 import copy
 
 ERR_STRING_EXPR         = 'This operator cannot be used in string expression: [%s].'
 ERR_SNYTAX              = 'Syntax error, the rest of expression cannot be evaluated: [%s].'
@@ -123,10 +123,29 @@ def IsValidCString(Str):
     ValidString = re.compile(r'[_a-zA-Z][_0-9a-zA-Z]*$')
     if not ValidString.match(Str):
         return False
     return True
 
+def BuildOptionValue(PcdValue, GuidDict):
+    IsArray = False
+    if PcdValue.startswith('H'):
+        InputValue = PcdValue[1:]
+    elif PcdValue.startswith("L'") or PcdValue.startswith("'"):
+        InputValue = PcdValue
+    elif PcdValue.startswith('L'):
+        InputValue = 'L"' + PcdValue[1:] + '"'
+    else:
+        InputValue = PcdValue
+    if IsFieldValueAnArray(InputValue):
+        IsArray = True
+    if IsArray:
+        try:
+            PcdValue = ValueExpressionEx(InputValue, 'VOID*', GuidDict)(True)
+        except:
+            pass
+    return PcdValue
+
 ## ReplaceExprMacro
 #
 def ReplaceExprMacro(String, Macros, ExceptionList = None):
     StrList = SplitString(String)
     for i, String in enumerate(StrList):
diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py
index af374d8..2086b4c 100644
--- a/BaseTools/Source/Python/Common/Misc.py
+++ b/BaseTools/Source/Python/Common/Misc.py
@@ -1439,10 +1439,26 @@ def ParseConsoleLog(Filename):
             Opw.write('%s\n' % Line)
 
     Opr.close()
     Opw.close()
 
+def IsFieldValueAnArray (Value):
+    Value = Value.strip()
+    if Value.startswith('GUID') and Value.endswith(')'):
+        return True
+    if Value.startswith('L"') and Value.endswith('"')  and len(list(Value[2:-1])) > 1:
+        return True
+    if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
+        return True
+    if Value[0] == '{' and Value[-1] == '}':
+        return True
+    if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
+        return True
+    if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
+        return True
+    return False
+
 def AnalyzePcdExpression(Setting):
     Setting = Setting.strip()
     # There might be escaped quote in a string: \", \\\" , \', \\\'
     Data = Setting
     # There might be '|' in string and in ( ... | ... ), replace it with '-'
@@ -2375,35 +2391,10 @@ def PackRegistryFormatGuid(Guid):
                 int(Guid[4][-6:-4], 16),
                 int(Guid[4][-4:-2], 16),
                 int(Guid[4][-2:], 16)
                 )
 
-def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Value):
-    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64,'BOOLEAN']:
-        if Value.startswith('L') or Value.startswith('"'):
-            if not Value[1]:
-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
-            Value = Value
-        elif Value.startswith('H'):
-            if not Value[1]:
-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
-            Value = Value[1:]
-        else:
-            if not Value[0]:
-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
-            Value = '"' + Value + '"'
-
-    IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)
-    if not IsValid:
-        EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))
-    if PcdDatumType == 'BOOLEAN':
-        Value = Value.upper()
-        if Value == 'TRUE' or Value == '1':
-            Value = '1'
-        elif Value == 'FALSE' or Value == '0':
-            Value = '0'
-    return  Value
 ##  Get the integer value from string like "14U" or integer like 2
 #
 #   @param      Input   The object that may be either a integer value or a string
 #
 #   @retval     Value    The integer value that the input represents
diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py
index fc2b409..76d7e6a 100644
--- a/BaseTools/Source/Python/GenFds/FdfParser.py
+++ b/BaseTools/Source/Python/GenFds/FdfParser.py
@@ -926,10 +926,11 @@ class FdfParser:
         MacroDict.update(GlobalData.gGlobalDefines)
         MacroDict.update(GlobalData.gCommandLineDefines)
         if GlobalData.BuildOptionPcd:
             for Item in GlobalData.BuildOptionPcd:
                 PcdName, TmpValue = Item.split("=")
+                TmpValue = BuildOptionValue(TmpValue, {})
                 MacroDict[PcdName.strip()] = TmpValue
         # Highest priority
 
         return MacroDict
 
diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py b/BaseTools/Source/Python/GenFds/FfsInfStatement.py
index dfff892..a348233 100644
--- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py
+++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py
@@ -1,9 +1,9 @@
 ## @file
 # process FFS generation from INF statement
 #
-#  Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
 #
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
 #  which accompanies this distribution.  The full text of the license may be found at
@@ -272,11 +272,13 @@ class FfsInfStatement(FfsInfStatementClassObject):
             # Override Patchable PCD value by the value from Build Option
             BuildOptionOverride = False
             if GlobalData.BuildOptionPcd:
                 for pcd in GlobalData.BuildOptionPcd:
                     if PcdKey == (pcd[1], pcd[0]):
-                        DefaultValue = pcd[2]
+                        if pcd[2]:
+                            continue
+                        DefaultValue = pcd[3]
                         BuildOptionOverride = True
                         break
 
             if not DscOverride and not FdfOverride and not BuildOptionOverride:
                 continue
@@ -286,19 +288,19 @@ class FfsInfStatement(FfsInfStatementClassObject):
                 try:
                     DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
                 except BadExpression:
                     EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue), File=self.InfFileName)
 
-            if Pcd.DefaultValue:
+            if Pcd.InfDefaultValue:
                 try:
-                    Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
+                    Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue, Pcd.DatumType, Platform._GuidDict)(True)
                 except BadExpression:
                     EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value "%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DefaultValue),File=self.InfFileName)
 
             # Check value, if value are equal, no need to patch
             if Pcd.DatumType == "VOID*":
-                if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']:
+                if Pcd.InfDefaultValue == DefaultValue or DefaultValue in [None, '']:
                     continue
                 # Get the string size from FDF or DSC
                 if DefaultValue[0] == 'L':
                     # Remove L"", but the '\0' must be appended
                     MaxDatumSize = str((len(DefaultValue) - 2) * 2)
@@ -308,19 +310,19 @@ class FfsInfStatement(FfsInfStatementClassObject):
                     MaxDatumSize = str(len(DefaultValue) - 1)
                 if DscOverride:
                     Pcd.MaxDatumSize = PatchPcd.MaxDatumSize
                 # If no defined the maximum size in DSC, try to get current size from INF
                 if Pcd.MaxDatumSize in ['', None]:
-                    Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(',')))
+                    Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))
             else:
                 Base1 = Base2 = 10
-                if Pcd.DefaultValue.upper().startswith('0X'):
+                if Pcd.InfDefaultValue.upper().startswith('0X'):
                     Base1 = 16
                 if DefaultValue.upper().startswith('0X'):
                     Base2 = 16
                 try:
-                    PcdValueInImg = int(Pcd.DefaultValue, Base1)
+                    PcdValueInImg = int(Pcd.InfDefaultValue, Base1)
                     PcdValueInDscOrFdf = int(DefaultValue, Base2)
                     if PcdValueInImg == PcdValueInDscOrFdf:
                         continue
                 except:
                     continue
diff --git a/BaseTools/Source/Python/GenFds/GenFds.py b/BaseTools/Source/Python/GenFds/GenFds.py
index 9ca7c87..4c56cbb 100644
--- a/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/BaseTools/Source/Python/GenFds/GenFds.py
@@ -36,12 +36,10 @@ from Common import EdkLogger
 from Common.String import *
 from Common.Misc import DirCache, PathClass
 from Common.Misc import SaveFileOnChange
 from Common.Misc import ClearDuplicatedInf
 from Common.Misc import GuidStructureStringToGuidString
-from Common.Misc import CheckPcdDatum
-from Common.Misc import BuildOptionPcdValueFormat
 from Common.BuildVersion import gBUILD_VERSION
 from Common.MultipleWorkspace import MultipleWorkspace as mws
 import FfsFileStatement
 import glob
 from struct import unpack
@@ -367,57 +365,10 @@ def SingleCheckCallback(option, opt_str, value, parser):
         setattr(parser.values, option.dest, value)
         gParamCheck.append(option)
     else:
         parser.error("Option %s only allows one instance in command line!" % option)
 
-def CheckBuildOptionPcd():
-    for Arch in GenFdsGlobalVariable.ArchList:
-        PkgList  = GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag)
-        for i, pcd in enumerate(GlobalData.BuildOptionPcd):
-            if type(pcd) is tuple:
-                continue
-            (pcdname, pcdvalue) = pcd.split('=')
-            if not pcdvalue:
-                EdkLogger.error('GenFds', OPTION_MISSING, "No Value specified for the PCD %s." % (pcdname))
-            if '.' in pcdname:
-                (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')
-                HasTokenSpace = True
-            else:
-                TokenCName = pcdname
-                TokenSpaceGuidCName = ''
-                HasTokenSpace = False
-            TokenSpaceGuidCNameList = []
-            FoundFlag = False
-            PcdDatumType = ''
-            NewValue = ''
-            for package in PkgList:
-                for key in package.Pcds:
-                    PcdItem = package.Pcds[key]
-                    if HasTokenSpace:
-                        if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
-                            PcdDatumType = PcdItem.DatumType
-                            NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
-                            FoundFlag = True
-                    else:
-                        if PcdItem.TokenCName == TokenCName:
-                            if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
-                                if len (TokenSpaceGuidCNameList) < 1:
-                                    TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
-                                    PcdDatumType = PcdItem.DatumType
-                                    TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
-                                    NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
-                                    FoundFlag = True
-                                else:
-                                    EdkLogger.error(
-                                            'GenFds',
-                                            PCD_VALIDATION_INFO_ERROR,
-                                            "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
-                                            )
-
-            GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, NewValue)
-
-
 ## FindExtendTool()
 #
 #  Find location of tools to process data
 #
 #  @param  KeyStringList    Filter for inputs of section generation
diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py b/BaseTools/Source/Python/Workspace/DscBuildData.py
index e72b777..91b3a27 100644
--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -19,11 +19,11 @@
 #
 from Common.String import *
 from Common.DataType import *
 from Common.Misc import *
 from types import *
-
+from Common.Expression import *
 from CommonDataClass.CommonClass import SkuInfoClass
 from Common.TargetTxtClassObject import *
 from Common.ToolDefClassObject import *
 from MetaDataTable import *
 from MetaFileTable import *
@@ -903,40 +903,10 @@ class DscBuildData(PlatformBuildClassObject):
                 pcd.PcdValueFromComm = pcd.SkuInfoList.get("DEFAULT").DefaultValue
         for pcd in self._Pcds:
             if isinstance(self._Pcds[pcd],StructurePcd) and (self._Pcds[pcd].PcdValueFromComm or self._Pcds[pcd].PcdFieldValueFromComm):
                 UpdateCommandLineValue(self._Pcds[pcd])
 
-    def GetFieldValueFromComm(self,ValueStr,TokenSpaceGuidCName, TokenCName, FieldName):
-        PredictedFieldType = "VOID*"
-        if ValueStr.startswith('L'):
-            if not ValueStr[1]:
-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
-            ValueStr = ValueStr[0] + '"' + ValueStr[1:] + '"'
-            PredictedFieldType = "VOID*"
-        elif ValueStr.startswith('H') or ValueStr.startswith('{'):
-            EdkLogger.error("build", FORMAT_INVALID, 'Currently we do not support assign H"{...}" format for Pcd field.', ExtraData="%s.%s.%s from command line" % (TokenSpaceGuidCName, TokenCName, FieldName))
-            ValueStr = ValueStr[1:]
-            PredictedFieldType = "VOID*"
-        elif ValueStr.upper() in ['TRUE', '0X1', '0X01', '1', 'FALSE', '0X0', '0X00', '0']:
-            PredictedFieldType = "BOOLEAN"
-        elif ValueStr.isdigit() or ValueStr.upper().startswith('0X'):
-            PredictedFieldType = TAB_UINT16
-        else:
-            if not ValueStr[0]:
-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
-            ValueStr = '"' + ValueStr + '"'
-            PredictedFieldType = "VOID*"
-        IsValid, Cause = CheckPcdDatum(PredictedFieldType, ValueStr)
-        if not IsValid:
-            EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s.%s from command line" % (TokenSpaceGuidCName, TokenCName, FieldName))
-        if PredictedFieldType == 'BOOLEAN':
-            ValueStr = ValueStr.upper()
-            if ValueStr == 'TRUE' or ValueStr == '1':
-                ValueStr = '1'
-            elif ValueStr == 'FALSE' or ValueStr == '0':
-                ValueStr = '0'
-        return  ValueStr
     def __ParsePcdFromCommandLine(self):
         if GlobalData.BuildOptionPcd:
             for i, pcd in enumerate(GlobalData.BuildOptionPcd):
                 if type(pcd) is tuple:
                     continue
@@ -973,152 +943,122 @@ class DscBuildData(PlatformBuildClassObject):
                     TokenSpaceGuidCName = ''
                     HasTokenSpace = False
                 TokenSpaceGuidCNameList = []
                 FoundFlag = False
                 PcdDatumType = ''
-                NewValue = ''
+                DisplayName = TokenCName
+                if FieldName:
+                    DisplayName = TokenCName + '.' + FieldName
                 if not HasTokenSpace:
                     for key in self.DecPcds:
-                        if TokenCName == key[0]:
-                            if TokenSpaceGuidCName:
-                                EdkLogger.error(
-                                                'build',
-                                                 AUTOGEN_ERROR,
-                                                "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, TokenSpaceGuidCName, key[1])
-                                                )
-                            else:
-                                TokenSpaceGuidCName = key[1]
-                                FoundFlag = True
+                        PcdItem = self.DecPcds[key]
+                        if TokenCName == PcdItem.TokenCName:
+                            if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
+                                if len (TokenSpaceGuidCNameList) < 1:
+                                    TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
+                                    TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
+                                    PcdDatumType = PcdItem.DatumType
+                                    FoundFlag = True
+                                else:
+                                    EdkLogger.error(
+                                            'build',
+                                             AUTOGEN_ERROR,
+                                            "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (DisplayName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
+                                            )
                 else:
                     if (TokenCName, TokenSpaceGuidCName) in self.DecPcds:
                         FoundFlag = True
-                if FieldName:
-                    NewValue = self.GetFieldValueFromComm(pcdvalue, TokenSpaceGuidCName, TokenCName, FieldName)
-                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName,NewValue,("build command options",1))
-                else:
-                    # Replace \' to ', \\\' to \'
-                    pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'', '\'').replace('\\\\\\"', "\\'")
-                    for key in self.DecPcds:
-                        PcdItem = self.DecPcds[key]
-                        if HasTokenSpace:
-                            if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):
-                                PcdDatumType = PcdItem.DatumType
-                                if pcdvalue.startswith('H'):
-                                    try:
-                                        pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
-                                    except BadExpression, Value:
-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
-                                        pcdvalue = 'H' + pcdvalue
-                                elif pcdvalue.startswith("L'"):
-                                    try:
-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                    except BadExpression, Value:
-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
-                                        pcdvalue = 'H' + pcdvalue
-                                elif pcdvalue.startswith("'"):
-                                    try:
-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                    except BadExpression, Value:
-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
-                                        pcdvalue = 'H' + pcdvalue
-                                elif pcdvalue.startswith('L'):
-                                    pcdvalue = 'L"' + pcdvalue[1:] + '"'
-                                    try:
-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                    except BadExpression, Value:
-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                        (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                else:
-                                    try:
-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                    except BadExpression, Value:
-                                        try:
-                                            pcdvalue = '"' + pcdvalue + '"'
-                                            pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                        except BadExpression, Value:
-                                            EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                            (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
-                                FoundFlag = True
-                        else:
-                            if PcdItem.TokenCName == TokenCName:
-                                if not PcdItem.TokenSpaceGuidCName in TokenSpaceGuidCNameList:
-                                    if len (TokenSpaceGuidCNameList) < 1:
-                                        TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
-                                        PcdDatumType = PcdItem.DatumType
-                                        TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName
-                                        if pcdvalue.startswith('H'):
-                                            try:
-                                                pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)
-                                            except BadExpression, Value:
-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %
-                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64,'BOOLEAN']:
-                                                pcdvalue = 'H' + pcdvalue
-                                        elif pcdvalue.startswith("L'"):
-                                            try:
-                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(
-                                                    True)
-                                            except BadExpression, Value:
-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
-                                                pcdvalue = 'H' + pcdvalue
-                                        elif pcdvalue.startswith("'"):
-                                            try:
-                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(
-                                                    True)
-                                            except BadExpression, Value:
-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
-                                                pcdvalue = 'H' + pcdvalue
-                                        elif pcdvalue.startswith('L'):
-                                            pcdvalue = 'L"' + pcdvalue[1:] + '"'
-                                            try:
-                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(
-                                                    True)
-                                            except BadExpression, Value:
-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                        else:
-                                            try:
-                                                pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                            except BadExpression, Value:
-                                                try:
-                                                    pcdvalue = '"' + pcdvalue + '"'
-                                                    pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType, self._GuidDict)(True)
-                                                except BadExpression, Value:
-                                                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
-                                                                    (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))
-                                        NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)
-                                        FoundFlag = True
-                                    else:
-                                        EdkLogger.error(
-                                                'build',
-                                                 AUTOGEN_ERROR,
-                                                "The Pcd %s is found under multiple different TokenSpaceGuid: %s and %s." % (TokenCName, PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
-                                                )
-                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName,NewValue,("build command options",1))
                 if not FoundFlag:
                     if HasTokenSpace:
-                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, TokenCName))
+                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not found in the DEC file." % (TokenSpaceGuidCName, DisplayName))
                     else:
-                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (TokenCName))
+                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not found in the DEC file." % (DisplayName))
+                pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'', '\'').replace('\\\\\\"', "\\'")
+                if FieldName:
+                    pcdvalue = self.HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, pcdvalue, PcdDatumType, self._GuidDict, FieldName)
+                else:
+                    pcdvalue = self.HandleFlexiblePcd(TokenSpaceGuidCName, TokenCName, pcdvalue, PcdDatumType, self._GuidDict)
+                    IsValid, Cause = CheckPcdDatum(PcdDatumType, pcdvalue)
+                    if not IsValid:
+                        EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))
+                GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue,("build command options",1))
+
                 for BuildData in self._Bdb._CACHE_.values():
                     if BuildData.MetaFile.Ext == '.dec' or BuildData.MetaFile.Ext == '.dsc':
                         continue
                     for key in BuildData.Pcds:
                         PcdItem = BuildData.Pcds[key]
                         if (TokenSpaceGuidCName, TokenCName) == (PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName) and FieldName =="":
-                            PcdItem.DefaultValue = NewValue
+                            PcdItem.DefaultValue = pcdvalue
+
+    def HandleFlexiblePcd(self, TokenSpaceGuidCName, TokenCName, PcdValue, PcdDatumType, GuidDict, FieldName=''):
+        if FieldName:
+            IsArray = False
+            TokenCName += '.' + FieldName
+        if PcdValue.startswith('H'):
+            if FieldName and IsFieldValueAnArray(PcdValue[1:]):
+                PcdDatumType = 'VOID*'
+                IsArray = True
+            if FieldName and not IsArray:
+                return PcdValue
+            try:
+                PcdValue = ValueExpressionEx(PcdValue[1:], PcdDatumType, GuidDict)(True)
+            except BadExpression, Value:     
+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+        elif PcdValue.startswith("L'") or PcdValue.startswith("'"):
+            if FieldName and IsFieldValueAnArray(PcdValue):
+                PcdDatumType = 'VOID*'
+                IsArray = True
+            if FieldName and not IsArray:
+                return PcdValue
+            try:
+                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
+            except BadExpression, Value:
+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+        elif PcdValue.startswith('L'):
+            PcdValue = 'L"' + PcdValue[1:] + '"'
+            if FieldName and IsFieldValueAnArray(PcdValue):
+                PcdDatumType = 'VOID*'
+                IsArray = True
+            if FieldName and not IsArray:
+                return PcdValue
+            try:
+                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
+            except BadExpression, Value:
+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+        else:
+            if PcdValue.upper() == 'FALSE':
+                PcdValue = str(0)
+            if PcdValue.upper() == 'TRUE':
+                PcdValue = str(1)
+            if not FieldName:
+                if PcdDatumType not in ['UINT8','UINT16','UINT32','UINT64','BOOLEAN']:
+                    PcdValue = '"' + PcdValue + '"'
+            else:
+                IsArray = False
+                Base = 10
+                if PcdValue.upper().startswith('0X'):
+                    Base = 16
+                try:
+                    Num = int(PcdValue, Base)
+                except:
+                    PcdValue = '"' + PcdValue + '"'
+                if IsFieldValueAnArray(PcdValue):
+                    PcdDatumType = 'VOID*'
+                    IsArray = True
+                if not IsArray:
+                    return PcdValue
+            try:
+                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType, GuidDict)(True)
+            except BadExpression, Value:
+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %
+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
+        return PcdValue
+
     ## Retrieve all PCD settings in platform
     def _GetPcds(self):
         if self._Pcds == None:
             self._Pcds = sdict()
             self.__ParsePcdFromCommandLine()
@@ -1553,26 +1493,10 @@ class DscBuildData(PlatformBuildClassObject):
                     return len(Value) - 2
             return len(Value)
 
         return str(max([pcd_size for pcd_size in [get_length(item) for item in sku_values]]))
 
-    def IsFieldValueAnArray (self, Value):
-        Value = Value.strip()
-        if Value.startswith('GUID') and Value.endswith(')'):
-            return True
-        if Value.startswith('L"') and Value.endswith('"')  and len(list(Value[2:-1])) > 1:
-            return True
-        if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
-            return True
-        if Value[0] == '{' and Value[-1] == '}':
-            return True
-        if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:
-            return True
-        if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
-            return True
-        return False
-
     def ExecuteCommand (self, Command):
         try:
             Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
         except:
             EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s' % Command)
@@ -1615,11 +1539,11 @@ class DscBuildData(PlatformBuildClassObject):
         for FieldList in [Pcd.DefaultValues]:
             if not FieldList:
                 continue
             for FieldName in FieldList:
                 FieldName = "." + FieldName
-                IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
+                IsArray = IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
                 if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
                     try:
                         Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], "VOID*", self._GuidDict)(True)
                     except BadExpression:
                         EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
@@ -1645,11 +1569,11 @@ class DscBuildData(PlatformBuildClassObject):
                 for FieldList in [Pcd.SkuOverrideValues[skuname].get(defaultstorenameitem)]:
                     if not FieldList:
                         continue
                     for FieldName in FieldList:
                         FieldName = "." + FieldName
-                        IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
+                        IsArray = IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
                         if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID') and FieldList[FieldName.strip(".")][0].endswith('}')):
                             try:
                                 Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0], "VOID*", self._GuidDict)(True)
                             except BadExpression:
                                 EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
@@ -1669,11 +1593,11 @@ class DscBuildData(PlatformBuildClassObject):
                                 CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); // From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."), ArrayIndex + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2], FieldList[FieldName_ori][0])
         if Pcd.PcdFieldValueFromComm:
             CApp = CApp + "// From Command Line \n"
         for FieldName in Pcd.PcdFieldValueFromComm:
             FieldName = "." + FieldName
-            IsArray = self.IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0])
+            IsArray = IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0])
             if IsArray and not (Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].startswith('{GUID') and Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].endswith('}')):
                 try:
                     Value = ValueExpressionEx(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0], "VOID*", self._GuidDict)(True)
                 except BadExpression:
                     EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
@@ -1702,11 +1626,11 @@ class DscBuildData(PlatformBuildClassObject):
         CApp = "// Default value in Dec \n"
         CApp = CApp + "void Assign_%s_%s_Default_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType)
         CApp = CApp + '  UINT32  FieldSize;\n'
         CApp = CApp + '  CHAR8   *Value;\n'
         DefaultValueFromDec = Pcd.DefaultValueFromDec
-        IsArray = self.IsFieldValueAnArray(Pcd.DefaultValueFromDec)
+        IsArray = IsFieldValueAnArray(Pcd.DefaultValueFromDec)
         if IsArray:
             try:
                 DefaultValueFromDec = ValueExpressionEx(Pcd.DefaultValueFromDec, "VOID*")(True)
             except BadExpression:
                 EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DEC: %s" %
@@ -1723,11 +1647,11 @@ class DscBuildData(PlatformBuildClassObject):
             CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
         for FieldList in [Pcd.DefaultValues]:
             if not FieldList:
                 continue
             for FieldName in FieldList:
-                IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
+                IsArray = IsFieldValueAnArray(FieldList[FieldName][0])
                 if IsArray:
                     try:
                         FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
                     except BadExpression:
                         EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
@@ -1773,11 +1697,11 @@ class DscBuildData(PlatformBuildClassObject):
             pcddefaultvalue = Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName)
         for FieldList in [pcddefaultvalue,inherit_OverrideValues.get(DefaultStoreName)]:
             if not FieldList:
                 continue
             if pcddefaultvalue and FieldList == pcddefaultvalue:
-                IsArray = self.IsFieldValueAnArray(FieldList)
+                IsArray = IsFieldValueAnArray(FieldList)
                 if IsArray:
                     try:
                         FieldList = ValueExpressionEx(FieldList, "VOID*")(True)
                     except BadExpression:
                         EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from DSC: %s" %
@@ -1803,11 +1727,11 @@ class DscBuildData(PlatformBuildClassObject):
                         CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' % (self.IntToCString(Value, ValueSize), Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName))
                         CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
                 continue
             if (SkuName,DefaultStoreName) == ('DEFAULT','STANDARD') or (( (SkuName,'') not in Pcd.ValueChain) and ( (SkuName,DefaultStoreName) not in Pcd.ValueChain )):
                 for FieldName in FieldList:
-                    IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
+                    IsArray = IsFieldValueAnArray(FieldList[FieldName][0])
                     if IsArray:
                         try:
                             FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
                         except BadExpression:
                             EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
@@ -1844,11 +1768,11 @@ class DscBuildData(PlatformBuildClassObject):
         pcddefaultvalue = Pcd.PcdValueFromComm
         for FieldList in [pcddefaultvalue,Pcd.PcdFieldValueFromComm]:
             if not FieldList:
                 continue
             if pcddefaultvalue and FieldList == pcddefaultvalue:
-                IsArray = self.IsFieldValueAnArray(FieldList)
+                IsArray = IsFieldValueAnArray(FieldList)
                 if IsArray:
                     try:
                         FieldList = ValueExpressionEx(FieldList, "VOID*")(True)
                     except BadExpression:
                         EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from Command: %s" %
@@ -1863,11 +1787,11 @@ class DscBuildData(PlatformBuildClassObject):
                 #
                     CApp = CApp + '  Value     = %s; // From Command Line.\n' % (self.IntToCString(Value, ValueSize))
                     CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
                 continue
             for FieldName in FieldList:
-                IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
+                IsArray = IsFieldValueAnArray(FieldList[FieldName][0])
                 if IsArray:
                     try:
                         FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
                     except BadExpression:
                         EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py b/BaseTools/Source/Python/Workspace/MetaFileParser.py
index 6809003..69bdf21 100644
--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
@@ -1244,10 +1244,11 @@ class DscParser(MetaFileParser):
         if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
             Macros.update(self._Symbols)
         if GlobalData.BuildOptionPcd:
             for Item in GlobalData.BuildOptionPcd:
                 PcdName, TmpValue = Item.split("=")
+                TmpValue = BuildOptionValue(TmpValue, self._GuidDict)
                 Macros[PcdName.strip()] = TmpValue
         return Macros
 
     def _PostProcess(self):
         Processer = {
diff --git a/BaseTools/Source/Python/build/BuildReport.py b/BaseTools/Source/Python/build/BuildReport.py
index 89bdfa1..d555dce 100644
--- a/BaseTools/Source/Python/build/BuildReport.py
+++ b/BaseTools/Source/Python/build/BuildReport.py
@@ -975,11 +975,13 @@ class PcdReport(object):
 
                     BuildOptionMatch = False
                     if GlobalData.BuildOptionPcd:
                         for pcd in GlobalData.BuildOptionPcd:
                             if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (pcd[0], pcd[1]):
-                                PcdValue = pcd[2]
+                                if pcd[2]:
+                                    continue
+                                PcdValue = pcd[3]
                                 Pcd.DefaultValue = PcdValue
                                 BuildOptionMatch = True
                                 break
 
                     if First:
-- 
2.6.1.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [Patch V2] BaseTools: Update --pcd parser to support flexible pcd format
Posted by Gao, Liming 6 years, 1 month ago
Reviewed-by: Liming Gao <liming.gao@intel.com>

>-----Original Message-----
>From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
>Yonghong Zhu
>Sent: Friday, March 09, 2018 12:32 PM
>To: edk2-devel@lists.01.org
>Subject: [edk2] [Patch V2] BaseTools: Update --pcd parser to support flexible
>pcd format
>
>This patch update --pcd parser to support flexible pcd format.
>
>Contributed-under: TianoCore Contribution Agreement 1.1
>Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
>---
> BaseTools/Source/Python/Common/Expression.py       |  21 +-
> BaseTools/Source/Python/Common/Misc.py             |  41 ++-
> BaseTools/Source/Python/GenFds/FdfParser.py        |   1 +
> BaseTools/Source/Python/GenFds/FfsInfStatement.py  |  18 +-
> BaseTools/Source/Python/GenFds/GenFds.py           |  49 ----
> BaseTools/Source/Python/Workspace/DscBuildData.py  | 292 ++++++++------
>-------
> .../Source/Python/Workspace/MetaFileParser.py      |   1 +
> BaseTools/Source/Python/build/BuildReport.py       |   4 +-
> 8 files changed, 159 insertions(+), 268 deletions(-)
>
>diff --git a/BaseTools/Source/Python/Common/Expression.py
>b/BaseTools/Source/Python/Common/Expression.py
>index 5a0ade9..79dc83e 100644
>--- a/BaseTools/Source/Python/Common/Expression.py
>+++ b/BaseTools/Source/Python/Common/Expression.py
>@@ -13,11 +13,11 @@
> ## Import Modules
> #
> from Common.GlobalData import *
> from CommonDataClass.Exceptions import BadExpression
> from CommonDataClass.Exceptions import WrnExpression
>-from Misc import GuidStringToGuidStructureString, ParseFieldValue
>+from Misc import GuidStringToGuidStructureString, ParseFieldValue,
>IsFieldValueAnArray
> import Common.EdkLogger as EdkLogger
> import copy
>
> ERR_STRING_EXPR         = 'This operator cannot be used in string expression:
>[%s].'
> ERR_SNYTAX              = 'Syntax error, the rest of expression cannot be
>evaluated: [%s].'
>@@ -123,10 +123,29 @@ def IsValidCString(Str):
>     ValidString = re.compile(r'[_a-zA-Z][_0-9a-zA-Z]*$')
>     if not ValidString.match(Str):
>         return False
>     return True
>
>+def BuildOptionValue(PcdValue, GuidDict):
>+    IsArray = False
>+    if PcdValue.startswith('H'):
>+        InputValue = PcdValue[1:]
>+    elif PcdValue.startswith("L'") or PcdValue.startswith("'"):
>+        InputValue = PcdValue
>+    elif PcdValue.startswith('L'):
>+        InputValue = 'L"' + PcdValue[1:] + '"'
>+    else:
>+        InputValue = PcdValue
>+    if IsFieldValueAnArray(InputValue):
>+        IsArray = True
>+    if IsArray:
>+        try:
>+            PcdValue = ValueExpressionEx(InputValue, 'VOID*', GuidDict)(True)
>+        except:
>+            pass
>+    return PcdValue
>+
> ## ReplaceExprMacro
> #
> def ReplaceExprMacro(String, Macros, ExceptionList = None):
>     StrList = SplitString(String)
>     for i, String in enumerate(StrList):
>diff --git a/BaseTools/Source/Python/Common/Misc.py
>b/BaseTools/Source/Python/Common/Misc.py
>index af374d8..2086b4c 100644
>--- a/BaseTools/Source/Python/Common/Misc.py
>+++ b/BaseTools/Source/Python/Common/Misc.py
>@@ -1439,10 +1439,26 @@ def ParseConsoleLog(Filename):
>             Opw.write('%s\n' % Line)
>
>     Opr.close()
>     Opw.close()
>
>+def IsFieldValueAnArray (Value):
>+    Value = Value.strip()
>+    if Value.startswith('GUID') and Value.endswith(')'):
>+        return True
>+    if Value.startswith('L"') and Value.endswith('"')  and len(list(Value[2:-1])) >
>1:
>+        return True
>+    if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
>+        return True
>+    if Value[0] == '{' and Value[-1] == '}':
>+        return True
>+    if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) >
>1:
>+        return True
>+    if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
>+        return True
>+    return False
>+
> def AnalyzePcdExpression(Setting):
>     Setting = Setting.strip()
>     # There might be escaped quote in a string: \", \\\" , \', \\\'
>     Data = Setting
>     # There might be '|' in string and in ( ... | ... ), replace it with '-'
>@@ -2375,35 +2391,10 @@ def PackRegistryFormatGuid(Guid):
>                 int(Guid[4][-6:-4], 16),
>                 int(Guid[4][-4:-2], 16),
>                 int(Guid[4][-2:], 16)
>                 )
>
>-def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName,
>PcdDatumType, Value):
>-    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32,
>TAB_UINT64,'BOOLEAN']:
>-        if Value.startswith('L') or Value.startswith('"'):
>-            if not Value[1]:
>-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD,
>when specify the Value in the command line, please use the following format:
>"string", L"string", H"{...}"')
>-            Value = Value
>-        elif Value.startswith('H'):
>-            if not Value[1]:
>-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD,
>when specify the Value in the command line, please use the following format:
>"string", L"string", H"{...}"')
>-            Value = Value[1:]
>-        else:
>-            if not Value[0]:
>-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD,
>when specify the Value in the command line, please use the following format:
>"string", L"string", H"{...}"')
>-            Value = '"' + Value + '"'
>-
>-    IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)
>-    if not IsValid:
>-        EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" %
>(TokenSpaceGuidCName, TokenCName))
>-    if PcdDatumType == 'BOOLEAN':
>-        Value = Value.upper()
>-        if Value == 'TRUE' or Value == '1':
>-            Value = '1'
>-        elif Value == 'FALSE' or Value == '0':
>-            Value = '0'
>-    return  Value
> ##  Get the integer value from string like "14U" or integer like 2
> #
> #   @param      Input   The object that may be either a integer value or a string
> #
> #   @retval     Value    The integer value that the input represents
>diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py
>b/BaseTools/Source/Python/GenFds/FdfParser.py
>index fc2b409..76d7e6a 100644
>--- a/BaseTools/Source/Python/GenFds/FdfParser.py
>+++ b/BaseTools/Source/Python/GenFds/FdfParser.py
>@@ -926,10 +926,11 @@ class FdfParser:
>         MacroDict.update(GlobalData.gGlobalDefines)
>         MacroDict.update(GlobalData.gCommandLineDefines)
>         if GlobalData.BuildOptionPcd:
>             for Item in GlobalData.BuildOptionPcd:
>                 PcdName, TmpValue = Item.split("=")
>+                TmpValue = BuildOptionValue(TmpValue, {})
>                 MacroDict[PcdName.strip()] = TmpValue
>         # Highest priority
>
>         return MacroDict
>
>diff --git a/BaseTools/Source/Python/GenFds/FfsInfStatement.py
>b/BaseTools/Source/Python/GenFds/FfsInfStatement.py
>index dfff892..a348233 100644
>--- a/BaseTools/Source/Python/GenFds/FfsInfStatement.py
>+++ b/BaseTools/Source/Python/GenFds/FfsInfStatement.py
>@@ -1,9 +1,9 @@
> ## @file
> # process FFS generation from INF statement
> #
>-#  Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
>+#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
> #  Copyright (c) 2014-2016 Hewlett-Packard Development Company, L.P.<BR>
> #
> #  This program and the accompanying materials
> #  are licensed and made available under the terms and conditions of the BSD
>License
> #  which accompanies this distribution.  The full text of the license may be
>found at
>@@ -272,11 +272,13 @@ class FfsInfStatement(FfsInfStatementClassObject):
>             # Override Patchable PCD value by the value from Build Option
>             BuildOptionOverride = False
>             if GlobalData.BuildOptionPcd:
>                 for pcd in GlobalData.BuildOptionPcd:
>                     if PcdKey == (pcd[1], pcd[0]):
>-                        DefaultValue = pcd[2]
>+                        if pcd[2]:
>+                            continue
>+                        DefaultValue = pcd[3]
>                         BuildOptionOverride = True
>                         break
>
>             if not DscOverride and not FdfOverride and not BuildOptionOverride:
>                 continue
>@@ -286,19 +288,19 @@ class FfsInfStatement(FfsInfStatementClassObject):
>                 try:
>                     DefaultValue = ValueExpressionEx(DefaultValue, Pcd.DatumType,
>Platform._GuidDict)(True)
>                 except BadExpression:
>                     EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value
>"%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName, DefaultValue),
>File=self.InfFileName)
>
>-            if Pcd.DefaultValue:
>+            if Pcd.InfDefaultValue:
>                 try:
>-                    Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue,
>Pcd.DatumType, Platform._GuidDict)(True)
>+                    Pcd.InfDefaultValue = ValueExpressionEx(Pcd.InfDefaultValue,
>Pcd.DatumType, Platform._GuidDict)(True)
>                 except BadExpression:
>                     EdkLogger.error("GenFds", GENFDS_ERROR, 'PCD [%s.%s] Value
>"%s"' %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName,
>Pcd.DefaultValue),File=self.InfFileName)
>
>             # Check value, if value are equal, no need to patch
>             if Pcd.DatumType == "VOID*":
>-                if Pcd.DefaultValue == DefaultValue or DefaultValue in [None, '']:
>+                if Pcd.InfDefaultValue == DefaultValue or DefaultValue in [None, '']:
>                     continue
>                 # Get the string size from FDF or DSC
>                 if DefaultValue[0] == 'L':
>                     # Remove L"", but the '\0' must be appended
>                     MaxDatumSize = str((len(DefaultValue) - 2) * 2)
>@@ -308,19 +310,19 @@ class FfsInfStatement(FfsInfStatementClassObject):
>                     MaxDatumSize = str(len(DefaultValue) - 1)
>                 if DscOverride:
>                     Pcd.MaxDatumSize = PatchPcd.MaxDatumSize
>                 # If no defined the maximum size in DSC, try to get current size from
>INF
>                 if Pcd.MaxDatumSize in ['', None]:
>-                    Pcd.MaxDatumSize = str(len(Pcd.DefaultValue.split(',')))
>+                    Pcd.MaxDatumSize = str(len(Pcd.InfDefaultValue.split(',')))
>             else:
>                 Base1 = Base2 = 10
>-                if Pcd.DefaultValue.upper().startswith('0X'):
>+                if Pcd.InfDefaultValue.upper().startswith('0X'):
>                     Base1 = 16
>                 if DefaultValue.upper().startswith('0X'):
>                     Base2 = 16
>                 try:
>-                    PcdValueInImg = int(Pcd.DefaultValue, Base1)
>+                    PcdValueInImg = int(Pcd.InfDefaultValue, Base1)
>                     PcdValueInDscOrFdf = int(DefaultValue, Base2)
>                     if PcdValueInImg == PcdValueInDscOrFdf:
>                         continue
>                 except:
>                     continue
>diff --git a/BaseTools/Source/Python/GenFds/GenFds.py
>b/BaseTools/Source/Python/GenFds/GenFds.py
>index 9ca7c87..4c56cbb 100644
>--- a/BaseTools/Source/Python/GenFds/GenFds.py
>+++ b/BaseTools/Source/Python/GenFds/GenFds.py
>@@ -36,12 +36,10 @@ from Common import EdkLogger
> from Common.String import *
> from Common.Misc import DirCache, PathClass
> from Common.Misc import SaveFileOnChange
> from Common.Misc import ClearDuplicatedInf
> from Common.Misc import GuidStructureStringToGuidString
>-from Common.Misc import CheckPcdDatum
>-from Common.Misc import BuildOptionPcdValueFormat
> from Common.BuildVersion import gBUILD_VERSION
> from Common.MultipleWorkspace import MultipleWorkspace as mws
> import FfsFileStatement
> import glob
> from struct import unpack
>@@ -367,57 +365,10 @@ def SingleCheckCallback(option, opt_str, value,
>parser):
>         setattr(parser.values, option.dest, value)
>         gParamCheck.append(option)
>     else:
>         parser.error("Option %s only allows one instance in command line!" %
>option)
>
>-def CheckBuildOptionPcd():
>-    for Arch in GenFdsGlobalVariable.ArchList:
>-        PkgList  =
>GenFdsGlobalVariable.WorkSpace.GetPackageList(GenFdsGlobalVariable.Acti
>vePlatform, Arch, GenFdsGlobalVariable.TargetName,
>GenFdsGlobalVariable.ToolChainTag)
>-        for i, pcd in enumerate(GlobalData.BuildOptionPcd):
>-            if type(pcd) is tuple:
>-                continue
>-            (pcdname, pcdvalue) = pcd.split('=')
>-            if not pcdvalue:
>-                EdkLogger.error('GenFds', OPTION_MISSING, "No Value specified for
>the PCD %s." % (pcdname))
>-            if '.' in pcdname:
>-                (TokenSpaceGuidCName, TokenCName) = pcdname.split('.')
>-                HasTokenSpace = True
>-            else:
>-                TokenCName = pcdname
>-                TokenSpaceGuidCName = ''
>-                HasTokenSpace = False
>-            TokenSpaceGuidCNameList = []
>-            FoundFlag = False
>-            PcdDatumType = ''
>-            NewValue = ''
>-            for package in PkgList:
>-                for key in package.Pcds:
>-                    PcdItem = package.Pcds[key]
>-                    if HasTokenSpace:
>-                        if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) ==
>(TokenCName, TokenSpaceGuidCName):
>-                            PcdDatumType = PcdItem.DatumType
>-                            NewValue =
>BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName,
>PcdDatumType, pcdvalue)
>-                            FoundFlag = True
>-                    else:
>-                        if PcdItem.TokenCName == TokenCName:
>-                            if not PcdItem.TokenSpaceGuidCName in
>TokenSpaceGuidCNameList:
>-                                if len (TokenSpaceGuidCNameList) < 1:
>-
>TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
>-                                    PcdDatumType = PcdItem.DatumType
>-                                    TokenSpaceGuidCName =
>PcdItem.TokenSpaceGuidCName
>-                                    NewValue =
>BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName,
>PcdDatumType, pcdvalue)
>-                                    FoundFlag = True
>-                                else:
>-                                    EdkLogger.error(
>-                                            'GenFds',
>-                                            PCD_VALIDATION_INFO_ERROR,
>-                                            "The Pcd %s is found under multiple different
>TokenSpaceGuid: %s and %s." % (TokenCName,
>PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
>-                                            )
>-
>-            GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName, TokenCName,
>NewValue)
>-
>-
> ## FindExtendTool()
> #
> #  Find location of tools to process data
> #
> #  @param  KeyStringList    Filter for inputs of section generation
>diff --git a/BaseTools/Source/Python/Workspace/DscBuildData.py
>b/BaseTools/Source/Python/Workspace/DscBuildData.py
>index e72b777..91b3a27 100644
>--- a/BaseTools/Source/Python/Workspace/DscBuildData.py
>+++ b/BaseTools/Source/Python/Workspace/DscBuildData.py
>@@ -19,11 +19,11 @@
> #
> from Common.String import *
> from Common.DataType import *
> from Common.Misc import *
> from types import *
>-
>+from Common.Expression import *
> from CommonDataClass.CommonClass import SkuInfoClass
> from Common.TargetTxtClassObject import *
> from Common.ToolDefClassObject import *
> from MetaDataTable import *
> from MetaFileTable import *
>@@ -903,40 +903,10 @@ class DscBuildData(PlatformBuildClassObject):
>                 pcd.PcdValueFromComm =
>pcd.SkuInfoList.get("DEFAULT").DefaultValue
>         for pcd in self._Pcds:
>             if isinstance(self._Pcds[pcd],StructurePcd) and
>(self._Pcds[pcd].PcdValueFromComm or
>self._Pcds[pcd].PcdFieldValueFromComm):
>                 UpdateCommandLineValue(self._Pcds[pcd])
>
>-    def GetFieldValueFromComm(self,ValueStr,TokenSpaceGuidCName,
>TokenCName, FieldName):
>-        PredictedFieldType = "VOID*"
>-        if ValueStr.startswith('L'):
>-            if not ValueStr[1]:
>-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD,
>when specify the Value in the command line, please use the following format:
>"string", L"string", H"{...}"')
>-            ValueStr = ValueStr[0] + '"' + ValueStr[1:] + '"'
>-            PredictedFieldType = "VOID*"
>-        elif ValueStr.startswith('H') or ValueStr.startswith('{'):
>-            EdkLogger.error("build", FORMAT_INVALID, 'Currently we do not
>support assign H"{...}" format for Pcd field.', ExtraData="%s.%s.%s from
>command line" % (TokenSpaceGuidCName, TokenCName, FieldName))
>-            ValueStr = ValueStr[1:]
>-            PredictedFieldType = "VOID*"
>-        elif ValueStr.upper() in ['TRUE', '0X1', '0X01', '1', 'FALSE', '0X0', '0X00', '0']:
>-            PredictedFieldType = "BOOLEAN"
>-        elif ValueStr.isdigit() or ValueStr.upper().startswith('0X'):
>-            PredictedFieldType = TAB_UINT16
>-        else:
>-            if not ValueStr[0]:
>-                EdkLogger.error("build", FORMAT_INVALID, 'For Void* type PCD,
>when specify the Value in the command line, please use the following format:
>"string", L"string", H"{...}"')
>-            ValueStr = '"' + ValueStr + '"'
>-            PredictedFieldType = "VOID*"
>-        IsValid, Cause = CheckPcdDatum(PredictedFieldType, ValueStr)
>-        if not IsValid:
>-            EdkLogger.error("build", FORMAT_INVALID, Cause,
>ExtraData="%s.%s.%s from command line" % (TokenSpaceGuidCName,
>TokenCName, FieldName))
>-        if PredictedFieldType == 'BOOLEAN':
>-            ValueStr = ValueStr.upper()
>-            if ValueStr == 'TRUE' or ValueStr == '1':
>-                ValueStr = '1'
>-            elif ValueStr == 'FALSE' or ValueStr == '0':
>-                ValueStr = '0'
>-        return  ValueStr
>     def __ParsePcdFromCommandLine(self):
>         if GlobalData.BuildOptionPcd:
>             for i, pcd in enumerate(GlobalData.BuildOptionPcd):
>                 if type(pcd) is tuple:
>                     continue
>@@ -973,152 +943,122 @@ class DscBuildData(PlatformBuildClassObject):
>                     TokenSpaceGuidCName = ''
>                     HasTokenSpace = False
>                 TokenSpaceGuidCNameList = []
>                 FoundFlag = False
>                 PcdDatumType = ''
>-                NewValue = ''
>+                DisplayName = TokenCName
>+                if FieldName:
>+                    DisplayName = TokenCName + '.' + FieldName
>                 if not HasTokenSpace:
>                     for key in self.DecPcds:
>-                        if TokenCName == key[0]:
>-                            if TokenSpaceGuidCName:
>-                                EdkLogger.error(
>-                                                'build',
>-                                                 AUTOGEN_ERROR,
>-                                                "The Pcd %s is found under multiple different
>TokenSpaceGuid: %s and %s." % (TokenCName, TokenSpaceGuidCName,
>key[1])
>-                                                )
>-                            else:
>-                                TokenSpaceGuidCName = key[1]
>-                                FoundFlag = True
>+                        PcdItem = self.DecPcds[key]
>+                        if TokenCName == PcdItem.TokenCName:
>+                            if not PcdItem.TokenSpaceGuidCName in
>TokenSpaceGuidCNameList:
>+                                if len (TokenSpaceGuidCNameList) < 1:
>+
>TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
>+                                    TokenSpaceGuidCName =
>PcdItem.TokenSpaceGuidCName
>+                                    PcdDatumType = PcdItem.DatumType
>+                                    FoundFlag = True
>+                                else:
>+                                    EdkLogger.error(
>+                                            'build',
>+                                             AUTOGEN_ERROR,
>+                                            "The Pcd %s is found under multiple different
>TokenSpaceGuid: %s and %s." % (DisplayName,
>PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
>+                                            )
>                 else:
>                     if (TokenCName, TokenSpaceGuidCName) in self.DecPcds:
>                         FoundFlag = True
>-                if FieldName:
>-                    NewValue = self.GetFieldValueFromComm(pcdvalue,
>TokenSpaceGuidCName, TokenCName, FieldName)
>-                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName,
>TokenCName, FieldName,NewValue,("build command options",1))
>-                else:
>-                    # Replace \' to ', \\\' to \'
>-                    pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'',
>'\'').replace('\\\\\\"', "\\'")
>-                    for key in self.DecPcds:
>-                        PcdItem = self.DecPcds[key]
>-                        if HasTokenSpace:
>-                            if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName)
>== (TokenCName, TokenSpaceGuidCName):
>-                                PcdDatumType = PcdItem.DatumType
>-                                if pcdvalue.startswith('H'):
>-                                    try:
>-                                        pcdvalue = ValueExpressionEx(pcdvalue[1:],
>PcdDatumType, self._GuidDict)(True)
>-                                    except BadExpression, Value:
>-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s]
>Value "%s",  %s' %
>-                                                        (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16,
>TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
>-                                        pcdvalue = 'H' + pcdvalue
>-                                elif pcdvalue.startswith("L'"):
>-                                    try:
>-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType,
>self._GuidDict)(True)
>-                                    except BadExpression, Value:
>-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s]
>Value "%s",  %s' %
>-                                                        (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16,
>TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
>-                                        pcdvalue = 'H' + pcdvalue
>-                                elif pcdvalue.startswith("'"):
>-                                    try:
>-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType,
>self._GuidDict)(True)
>-                                    except BadExpression, Value:
>-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s]
>Value "%s",  %s' %
>-                                                        (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                    if PcdDatumType not in [TAB_UINT8, TAB_UINT16,
>TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
>-                                        pcdvalue = 'H' + pcdvalue
>-                                elif pcdvalue.startswith('L'):
>-                                    pcdvalue = 'L"' + pcdvalue[1:] + '"'
>-                                    try:
>-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType,
>self._GuidDict)(True)
>-                                    except BadExpression, Value:
>-                                        EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s]
>Value "%s",  %s' %
>-                                                        (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                else:
>-                                    try:
>-                                        pcdvalue = ValueExpressionEx(pcdvalue, PcdDatumType,
>self._GuidDict)(True)
>-                                    except BadExpression, Value:
>-                                        try:
>-                                            pcdvalue = '"' + pcdvalue + '"'
>-                                            pcdvalue = ValueExpressionEx(pcdvalue,
>PcdDatumType, self._GuidDict)(True)
>-                                        except BadExpression, Value:
>-                                            EdkLogger.error('Parser', FORMAT_INVALID, 'PCD
>[%s.%s] Value "%s",  %s' %
>-                                                            (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                NewValue =
>BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName,
>PcdDatumType, pcdvalue)
>-                                FoundFlag = True
>-                        else:
>-                            if PcdItem.TokenCName == TokenCName:
>-                                if not PcdItem.TokenSpaceGuidCName in
>TokenSpaceGuidCNameList:
>-                                    if len (TokenSpaceGuidCNameList) < 1:
>-
>TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)
>-                                        PcdDatumType = PcdItem.DatumType
>-                                        TokenSpaceGuidCName =
>PcdItem.TokenSpaceGuidCName
>-                                        if pcdvalue.startswith('H'):
>-                                            try:
>-                                                pcdvalue = ValueExpressionEx(pcdvalue[1:],
>PcdDatumType, self._GuidDict)(True)
>-                                            except BadExpression, Value:
>-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD
>[%s.%s] Value "%s", %s' %
>-                                                                (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16,
>TAB_UINT32, TAB_UINT64,'BOOLEAN']:
>-                                                pcdvalue = 'H' + pcdvalue
>-                                        elif pcdvalue.startswith("L'"):
>-                                            try:
>-                                                pcdvalue = ValueExpressionEx(pcdvalue,
>PcdDatumType, self._GuidDict)(
>-                                                    True)
>-                                            except BadExpression, Value:
>-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD
>[%s.%s] Value "%s",  %s' %
>-                                                                (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16,
>TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
>-                                                pcdvalue = 'H' + pcdvalue
>-                                        elif pcdvalue.startswith("'"):
>-                                            try:
>-                                                pcdvalue = ValueExpressionEx(pcdvalue,
>PcdDatumType, self._GuidDict)(
>-                                                    True)
>-                                            except BadExpression, Value:
>-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD
>[%s.%s] Value "%s",  %s' %
>-                                                                (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                            if PcdDatumType not in [TAB_UINT8, TAB_UINT16,
>TAB_UINT32, TAB_UINT64, 'BOOLEAN']:
>-                                                pcdvalue = 'H' + pcdvalue
>-                                        elif pcdvalue.startswith('L'):
>-                                            pcdvalue = 'L"' + pcdvalue[1:] + '"'
>-                                            try:
>-                                                pcdvalue = ValueExpressionEx(pcdvalue,
>PcdDatumType, self._GuidDict)(
>-                                                    True)
>-                                            except BadExpression, Value:
>-                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD
>[%s.%s] Value "%s",  %s' %
>-                                                                (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                        else:
>-                                            try:
>-                                                pcdvalue = ValueExpressionEx(pcdvalue,
>PcdDatumType, self._GuidDict)(True)
>-                                            except BadExpression, Value:
>-                                                try:
>-                                                    pcdvalue = '"' + pcdvalue + '"'
>-                                                    pcdvalue = ValueExpressionEx(pcdvalue,
>PcdDatumType, self._GuidDict)(True)
>-                                                except BadExpression, Value:
>-                                                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD
>[%s.%s] Value "%s",  %s' %
>-                                                                    (TokenSpaceGuidCName, TokenCName,
>pcdvalue, Value))
>-                                        NewValue =
>BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName,
>PcdDatumType, pcdvalue)
>-                                        FoundFlag = True
>-                                    else:
>-                                        EdkLogger.error(
>-                                                'build',
>-                                                 AUTOGEN_ERROR,
>-                                                "The Pcd %s is found under multiple different
>TokenSpaceGuid: %s and %s." % (TokenCName,
>PcdItem.TokenSpaceGuidCName, TokenSpaceGuidCNameList[0])
>-                                                )
>-                    GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName,
>TokenCName, FieldName,NewValue,("build command options",1))
>                 if not FoundFlag:
>                     if HasTokenSpace:
>-                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not
>found in the DEC file." % (TokenSpaceGuidCName, TokenCName))
>+                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s.%s is not
>found in the DEC file." % (TokenSpaceGuidCName, DisplayName))
>                     else:
>-                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not
>found in the DEC file." % (TokenCName))
>+                        EdkLogger.error('build', AUTOGEN_ERROR, "The Pcd %s is not
>found in the DEC file." % (DisplayName))
>+                pcdvalue = pcdvalue.replace("\\\\\\'", '\\\\\\"').replace('\\\'',
>'\'').replace('\\\\\\"', "\\'")
>+                if FieldName:
>+                    pcdvalue = self.HandleFlexiblePcd(TokenSpaceGuidCName,
>TokenCName, pcdvalue, PcdDatumType, self._GuidDict, FieldName)
>+                else:
>+                    pcdvalue = self.HandleFlexiblePcd(TokenSpaceGuidCName,
>TokenCName, pcdvalue, PcdDatumType, self._GuidDict)
>+                    IsValid, Cause = CheckPcdDatum(PcdDatumType, pcdvalue)
>+                    if not IsValid:
>+                        EdkLogger.error("build", FORMAT_INVALID, Cause,
>ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))
>+                GlobalData.BuildOptionPcd[i] = (TokenSpaceGuidCName,
>TokenCName, FieldName, pcdvalue,("build command options",1))
>+
>                 for BuildData in self._Bdb._CACHE_.values():
>                     if BuildData.MetaFile.Ext == '.dec' or BuildData.MetaFile.Ext ==
>'.dsc':
>                         continue
>                     for key in BuildData.Pcds:
>                         PcdItem = BuildData.Pcds[key]
>                         if (TokenSpaceGuidCName, TokenCName) ==
>(PcdItem.TokenSpaceGuidCName, PcdItem.TokenCName) and FieldName
>=="":
>-                            PcdItem.DefaultValue = NewValue
>+                            PcdItem.DefaultValue = pcdvalue
>+
>+    def HandleFlexiblePcd(self, TokenSpaceGuidCName, TokenCName,
>PcdValue, PcdDatumType, GuidDict, FieldName=''):
>+        if FieldName:
>+            IsArray = False
>+            TokenCName += '.' + FieldName
>+        if PcdValue.startswith('H'):
>+            if FieldName and IsFieldValueAnArray(PcdValue[1:]):
>+                PcdDatumType = 'VOID*'
>+                IsArray = True
>+            if FieldName and not IsArray:
>+                return PcdValue
>+            try:
>+                PcdValue = ValueExpressionEx(PcdValue[1:], PcdDatumType,
>GuidDict)(True)
>+            except BadExpression, Value:
>+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value
>"%s",  %s' %
>+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
>+        elif PcdValue.startswith("L'") or PcdValue.startswith("'"):
>+            if FieldName and IsFieldValueAnArray(PcdValue):
>+                PcdDatumType = 'VOID*'
>+                IsArray = True
>+            if FieldName and not IsArray:
>+                return PcdValue
>+            try:
>+                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType,
>GuidDict)(True)
>+            except BadExpression, Value:
>+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value
>"%s",  %s' %
>+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
>+        elif PcdValue.startswith('L'):
>+            PcdValue = 'L"' + PcdValue[1:] + '"'
>+            if FieldName and IsFieldValueAnArray(PcdValue):
>+                PcdDatumType = 'VOID*'
>+                IsArray = True
>+            if FieldName and not IsArray:
>+                return PcdValue
>+            try:
>+                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType,
>GuidDict)(True)
>+            except BadExpression, Value:
>+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value
>"%s",  %s' %
>+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
>+        else:
>+            if PcdValue.upper() == 'FALSE':
>+                PcdValue = str(0)
>+            if PcdValue.upper() == 'TRUE':
>+                PcdValue = str(1)
>+            if not FieldName:
>+                if PcdDatumType not in
>['UINT8','UINT16','UINT32','UINT64','BOOLEAN']:
>+                    PcdValue = '"' + PcdValue + '"'
>+            else:
>+                IsArray = False
>+                Base = 10
>+                if PcdValue.upper().startswith('0X'):
>+                    Base = 16
>+                try:
>+                    Num = int(PcdValue, Base)
>+                except:
>+                    PcdValue = '"' + PcdValue + '"'
>+                if IsFieldValueAnArray(PcdValue):
>+                    PcdDatumType = 'VOID*'
>+                    IsArray = True
>+                if not IsArray:
>+                    return PcdValue
>+            try:
>+                PcdValue = ValueExpressionEx(PcdValue, PcdDatumType,
>GuidDict)(True)
>+            except BadExpression, Value:
>+                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value
>"%s",  %s' %
>+                                (TokenSpaceGuidCName, TokenCName, PcdValue, Value))
>+        return PcdValue
>+
>     ## Retrieve all PCD settings in platform
>     def _GetPcds(self):
>         if self._Pcds == None:
>             self._Pcds = sdict()
>             self.__ParsePcdFromCommandLine()
>@@ -1553,26 +1493,10 @@ class DscBuildData(PlatformBuildClassObject):
>                     return len(Value) - 2
>             return len(Value)
>
>         return str(max([pcd_size for pcd_size in [get_length(item) for item in
>sku_values]]))
>
>-    def IsFieldValueAnArray (self, Value):
>-        Value = Value.strip()
>-        if Value.startswith('GUID') and Value.endswith(')'):
>-            return True
>-        if Value.startswith('L"') and Value.endswith('"')  and len(list(Value[2:-1])) >
>1:
>-            return True
>-        if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:
>-            return True
>-        if Value[0] == '{' and Value[-1] == '}':
>-            return True
>-        if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-
>1])) > 1:
>-            return True
>-        if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:
>-            return True
>-        return False
>-
>     def ExecuteCommand (self, Command):
>         try:
>             Process = subprocess.Popen(Command, stdout=subprocess.PIPE,
>stderr=subprocess.PIPE, shell=True)
>         except:
>             EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute
>command: %s' % Command)
>@@ -1615,11 +1539,11 @@ class DscBuildData(PlatformBuildClassObject):
>         for FieldList in [Pcd.DefaultValues]:
>             if not FieldList:
>                 continue
>             for FieldName in FieldList:
>                 FieldName = "." + FieldName
>-                IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
>+                IsArray = IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
>                 if IsArray and not (FieldList[FieldName.strip(".")][0].startswith('{GUID')
>and FieldList[FieldName.strip(".")][0].endswith('}')):
>                     try:
>                         Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0],
>"VOID*", self._GuidDict)(True)
>                     except BadExpression:
>                         EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format
>for %s. From %s Line %d " %
>@@ -1645,11 +1569,11 @@ class DscBuildData(PlatformBuildClassObject):
>                 for FieldList in
>[Pcd.SkuOverrideValues[skuname].get(defaultstorenameitem)]:
>                     if not FieldList:
>                         continue
>                     for FieldName in FieldList:
>                         FieldName = "." + FieldName
>-                        IsArray =
>self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
>+                        IsArray = IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])
>                         if IsArray and not
>(FieldList[FieldName.strip(".")][0].startswith('{GUID') and
>FieldList[FieldName.strip(".")][0].endswith('}')):
>                             try:
>                                 Value = ValueExpressionEx(FieldList[FieldName.strip(".")][0],
>"VOID*", self._GuidDict)(True)
>                             except BadExpression:
>                                 EdkLogger.error('Build', FORMAT_INVALID, "Invalid value
>format for %s. From %s Line %d " %
>@@ -1669,11 +1593,11 @@ class DscBuildData(PlatformBuildClassObject):
>                                 CApp = CApp + '  __FLEXIBLE_SIZE(*Size, %s, %s, %d); //
>From %s Line %d Value %s \n' % (Pcd.DatumType, FieldName.strip("."),
>ArrayIndex + 1, FieldList[FieldName_ori][1], FieldList[FieldName_ori][2],
>FieldList[FieldName_ori][0])
>         if Pcd.PcdFieldValueFromComm:
>             CApp = CApp + "// From Command Line \n"
>         for FieldName in Pcd.PcdFieldValueFromComm:
>             FieldName = "." + FieldName
>-            IsArray =
>self.IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")]
>[0])
>+            IsArray =
>IsFieldValueAnArray(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0])
>             if IsArray and not
>(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].startswith('{GUID')
>and Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0].endswith('}')):
>                 try:
>                     Value =
>ValueExpressionEx(Pcd.PcdFieldValueFromComm[FieldName.strip(".")][0],
>"VOID*", self._GuidDict)(True)
>                 except BadExpression:
>                     EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format
>for %s. From %s Line %d " %
>@@ -1702,11 +1626,11 @@ class DscBuildData(PlatformBuildClassObject):
>         CApp = "// Default value in Dec \n"
>         CApp = CApp + "void Assign_%s_%s_Default_Value(%s *Pcd){\n" %
>(Pcd.TokenSpaceGuidCName, Pcd.TokenCName,Pcd.DatumType)
>         CApp = CApp + '  UINT32  FieldSize;\n'
>         CApp = CApp + '  CHAR8   *Value;\n'
>         DefaultValueFromDec = Pcd.DefaultValueFromDec
>-        IsArray = self.IsFieldValueAnArray(Pcd.DefaultValueFromDec)
>+        IsArray = IsFieldValueAnArray(Pcd.DefaultValueFromDec)
>         if IsArray:
>             try:
>                 DefaultValueFromDec =
>ValueExpressionEx(Pcd.DefaultValueFromDec, "VOID*")(True)
>             except BadExpression:
>                 EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format
>for %s.%s, from DEC: %s" %
>@@ -1723,11 +1647,11 @@ class DscBuildData(PlatformBuildClassObject):
>             CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
>         for FieldList in [Pcd.DefaultValues]:
>             if not FieldList:
>                 continue
>             for FieldName in FieldList:
>-                IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
>+                IsArray = IsFieldValueAnArray(FieldList[FieldName][0])
>                 if IsArray:
>                     try:
>                         FieldList[FieldName][0] =
>ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
>                     except BadExpression:
>                         EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format
>for %s. From %s Line %d " %
>@@ -1773,11 +1697,11 @@ class DscBuildData(PlatformBuildClassObject):
>             pcddefaultvalue =
>Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName)
>         for FieldList in
>[pcddefaultvalue,inherit_OverrideValues.get(DefaultStoreName)]:
>             if not FieldList:
>                 continue
>             if pcddefaultvalue and FieldList == pcddefaultvalue:
>-                IsArray = self.IsFieldValueAnArray(FieldList)
>+                IsArray = IsFieldValueAnArray(FieldList)
>                 if IsArray:
>                     try:
>                         FieldList = ValueExpressionEx(FieldList, "VOID*")(True)
>                     except BadExpression:
>                         EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format
>for %s.%s, from DSC: %s" %
>@@ -1803,11 +1727,11 @@ class DscBuildData(PlatformBuildClassObject):
>                         CApp = CApp + '  Value     = %s; // From DSC Default Value %s\n' %
>(self.IntToCString(Value, ValueSize),
>Pcd.DscRawValue.get(SkuName,{}).get(DefaultStoreName))
>                         CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
>                 continue
>             if (SkuName,DefaultStoreName) == ('DEFAULT','STANDARD') or
>(( (SkuName,'') not in Pcd.ValueChain) and ( (SkuName,DefaultStoreName)
>not in Pcd.ValueChain )):
>                 for FieldName in FieldList:
>-                    IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
>+                    IsArray = IsFieldValueAnArray(FieldList[FieldName][0])
>                     if IsArray:
>                         try:
>                             FieldList[FieldName][0] =
>ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
>                         except BadExpression:
>                             EdkLogger.error('Build', FORMAT_INVALID, "Invalid value
>format for %s. From %s Line %d " %
>@@ -1844,11 +1768,11 @@ class DscBuildData(PlatformBuildClassObject):
>         pcddefaultvalue = Pcd.PcdValueFromComm
>         for FieldList in [pcddefaultvalue,Pcd.PcdFieldValueFromComm]:
>             if not FieldList:
>                 continue
>             if pcddefaultvalue and FieldList == pcddefaultvalue:
>-                IsArray = self.IsFieldValueAnArray(FieldList)
>+                IsArray = IsFieldValueAnArray(FieldList)
>                 if IsArray:
>                     try:
>                         FieldList = ValueExpressionEx(FieldList, "VOID*")(True)
>                     except BadExpression:
>                         EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format
>for %s.%s, from Command: %s" %
>@@ -1863,11 +1787,11 @@ class DscBuildData(PlatformBuildClassObject):
>                 #
>                     CApp = CApp + '  Value     = %s; // From Command Line.\n' %
>(self.IntToCString(Value, ValueSize))
>                     CApp = CApp + '  memcpy (Pcd, Value, %d);\n' % (ValueSize)
>                 continue
>             for FieldName in FieldList:
>-                IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])
>+                IsArray = IsFieldValueAnArray(FieldList[FieldName][0])
>                 if IsArray:
>                     try:
>                         FieldList[FieldName][0] =
>ValueExpressionEx(FieldList[FieldName][0], "VOID*", self._GuidDict)(True)
>                     except BadExpression:
>                         EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format
>for %s. From %s Line %d " %
>diff --git a/BaseTools/Source/Python/Workspace/MetaFileParser.py
>b/BaseTools/Source/Python/Workspace/MetaFileParser.py
>index 6809003..69bdf21 100644
>--- a/BaseTools/Source/Python/Workspace/MetaFileParser.py
>+++ b/BaseTools/Source/Python/Workspace/MetaFileParser.py
>@@ -1244,10 +1244,11 @@ class DscParser(MetaFileParser):
>         if self._ItemType not in [MODEL_META_DATA_DEFINE,
>MODEL_META_DATA_GLOBAL_DEFINE]:
>             Macros.update(self._Symbols)
>         if GlobalData.BuildOptionPcd:
>             for Item in GlobalData.BuildOptionPcd:
>                 PcdName, TmpValue = Item.split("=")
>+                TmpValue = BuildOptionValue(TmpValue, self._GuidDict)
>                 Macros[PcdName.strip()] = TmpValue
>         return Macros
>
>     def _PostProcess(self):
>         Processer = {
>diff --git a/BaseTools/Source/Python/build/BuildReport.py
>b/BaseTools/Source/Python/build/BuildReport.py
>index 89bdfa1..d555dce 100644
>--- a/BaseTools/Source/Python/build/BuildReport.py
>+++ b/BaseTools/Source/Python/build/BuildReport.py
>@@ -975,11 +975,13 @@ class PcdReport(object):
>
>                     BuildOptionMatch = False
>                     if GlobalData.BuildOptionPcd:
>                         for pcd in GlobalData.BuildOptionPcd:
>                             if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) == (pcd[0],
>pcd[1]):
>-                                PcdValue = pcd[2]
>+                                if pcd[2]:
>+                                    continue
>+                                PcdValue = pcd[3]
>                                 Pcd.DefaultValue = PcdValue
>                                 BuildOptionMatch = True
>                                 break
>
>                     if First:
>--
>2.6.1.windows.1
>
>_______________________________________________
>edk2-devel mailing list
>edk2-devel@lists.01.org
>https://lists.01.org/mailman/listinfo/edk2-devel
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel