]> git.proxmox.com Git - mirror_edk2.git/commitdiff
BaseTools: Support PCD flexible values format
authorYonghong Zhu <yonghong.zhu@intel.com>
Tue, 26 Dec 2017 08:17:13 +0000 (16:17 +0800)
committerYonghong Zhu <yonghong.zhu@intel.com>
Wed, 27 Dec 2017 06:43:27 +0000 (14:43 +0800)
https://bugzilla.tianocore.org/show_bug.cgi?id=541

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Yunhua Feng <yunhuax.feng@intel.com>
Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools/Source/Python/AutoGen/GenC.py
BaseTools/Source/Python/Common/Expression.py
BaseTools/Source/Python/Common/Misc.py
BaseTools/Source/Python/Workspace/DscBuildData.py
BaseTools/Source/Python/Workspace/InfBuildData.py
BaseTools/Source/Python/Workspace/MetaFileParser.py
BaseTools/Source/Python/Workspace/WorkspaceCommon.py
BaseTools/Source/Python/build/BuildReport.py

index cacd00922b6fb22e9187806d2833aca7f4340dcc..8be5bfca8342a43beec2b31d4e5dd26e94a830c2 100644 (file)
@@ -271,6 +271,7 @@ class WorkspaceAutoGen(AutoGen):
         self._FvDir         = None\r
         self._MakeFileDir   = None\r
         self._BuildCommand  = None\r
+        self._GuidDict = {}\r
 \r
         # there's many relative directory operations, so ...\r
         os.chdir(self.WorkspaceDir)\r
@@ -418,12 +419,23 @@ class WorkspaceAutoGen(AutoGen):
                     FoundFlag = False\r
                     PcdDatumType = ''\r
                     NewValue = ''\r
+                    for package in PGen.PackageList:\r
+                        Guids = package.Guids\r
+                        self._GuidDict.update(Guids)\r
                     for package in PGen.PackageList:\r
                         for key in package.Pcds:\r
                             PcdItem = package.Pcds[key]\r
                             if HasTokenSpace:\r
                                 if (PcdItem.TokenCName, PcdItem.TokenSpaceGuidCName) == (TokenCName, TokenSpaceGuidCName):\r
                                     PcdDatumType = PcdItem.DatumType\r
+                                    if pcdvalue.startswith('H'):\r
+                                        try:\r
+                                            pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)\r
+                                        except BadExpression, Value:\r
+                                            if Value.result > 1:\r
+                                                EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s",  %s' %\r
+                                                                (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))\r
+                                        pcdvalue = 'H' + pcdvalue\r
                                     NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)\r
                                     FoundFlag = True\r
                             else:\r
@@ -433,6 +445,13 @@ class WorkspaceAutoGen(AutoGen):
                                             TokenSpaceGuidCNameList.append(PcdItem.TokenSpaceGuidCName)\r
                                             PcdDatumType = PcdItem.DatumType\r
                                             TokenSpaceGuidCName = PcdItem.TokenSpaceGuidCName\r
+                                            if pcdvalue.startswith('H'):\r
+                                                try:\r
+                                                    pcdvalue = ValueExpressionEx(pcdvalue[1:], PcdDatumType, self._GuidDict)(True)\r
+                                                except BadExpression, Value:\r
+                                                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %\r
+                                                                    (TokenSpaceGuidCName, TokenCName, pcdvalue, Value))\r
+                                                pcdvalue = 'H' + pcdvalue\r
                                             NewValue = BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, pcdvalue)\r
                                             FoundFlag = True\r
                                         else:\r
@@ -2446,6 +2465,26 @@ class PlatformAutoGen(AutoGen):
                 ToPcd.DatumType = FromPcd.DatumType\r
             if FromPcd.SkuInfoList not in [None, '', []]:\r
                 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
+            # Add Flexible PCD format parse\r
+            PcdValue = ToPcd.DefaultValue\r
+            if PcdValue:\r
+                try:\r
+                    ToPcd.DefaultValue = ValueExpression(PcdValue)(True)\r
+                except WrnExpression, Value:\r
+                    ToPcd.DefaultValue = Value.result\r
+                except BadExpression, Value:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
+                                    File=self.MetaFile)\r
+            if ToPcd.DefaultValue:\r
+                _GuidDict = {}\r
+                for Pkg in self.PackageList:\r
+                    Guids = Pkg.Guids\r
+                    _GuidDict.update(Guids)\r
+                try:\r
+                    ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, _GuidDict)(True)\r
+                except BadExpression, Value:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
+                                        File=self.MetaFile)\r
 \r
             # check the validation of datum\r
             IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
index 6b95cd47c2c235a8c7b081861de2e6e972b9ad95..3e98506cc80774b57e1accf978e5b00fb161ebe9 100644 (file)
@@ -1033,6 +1033,8 @@ def CreateModulePcdCode(Info, AutoGenC, AutoGenH, Pcd):
 \r
         if Pcd.DatumType in ['UINT64', 'UINT32', 'UINT16', 'UINT8']:\r
             try:\r
