]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Common/Misc.py
BaseTools: Fix eval parse string issue
[mirror_edk2.git] / BaseTools / Source / Python / Common / Misc.py
index 390ef3606fb56b02a0be70712a64e4c7dfe65be8..af374d804d86b8a01a5fee2ae38b0c2968169eaf 100644 (file)
@@ -1,7 +1,7 @@
 ## @file\r
 # Common routines used by all tools\r
 #\r
 ## @file\r
 # Common routines used by all tools\r
 #\r
-# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2007 - 2018, 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
 # 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
@@ -36,7 +36,9 @@ from CommonDataClass.DataClass import *
 from Parsing import GetSplitValueList\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
 from Parsing import GetSplitValueList\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
-\r
+import uuid\r
+from CommonDataClass.Exceptions import BadExpression\r
+import subprocess\r
 ## Regular expression used to find out place holders in string template\r
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)\r
 \r
 ## Regular expression used to find out place holders in string template\r
 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE)\r
 \r
@@ -67,8 +69,26 @@ def GetVariableOffset(mapfilepath, efifilepath, varnames):
     if (firstline.startswith("Archive member included ") and\r
         firstline.endswith(" file (symbol)")):\r
         return _parseForGCC(lines, efifilepath, varnames)\r
     if (firstline.startswith("Archive member included ") and\r
         firstline.endswith(" file (symbol)")):\r
         return _parseForGCC(lines, efifilepath, varnames)\r
+    if firstline.startswith("# Path:"):\r
+        return _parseForXcode(lines, efifilepath, varnames)\r
     return _parseGeneral(lines, efifilepath, varnames)\r
 \r
     return _parseGeneral(lines, efifilepath, varnames)\r
 \r
+def _parseForXcode(lines, efifilepath, varnames):\r
+    status = 0\r
+    ret = []\r
+    for index, line in enumerate(lines):\r
+        line = line.strip()\r
+        if status == 0 and line == "# Symbols:":\r
+            status = 1\r
+            continue\r
+        if status == 1 and len(line) != 0:\r
+            for varname in varnames:\r
+                if varname in line:\r
+                    m = re.match('^([\da-fA-FxX]+)([\s\S]*)([_]*%s)$' % varname, line)\r
+                    if m != None:\r
+                        ret.append((varname, m.group(1)))\r
+    return ret\r
+\r
 def _parseForGCC(lines, efifilepath, varnames):\r
     """ Parse map file generated by GCC linker """\r
     status = 0\r
 def _parseForGCC(lines, efifilepath, varnames):\r
     """ Parse map file generated by GCC linker """\r
     status = 0\r
@@ -1423,21 +1443,26 @@ def ParseConsoleLog(Filename):
 \r
 def AnalyzePcdExpression(Setting):\r
     Setting = Setting.strip()\r
 \r
 def AnalyzePcdExpression(Setting):\r
     Setting = Setting.strip()\r
-    # There might be escaped quote in a string: \", \\\"\r
-    Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')\r
+    # There might be escaped quote in a string: \", \\\" , \', \\\'\r
+    Data = Setting\r
     # There might be '|' in string and in ( ... | ... ), replace it with '-'\r
     NewStr = ''\r
     # There might be '|' in string and in ( ... | ... ), replace it with '-'\r
     NewStr = ''\r
-    InStr = False\r
+    InSingleQuoteStr = False\r
+    InDoubleQuoteStr = False\r
     Pair = 0\r
     Pair = 0\r
-    for ch in Data:\r
-        if ch == '"':\r
-            InStr = not InStr\r
-        elif ch == '(' and not InStr:\r
+    for Index, ch in enumerate(Data):\r
+        if ch == '"' and not InSingleQuoteStr:\r
+            if Data[Index - 1] != '\\':\r
+                InDoubleQuoteStr = not InDoubleQuoteStr\r
+        elif ch == "'" and not InDoubleQuoteStr:\r
+            if Data[Index - 1] != '\\':\r
+                InSingleQuoteStr = not InSingleQuoteStr\r
+        elif ch == '(' and not (InSingleQuoteStr or InDoubleQuoteStr):\r
             Pair += 1\r
             Pair += 1\r
-        elif ch == ')' and not InStr:\r
+        elif ch == ')' and not (InSingleQuoteStr or InDoubleQuoteStr):\r
             Pair -= 1\r
 \r
             Pair -= 1\r
 \r
