X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FCommon%2FMisc.py;h=8b5598b5f0b36465f4593744714c716742c23f2b;hb=d0acc87a41d9aa25fe87eb096efa62afacd1f865;hp=76dfbb665e382844af5a511e669110d96c70018f;hpb=b303ea726e1c8ed240dad2bce54821318567eab3;p=mirror_edk2.git diff --git a/BaseTools/Source/Python/Common/Misc.py b/BaseTools/Source/Python/Common/Misc.py index 76dfbb665e..8b5598b5f0 100644 --- a/BaseTools/Source/Python/Common/Misc.py +++ b/BaseTools/Source/Python/Common/Misc.py @@ -1,8 +1,8 @@ ## @file # Common routines used by all tools # -# Copyright (c) 2007, Intel Corporation -# All rights reserved. This program and the accompanying materials +# Copyright (c) 2007 - 2010, 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 # http://opensource.org/licenses/bsd-license.php @@ -22,12 +22,13 @@ import threading import time import re import cPickle +import array from UserDict import IterableUserDict from UserList import UserList from Common import EdkLogger as EdkLogger from Common import GlobalData as GlobalData - +from DataType import * from BuildToolError import * ## Regular expression used to find out place holders in string template @@ -155,7 +156,7 @@ def GuidStructureStringToGuidValueName(GuidValue): guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "") guidValueList = guidValueString.split(",") if len(guidValueList) != 11: - EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue) + EdkLogger.error(None, FORMAT_INVALID, "Invalid GUID value string [%s]" % GuidValue) return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % ( int(guidValueList[0], 16), int(guidValueList[1], 16), @@ -251,7 +252,15 @@ def SaveFileOnChange(File, Content, IsBinaryFile=True): except: EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File) - CreateDirectory(os.path.dirname(File)) + DirName = os.path.dirname(File) + if not CreateDirectory(DirName): + EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName) + else: + if DirName == '': + DirName = os.getcwd() + if not os.access(DirName, os.W_OK): + EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName) + try: if GlobalData.gIsWindows: try: @@ -266,8 +275,8 @@ def SaveFileOnChange(File, Content, IsBinaryFile=True): Fd = open(File, "wb") Fd.write(Content) Fd.close() - except: - EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File) + except IOError, X: + EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s'%X) return True @@ -436,8 +445,10 @@ def RealPath2(File, Dir='', OverrideDir=''): return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)] else: return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)] - - NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))] + if GlobalData.gAllFiles: + NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))] + else: + NewFile = os.path.normpath(os.path.join(Dir, File)) if NewFile: if Dir: if Dir[-1] == os.path.sep: @@ -459,7 +470,7 @@ def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource=' if FileExt.lower() != Ext.lower(): return False, File - # Replace the R8 macros + # Replace the Edk macros if OverrideDir != '' and OverrideDir != None: if OverrideDir.find('$(EFI_SOURCE)') > -1: OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) @@ -471,7 +482,7 @@ def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource=' Dir = os.getcwd() Dir = Dir[len(Workspace)+1:] - # First check if File has R8 definition itself + # First check if File has Edk definition itself if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1: NewFile = File.replace('$(EFI_SOURCE)', EfiSource) NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource) @@ -497,7 +508,7 @@ def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource=' # # def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): - # Replace the R8 macros + # Replace the Edk macros if OverrideDir != '' and OverrideDir != None: if OverrideDir.find('$(EFI_SOURCE)') > -1: OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) @@ -515,7 +526,7 @@ def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.' NewRelaPath = RelaPath while(True): - # First check if File has R8 definition itself + # First check if File has Edk definition itself if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1: File = File.replace('$(EFI_SOURCE)', EfiSource) File = File.replace('$(EDK_SOURCE)', EdkSource) @@ -718,7 +729,7 @@ class TemplateString(object): while Template: MatchObj = gPlaceholderPattern.search(Template, SearchFrom) if not MatchObj: - if MatchEnd < len(Template): + if MatchEnd <= len(Template): TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList) TemplateSectionList.append(TemplateSection) break @@ -1125,6 +1136,16 @@ class tdict: for Key in self.data: self.data[Key].SetSingleMode() + def GetKeys(self, KeyIndex=0): + assert KeyIndex >= 0 + if KeyIndex == 0: + return set(self.data.keys()) + else: + keys = set() + for Key in self.data: + keys |= self.data[Key].GetKeys(KeyIndex - 1) + return keys + ## Boolean chain list # class Blist(UserList): @@ -1155,20 +1176,108 @@ def ParseConsoleLog(Filename): Opr.close() Opw.close() +## AnalyzePcdData +# +# Analyze the pcd Value, Datum type and TokenNumber. +# Used to avoid split issue while the value string contain "|" character +# +# @param[in] Setting: A String contain value/datum type/token number information; +# +# @retval ValueList: A List contain value, datum type and toke number. +# +def AnalyzePcdData(Setting): + ValueList = ['', '', ''] + + ValueRe = re.compile(r'^\s*L?\".*\|.*\"') + PtrValue = ValueRe.findall(Setting) + + ValueUpdateFlag = False + + if len(PtrValue) >= 1: + Setting = re.sub(ValueRe, '', Setting) + ValueUpdateFlag = True + + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + + if ValueUpdateFlag: + ValueList[0] = PtrValue[0] + + return ValueList + +## AnalyzeHiiPcdData +# +# Analyze the pcd Value, variable name, variable Guid and variable offset. +# Used to avoid split issue while the value string contain "|" character +# +# @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information; +# +# @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue. +# +def AnalyzeHiiPcdData(Setting): + ValueList = ['', '', '', ''] + + ValueRe = re.compile(r'^\s*L?\".*\|.*\"') + PtrValue = ValueRe.findall(Setting) + + ValueUpdateFlag = False + + if len(PtrValue) >= 1: + Setting = re.sub(ValueRe, '', Setting) + ValueUpdateFlag = True + + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + + if ValueUpdateFlag: + ValueList[0] = PtrValue[0] + + return ValueList + +## AnalyzeVpdPcdData +# +# Analyze the vpd pcd Value, Datum type and TokenNumber. +# Used to avoid split issue while the value string contain "|" character +# +# @param[in] Setting: A String contain value/datum type/token number information; +# +# @retval ValueList: A List contain value, datum type and toke number. +# +def AnalyzeVpdPcdData(Setting): + ValueList = ['', '', ''] + + ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$') + PtrValue = ValueRe.findall(Setting) + + ValueUpdateFlag = False + + if len(PtrValue) >= 1: + Setting = re.sub(ValueRe, '', Setting) + ValueUpdateFlag = True + + TokenList = Setting.split(TAB_VALUE_SPLIT) + ValueList[0:len(TokenList)] = TokenList + + if ValueUpdateFlag: + ValueList[2] = PtrValue[0] + + return ValueList + ## check format of PCD value against its the datum type # # For PCD value setting # def CheckPcdDatum(Type, Value): if Type == "VOID*": - if not ((Value.startswith('L"') or Value.startswith('"') and Value.endswith('"')) + if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"')) 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) elif Type == 'BOOLEAN': - if Value not in ['TRUE', 'FALSE']: - return False, "Invalid value [%s] of type [%s]; must be TRUE or FALSE" % (Value, Type) + if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']: + return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\ + ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type) elif type(Value) == type(""): try: Value = long(Value, 0) @@ -1289,6 +1398,27 @@ class PathClass(object): else: return self.Path == str(Other) + ## Override __cmp__ function + # + # Customize the comparsion operation of two PathClass + # + # @retval 0 The two PathClass are different + # @retval -1 The first PathClass is less than the second PathClass + # @retval 1 The first PathClass is Bigger than the second PathClass + def __cmp__(self, Other): + if type(Other) == type(self): + OtherKey = Other.Path + else: + OtherKey = str(Other) + + SelfKey = self.Path + if SelfKey == OtherKey: + return 0 + elif SelfKey > OtherKey: + return 1 + else: + return -1 + ## Override __hash__ function # # Use Path as key in hash table @@ -1303,6 +1433,9 @@ class PathClass(object): self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target return self._Key + def _GetTimeStamp(self): + return os.stat(self.Path)[8] + def Validate(self, Type='', CaseSensitive=True): if GlobalData.gCaseInsensitive: CaseSensitive = False @@ -1311,7 +1444,12 @@ class PathClass(object): RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot) if not RealRoot and not RealFile: - return FILE_NOT_FOUND, self.File + RealFile = self.File + if self.AlterRoot: + RealFile = os.path.join(self.AlterRoot, self.File) + elif self.Root: + RealFile = os.path.join(self.Root, self.File) + return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile) ErrorCode = 0 ErrorInfo = '' @@ -1332,7 +1470,92 @@ class PathClass(object): return ErrorCode, ErrorInfo Key = property(_GetFileKey) + TimeStamp = property(_GetTimeStamp) +## Parse PE image to get the required PE informaion. +# +class PeImageClass(): + ## Constructor + # + # @param File FilePath of PeImage + # + def __init__(self, PeFile): + self.FileName = PeFile + self.IsValid = False + self.Size = 0 + self.EntryPoint = 0 + self.SectionAlignment = 0 + self.SectionHeaderList = [] + self.ErrorInfo = '' + try: + PeObject = open(PeFile, 'rb') + except: + self.ErrorInfo = self.FileName + ' can not be found\n' + return + # Read DOS header + ByteArray = array.array('B') + ByteArray.fromfile(PeObject, 0x3E) + ByteList = ByteArray.tolist() + # DOS signature should be 'MZ' + if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ': + self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ' + return + + # Read 4 byte PE Signature + PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E]) + PeObject.seek(PeOffset) + ByteArray = array.array('B') + ByteArray.fromfile(PeObject, 4) + # PE signature should be 'PE\0\0' + if ByteArray.tostring() != 'PE\0\0': + self.ErrorInfo = self.FileName + ' has no valid PE signature PE00' + return + + # Read PE file header + ByteArray = array.array('B') + ByteArray.fromfile(PeObject, 0x14) + ByteList = ByteArray.tolist() + SecNumber = self._ByteListToInt(ByteList[0x2:0x4]) + if SecNumber == 0: + self.ErrorInfo = self.FileName + ' has no section header' + return + + # Read PE optional header + OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12]) + ByteArray = array.array('B') + ByteArray.fromfile(PeObject, OptionalHeaderSize) + ByteList = ByteArray.tolist() + self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14]) + self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24]) + self.Size = self._ByteListToInt(ByteList[0x38:0x3C]) + + # Read each Section Header + for Index in range(SecNumber): + ByteArray = array.array('B') + ByteArray.fromfile(PeObject, 0x28) + ByteList = ByteArray.tolist() + SecName = self._ByteListToStr(ByteList[0:8]) + SecVirtualSize = self._ByteListToInt(ByteList[8:12]) + SecRawAddress = self._ByteListToInt(ByteList[20:24]) + SecVirtualAddress = self._ByteListToInt(ByteList[12:16]) + self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize)) + self.IsValid = True + PeObject.close() + + def _ByteListToStr(self, ByteList): + String = '' + for index in range(len(ByteList)): + if ByteList[index] == 0: + break + String += chr(ByteList[index]) + return String + + def _ByteListToInt(self, ByteList): + Value = 0 + for index in range(len(ByteList) - 1, -1, -1): + Value = (Value << 8) | int(ByteList[index]) + return Value + ## # # This acts like the main() function for the script, unless it is 'import'ed into another