+                if Value.upper().endswith('L'):\r
+                    Value = Value[:-1]\r
                 if Value.upper().startswith('0X'):\r
                     ValueNumber = int (Value, 16)\r
                 else:\r
index ba83e02f75d3bfc00ef2993f80f7a64e221a01cc..953a412e806ee29f1be6c84d5d28f08c6b0a2c89 100644 (file)
@@ -15,7 +15,9 @@
 from Common.GlobalData import *\r
 from CommonDataClass.Exceptions import BadExpression\r
 from CommonDataClass.Exceptions import WrnExpression\r
-from Misc import GuidStringToGuidStructureString\r
+from Misc import GuidStringToGuidStructureString, ParseFieldValue\r
+import Common.EdkLogger as EdkLogger\r
+import copy\r
 \r
 ERR_STRING_EXPR         = 'This operator cannot be used in string expression: [%s].'\r
 ERR_SNYTAX              = 'Syntax error, the rest of expression cannot be evaluated: [%s].'\r
@@ -114,6 +116,15 @@ def ReplaceExprMacro(String, Macros, ExceptionList = None):
         StrList[i] = RetStr\r
     return ''.join(StrList)\r
 \r
+# transfer int to string for in/not in expression\r
+def IntToStr(Value):\r
+    StrList = []\r
+    while Value > 0:\r
+        StrList.append(chr(Value & 0xff))\r
+        Value = Value >> 8\r
+    Value = '"' + ''.join(StrList) + '"'\r
+    return Value\r
+\r
 SupportedInMacroList = ['TARGET', 'TOOL_CHAIN_TAG', 'ARCH', 'FAMILY']\r
 \r
 class ValueExpression(object):\r
@@ -146,10 +157,24 @@ class ValueExpression(object):
     def Eval(Operator, Oprand1, Oprand2 = None):\r
         WrnExp = None\r
 \r