-        if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT:\r
+        if (Pair > 0 or InSingleQuoteStr or InDoubleQuoteStr) and ch == TAB_VALUE_SPLIT:\r
             NewStr += '-'\r
         else:\r
             NewStr += ch\r
             NewStr += '-'\r
         else:\r
             NewStr += ch\r
@@ -1453,6 +1478,171 @@ def AnalyzePcdExpression(Setting):
 \r
     return FieldList\r
 \r
 \r
     return FieldList\r
 \r
+def ParseDevPathValue (Value):\r
+    DevPathList = [ "Path","HardwarePath","Pci","PcCard","MemoryMapped","VenHw","Ctrl","BMC","AcpiPath","Acpi","PciRoot",\r
+                    "PcieRoot","Floppy","Keyboard","Serial","ParallelPort","AcpiEx","AcpiExp","AcpiAdr","Msg","Ata","Scsi",\r
+                    "Fibre","FibreEx","I1394","USB","I2O","Infiniband","VenMsg","VenPcAnsi","VenVt100","VenVt100Plus",\r
+                    "VenUtf8","UartFlowCtrl","SAS","SasEx","NVMe","UFS","SD","eMMC","DebugPort","MAC","IPv4","IPv6","Uart",\r
+                    "UsbClass","UsbAudio","UsbCDCControl","UsbHID","UsbImage","UsbPrinter","UsbMassStorage","UsbHub",\r
+                    "UsbCDCData","UsbSmartCard","UsbVideo","UsbDiagnostic","UsbWireless","UsbDeviceFirmwareUpdate",\r
+                    "UsbIrdaBridge","UsbTestAndMeasurement","UsbWwid","Unit","iSCSI","Vlan","Uri","Bluetooth","Wi-Fi",\r
+                    "MediaPath","HD","CDROM","VenMedia","Media","Fv","FvFile","Offset","RamDisk","VirtualDisk","VirtualCD",\r
+                    "PersistentVirtualDisk","PersistentVirtualCD","BbsPath","BBS","Sata" ]\r
+    if '\\' in Value:\r
+        Value.replace('\\', '/').replace(' ', '')\r
+    for Item in Value.split('/'):\r
+        Key = Item.strip().split('(')[0]\r
+        if Key not in DevPathList:\r
+            pass\r
+\r
+    Cmd = 'DevicePath ' + '"' + Value + '"'\r
+    try:\r
+        p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)\r
+        out, err = p.communicate()\r
+    except Exception, X:\r
+        raise BadExpression("DevicePath: %s" % (str(X)) )\r
+    finally:\r
+        subprocess._cleanup()\r
+        p.stdout.close()\r
+        p.stderr.close()\r
+    if err:\r
+        raise BadExpression("DevicePath: %s" % str(err))\r
+    Size = len(out.split())\r
+    out = ','.join(out.split())\r
+    return '{' + out + '}', Size\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 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
+            TmpValue = GuidStructureStringToGuidString(Value)\r
+            if len(TmpValue) == 0:\r
+                raise BadExpression("Invalid GUID value string %s" % Value)\r
+            Value = TmpValue\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
+        # translate escape character\r
+        Value = Value[1:]\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\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
+        # translate escape character\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\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
+        # translate escape character\r
+        Value = Value[1:]\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\r
+        if len(List) == 0:\r
+            raise BadExpression('Length %s is %s' % (Value, len(List)))\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
+        # translate escape character\r
+        try:\r
+            Value = eval(Value)\r
+        except:\r
+            Value = Value[1:-1]\r
+        List = list(Value)\r
+        if len(List) == 0:\r
+            raise BadExpression('Length %s is %s' % (Value, len(List)))\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.replace("DEVICE_PATH(", '').rstrip(')')\r
+        Value = Value.strip().strip('"')\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
+\r
 ## AnalyzeDscPcd\r
 #\r
 #  Analyze DSC PCD value, since there is no data type info in DSC\r
 ## AnalyzeDscPcd\r
 #\r
 #  Analyze DSC PCD value, since there is no data type info in DSC\r
@@ -1486,19 +1676,25 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
         Value = FieldList[0]\r
         Size = ''\r
         if len(FieldList) > 1:\r
         Value = FieldList[0]\r
         Size = ''\r
         if len(FieldList) > 1:\r
