X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=d1752d8a624e7087061779fb48e8ff9f292c5a26;hp=59d1ba2639433cdd27a581590e639bba7c21c93f;hb=5fbb0f9908ded1944aa4bba599ccc4c605987cb7;hpb=726c501c2c9a1ef103fab7846e2d1a34506715d8 diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 59d1ba2639..d1752d8a62 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -1,7 +1,7 @@ ## @file # Common routines used by all tools # -# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
# 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 @@ -38,7 +38,7 @@ from Common.LongFilePathSupport import OpenLongFilePath as open from Common.MultipleWorkspace import MultipleWorkspace as mws import uuid from CommonDataClass.Exceptions import BadExpression - +import subprocess ## Regular expression used to find out place holders in string template gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE) @@ -76,7 +76,7 @@ def GetVariableOffset(mapfilepath, efifilepath, varnames): def _parseForXcode(lines, efifilepath, varnames): status = 0 ret = [] - for index, line in enumerate(lines): + for line in lines: line = line.strip() if status == 0 and line == "# Symbols:": status = 1 @@ -85,7 +85,7 @@ def _parseForXcode(lines, efifilepath, varnames): for varname in varnames: if varname in line: m = re.match('^([\da-fA-FxX]+)([\s\S]*)([_]*%s)$' % varname, line) - if m != None: + if m is not None: ret.append((varname, m.group(1))) return ret @@ -110,27 +110,27 @@ def _parseForGCC(lines, efifilepath, varnames): # status handler if status == 3: m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line) - if m != None: + if m is not None: sections.append(m.groups(0)) for varname in varnames: Str = '' m = re.match("^.data.(%s)" % varname, line) - if m != None: + if m is not None: m = re.match(".data.(%s)$" % varname, line) - if m != None: + if m is not None: Str = lines[index + 1] else: Str = line[len(".data.%s" % varname):] if Str: m = re.match('^([\da-fA-Fx]+) +([\da-fA-Fx]+)', Str.strip()) - if m != None: + if m is not None: varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0])) if not varoffset: return [] # get section information from efi file efisecs = PeImageClass(efifilepath).SectionHeaderList - if efisecs == None or len(efisecs) == 0: + if efisecs is None or len(efisecs) == 0: return [] #redirection redirection = 0 @@ -166,19 +166,19 @@ def _parseGeneral(lines, efifilepath, varnames): continue if status == 1 and len(line) != 0: m = secRe.match(line) - assert m != None, "Fail to parse the section in map file , line is %s" % line + assert m is not None, "Fail to parse the section in map file , line is %s" % line sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0) secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class]) if status == 2 and len(line) != 0: for varname in varnames: m = symRe.match(line) - assert m != None, "Fail to parse the symbol in map file, line is %s" % line + assert m is not None, "Fail to parse the symbol in map file, line is %s" % line sec_no, sym_offset, sym_name, vir_addr = m.groups(0) sec_no = int(sec_no, 16) sym_offset = int(sym_offset, 16) vir_addr = int(vir_addr, 16) m2 = re.match('^[_]*(%s)' % varname, sym_name) - if m2 != None: + if m2 is not None: # fond a binary pcd entry in map file for sec in secs: if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]): @@ -188,7 +188,7 @@ def _parseGeneral(lines, efifilepath, varnames): # get section information from efi file efisecs = PeImageClass(efifilepath).SectionHeaderList - if efisecs == None or len(efisecs) == 0: + if efisecs is None or len(efisecs) == 0: return [] ret = [] @@ -423,7 +423,7 @@ def GuidStructureStringToGuidValueName(GuidValue): # @param Directory The directory name # def CreateDirectory(Directory): - if Directory == None or Directory.strip() == "": + if Directory is None or Directory.strip() == "": return True try: if not os.access(Directory, os.F_OK): @@ -437,7 +437,7 @@ def CreateDirectory(Directory): # @param Directory The directory name # def RemoveDirectory(Directory, Recursively=False): - if Directory == None or Directory.strip() == "" or not os.path.exists(Directory): + if Directory is None or Directory.strip() == "" or not os.path.exists(Directory): return if Recursively: CurrentDirectory = os.getcwd() @@ -540,7 +540,7 @@ def DataDump(Data, File): except: EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False) finally: - if Fd != None: + if Fd is not None: Fd.close() ## Restore a Python object from a file @@ -560,7 +560,7 @@ def DataRestore(File): EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e))) Data = None finally: - if Fd != None: + if Fd is not None: Fd.close() return Data @@ -668,7 +668,7 @@ def GetFiles(Root, SkipList=None, FullPath=True): # @retval False if file doesn't exists # def ValidFile(File, Ext=None): - if Ext != None: + if Ext is not None: Dummy, FileExt = os.path.splitext(File) if FileExt.lower() != Ext.lower(): return False @@ -715,13 +715,13 @@ def RealPath2(File, Dir='', OverrideDir=''): # def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): NewFile = File - if Ext != None: + if Ext is not None: Dummy, FileExt = os.path.splitext(File) if FileExt.lower() != Ext.lower(): return False, File # Replace the Edk macros - if OverrideDir != '' and OverrideDir != None: + if OverrideDir != '' and OverrideDir is not None: if OverrideDir.find('$(EFI_SOURCE)') > -1: OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) if OverrideDir.find('$(EDK_SOURCE)') > -1: @@ -737,19 +737,19 @@ def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource=' NewFile = File.replace('$(EFI_SOURCE)', EfiSource) NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource) NewFile = AllFiles[os.path.normpath(NewFile)] - if NewFile != None: + if NewFile is not None: return True, NewFile # Second check the path with override value - if OverrideDir != '' and OverrideDir != None: + if OverrideDir != '' and OverrideDir is not None: NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))] - if NewFile != None: + if NewFile is not None: return True, NewFile # Last check the path with normal definitions File = os.path.join(Dir, File) NewFile = AllFiles[os.path.normpath(File)] - if NewFile != None: + if NewFile is not None: return True, NewFile return False, File @@ -759,7 +759,7 @@ def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource=' # def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): # Replace the Edk macros - if OverrideDir != '' and OverrideDir != None: + if OverrideDir != '' and OverrideDir is not None: if OverrideDir.find('$(EFI_SOURCE)') > -1: OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) if OverrideDir.find('$(EDK_SOURCE)') > -1: @@ -781,23 +781,23 @@ def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.' File = File.replace('$(EFI_SOURCE)', EfiSource) File = File.replace('$(EDK_SOURCE)', EdkSource) NewFile = AllFiles[os.path.normpath(File)] - if NewFile != None: + if NewFile is not None: NewRelaPath = os.path.dirname(NewFile) File = os.path.basename(NewFile) #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1] break # Second check the path with override value - if OverrideDir != '' and OverrideDir != None: + if OverrideDir != '' and OverrideDir is not None: NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))] - if NewFile != None: + if NewFile is not None: #NewRelaPath = os.path.dirname(NewFile) NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1] break # Last check the path with normal definitions NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))] - if NewFile != None: + if NewFile is not None: break # No file found @@ -1062,7 +1062,7 @@ class Progressor: self.CodaMessage = CloseMessage self.ProgressChar = ProgressChar self.Interval = Interval - if Progressor._StopFlag == None: + if Progressor._StopFlag is None: Progressor._StopFlag = threading.Event() ## Start to print progress charater @@ -1070,10 +1070,10 @@ class Progressor: # @param OpenMessage The string printed before progress charaters # def Start(self, OpenMessage=None): - if OpenMessage != None: + if OpenMessage is not None: self.PromptMessage = OpenMessage Progressor._StopFlag.clear() - if Progressor._ProgressThread == None: + if Progressor._ProgressThread is None: Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry) Progressor._ProgressThread.setDaemon(False) Progressor._ProgressThread.start() @@ -1084,7 +1084,7 @@ class Progressor: # def Stop(self, CloseMessage=None): OriginalCodaMessage = self.CodaMessage - if CloseMessage != None: + if CloseMessage is not None: self.CodaMessage = CloseMessage self.Abort() self.CodaMessage = OriginalCodaMessage @@ -1107,9 +1107,9 @@ class Progressor: ## Abort the progress display @staticmethod def Abort(): - if Progressor._StopFlag != None: + if Progressor._StopFlag is not None: Progressor._StopFlag.set() - if Progressor._ProgressThread != None: + if Progressor._ProgressThread is not None: Progressor._ProgressThread.join() Progressor._ProgressThread = None @@ -1228,7 +1228,7 @@ class sdict(IterableUserDict): return key, value def update(self, dict=None, **kwargs): - if dict != None: + if dict is not None: for k, v in dict.items(): self[k] = v if len(kwargs): @@ -1301,7 +1301,7 @@ class tdict: if self._Level_ > 1: RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)] - if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList: + if FirstKey is None or str(FirstKey).upper() in self._ValidWildcardList: FirstKey = self._Wildcard if self._Single_: @@ -1316,24 +1316,24 @@ class tdict: if FirstKey == self._Wildcard: if FirstKey in self.data: Value = self.data[FirstKey][RestKeys] - if Value == None: + if Value is None: for Key in self.data: Value = self.data[Key][RestKeys] - if Value != None: break + if Value is not None: break else: if FirstKey in self.data: Value = self.data[FirstKey][RestKeys] - if Value == None and self._Wildcard in self.data: + if Value is None and self._Wildcard in self.data: #print "Value=None" Value = self.data[self._Wildcard][RestKeys] else: if FirstKey == self._Wildcard: if FirstKey in self.data: Value = self.data[FirstKey] - if Value == None: + if Value is None: for Key in self.data: Value = self.data[Key] - if Value != None: break + if Value is not None: break else: if FirstKey in self.data: Value = self.data[FirstKey] @@ -1441,23 +1441,44 @@ def ParseConsoleLog(Filename): 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.replace('\\\\', '//').replace('\\\"', '\\\'') + # There might be escaped quote in a string: \", \\\" , \', \\\' + Data = Setting # There might be '|' in string and in ( ... | ... ), replace it with '-' NewStr = '' - InStr = False + InSingleQuoteStr = False + InDoubleQuoteStr = False Pair = 0 - for ch in Data: - if ch == '"': - InStr = not InStr - elif ch == '(' and not InStr: + for Index, ch in enumerate(Data): + if ch == '"' and not InSingleQuoteStr: + if Data[Index - 1] != '\\': + InDoubleQuoteStr = not InDoubleQuoteStr + elif ch == "'" and not InDoubleQuoteStr: + if Data[Index - 1] != '\\': + InSingleQuoteStr = not InSingleQuoteStr + elif ch == '(' and not (InSingleQuoteStr or InDoubleQuoteStr): Pair += 1 - elif ch == ')' and not InStr: + elif ch == ')' and not (InSingleQuoteStr or InDoubleQuoteStr): Pair -= 1 - if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT: + if (Pair > 0 or InSingleQuoteStr or InDoubleQuoteStr) and ch == TAB_VALUE_SPLIT: NewStr += '-' else: NewStr += ch @@ -1474,7 +1495,24 @@ def AnalyzePcdExpression(Setting): return FieldList def ParseDevPathValue (Value): - pass + if '\\' in Value: + Value.replace('\\', '/').replace(' ', '') + + Cmd = 'DevicePath ' + '"' + Value + '"' + try: + p = subprocess.Popen(Cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + out, err = p.communicate() + except Exception, X: + raise BadExpression("DevicePath: %s" % (str(X)) ) + finally: + subprocess._cleanup() + p.stdout.close() + p.stderr.close() + if err: + raise BadExpression("DevicePath: %s" % str(err)) + Size = len(out.split()) + out = ','.join(out.split()) + return '{' + out + '}', Size def ParseFieldValue (Value): if type(Value) == type(0): @@ -1505,16 +1543,10 @@ def ParseFieldValue (Value): if Value.startswith('GUID') and Value.endswith(')'): Value = Value.split('(', 1)[1][:-1].strip() if Value[0] == '{' and Value[-1] == '}': - Value = Value[1:-1].strip() - Value = Value.split('{', 1) - Value = ['%02x' % int(Item, 16) for Item in (Value[0] + Value[1][:-1]).split(',')] - if len(Value[0]) != 8: - Value[0] = '%08X' % int(Value[0], 16) - if len(Value[1]) != 4: - Value[1] = '%04X' % int(Value[1], 16) - if len(Value[2]) != 4: - Value[2] = '%04X' % int(Value[2], 16) - Value = '-'.join(Value[0:3]) + '-' + ''.join(Value[3:5]) + '-' + ''.join(Value[5:11]) + TmpValue = GuidStructureStringToGuidString(Value) + if len(TmpValue) == 0: + raise BadExpression("Invalid GUID value string %s" % Value) + Value = TmpValue if Value[0] == '"' and Value[-1] == '"': Value = Value[1:-1] try: @@ -1525,7 +1557,13 @@ def ParseFieldValue (Value): return Value, 16 if Value.startswith('L"') and Value.endswith('"'): # Unicode String - List = list(Value[2:-1]) + # translate escape character + Value = Value[1:] + try: + Value = eval(Value) + except: + Value = Value[1:-1] + List = list(Value) List.reverse() Value = 0 for Char in List: @@ -1533,7 +1571,12 @@ def ParseFieldValue (Value): return Value, (len(List) + 1) * 2 if Value.startswith('"') and Value.endswith('"'): # ASCII String - List = list(Value[1:-1]) + # translate escape character + try: + Value = eval(Value) + except: + Value = Value[1:-1] + List = list(Value) List.reverse() Value = 0 for Char in List: @@ -1541,7 +1584,15 @@ def ParseFieldValue (Value): return Value, len(List) + 1 if Value.startswith("L'") and Value.endswith("'"): # Unicode Character Constant - List = list(Value[2:-1]) + # translate escape character + Value = Value[1:] + try: + Value = eval(Value) + except: + Value = Value[1:-1] + List = list(Value) + if len(List) == 0: + raise BadExpression('Length %s is %s' % (Value, len(List))) List.reverse() Value = 0 for Char in List: @@ -1549,7 +1600,14 @@ def ParseFieldValue (Value): return Value, len(List) * 2 if Value.startswith("'") and Value.endswith("'"): # Character constant - List = list(Value[1:-1]) + # translate escape character + try: + Value = eval(Value) + except: + Value = Value[1:-1] + List = list(Value) + if len(List) == 0: + raise BadExpression('Length %s is %s' % (Value, len(List))) List.reverse() Value = 0 for Char in List: @@ -1569,7 +1627,8 @@ def ParseFieldValue (Value): Value = (Value << 8) | ((ItemValue >> 8 * I) & 0xff) return Value, RetSize if Value.startswith('DEVICE_PATH(') and Value.endswith(')'): - Value = Value.split('"')[1] + Value = Value.replace("DEVICE_PATH(", '').rstrip(')') + Value = Value.strip().strip('"') return ParseDevPathValue(Value) if Value.lower().startswith('0x'): Value = int(Value, 16) @@ -1648,14 +1707,6 @@ def AnalyzeDscPcd(Setting, PcdType, DataType=''): Type = DataType if len(FieldList) > 2: Size = FieldList[2] - else: - if Type == 'VOID*': - if Value.startswith("L"): - Size = str((len(Value)- 3 + 1) * 2) - elif Value.startswith("{"): - Size = str(len(Value.split(","))) - else: - Size = str(len(Value) -2 + 1 ) if DataType == "": IsValid = (len(FieldList) <= 1) else: @@ -1788,10 +1839,10 @@ def CheckPcdDatum(Type, Value): if Type == "VOID*": ValueRe = re.compile(r'\s*L?\".*\"\s*$') if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"')) - or (Value.startswith('{') and Value.endswith('}')) + or (Value.startswith('{') and Value.endswith('}')) or (Value.startswith("L'") or Value.startswith("'") and Value.endswith("'")) ): return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\ - ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type) + ", \"...\" or \'...\' for string, L\"...\" or L\'...\' for unicode string" % (Value, Type) elif ValueRe.match(Value): # Check the chars in UnicodeString or CString is printable if Value.startswith("L"): @@ -2002,7 +2053,7 @@ class PathClass(object): return hash(self.Path) def _GetFileKey(self): - if self._Key == None: + if self._Key is None: self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target return self._Key @@ -2210,6 +2261,10 @@ class SkuClass(): GlobalData.gSkuids = (self.SkuIdSet) if 'COMMON' in GlobalData.gSkuids: GlobalData.gSkuids.remove('COMMON') + if self.SkuUsageType == self.SINGLE: + if len(GlobalData.gSkuids) != 1: + if 'DEFAULT' in GlobalData.gSkuids: + GlobalData.gSkuids.remove('DEFAULT') if GlobalData.gSkuids: GlobalData.gSkuids.sort() @@ -2221,6 +2276,8 @@ class SkuClass(): return self.__SkuInherit.get(skuname,"DEFAULT") def GetSkuChain(self,sku): + if sku == "DEFAULT": + return ["DEFAULT"] skulist = [sku] nextsku = sku while 1: @@ -2315,31 +2372,6 @@ def PackRegistryFormatGuid(Guid): int(Guid[4][-2:], 16) ) -def BuildOptionPcdValueFormat(TokenSpaceGuidCName, TokenCName, PcdDatumType, Value): - if PcdDatumType == 'VOID*': - if Value.startswith('L'): - 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[0] + '"' + Value[1:] + '"' - 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