-        if Operator not in ["==", "!=", ">=", "<=", ">", "<", "in", "not in"] and \\r
-            (type(Oprand1) == type('') or type(Oprand2) == type('')):\r
-            raise BadExpression(ERR_STRING_EXPR % Operator)\r
-\r
+        if Operator not in ["in", "not in"] and (type(Oprand1) == type('') or type(Oprand2) == type('')):\r
+            if type(Oprand1) == type(''):\r
+                if Oprand1[0] in ['"', "'"] or Oprand1.startswith('L"') or Oprand1.startswith("L'")or Oprand1.startswith('UINT'):\r
+                    Oprand1, Size = ParseFieldValue(Oprand1)\r
+                else:\r
+                    Oprand1,Size = ParseFieldValue('"' + Oprand1 + '"')\r
+            if type(Oprand2) == type(''):\r
+                if Oprand2[0] in ['"', "'", 'L'] or Oprand2.startswith('UINT'):\r
+                    Oprand2, Size = ParseFieldValue(Oprand2)\r
+                else:\r
+                    Oprand2, Size = ParseFieldValue('"' + Oprand2 + '"')\r
+            if type(Oprand1) == type('') or type(Oprand2) == type(''):\r
+                raise BadExpression(ERR_STRING_EXPR % Operator)\r
+        if Operator in ['in', 'not in']:\r
+            if type(Oprand1) != type(''):\r
+                Oprand1 = IntToStr(Oprand1)\r
+            if type(Oprand2) != type(''):\r
+                Oprand2 = IntToStr(Oprand2)\r
         TypeDict = {\r
             type(0)  : 0,\r
             type(0L) : 0,\r
@@ -226,6 +251,9 @@ class ValueExpression(object):
             self._Expr = Expression\r
             self._NoProcess = True\r
             return\r
+        if Expression.strip().startswith('{') and Expression.strip().endswith('}'):\r
+            self._Expr = Expression\r
+            self._NoProcess = True\r
 \r
         self._Expr = ReplaceExprMacro(Expression.strip(),\r
                                   SymbolTable,\r
@@ -237,7 +265,7 @@ class ValueExpression(object):
         #\r
         # The symbol table including PCD and macro mapping\r
         #\r
-        self._Symb = SymbolTable\r
+        self._Symb = copy.deepcopy(SymbolTable)\r
         self._Symb.update(self.LogicalOperators)\r
         self._Idx = 0\r
         self._Len = len(self._Expr)\r
@@ -284,7 +312,7 @@ class ValueExpression(object):
             elif not Val:\r
                 Val = False\r
                 RealVal = '""'\r
-            elif not Val.startswith('L"') and not Val.startswith('{'):\r
+            elif not Val.startswith('L"') and not Val.startswith('{') and not Val.startswith("L'"):\r
                 Val = True\r
                 RealVal = '"' + RealVal + '"'\r
 \r
@@ -426,6 +454,15 @@ class ValueExpression(object):
         Radix = 10\r
         if self._Token.lower()[0:2] == '0x' and len(self._Token) > 2:\r
             Radix = 16\r
+        if self._Token.startswith('"') or self._Token.startswith("'")\\r
+            or self._Token.startswith("L'") or self._Token.startswith('L"'):\r
+            Flag = 0\r
+            for Index in range(len(self._Token)):\r
+                if self._Token[Index] in ['"', "'"]:\r
+                    Flag += 1\r
+            if Flag == 2:\r
+                self._Token = ParseFieldValue(self._Token)[0]\r
+                return True\r
         try:\r
             self._Token = int(self._Token, Radix)\r
             return True\r
@@ -473,10 +510,12 @@ class ValueExpression(object):
         Expr = self._Expr[self._Idx:].replace('\\\\', '//').replace('\\\"', '\\\'')\r
         for Ch in Expr:\r
             self._Idx += 1\r
-            if Ch == '"':\r
+            if Ch == '"' or Ch == "'":\r
                 break\r
         self._Token = self._LiteralToken = self._Expr[Idx:self._Idx]\r
-        if not self._Token.endswith('"'):\r
+        if self._Token.startswith('"') and not self._Token.endswith('"'):\r
+            raise BadExpression(ERR_STRING_TOKEN % self._Token)\r
+        if self._Token.startswith("'") and not self._Token.endswith("'"):\r
             raise BadExpression(ERR_STRING_TOKEN % self._Token)\r
         self._Token = self._Token[1:-1]\r
         return self._Token\r
@@ -578,7 +617,44 @@ class ValueExpression(object):
             self._Idx += 1\r
             UStr = self.__GetString()\r
             self._Token = 'L"' + UStr + '"'\r
+            self._Token, Size = ParseFieldValue(self._Token)\r
+            return self._Token\r
+        elif Expr.startswith("L'"):\r
+            # Skip L\r
+            self._Idx += 1\r
+            UStr = self.__GetString()\r
+            self._Token = "L'" + UStr + "'"\r
+            self._Token, Size = ParseFieldValue(self._Token)\r
+            return self._Token\r
+        elif Expr.startswith('"'):\r
+            UStr = self.__GetString()\r
+            self._Token = '"' + UStr + '"'\r
+            self._Token, Size = ParseFieldValue(self._Token)\r
             return self._Token\r
+        elif Expr.startswith("'"):\r
+            UStr = self.__GetString()\r
+            self._Token = "'" + UStr + "'"\r
+            self._Token, Size = ParseFieldValue(self._Token)\r
+            return self._Token\r
+        elif Expr.startswith('UINT'):\r
+            Re = re.compile('(?:UINT8|UINT16|UINT32|UINT64)\((.+)\)')\r
+            try:\r
+                RetValue = Re.search(Expr).group(1)\r
+            except:\r
+                 raise BadExpression('Invalid Expression %s' % Expr)\r
+            Idx = self._Idx\r
+            for Ch in Expr:\r
+                self._Idx += 1\r
+                if Ch == '(':\r
+                    Prefix = self._Expr[Idx:self._Idx - 1]\r
+                    Idx = self._Idx\r
+                if Ch == ')':\r
+                    TmpValue = self._Expr[Idx :self._Idx - 1]\r
+                    TmpValue = ValueExpression(TmpValue)(True)\r
+                    TmpValue = '0x%x' % int(TmpValue) if type(TmpValue) != type('') else TmpValue\r
+                    break\r
+            self._Token, Size = ParseFieldValue(Prefix + '(' + TmpValue + ')')\r
+            return  self._Token\r
 \r
         self._Token = ''\r
         if Expr:\r
@@ -648,6 +724,158 @@ class ValueExpression(object):
         self._Idx = Idx\r
         return False\r
 \r
+class ValueExpressionEx(ValueExpression):\r
+    def __init__(self, PcdValue, PcdType, SymbolTable={}):\r
+        ValueExpression.__init__(self, PcdValue, SymbolTable)\r
+        self.PcdValue = PcdValue\r
+        self.PcdType = PcdType\r
+\r
+    def __call__(self, RealValue=False, Depth=0):\r
+        PcdValue = self.PcdValue\r
+        try:\r
+            PcdValue = ValueExpression.__call__(self, RealValue, Depth)\r
+        except WrnExpression, Value:\r
+            PcdValue = Value.result\r
+\r
+        if PcdValue == 'True':\r
+            PcdValue = '1'\r
+        if PcdValue == 'False':\r
+            PcdValue = '0'\r
+        if self.PcdType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:\r
+            PcdValue = PcdValue.strip()\r
+            if type(PcdValue) == type('') and PcdValue.startswith('{') and PcdValue.endswith('}'):\r
+                PcdValue = PcdValue[1:-1].split(',')\r
+            if type(PcdValue) == type([]):\r
+                TmpValue = 0\r
+                Size = 0\r
+                for Item in PcdValue:\r
+                    if Item.startswith('UINT16'):\r
+                        ItemSize = 2\r
+                    elif Item.startswith('UINT32'):\r
+                        ItemSize = 4\r
+                    elif Item.startswith('UINT64'):\r
+                        ItemSize = 8\r
+                    else:\r
+                        ItemSize = 0\r
+                    Item = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)\r
+\r
+                    if ItemSize == 0:\r
+                        ItemValue, ItemSize = ParseFieldValue(Item)\r
+                    else:\r
+                        ItemValue = ParseFieldValue(Item)[0]\r
+\r
+                    if type(ItemValue) == type(''):\r
+                        ItemValue = int(ItemValue, 16) if ItemValue.startswith('0x') else int(ItemValue)\r
+\r
+                    TmpValue = (ItemValue << (Size * 8)) | TmpValue\r
+                    Size = Size + ItemSize\r
+            else:\r
+                TmpValue, Size = ParseFieldValue(PcdValue)\r
+            if type(TmpValue) == type(''):\r
+                TmpValue = int(TmpValue)\r
+            else:\r
+                PcdValue = '0x%0{}X'.format(Size) % (TmpValue)\r
+            if TmpValue < 0:\r
+                raise  BadExpression('Type %s PCD Value is negative' % self.PcdType)\r
+            if self.PcdType == 'UINT8' and Size > 1:\r
+                raise BadExpression('Type %s PCD Value Size is Larger than 1 byte' % self.PcdType)\r
+            if self.PcdType == 'UINT16' and Size > 2:\r
+                raise BadExpression('Type %s PCD Value Size is Larger than 2 byte' % self.PcdType)\r
+            if self.PcdType == 'UINT32' and Size > 4:\r
+                raise BadExpression('Type %s PCD Value Size is Larger than 4 byte' % self.PcdType)\r
+            if self.PcdType == 'UINT64' and Size > 8:\r
+                raise BadExpression('Type %s PCD Value Size is Larger than 8 byte' % self.PcdType)\r
+        if self.PcdType in ['VOID*']:\r
+            try:\r
+                TmpValue = long(PcdValue)\r
+                TmpList = []\r
+                if TmpValue.bit_length() == 0:\r
+                    PcdValue = '{0x00}'\r
+                else:\r
+                    for I in range((TmpValue.bit_length() + 7) / 8):\r
+                        TmpList.append('0x%02x' % ((TmpValue >> I * 8) & 0xff))\r
+                    PcdValue = '{' + ', '.join(TmpList) + '}'\r
+            except:\r
+                if PcdValue.strip().startswith('{'):\r
+                    PcdValue = PcdValue.strip()[1:-1].strip()\r
+                    Size = 0\r
+                    ValueStr = ''\r
+                    TokenSpaceGuidName = ''\r
+                    if PcdValue.startswith('GUID') and PcdValue.endswith(')'):\r
+                        try:\r
+                            TokenSpaceGuidName = re.search('GUID\((\w+)\)', PcdValue).group(1)\r
+                        except:\r
+                            pass\r
+                        if TokenSpaceGuidName and TokenSpaceGuidName in self._Symb:\r
+                            PcdValue = 'GUID(' + self._Symb[TokenSpaceGuidName] + ')'\r
+                        elif TokenSpaceGuidName:\r
+                            raise BadExpression('%s not found in DEC file' % TokenSpaceGuidName)\r
+\r
+                        ListItem, Size = ParseFieldValue(PcdValue)\r
+                    elif PcdValue.startswith('DEVICE_PATH') and PcdValue.endswith(')'):\r
+                        ListItem, Size = ParseFieldValue(PcdValue)\r
+                    else:\r
+                        ListItem = PcdValue.split(',')\r
+\r
+                    if type(ListItem) == type(0) or type(ListItem) == type(0L):\r
+                        for Index in range(0, Size):\r
+                            ValueStr += '0x%02X' % (int(ListItem) & 255)\r
+                            ListItem >>= 8\r
+                            ValueStr += ', '\r
+                            PcdValue = '{' + ValueStr[:-2] + '}'\r
+                    elif type(ListItem) == type(''):\r
+                        if ListItem.startswith('{') and ListItem.endswith('}'):\r
+                            PcdValue = ListItem\r
+                    else:\r
+                        LabelDict = {}\r
+                        ReLabel = re.compile('LABEL\((\w+)\)')\r
+                        ReOffset = re.compile('OFFSET_OF\((\w+)\)')\r
+                        for Index, Item in enumerate(ListItem):\r
+                            # for LABEL parse\r
+                            Item = Item.strip()\r
+                            try:\r
+                                LabelList = ReLabel.findall(Item)\r
+                                for Label in LabelList:\r
+                                    if Label not in LabelDict.keys():\r
+                                        LabelDict[Label] = str(Index)\r
+                                Item = ReLabel.sub('', Item)\r
+                            except:\r
+                                pass\r
+                            try:\r
+                                OffsetList = ReOffset.findall(Item)\r
+                            except:\r
+                                pass\r
+                            for Offset in OffsetList:\r
+                                if Offset in LabelDict.keys():\r
+                                    Re = re.compile('OFFSET_OF\(%s\)'% Offset)\r
+                                    Item = Re.sub(LabelDict[Offset], Item)\r
+                                else:\r
+                                    raise BadExpression('%s not defined before use' % Offset)\r
+                            if Item.startswith('UINT16'):\r
+                                ItemSize = 2\r
+                            elif Item.startswith('UINT32'):\r
+                                ItemSize = 4\r
+                            elif Item.startswith('UINT64'):\r
+                                ItemSize = 8\r
+                            else:\r
+                                ItemSize = 0\r
+                            TmpValue = ValueExpressionEx(Item, self.PcdType, self._Symb)(True)\r
+                            Item = '0x%x' % TmpValue if type(TmpValue) != type('') else TmpValue\r
+                            if ItemSize == 0:\r
+                                ItemValue, ItemSize = ParseFieldValue(Item)\r
+                            else:\r
+                                ItemValue = ParseFieldValue(Item)[0]\r
+                            for I in range(0, ItemSize):\r
+                                ValueStr += '0x%02X' % (int(ItemValue) & 255)\r
+                                ItemValue >>= 8\r
+                                ValueStr += ', '\r
+                            Size += ItemSize\r
+\r
+                        if Size > 0:\r
+                            PcdValue = '{' + ValueStr[:-2] + '}'\r
+        if RealValue:\r
+            return PcdValue\r
+\r
 if __name__ == '__main__':\r
     pass\r
     while True:\r
index f44000829aacfe5dacc7090d6a1fc1506946ee59..59d1ba2639433cdd27a581590e639bba7c21c93f 100644 (file)
@@ -37,6 +37,7 @@ from Parsing import GetSplitValueList
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 import uuid\r
+from CommonDataClass.Exceptions import BadExpression\r
 \r
 ## Regular expression used to find out place holders in string template\r
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)\r
@@ -1472,99 +1473,119 @@ def AnalyzePcdExpression(Setting):
 \r
     return FieldList\r
 \r