-            Type = FieldList[1]\r
-            # Fix the PCD type when no DataType input\r
-            if Type == 'VOID*':\r
-                DataType = 'VOID*'\r
-            else:\r
+            if FieldList[1].upper().startswith("0X") or FieldList[1].isdigit():\r
                 Size = FieldList[1]\r
                 Size = FieldList[1]\r
+            else:\r
+                DataType = FieldList[1]\r
+\r
         if len(FieldList) > 2:\r
             Size = FieldList[2]\r
         if len(FieldList) > 2:\r
             Size = FieldList[2]\r
-        if DataType == 'VOID*':\r
-            IsValid = (len(FieldList) <= 3)\r
-        else:\r
+        if DataType == "":\r
             IsValid = (len(FieldList) <= 1)\r
             IsValid = (len(FieldList) <= 1)\r
-        return [Value, '', Size], IsValid, 0\r
+        else:\r
+            IsValid = (len(FieldList) <= 3)\r
+#         Value, Size = ParseFieldValue(Value)\r
+        if Size:\r
+            try:\r
+                int(Size,16) if Size.upper().startswith("0X") else int(Size)\r
+            except:\r
+                IsValid = False\r
+                Size = -1\r
+        return [str(Value), '', str(Size)], IsValid, 0\r
     elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
         Value = FieldList[0]\r
         Size = Type = ''\r
     elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
         Value = FieldList[0]\r
         Size = Type = ''\r
@@ -1516,11 +1712,18 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
                     Size = str(len(Value.split(",")))\r
                 else:\r
                     Size = str(len(Value) -2 + 1 )\r
                     Size = str(len(Value.split(",")))\r
                 else:\r
                     Size = str(len(Value) -2 + 1 )\r
-        if DataType == 'VOID*':\r
-            IsValid = (len(FieldList) <= 3)\r
-        else:\r
+        if DataType == "":\r
             IsValid = (len(FieldList) <= 1)\r
             IsValid = (len(FieldList) <= 1)\r
-        return [Value, Type, Size], IsValid, 0\r
+        else:\r
+            IsValid = (len(FieldList) <= 3)\r
+\r
+        if Size:\r
+            try:\r
+                int(Size,16) if Size.upper().startswith("0X") else int(Size)\r
+            except:\r
+                IsValid = False\r
+                Size = -1\r
+        return [Value, Type, str(Size)], IsValid, 0\r
     elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):\r
         VpdOffset = FieldList[0]\r
         Value = Size = ''\r
     elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):\r
         VpdOffset = FieldList[0]\r
         Value = Size = ''\r
@@ -1532,11 +1735,17 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''):
                 Size = FieldList[1]\r
             if len(FieldList) > 2:\r
                 Value = FieldList[2]\r
                 Size = FieldList[1]\r
             if len(FieldList) > 2:\r
                 Value = FieldList[2]\r
-        if DataType == 'VOID*':\r
-            IsValid = (len(FieldList) <= 3)\r
+        if DataType == "":\r
+            IsValid = (len(FieldList) <= 1)\r
         else:\r
         else:\r
-            IsValid = (len(FieldList) <= 2)\r
-        return [VpdOffset, Size, Value], IsValid, 2\r
+            IsValid = (len(FieldList) <= 3)\r
+        if Size:\r
+            try:\r
+                int(Size,16) if Size.upper().startswith("0X") else int(Size)\r
+            except:\r
+                IsValid = False\r
+                Size = -1\r
+        return [VpdOffset, str(Size), Value], IsValid, 2\r
     elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):\r
         HiiString = FieldList[0]\r
         Guid = Offset = Value = Attribute = ''\r
     elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):\r
         HiiString = FieldList[0]\r
         Guid = Offset = Value = Attribute = ''\r
@@ -1635,10 +1844,10 @@ def CheckPcdDatum(Type, Value):
     if Type == "VOID*":\r
         ValueRe = re.compile(r'\s*L?\".*\"\s*$')\r
         if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))\r
     if Type == "VOID*":\r
         ValueRe = re.compile(r'\s*L?\".*\"\s*$')\r
         if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))\r
-                or (Value.startswith('{') and Value.endswith('}'))\r
+                or (Value.startswith('{') and Value.endswith('}')) or (Value.startswith("L'") or Value.startswith("'") and Value.endswith("'"))\r
                ):\r
             return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\\r
                ):\r
             return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\\r