+def ParseDevPathValue (Value):\r
+    pass\r
+\r
 def ParseFieldValue (Value):\r
-  if type(Value) == type(0):\r
-    return Value, (Value.bit_length() + 7) / 8\r
-  if type(Value) <> type(''):\r
-    raise ValueError\r
-  Value = Value.strip()\r
-  if Value.startswith('UINT8') and Value.endswith(')'):\r
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
-    if Size > 1:\r
-      raise ValueError\r
+    if type(Value) == type(0):\r
+        return Value, (Value.bit_length() + 7) / 8\r
+    if type(Value) <> type(''):\r
+        raise BadExpression('Type %s is %s' %(Value, type(Value)))\r
+    Value = Value.strip()\r
+    if Value.startswith('UINT8') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 1:\r
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))\r
+        return Value, 1\r
+    if Value.startswith('UINT16') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 2:\r
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))\r
+        return Value, 2\r
+    if Value.startswith('UINT32') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 4:\r
+            raise BadExpression('Value (%s) Size larger than %d' %(Value, Size))\r
+        return Value, 4\r
+    if Value.startswith('UINT64') and Value.endswith(')'):\r
+        Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
+        if Size > 8:\r
+            raise BadExpression('Value (%s) Size larger than %d' % (Value, Size))\r
+        return Value, 8\r
+    if Value.startswith('GUID') and Value.endswith(')'):\r
+        Value = Value.split('(', 1)[1][:-1].strip()\r
+        if Value[0] == '{' and Value[-1] == '}':\r
+            Value = Value[1:-1].strip()\r
+            Value = Value.split('{', 1)\r
+            Value = ['%02x' % int(Item, 16) for Item in (Value[0] + Value[1][:-1]).split(',')]\r
+            if len(Value[0]) != 8:\r
+                Value[0] = '%08X' % int(Value[0], 16)\r
+            if len(Value[1]) != 4:\r
+                Value[1] = '%04X' % int(Value[1], 16)\r
+            if len(Value[2]) != 4:\r
+                Value[2] = '%04X' % int(Value[2], 16)\r
+            Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11])\r
+        if Value[0] == '"' and Value[-1] == '"':\r
+            Value = Value[1:-1]\r
+        try:\r
+            Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"\r
+        except ValueError, Message:\r
+            raise BadExpression('%s' % Message)\r
+        Value, Size = ParseFieldValue(Value)\r
+        return Value, 16\r
+    if Value.startswith('L"') and Value.endswith('"'):\r
+        # Unicode String\r
+        List = list(Value[2:-1])\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 16) | ord(Char)\r
+        return Value, (len(List) + 1) * 2\r
+    if Value.startswith('"') and Value.endswith('"'):\r
+        # ASCII String\r
+        List = list(Value[1:-1])\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 8) | ord(Char)\r
+        return Value, len(List) + 1\r
+    if Value.startswith("L'") and Value.endswith("'"):\r
+        # Unicode Character Constant\r
+        List = list(Value[2:-1])\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 16) | ord(Char)\r
+        return Value, len(List) * 2\r
+    if Value.startswith("'") and Value.endswith("'"):\r
+        # Character constant\r
+        List = list(Value[1:-1])\r
+        List.reverse()\r
+        Value = 0\r
+        for Char in List:\r
+            Value = (Value << 8) | ord(Char)\r
+        return Value, len(List)\r
+    if Value.startswith('{') and Value.endswith('}'):\r
+        # Byte array\r
+        Value = Value[1:-1]\r
+        List = [Item.strip() for Item in Value.split(',')]\r
+        List.reverse()\r
+        Value = 0\r
+        RetSize = 0\r
+        for Item in List:\r
+            ItemValue, Size = ParseFieldValue(Item)\r
+            RetSize += Size\r
+            for I in range(Size):\r
+                Value = (Value << 8) | ((ItemValue >> 8 * I) & 0xff)\r
+        return Value, RetSize\r
+    if Value.startswith('DEVICE_PATH(') and Value.endswith(')'):\r
+        Value = Value.split('"')[1]\r
+        return ParseDevPathValue(Value)\r
+    if Value.lower().startswith('0x'):\r
+        Value = int(Value, 16)\r
+        if Value == 0:\r
+            return 0, 1\r
+        return Value, (Value.bit_length() + 7) / 8\r
+    if Value[0].isdigit():\r
+        Value = int(Value, 10)\r
+        if Value == 0:\r
+            return 0, 1\r
+        return Value, (Value.bit_length() + 7) / 8\r
+    if Value.lower() == 'true':\r
+        return 1, 1\r
+    if Value.lower() == 'false':\r
+        return 0, 1\r
     return Value, 1\r