-                          ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type)\r
+                          ", \"...\" or \'...\' for string, L\"...\" or L\'...\' for unicode string" % (Value, Type)\r
         elif ValueRe.match(Value):\r
             # Check the chars in UnicodeString or CString is printable\r
             if Value.startswith("L"):\r
         elif ValueRe.match(Value):\r
             # Check the chars in UnicodeString or CString is printable\r
             if Value.startswith("L"):\r
@@ -1664,7 +1873,7 @@ def CheckPcdDatum(Type, Value):
             return False, "Invalid value [%s] of type [%s];"\\r
                           " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)\r
     else:\r
             return False, "Invalid value [%s] of type [%s];"\\r
                           " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)\r
     else:\r
-        return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type)\r
+        return True, "StructurePcd"\r
 \r
     return True, ""\r
 \r
 \r
     return True, ""\r
 \r
@@ -1979,61 +2188,167 @@ class PeImageClass():
             Value = (Value << 8) | int(ByteList[index])\r
         return Value\r
 \r
             Value = (Value << 8) | int(ByteList[index])\r
         return Value\r
 \r
+class DefaultStore():\r
+    def __init__(self,DefaultStores ):\r
 \r
 \r
+        self.DefaultStores = DefaultStores\r
+    def DefaultStoreID(self,DefaultStoreName):\r
+        for key,value in self.DefaultStores.items():\r
+            if value == DefaultStoreName:\r
+                return key\r
+        return None\r
+    def GetDefaultDefault(self):\r
+        if not self.DefaultStores or "0" in self.DefaultStores:\r
+            return "0",TAB_DEFAULT_STORES_DEFAULT\r
+        else:\r
+            minvalue = min([int(value_str) for value_str in self.DefaultStores.keys()])\r
+            return (str(minvalue), self.DefaultStores[str(minvalue)])\r
+    def GetMin(self,DefaultSIdList):\r
+        if not DefaultSIdList:\r
+            return "STANDARD"\r
+        storeidset = {storeid for storeid, storename in self.DefaultStores.values() if storename in DefaultSIdList}\r
+        if not storeidset:\r
+            return ""\r
+        minid = min(storeidset )\r
+        for sid,name in self.DefaultStores.values():\r
+            if sid == minid:\r
+                return name\r
 class SkuClass():\r
     \r
     DEFAULT = 0\r
     SINGLE = 1\r
     MULTIPLE =2\r
     \r
 class SkuClass():\r
     \r
     DEFAULT = 0\r
     SINGLE = 1\r
     MULTIPLE =2\r
     \r
-    def __init__(self,SkuIdentifier='', SkuIds={}):\r
+    def __init__(self,SkuIdentifier='', SkuIds=None):\r
+        if SkuIds is None:\r
+            SkuIds = {}\r
+\r
+        for SkuName in SkuIds:\r
+            SkuId = SkuIds[SkuName][0]\r
+            skuid_num = int(SkuId,16) if SkuId.upper().startswith("0X") else int(SkuId)\r
+            if skuid_num > 0xFFFFFFFFFFFFFFFF:\r
+                EdkLogger.error("build", PARAMETER_INVALID,\r
+                            ExtraData = "SKU-ID [%s] value %s exceeds the max value of UINT64"\r
+                                      % (SkuName, SkuId))\r
         \r
         self.AvailableSkuIds = sdict()\r
         self.SkuIdSet = []\r
         self.SkuIdNumberSet = []\r
         \r
         self.AvailableSkuIds = sdict()\r
         self.SkuIdSet = []\r
         self.SkuIdNumberSet = []\r
+        self.SkuData = SkuIds\r
+        self.__SkuInherit = {}\r
+        self.__SkuIdentifier = SkuIdentifier\r
         if SkuIdentifier == '' or SkuIdentifier is None:\r
             self.SkuIdSet = ['DEFAULT']\r
             self.SkuIdNumberSet = ['0U']\r
         elif SkuIdentifier == 'ALL':\r
             self.SkuIdSet = SkuIds.keys()\r
         if SkuIdentifier == '' or SkuIdentifier is None:\r
             self.SkuIdSet = ['DEFAULT']\r
             self.SkuIdNumberSet = ['0U']\r
         elif SkuIdentifier == 'ALL':\r
             self.SkuIdSet = SkuIds.keys()\r
-            self.SkuIdNumberSet = [num.strip() + 'U' for num in SkuIds.values()]\r
+            self.SkuIdNumberSet = [num[0].strip() + 'U' for num in SkuIds.values()]\r
         else:\r
             r = SkuIdentifier.split('|') \r
         else:\r
             r = SkuIdentifier.split('|') \r