-  if Value.startswith('UINT16') and Value.endswith(')'):\r
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
-    if Size > 2:\r
-      raise ValueError\r
-    return Value, 2\r
-  if Value.startswith('UINT32') and Value.endswith(')'):\r
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
-    if Size > 4:\r
-      raise ValueError\r
-    return Value, 4\r
-  if Value.startswith('UINT64') and Value.endswith(')'):\r
-    Value, Size = ParseFieldValue(Value.split('(', 1)[1][:-1])\r
-    if Size > 8:\r
-      raise ValueError\r
-    return Value, 8\r
-  if Value.startswith('GUID') and Value.endswith(')'):\r
-    Value = Value.split('(', 1)[1][:-1].strip()\r
-    if Value[0] == '{' and Value[-1] == '}':\r
-      Value = Value[1:-1].strip()\r
-      Value = Value.split('{', 1)\r
-      Value = [Item.strip()[2:] for Item in (Value[0] + Value[1][:-1]).split(',')]\r
-      Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11])\r
-    if Value[0] == '"' and Value[-1] == '"':\r
-      Value = Value[1:-1]\r
-    Value = "'" + uuid.UUID(Value).get_bytes_le() + "'"\r
-    Value, Size = ParseFieldValue(Value)\r
-    return Value, 16\r
-  if Value.startswith('L"') and Value.endswith('"'):\r
-    # Unicode String\r
-    List = list(Value[2:-1])\r
-    List.reverse()\r
-    Value = 0\r
-    for Char in List:\r
-      Value = (Value << 16) | ord(Char)\r
-    return Value, (len(List) + 1) * 2\r
-  if Value.startswith('"') and Value.endswith('"'):\r
-    # ASCII String\r
-    List = list(Value[1:-1])\r
-    List.reverse()\r
-    Value = 0\r
-    for Char in List:\r
-      Value = (Value << 8) | ord(Char)\r
-    return Value, len(List) + 1\r
-  if Value.startswith("L'") and Value.endswith("'"):\r
-    # Unicode Character Constant\r
-    List = list(Value[2:-1])\r
-    List.reverse()\r
-    Value = 0\r
-    for Char in List:\r
-      Value = (Value << 16) | ord(Char)\r
-    return Value, len(List) * 2\r
-  if Value.startswith("'") and Value.endswith("'"):\r
-    # Character constant\r
-    List = list(Value[1:-1])\r
-    List.reverse()\r
-    Value = 0\r
-    for Char in List:\r
-      Value = (Value << 8) | ord(Char)\r
-    return Value, len(List)\r
-  if Value.startswith('{') and Value.endswith('}'):\r
-    # Byte array\r
-    Value = Value[1:-1]\r
-    List = [Item.strip() for Item in Value.split(',')]\r
-    List.reverse()\r
-    Value = 0\r
-    for Item in List:\r
-      ItemValue, Size = ParseFieldValue(Item)\r
-      if Size > 1:\r
-        raise ValueError\r
-      Value = (Value << 8) | ItemValue\r
-    return Value, len(List)\r
-  if Value.lower().startswith('0x'):\r
-    Value = int(Value, 16)\r
-    return Value, (Value.bit_length() + 7) / 8\r
-  if Value[0].isdigit():\r
-    Value = int(Value, 10)\r
-    return Value, (Value.bit_length() + 7) / 8\r
-  if Value.lower() == 'true':\r
-    return 1, 1\r
-  if Value.lower() == 'false':\r
-    return 0, 1\r
-  return Value, 1\r
 \r
 ## AnalyzeDscPcd\r
 #\r
index e42210079dd39cc7a572c5282107c0198ad01409..f9cd429f29f6a18718bf36c15d27e560cf10e880 100644 (file)
@@ -800,7 +800,7 @@ class DscBuildData(PlatformBuildClassObject):
                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]\r
                 PkgSet.update(ModuleData.Packages)\r
 \r
-            self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)\r
+            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)\r
 \r
 \r
         if (PcdCName, TokenSpaceGuid) not in self._DecPcds:\r
@@ -821,6 +821,8 @@ class DscBuildData(PlatformBuildClassObject):
                 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)\r
             except WrnExpression, Value:\r
                 ValueList[Index] = Value.result\r
+            except BadExpression, Value:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)\r
             except EvaluationException, Excpt:\r
                 if hasattr(Excpt, 'Pcd'):\r
                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
@@ -834,11 +836,13 @@ class DscBuildData(PlatformBuildClassObject):
                 else:\r
                     EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
                                     File=self.MetaFile, Line=LineNo)\r
-            if ValueList[Index] == 'True':\r
-                ValueList[Index] = '1'\r
-            elif ValueList[Index] == 'False':\r
-                ValueList[Index] = '0'\r
         if ValueList[Index]:\r
+            DatumType = self._DecPcds[PcdCName, TokenSpaceGuid].DatumType\r
+            try:\r
+                ValueList[Index] = ValueExpressionEx(ValueList[Index], DatumType, self._GuidDict)(True)\r
+            except BadExpression, Value:\r
+                EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=LineNo,\r
+                                ExtraData="PCD [%s.%s] Value \"%s\" " % (TokenSpaceGuid, PcdCName, ValueList[Index]))\r
             Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])\r
             if not Valid:\r
                 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,\r