-            self.SkuIdSet=[r[k].strip() for k in range(len(r))]      \r
+            self.SkuIdSet=[(r[k].strip()).upper() for k in range(len(r))]\r
             k = None\r
             try: \r
             k = None\r
             try: \r
-                self.SkuIdNumberSet = [SkuIds[k].strip() + 'U' for k in self.SkuIdSet]   \r
+                self.SkuIdNumberSet = [SkuIds[k][0].strip() + 'U' for k in self.SkuIdSet]\r
             except Exception:\r
                 EdkLogger.error("build", PARAMETER_INVALID,\r
                             ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
                                       % (k, " | ".join(SkuIds.keys())))\r
             except Exception:\r
                 EdkLogger.error("build", PARAMETER_INVALID,\r
                             ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
                                       % (k, " | ".join(SkuIds.keys())))\r
-        if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':\r
-            self.SkuIdSet.remove('DEFAULT')\r
-            self.SkuIdNumberSet.remove('0U')\r
         for each in self.SkuIdSet:\r
             if each in SkuIds:\r
         for each in self.SkuIdSet:\r
             if each in SkuIds:\r
-                self.AvailableSkuIds[each] = SkuIds[each]\r
+                self.AvailableSkuIds[each] = SkuIds[each][0]\r
             else:\r
                 EdkLogger.error("build", PARAMETER_INVALID,\r
                             ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
                                       % (each, " | ".join(SkuIds.keys())))\r
             else:\r
                 EdkLogger.error("build", PARAMETER_INVALID,\r
                             ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
                                       % (each, " | ".join(SkuIds.keys())))\r
+        if self.SkuUsageType != self.SINGLE:\r
+            self.AvailableSkuIds.update({'DEFAULT':0, 'COMMON':0})\r
+        if self.SkuIdSet:\r
+            GlobalData.gSkuids = (self.SkuIdSet)\r
+            if 'COMMON' in GlobalData.gSkuids:\r
+                GlobalData.gSkuids.remove('COMMON')\r
+            if self.SkuUsageType == self.SINGLE:\r
+                if len(GlobalData.gSkuids) != 1:\r
+                    if 'DEFAULT' in GlobalData.gSkuids:\r
+                        GlobalData.gSkuids.remove('DEFAULT')\r
+            if GlobalData.gSkuids:\r
+                GlobalData.gSkuids.sort()\r
+\r
+    def GetNextSkuId(self, skuname):\r
+        if not self.__SkuInherit:\r
+            self.__SkuInherit = {}\r
+            for item in self.SkuData.values():\r
+                self.__SkuInherit[item[1]]=item[2] if item[2] else "DEFAULT"\r
+        return self.__SkuInherit.get(skuname,"DEFAULT")\r
+\r
+    def GetSkuChain(self,sku):\r
+        if sku == "DEFAULT":\r
+            return ["DEFAULT"]\r
+        skulist = [sku]\r
+        nextsku = sku\r
+        while 1:\r
+            nextsku = self.GetNextSkuId(nextsku)\r
+            skulist.append(nextsku)\r
+            if nextsku == "DEFAULT":\r
+                break\r
+        skulist.reverse()\r
+        return skulist\r
+    def SkuOverrideOrder(self):\r
+        skuorderset = []\r
+        for skuname in self.SkuIdSet:\r
+            skuorderset.append(self.GetSkuChain(skuname))\r
         \r
         \r
+        skuorder = []\r
+        for index in range(max([len(item) for item in skuorderset])):\r
+            for subset in skuorderset:\r
+                if index > len(subset)-1:\r
+                    continue\r
+                if subset[index] in skuorder:\r
+                    continue\r
+                skuorder.append(subset[index])\r
+\r
+        return skuorder\r
+\r
     def __SkuUsageType(self): \r
         \r
     def __SkuUsageType(self): \r
         \r
+        if self.__SkuIdentifier.upper() == "ALL":\r
+            return SkuClass.MULTIPLE\r
+\r
         if len(self.SkuIdSet) == 1:\r
             if self.SkuIdSet[0] == 'DEFAULT':\r
                 return SkuClass.DEFAULT\r
             else:\r
                 return SkuClass.SINGLE\r
         if len(self.SkuIdSet) == 1:\r
             if self.SkuIdSet[0] == 'DEFAULT':\r
                 return SkuClass.DEFAULT\r
             else:\r
                 return SkuClass.SINGLE\r