@@ -2058,7 +2062,7 @@ class DscBuildData(PlatformBuildClassObject):
                     continue\r
                 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]\r
                 PkgSet.update(ModuleData.Packages)\r
-            self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)\r
+            self._DecPcds, self._GuidDict = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain,PkgSet)\r
         return self._DecPcds\r
     _Macros             = property(_GetMacros)\r
     Arch                = property(_GetArch, _SetArch)\r
index fd94067c93e4deab338982fc3ea71207ed76d24d..7ea9b56d5decba82b52e742d15851d1c63ce6619 100644 (file)
@@ -16,6 +16,7 @@ from Common.String import *
 from Common.DataType import *\r
 from Common.Misc import *\r
 from types import *\r
+from MetaFileParser import *\r
 \r
 from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject\r
 ## Module build information from INF file\r
@@ -1144,6 +1145,12 @@ class InfBuildData(ModuleBuildClassObject):
                     Pcd.InfDefaultValue = Pcd.DefaultValue\r
                     if Pcd.DefaultValue in [None, '']:\r
                         Pcd.DefaultValue = PcdInPackage.DefaultValue\r
+                    else:\r
+                        try:\r
+                            Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, self.Guids)(True)\r
+                        except BadExpression, Value:\r
+                            EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid, PcdRealName, Pcd.DefaultValue, Value),\r
+                                            File=self.MetaFile, Line=LineNo)\r
                     break\r
             else:\r
                 EdkLogger.error(\r
index 303844785043405bc4489806eef628a926a370e8..b2b0e282eb91098303837dcbe4e06e7b7dcd9267 100644 (file)
@@ -27,7 +27,7 @@ import Common.GlobalData as GlobalData
 from CommonDataClass.DataClass import *\r
 from Common.DataType import *\r
 from Common.String import *\r
-from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression\r
+from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue\r
 from Common.Expression import *\r
 from CommonDataClass.Exceptions import *\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
@@ -182,6 +182,7 @@ class MetaFileParser(object):
         self._PostProcessed = False\r
         # Different version of meta-file has different way to parse.\r
         self._Version = 0\r
+        self._GuidDict = {}  # for Parser PCD value {GUID(gTokeSpaceGuidName)}\r
 \r
     ## Store the parsed data in table\r
     def _Store(self, *Args):\r
@@ -1871,6 +1872,8 @@ class DecParser(MetaFileParser):
                             File=self.MetaFile, Line=self._LineIndex + 1)\r
         self._ValueList[0] = TokenList[0]\r
         self._ValueList[1] = TokenList[1]\r
+        if self._ValueList[0] not in self._GuidDict:\r
+            self._GuidDict[self._ValueList[0]] = self._ValueList[1]\r
 \r
     ## PCD sections parser\r
     #\r
@@ -1987,12 +1990,14 @@ class DecParser(MetaFileParser):
                     ValueList[0] = ValueExpression(PcdValue, self._AllPcdDict)(True)\r
                 except WrnExpression, Value:\r
                     ValueList[0] = Value.result\r
+                except BadExpression, Value:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID, Value, File=self.MetaFile, Line=self._LineIndex + 1)\r
 \r
-            if ValueList[0] == 'True':\r
-                ValueList[0] = '1'\r
-            if ValueList[0] == 'False':\r
-                ValueList[0] = '0'\r
-\r
+            if ValueList[0]:\r
+                try:\r
+                    ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)\r
+                except BadExpression, Value:\r
+                    EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)\r
             # check format of default value against the datum type\r
             IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])\r
             if not IsValid:\r
index c289b9d2b5cf10a58aabef771f2d0bae7a435531..c760e57b8f64d0699791e8361098a751b2974598 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # Common routines used by workspace\r
 #\r
-# Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>\r
 # This program and the accompanying materials\r
 # are licensed and made available under the terms and conditions of the BSD License\r
 # which accompanies this distribution.  The full text of the license may be found at\r
@@ -43,13 +43,17 @@ def GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain):
 #  @param Target: Current target\r
 #  @param Toolchain: Current toolchain\r
 #  @retval: A dictionary contains instances of PcdClassObject with key (PcdCName, TokenSpaceGuid)\r
+#  @retval: A dictionary contains real GUIDs of TokenSpaceGuid\r
 #\r
 def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain,additionalPkgs):\r
     PkgList = GetPackageList(Platform, BuildDatabase, Arch, Target, Toolchain)\r
     PkgList = set(PkgList)\r
     PkgList |= additionalPkgs\r
     DecPcds = {}\r
+    GuidDict = {}\r
     for Pkg in PkgList:\r
+        Guids = Pkg.Guids\r
+        GuidDict.update(Guids)\r
         for Pcd in Pkg.Pcds:\r
             PcdCName = Pcd[0]\r
             PcdTokenName = Pcd[1]\r
@@ -60,7 +64,7 @@ def GetDeclaredPcd(Platform, BuildDatabase, Arch, Target, Toolchain,additionalPk
                         break\r
             if (PcdCName, PcdTokenName) not in DecPcds.keys():\r
                 DecPcds[PcdCName, PcdTokenName] = Pkg.Pcds[Pcd]\r
-    return DecPcds\r
+    return DecPcds, GuidDict\r
 \r
 ## Get all dependent libraries for a module\r
 #\r
index 75e8ec97ab8a74e224aebc4008627099c8c5384b..5da99145441a755b588c233df908c010f95b5978 100644 (file)
@@ -45,6 +45,7 @@ from Common.Misc import PathClass
 from Common.String import NormPath\r
 from Common.DataType import *\r
 import collections\r
+from Common.Expression import ValueExpressionEx\r
 \r
 ## Pattern to extract contents in EDK DXS files\r
 gDxsDependencyPattern = re.compile(r"DEPENDENCY_START(.+)DEPENDENCY_END", re.DOTALL)\r
@@ -849,8 +850,11 @@ class PcdReport(object):
         # Collect PCD DEC default value.\r
         #\r
         self.DecPcdDefault = {}\r
+        self._GuidDict = {}\r
         for Pa in Wa.AutoGenObjectList:\r
             for Package in Pa.PackageList:\r
+                Guids = Package.Guids\r
+                self._GuidDict.update(Guids)\r
                 for (TokenCName, TokenSpaceGuidCName, DecType) in Package.Pcds:\r
                     DecDefaultValue = Package.Pcds[TokenCName, TokenSpaceGuidCName, DecType].DefaultValue\r
                     self.DecPcdDefault.setdefault((TokenCName, TokenSpaceGuidCName, DecType), DecDefaultValue)\r
@@ -943,6 +947,8 @@ class PcdReport(object):
                     DscDefaultValue = self.DscPcdDefault.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
                     DscDefaultValBak= DscDefaultValue\r
                     DscDefaultValue = self.FdfPcdSet.get((Pcd.TokenCName, Key), DscDefaultValue)\r
+                    if DscDefaultValue:\r
+                        DscDefaultValue = ValueExpressionEx(DscDefaultValue, Pcd.DatumType, self._GuidDict)(True)\r
                     InfDefaultValue = None\r
                     \r
                     PcdValue = DecDefaultValue\r