+        elif len(self.SkuIdSet) == 2:\r
+            if 'DEFAULT' in self.SkuIdSet:\r
+                return SkuClass.SINGLE\r
+            else:\r
+                return SkuClass.MULTIPLE\r
         else:\r
             return SkuClass.MULTIPLE\r
         else:\r
             return SkuClass.MULTIPLE\r
+    def DumpSkuIdArrary(self):\r
 \r
 \r
+        ArrayStrList = []\r
+        if self.SkuUsageType == SkuClass.SINGLE:\r
+            ArrayStr = "{0x0}"\r
+        else:\r
+            for skuname in self.AvailableSkuIds:\r
+                if skuname == "COMMON":\r
+                    continue\r
+                while skuname != "DEFAULT":\r
+                    ArrayStrList.append(hex(int(self.AvailableSkuIds[skuname])))\r
+                    skuname = self.GetNextSkuId(skuname)\r
+                ArrayStrList.append("0x0")\r
+            ArrayStr = "{" + ",".join(ArrayStrList) +  "}"\r
+        return ArrayStr\r
     def __GetAvailableSkuIds(self):\r
         return self.AvailableSkuIds\r
     \r
     def __GetSystemSkuID(self):\r
         if self.__SkuUsageType() == SkuClass.SINGLE:\r
     def __GetAvailableSkuIds(self):\r
         return self.AvailableSkuIds\r
     \r
     def __GetSystemSkuID(self):\r
         if self.__SkuUsageType() == SkuClass.SINGLE:\r
-            return self.SkuIdSet[0]\r
+            if len(self.SkuIdSet) == 1:\r
+                return self.SkuIdSet[0]\r
+            else:\r
+                return self.SkuIdSet[0] if self.SkuIdSet[0] != 'DEFAULT' else self.SkuIdSet[1]\r
         else:\r
             return 'DEFAULT'\r
     def __GetAvailableSkuIdNumber(self):\r
         else:\r
             return 'DEFAULT'\r
     def __GetAvailableSkuIdNumber(self):\r
@@ -2062,6 +2377,55 @@ def PackRegistryFormatGuid(Guid):
                 int(Guid[4][-2:], 16)\r
                 )\r
 \r
                 int(Guid[4][-2:], 16)\r
                 )\r
 \r
+def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Value):\r
+    if PcdDatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64,'BOOLEAN']:\r
+        if Value.startswith('L') or Value.startswith('"'):\r
+            if not Value[1]:\r
+                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"{...}"')\r
+            Value = Value\r
+        elif Value.startswith('H'):\r
+            if not Value[1]:\r
+                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"{...}"')\r
+            Value = Value[1:]\r
+        else:\r
+            if not Value[0]:\r
+                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"{...}"')\r
+            Value = '"' + Value + '"'\r
+\r
+    IsValid, Cause = CheckPcdDatum(PcdDatumType, Value)\r
+    if not IsValid:\r
+        EdkLogger.error("build", FORMAT_INVALID, Cause, ExtraData="%s.%s" % (TokenSpaceGuidCName, TokenCName))\r
+    if PcdDatumType == 'BOOLEAN':\r
+        Value = Value.upper()\r
+        if Value == 'TRUE' or Value == '1':\r
+            Value = '1'\r
+        elif Value == 'FALSE' or Value == '0':\r
+            Value = '0'\r
+    return  Value\r
+##  Get the integer value from string like "14U" or integer like 2\r
+#\r
+#   @param      Input   The object that may be either a integer value or a string\r
+#\r
+#   @retval     Value    The integer value that the input represents\r
+#\r
+def GetIntegerValue(Input):\r
+    if type(Input) in (int, long):\r
+        return Input\r
+    String = Input\r
+    if String.endswith("U"):\r
+        String = String[:-1]\r
+    if String.endswith("ULL"):\r
+        String = String[:-3]\r
+    if String.endswith("LL"):\r
+        String = String[:-2]\r
+\r
+    if String.startswith("0x") or String.startswith("0X"):\r
+        return int(String, 16)\r
+    elif String == '':\r
+        return 0\r
+    else:\r
+        return int(String)\r
+\r
 ##\r
 #\r
 # This acts like the main() function for the script, unless it is 'import'ed into another\r
 ##\r
 #\r
 # This acts like the main() function for the script, unless it is 'import'ed into another\r