1## @file 2# Common routines used by all tools 3# 4# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR> 5# This program and the accompanying materials 6# are licensed and made available under the terms and conditions of the BSD License 7# which accompanies this distribution. The full text of the license may be found at 8# http://opensource.org/licenses/bsd-license.php 9# 10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12# 13 14## 15# Import Modules 16# 17import Common.LongFilePathOs as os 18import sys 19import string 20import thread 21import threading 22import time 23import re 24import cPickle 25import array 26import shutil 27from struct import pack 28from UserDict import IterableUserDict 29from UserList import UserList 30 31from Common import EdkLogger as EdkLogger 32from Common import GlobalData as GlobalData 33from DataType import * 34from BuildToolError import * 35from CommonDataClass.DataClass import * 36from Parsing import GetSplitValueList 37from Common.LongFilePathSupport import OpenLongFilePath as open 38from Common.MultipleWorkspace import MultipleWorkspace as mws 39 40## Regular expression used to find out place holders in string template 41gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE | re.UNICODE) 42 43## Dictionary used to store file time stamp for quick re-access 44gFileTimeStampCache = {} # {file path : file time stamp} 45 46## Dictionary used to store dependencies of files 47gDependencyDatabase = {} # arch : {file path : [dependent files list]} 48 49def GetVariableOffset(mapfilepath, efifilepath, varnames): 50 """ Parse map file to get variable offset in current EFI file 51 @param mapfilepath Map file absolution path 52 @param efifilepath: EFI binary file full path 53 @param varnames iteratable container whose elements are variable names to be searched 54 55 @return List whos elements are tuple with variable name and raw offset 56 """ 57 lines = [] 58 try: 59 f = open(mapfilepath, 'r') 60 lines = f.readlines() 61 f.close() 62 except: 63 return None 64 65 if len(lines) == 0: return None 66 firstline = lines[0].strip() 67 if (firstline.startswith("Archive member included ") and 68 firstline.endswith(" file (symbol)")): 69 return _parseForGCC(lines, efifilepath, varnames) 70 return _parseGeneral(lines, efifilepath, varnames) 71 72def _parseForGCC(lines, efifilepath, varnames): 73 """ Parse map file generated by GCC linker """ 74 status = 0 75 sections = [] 76 varoffset = [] 77 for index, line in enumerate(lines): 78 line = line.strip() 79 # status machine transection 80 if status == 0 and line == "Memory Configuration": 81 status = 1 82 continue 83 elif status == 1 and line == 'Linker script and memory map': 84 status = 2 85 continue 86 elif status ==2 and line == 'START GROUP': 87 status = 3 88 continue 89 90 # status handler 91 if status == 3: 92 m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line) 93 if m != None: 94 sections.append(m.groups(0)) 95 for varname in varnames: 96 m = re.match(".data.(%s)$" % varname, line) 97 if m != None: 98 if lines[index + 1]: 99 m = re.match('^([\da-fA-Fx]+) +([\da-fA-Fx]+)', lines[index + 1].strip()) 100 if m != None: 101 varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0])) 102 103 if not varoffset: 104 return [] 105 # get section information from efi file 106 efisecs = PeImageClass(efifilepath).SectionHeaderList 107 if efisecs == None or len(efisecs) == 0: 108 return [] 109 #redirection 110 redirection = 0 111 for efisec in efisecs: 112 for section in sections: 113 if section[0].strip() == efisec[0].strip() and section[0].strip() == '.text': 114 redirection = int(section[1], 16) - efisec[1] 115 116 ret = [] 117 for var in varoffset: 118 for efisec in efisecs: 119 if var[1] >= efisec[1] and var[1] < efisec[1]+efisec[3]: 120 ret.append((var[0], hex(efisec[2] + var[1] - efisec[1] - redirection))) 121 return ret 122 123def _parseGeneral(lines, efifilepath, varnames): 124 status = 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table 125 secs = [] # key = section name 126 varoffset = [] 127 secRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE) 128 symRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE) 129 130 for line in lines: 131 line = line.strip() 132 if re.match("^Start[' ']+Length[' ']+Name[' ']+Class", line): 133 status = 1 134 continue 135 if re.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line): 136 status = 2 137 continue 138 if re.match("^entry point at", line): 139 status = 3 140 continue 141 if status == 1 and len(line) != 0: 142 m = secRe.match(line) 143 assert m != None, "Fail to parse the section in map file , line is %s" % line 144 sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0) 145 secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class]) 146 if status == 2 and len(line) != 0: 147 for varname in varnames: 148 m = symRe.match(line) 149 assert m != None, "Fail to parse the symbol in map file, line is %s" % line 150 sec_no, sym_offset, sym_name, vir_addr = m.groups(0) 151 sec_no = int(sec_no, 16) 152 sym_offset = int(sym_offset, 16) 153 vir_addr = int(vir_addr, 16) 154 m2 = re.match('^[_]*(%s)' % varname, sym_name) 155 if m2 != None: 156 # fond a binary pcd entry in map file 157 for sec in secs: 158 if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]): 159 varoffset.append([varname, sec[3], sym_offset, vir_addr, sec_no]) 160 161 if not varoffset: return [] 162 163 # get section information from efi file 164 efisecs = PeImageClass(efifilepath).SectionHeaderList 165 if efisecs == None or len(efisecs) == 0: 166 return [] 167 168 ret = [] 169 for var in varoffset: 170 index = 0 171 for efisec in efisecs: 172 index = index + 1 173 if var[1].strip() == efisec[0].strip(): 174 ret.append((var[0], hex(efisec[2] + var[2]))) 175 elif var[4] == index: 176 ret.append((var[0], hex(efisec[2] + var[2]))) 177 178 return ret 179 180## Routine to process duplicated INF 181# 182# This function is called by following two cases: 183# Case 1 in DSC: 184# [components.arch] 185# Pkg/module/module.inf 186# Pkg/module/module.inf { 187# <Defines> 188# FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836 189# } 190# Case 2 in FDF: 191# INF Pkg/module/module.inf 192# INF FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836 Pkg/module/module.inf 193# 194# This function copies Pkg/module/module.inf to 195# Conf/.cache/0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf 196# 197# @param Path Original PathClass object 198# @param BaseName New file base name 199# 200# @retval return the new PathClass object 201# 202def ProcessDuplicatedInf(Path, BaseName, Workspace): 203 Filename = os.path.split(Path.File)[1] 204 if '.' in Filename: 205 Filename = BaseName + Path.BaseName + Filename[Filename.rfind('.'):] 206 else: 207 Filename = BaseName + Path.BaseName 208 209 # 210 # If -N is specified on command line, cache is disabled 211 # The directory has to be created 212 # 213 DbDir = os.path.split(GlobalData.gDatabasePath)[0] 214 if not os.path.exists(DbDir): 215 os.makedirs(DbDir) 216 # 217 # A temporary INF is copied to database path which must have write permission 218 # The temporary will be removed at the end of build 219 # In case of name conflict, the file name is 220 # FILE_GUIDBaseName (0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf) 221 # 222 TempFullPath = os.path.join(DbDir, 223 Filename) 224 RtPath = PathClass(Path.File, Workspace) 225 # 226 # Modify the full path to temporary path, keep other unchanged 227 # 228 # To build same module more than once, the module path with FILE_GUID overridden has 229 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path 230 # in DSC which is used as relative path by C files and other files in INF. 231 # A trick was used: all module paths are PathClass instances, after the initialization 232 # of PathClass, the PathClass.Path is overridden by the temporary INF path. 233 # 234 # The reason for creating a temporary INF is: 235 # Platform.Modules which is the base to create ModuleAutoGen objects is a dictionary, 236 # the key is the full path of INF, the value is an object to save overridden library instances, PCDs. 237 # A different key for the same module is needed to create different output directory, 238 # retrieve overridden PCDs, library instances. 239 # 240 # The BaseName is the FILE_GUID which is also the output directory name. 241 # 242 # 243 RtPath.Path = TempFullPath 244 RtPath.BaseName = BaseName 245 # 246 # If file exists, compare contents 247 # 248 if os.path.exists(TempFullPath): 249 with open(str(Path), 'rb') as f1: Src = f1.read() 250 with open(TempFullPath, 'rb') as f2: Dst = f2.read() 251 if Src == Dst: 252 return RtPath 253 GlobalData.gTempInfs.append(TempFullPath) 254 shutil.copy2(str(Path), TempFullPath) 255 return RtPath 256 257## Remove temporary created INFs whose paths were saved in gTempInfs 258# 259def ClearDuplicatedInf(): 260 for File in GlobalData.gTempInfs: 261 if os.path.exists(File): 262 os.remove(File) 263 264## callback routine for processing variable option 265# 266# This function can be used to process variable number of option values. The 267# typical usage of it is specify architecure list on command line. 268# (e.g. <tool> -a IA32 X64 IPF) 269# 270# @param Option Standard callback function parameter 271# @param OptionString Standard callback function parameter 272# @param Value Standard callback function parameter 273# @param Parser Standard callback function parameter 274# 275# @retval 276# 277def ProcessVariableArgument(Option, OptionString, Value, Parser): 278 assert Value is None 279 Value = [] 280 RawArgs = Parser.rargs 281 while RawArgs: 282 Arg = RawArgs[0] 283 if (Arg[:2] == "--" and len(Arg) > 2) or \ 284 (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"): 285 break 286 Value.append(Arg) 287 del RawArgs[0] 288 setattr(Parser.values, Option.dest, Value) 289 290## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style 291# 292# @param Guid The GUID string 293# 294# @retval string The GUID string in C structure style 295# 296def GuidStringToGuidStructureString(Guid): 297 GuidList = Guid.split('-') 298 Result = '{' 299 for Index in range(0, 3, 1): 300 Result = Result + '0x' + GuidList[Index] + ', ' 301 Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4] 302 for Index in range(0, 12, 2): 303 Result = Result + ', 0x' + GuidList[4][Index:Index + 2] 304 Result += '}}' 305 return Result 306 307## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 308# 309# @param GuidValue The GUID value in byte array 310# 311# @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format 312# 313def GuidStructureByteArrayToGuidString(GuidValue): 314 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "") 315 guidValueList = guidValueString.split(",") 316 if len(guidValueList) != 16: 317 return '' 318 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue) 319 try: 320 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % ( 321 int(guidValueList[3], 16), 322 int(guidValueList[2], 16), 323 int(guidValueList[1], 16), 324 int(guidValueList[0], 16), 325 int(guidValueList[5], 16), 326 int(guidValueList[4], 16), 327 int(guidValueList[7], 16), 328 int(guidValueList[6], 16), 329 int(guidValueList[8], 16), 330 int(guidValueList[9], 16), 331 int(guidValueList[10], 16), 332 int(guidValueList[11], 16), 333 int(guidValueList[12], 16), 334 int(guidValueList[13], 16), 335 int(guidValueList[14], 16), 336 int(guidValueList[15], 16) 337 ) 338 except: 339 return '' 340 341## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 342# 343# @param GuidValue The GUID value in C structure format 344# 345# @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format 346# 347def GuidStructureStringToGuidString(GuidValue): 348 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "") 349 guidValueList = guidValueString.split(",") 350 if len(guidValueList) != 11: 351 return '' 352 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue) 353 try: 354 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % ( 355 int(guidValueList[0], 16), 356 int(guidValueList[1], 16), 357 int(guidValueList[2], 16), 358 int(guidValueList[3], 16), 359 int(guidValueList[4], 16), 360 int(guidValueList[5], 16), 361 int(guidValueList[6], 16), 362 int(guidValueList[7], 16), 363 int(guidValueList[8], 16), 364 int(guidValueList[9], 16), 365 int(guidValueList[10], 16) 366 ) 367 except: 368 return '' 369 370## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx 371# 372# @param GuidValue The GUID value in C structure format 373# 374# @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format 375# 376def GuidStructureStringToGuidValueName(GuidValue): 377 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "") 378 guidValueList = guidValueString.split(",") 379 if len(guidValueList) != 11: 380 EdkLogger.error(None, FORMAT_INVALID, "Invalid GUID value string [%s]" % GuidValue) 381 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % ( 382 int(guidValueList[0], 16), 383 int(guidValueList[1], 16), 384 int(guidValueList[2], 16), 385 int(guidValueList[3], 16), 386 int(guidValueList[4], 16), 387 int(guidValueList[5], 16), 388 int(guidValueList[6], 16), 389 int(guidValueList[7], 16), 390 int(guidValueList[8], 16), 391 int(guidValueList[9], 16), 392 int(guidValueList[10], 16) 393 ) 394 395## Create directories 396# 397# @param Directory The directory name 398# 399def CreateDirectory(Directory): 400 if Directory == None or Directory.strip() == "": 401 return True 402 try: 403 if not os.access(Directory, os.F_OK): 404 os.makedirs(Directory) 405 except: 406 return False 407 return True 408 409## Remove directories, including files and sub-directories in it 410# 411# @param Directory The directory name 412# 413def RemoveDirectory(Directory, Recursively=False): 414 if Directory == None or Directory.strip() == "" or not os.path.exists(Directory): 415 return 416 if Recursively: 417 CurrentDirectory = os.getcwd() 418 os.chdir(Directory) 419 for File in os.listdir("."): 420 if os.path.isdir(File): 421 RemoveDirectory(File, Recursively) 422 else: 423 os.remove(File) 424 os.chdir(CurrentDirectory) 425 os.rmdir(Directory) 426 427## Check if given file is changed or not 428# 429# This method is used to check if a file is changed or not between two build 430# actions. It makes use a cache to store files timestamp. 431# 432# @param File The path of file 433# 434# @retval True If the given file is changed, doesn't exist, or can't be 435# found in timestamp cache 436# @retval False If the given file is changed 437# 438def IsChanged(File): 439 if not os.path.exists(File): 440 return True 441 442 FileState = os.stat(File) 443 TimeStamp = FileState[-2] 444 445 if File in gFileTimeStampCache and TimeStamp == gFileTimeStampCache[File]: 446 FileChanged = False 447 else: 448 FileChanged = True 449 gFileTimeStampCache[File] = TimeStamp 450 451 return FileChanged 452 453## Store content in file 454# 455# This method is used to save file only when its content is changed. This is 456# quite useful for "make" system to decide what will be re-built and what won't. 457# 458# @param File The path of file 459# @param Content The new content of the file 460# @param IsBinaryFile The flag indicating if the file is binary file or not 461# 462# @retval True If the file content is changed and the file is renewed 463# @retval False If the file content is the same 464# 465def SaveFileOnChange(File, Content, IsBinaryFile=True): 466 if not IsBinaryFile: 467 Content = Content.replace("\n", os.linesep) 468 469 if os.path.exists(File): 470 try: 471 if Content == open(File, "rb").read(): 472 return False 473 except: 474 EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File) 475 476 DirName = os.path.dirname(File) 477 if not CreateDirectory(DirName): 478 EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName) 479 else: 480 if DirName == '': 481 DirName = os.getcwd() 482 if not os.access(DirName, os.W_OK): 483 EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName) 484 485 try: 486 if GlobalData.gIsWindows: 487 try: 488 from PyUtility import SaveFileToDisk 489 if not SaveFileToDisk(File, Content): 490 EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File) 491 except: 492 Fd = open(File, "wb") 493 Fd.write(Content) 494 Fd.close() 495 else: 496 Fd = open(File, "wb") 497 Fd.write(Content) 498 Fd.close() 499 except IOError, X: 500 EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X) 501 502 return True 503 504## Make a Python object persistent on file system 505# 506# @param Data The object to be stored in file 507# @param File The path of file to store the object 508# 509def DataDump(Data, File): 510 Fd = None 511 try: 512 Fd = open(File, 'wb') 513 cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL) 514 except: 515 EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False) 516 finally: 517 if Fd != None: 518 Fd.close() 519 520## Restore a Python object from a file 521# 522# @param File The path of file stored the object 523# 524# @retval object A python object 525# @retval None If failure in file operation 526# 527def DataRestore(File): 528 Data = None 529 Fd = None 530 try: 531 Fd = open(File, 'rb') 532 Data = cPickle.load(Fd) 533 except Exception, e: 534 EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e))) 535 Data = None 536 finally: 537 if Fd != None: 538 Fd.close() 539 return Data 540 541## Retrieve and cache the real path name in file system 542# 543# @param Root The root directory of path relative to 544# 545# @retval str The path string if the path exists 546# @retval None If path doesn't exist 547# 548class DirCache: 549 _CACHE_ = set() 550 _UPPER_CACHE_ = {} 551 552 def __init__(self, Root): 553 self._Root = Root 554 for F in os.listdir(Root): 555 self._CACHE_.add(F) 556 self._UPPER_CACHE_[F.upper()] = F 557 558 # =[] operator 559 def __getitem__(self, Path): 560 Path = Path[len(os.path.commonprefix([Path, self._Root])):] 561 if not Path: 562 return self._Root 563 if Path and Path[0] == os.path.sep: 564 Path = Path[1:] 565 if Path in self._CACHE_: 566 return os.path.join(self._Root, Path) 567 UpperPath = Path.upper() 568 if UpperPath in self._UPPER_CACHE_: 569 return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath]) 570 571 IndexList = [] 572 LastSepIndex = -1 573 SepIndex = Path.find(os.path.sep) 574 while SepIndex > -1: 575 Parent = UpperPath[:SepIndex] 576 if Parent not in self._UPPER_CACHE_: 577 break 578 LastSepIndex = SepIndex 579 SepIndex = Path.find(os.path.sep, LastSepIndex + 1) 580 581 if LastSepIndex == -1: 582 return None 583 584 Cwd = os.getcwd() 585 os.chdir(self._Root) 586 SepIndex = LastSepIndex 587 while SepIndex > -1: 588 Parent = Path[:SepIndex] 589 ParentKey = UpperPath[:SepIndex] 590 if ParentKey not in self._UPPER_CACHE_: 591 os.chdir(Cwd) 592 return None 593 594 if Parent in self._CACHE_: 595 ParentDir = Parent 596 else: 597 ParentDir = self._UPPER_CACHE_[ParentKey] 598 for F in os.listdir(ParentDir): 599 Dir = os.path.join(ParentDir, F) 600 self._CACHE_.add(Dir) 601 self._UPPER_CACHE_[Dir.upper()] = Dir 602 603 SepIndex = Path.find(os.path.sep, SepIndex + 1) 604 605 os.chdir(Cwd) 606 if Path in self._CACHE_: 607 return os.path.join(self._Root, Path) 608 elif UpperPath in self._UPPER_CACHE_: 609 return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath]) 610 return None 611 612## Get all files of a directory 613# 614# @param Root: Root dir 615# @param SkipList : The files need be skipped 616# 617# @retval A list of all files 618# 619def GetFiles(Root, SkipList=None, FullPath=True): 620 OriPath = Root 621 FileList = [] 622 for Root, Dirs, Files in os.walk(Root): 623 if SkipList: 624 for Item in SkipList: 625 if Item in Dirs: 626 Dirs.remove(Item) 627 628 for File in Files: 629 File = os.path.normpath(os.path.join(Root, File)) 630 if not FullPath: 631 File = File[len(OriPath) + 1:] 632 FileList.append(File) 633 634 return FileList 635 636## Check if gvien file exists or not 637# 638# @param File File name or path to be checked 639# @param Dir The directory the file is relative to 640# 641# @retval True if file exists 642# @retval False if file doesn't exists 643# 644def ValidFile(File, Ext=None): 645 if Ext != None: 646 Dummy, FileExt = os.path.splitext(File) 647 if FileExt.lower() != Ext.lower(): 648 return False 649 if not os.path.exists(File): 650 return False 651 return True 652 653def RealPath(File, Dir='', OverrideDir=''): 654 NewFile = os.path.normpath(os.path.join(Dir, File)) 655 NewFile = GlobalData.gAllFiles[NewFile] 656 if not NewFile and OverrideDir: 657 NewFile = os.path.normpath(os.path.join(OverrideDir, File)) 658 NewFile = GlobalData.gAllFiles[NewFile] 659 return NewFile 660 661def RealPath2(File, Dir='', OverrideDir=''): 662 NewFile = None 663 if OverrideDir: 664 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))] 665 if NewFile: 666 if OverrideDir[-1] == os.path.sep: 667 return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)] 668 else: 669 return NewFile[len(OverrideDir) + 1:], NewFile[0:len(OverrideDir)] 670 if GlobalData.gAllFiles: 671 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))] 672 if not NewFile: 673 NewFile = os.path.normpath(os.path.join(Dir, File)) 674 if not os.path.exists(NewFile): 675 return None, None 676 if NewFile: 677 if Dir: 678 if Dir[-1] == os.path.sep: 679 return NewFile[len(Dir):], NewFile[0:len(Dir)] 680 else: 681 return NewFile[len(Dir) + 1:], NewFile[0:len(Dir)] 682 else: 683 return NewFile, '' 684 685 return None, None 686 687## Check if gvien file exists or not 688# 689# 690def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): 691 NewFile = File 692 if Ext != None: 693 Dummy, FileExt = os.path.splitext(File) 694 if FileExt.lower() != Ext.lower(): 695 return False, File 696 697 # Replace the Edk macros 698 if OverrideDir != '' and OverrideDir != None: 699 if OverrideDir.find('$(EFI_SOURCE)') > -1: 700 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) 701 if OverrideDir.find('$(EDK_SOURCE)') > -1: 702 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource) 703 704 # Replace the default dir to current dir 705 if Dir == '.': 706 Dir = os.getcwd() 707 Dir = Dir[len(Workspace) + 1:] 708 709 # First check if File has Edk definition itself 710 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1: 711 NewFile = File.replace('$(EFI_SOURCE)', EfiSource) 712 NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource) 713 NewFile = AllFiles[os.path.normpath(NewFile)] 714 if NewFile != None: 715 return True, NewFile 716 717 # Second check the path with override value 718 if OverrideDir != '' and OverrideDir != None: 719 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))] 720 if NewFile != None: 721 return True, NewFile 722 723 # Last check the path with normal definitions 724 File = os.path.join(Dir, File) 725 NewFile = AllFiles[os.path.normpath(File)] 726 if NewFile != None: 727 return True, NewFile 728 729 return False, File 730 731## Check if gvien file exists or not 732# 733# 734def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''): 735 # Replace the Edk macros 736 if OverrideDir != '' and OverrideDir != None: 737 if OverrideDir.find('$(EFI_SOURCE)') > -1: 738 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource) 739 if OverrideDir.find('$(EDK_SOURCE)') > -1: 740 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource) 741 742 # Replace the default dir to current dir 743 # Dir is current module dir related to workspace 744 if Dir == '.': 745 Dir = os.getcwd() 746 Dir = Dir[len(Workspace) + 1:] 747 748 NewFile = File 749 RelaPath = AllFiles[os.path.normpath(Dir)] 750 NewRelaPath = RelaPath 751 752 while(True): 753 # First check if File has Edk definition itself 754 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1: 755 File = File.replace('$(EFI_SOURCE)', EfiSource) 756 File = File.replace('$(EDK_SOURCE)', EdkSource) 757 NewFile = AllFiles[os.path.normpath(File)] 758 if NewFile != None: 759 NewRelaPath = os.path.dirname(NewFile) 760 File = os.path.basename(NewFile) 761 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1] 762 break 763 764 # Second check the path with override value 765 if OverrideDir != '' and OverrideDir != None: 766 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))] 767 if NewFile != None: 768 #NewRelaPath = os.path.dirname(NewFile) 769 NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1] 770 break 771 772 # Last check the path with normal definitions 773 NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))] 774 if NewFile != None: 775 break 776 777 # No file found 778 break 779 780 return NewRelaPath, RelaPath, File 781 782 783def GetRelPath(Path1, Path2): 784 FileName = os.path.basename(Path2) 785 L1 = os.path.normpath(Path1).split(os.path.normpath('/')) 786 L2 = os.path.normpath(Path2).split(os.path.normpath('/')) 787 for Index in range(0, len(L1)): 788 if L1[Index] != L2[Index]: 789 FileName = '../' * (len(L1) - Index) 790 for Index2 in range(Index, len(L2)): 791 FileName = os.path.join(FileName, L2[Index2]) 792 break 793 return os.path.normpath(FileName) 794 795 796## Get GUID value from given packages 797# 798# @param CName The CName of the GUID 799# @param PackageList List of packages looking-up in 800# @param Inffile The driver file 801# 802# @retval GuidValue if the CName is found in any given package 803# @retval None if the CName is not found in all given packages 804# 805def GuidValue(CName, PackageList, Inffile = None): 806 for P in PackageList: 807 GuidKeys = P.Guids.keys() 808 if Inffile and P._PrivateGuids: 809 if not Inffile.startswith(P.MetaFile.Dir): 810 GuidKeys = (dict.fromkeys(x for x in P.Guids if x not in P._PrivateGuids)).keys() 811 if CName in GuidKeys: 812 return P.Guids[CName] 813 return None 814 815## Get Protocol value from given packages 816# 817# @param CName The CName of the GUID 818# @param PackageList List of packages looking-up in 819# @param Inffile The driver file 820# 821# @retval GuidValue if the CName is found in any given package 822# @retval None if the CName is not found in all given packages 823# 824def ProtocolValue(CName, PackageList, Inffile = None): 825 for P in PackageList: 826 ProtocolKeys = P.Protocols.keys() 827 if Inffile and P._PrivateProtocols: 828 if not Inffile.startswith(P.MetaFile.Dir): 829 ProtocolKeys = (dict.fromkeys(x for x in P.Protocols if x not in P._PrivateProtocols)).keys() 830 if CName in ProtocolKeys: 831 return P.Protocols[CName] 832 return None 833 834## Get PPI value from given packages 835# 836# @param CName The CName of the GUID 837# @param PackageList List of packages looking-up in 838# @param Inffile The driver file 839# 840# @retval GuidValue if the CName is found in any given package 841# @retval None if the CName is not found in all given packages 842# 843def PpiValue(CName, PackageList, Inffile = None): 844 for P in PackageList: 845 PpiKeys = P.Ppis.keys() 846 if Inffile and P._PrivatePpis: 847 if not Inffile.startswith(P.MetaFile.Dir): 848 PpiKeys = (dict.fromkeys(x for x in P.Ppis if x not in P._PrivatePpis)).keys() 849 if CName in PpiKeys: 850 return P.Ppis[CName] 851 return None 852 853## A string template class 854# 855# This class implements a template for string replacement. A string template 856# looks like following 857# 858# ${BEGIN} other_string ${placeholder_name} other_string ${END} 859# 860# The string between ${BEGIN} and ${END} will be repeated as many times as the 861# length of "placeholder_name", which is a list passed through a dict. The 862# "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can 863# be not used and, in this case, the "placeholder_name" must not a list and it 864# will just be replaced once. 865# 866class TemplateString(object): 867 _REPEAT_START_FLAG = "BEGIN" 868 _REPEAT_END_FLAG = "END" 869 870 class Section(object): 871 _LIST_TYPES = [type([]), type(set()), type((0,))] 872 873 def __init__(self, TemplateSection, PlaceHolderList): 874 self._Template = TemplateSection 875 self._PlaceHolderList = [] 876 877 # Split the section into sub-sections according to the position of placeholders 878 if PlaceHolderList: 879 self._SubSectionList = [] 880 SubSectionStart = 0 881 # 882 # The placeholders passed in must be in the format of 883 # 884 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint 885 # 886 for PlaceHolder, Start, End in PlaceHolderList: 887 self._SubSectionList.append(TemplateSection[SubSectionStart:Start]) 888 self._SubSectionList.append(TemplateSection[Start:End]) 889 self._PlaceHolderList.append(PlaceHolder) 890 SubSectionStart = End 891 if SubSectionStart < len(TemplateSection): 892 self._SubSectionList.append(TemplateSection[SubSectionStart:]) 893 else: 894 self._SubSectionList = [TemplateSection] 895 896 def __str__(self): 897 return self._Template + " : " + str(self._PlaceHolderList) 898 899 def Instantiate(self, PlaceHolderValues): 900 RepeatTime = -1 901 RepeatPlaceHolders = {} 902 NonRepeatPlaceHolders = {} 903 904 for PlaceHolder in self._PlaceHolderList: 905 if PlaceHolder not in PlaceHolderValues: 906 continue 907 Value = PlaceHolderValues[PlaceHolder] 908 if type(Value) in self._LIST_TYPES: 909 if RepeatTime < 0: 910 RepeatTime = len(Value) 911 elif RepeatTime != len(Value): 912 EdkLogger.error( 913 "TemplateString", 914 PARAMETER_INVALID, 915 "${%s} has different repeat time from others!" % PlaceHolder, 916 ExtraData=str(self._Template) 917 ) 918 RepeatPlaceHolders["${%s}" % PlaceHolder] = Value 919 else: 920 NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value 921 922 if NonRepeatPlaceHolders: 923 StringList = [] 924 for S in self._SubSectionList: 925 if S not in NonRepeatPlaceHolders: 926 StringList.append(S) 927 else: 928 StringList.append(str(NonRepeatPlaceHolders[S])) 929 else: 930 StringList = self._SubSectionList 931 932 if RepeatPlaceHolders: 933 TempStringList = [] 934 for Index in range(RepeatTime): 935 for S in StringList: 936 if S not in RepeatPlaceHolders: 937 TempStringList.append(S) 938 else: 939 TempStringList.append(str(RepeatPlaceHolders[S][Index])) 940 StringList = TempStringList 941 942 return "".join(StringList) 943 944 ## Constructor 945 def __init__(self, Template=None): 946 self.String = '' 947 self.IsBinary = False 948 self._Template = Template 949 self._TemplateSectionList = self._Parse(Template) 950 951 ## str() operator 952 # 953 # @retval string The string replaced 954 # 955 def __str__(self): 956 return self.String 957 958 ## Split the template string into fragments per the ${BEGIN} and ${END} flags 959 # 960 # @retval list A list of TemplateString.Section objects 961 # 962 def _Parse(self, Template): 963 SectionStart = 0 964 SearchFrom = 0 965 MatchEnd = 0 966 PlaceHolderList = [] 967 TemplateSectionList = [] 968 while Template: 969 MatchObj = gPlaceholderPattern.search(Template, SearchFrom) 970 if not MatchObj: 971 if MatchEnd <= len(Template): 972 TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList) 973 TemplateSectionList.append(TemplateSection) 974 break 975 976 MatchString = MatchObj.group(1) 977 MatchStart = MatchObj.start() 978 MatchEnd = MatchObj.end() 979 980 if MatchString == self._REPEAT_START_FLAG: 981 if MatchStart > SectionStart: 982 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList) 983 TemplateSectionList.append(TemplateSection) 984 SectionStart = MatchEnd 985 PlaceHolderList = [] 986 elif MatchString == self._REPEAT_END_FLAG: 987 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList) 988 TemplateSectionList.append(TemplateSection) 989 SectionStart = MatchEnd 990 PlaceHolderList = [] 991 else: 992 PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart)) 993 SearchFrom = MatchEnd 994 return TemplateSectionList 995 996 ## Replace the string template with dictionary of placeholders and append it to previous one 997 # 998 # @param AppendString The string template to append 999 # @param Dictionary The placeholder dictionaries 1000 # 1001 def Append(self, AppendString, Dictionary=None): 1002 if Dictionary: 1003 SectionList = self._Parse(AppendString) 1004 self.String += "".join([S.Instantiate(Dictionary) for S in SectionList]) 1005 else: 1006 self.String += AppendString 1007 1008 ## Replace the string template with dictionary of placeholders 1009 # 1010 # @param Dictionary The placeholder dictionaries 1011 # 1012 # @retval str The string replaced with placeholder values 1013 # 1014 def Replace(self, Dictionary=None): 1015 return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList]) 1016 1017## Progress indicator class 1018# 1019# This class makes use of thread to print progress on console. 1020# 1021class Progressor: 1022 # for avoiding deadloop 1023 _StopFlag = None 1024 _ProgressThread = None 1025 _CheckInterval = 0.25 1026 1027 ## Constructor 1028 # 1029 # @param OpenMessage The string printed before progress charaters 1030 # @param CloseMessage The string printed after progress charaters 1031 # @param ProgressChar The charater used to indicate the progress 1032 # @param Interval The interval in seconds between two progress charaters 1033 # 1034 def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0): 1035 self.PromptMessage = OpenMessage 1036 self.CodaMessage = CloseMessage 1037 self.ProgressChar = ProgressChar 1038 self.Interval = Interval 1039 if Progressor._StopFlag == None: 1040 Progressor._StopFlag = threading.Event() 1041 1042 ## Start to print progress charater 1043 # 1044 # @param OpenMessage The string printed before progress charaters 1045 # 1046 def Start(self, OpenMessage=None): 1047 if OpenMessage != None: 1048 self.PromptMessage = OpenMessage 1049 Progressor._StopFlag.clear() 1050 if Progressor._ProgressThread == None: 1051 Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry) 1052 Progressor._ProgressThread.setDaemon(False) 1053 Progressor._ProgressThread.start() 1054 1055 ## Stop printing progress charater 1056 # 1057 # @param CloseMessage The string printed after progress charaters 1058 # 1059 def Stop(self, CloseMessage=None): 1060 OriginalCodaMessage = self.CodaMessage 1061 if CloseMessage != None: 1062 self.CodaMessage = CloseMessage 1063 self.Abort() 1064 self.CodaMessage = OriginalCodaMessage 1065 1066 ## Thread entry method 1067 def _ProgressThreadEntry(self): 1068 sys.stdout.write(self.PromptMessage + " ") 1069 sys.stdout.flush() 1070 TimeUp = 0.0 1071 while not Progressor._StopFlag.isSet(): 1072 if TimeUp <= 0.0: 1073 sys.stdout.write(self.ProgressChar) 1074 sys.stdout.flush() 1075 TimeUp = self.Interval 1076 time.sleep(self._CheckInterval) 1077 TimeUp -= self._CheckInterval 1078 sys.stdout.write(" " + self.CodaMessage + "\n") 1079 sys.stdout.flush() 1080 1081 ## Abort the progress display 1082 @staticmethod 1083 def Abort(): 1084 if Progressor._StopFlag != None: 1085 Progressor._StopFlag.set() 1086 if Progressor._ProgressThread != None: 1087 Progressor._ProgressThread.join() 1088 Progressor._ProgressThread = None 1089 1090## A dict which can access its keys and/or values orderly 1091# 1092# The class implements a new kind of dict which its keys or values can be 1093# accessed in the order they are added into the dict. It guarantees the order 1094# by making use of an internal list to keep a copy of keys. 1095# 1096class sdict(IterableUserDict): 1097 ## Constructor 1098 def __init__(self): 1099 IterableUserDict.__init__(self) 1100 self._key_list = [] 1101 1102 ## [] operator 1103 def __setitem__(self, key, value): 1104 if key not in self._key_list: 1105 self._key_list.append(key) 1106 IterableUserDict.__setitem__(self, key, value) 1107 1108 ## del operator 1109 def __delitem__(self, key): 1110 self._key_list.remove(key) 1111 IterableUserDict.__delitem__(self, key) 1112 1113 ## used in "for k in dict" loop to ensure the correct order 1114 def __iter__(self): 1115 return self.iterkeys() 1116 1117 ## len() support 1118 def __len__(self): 1119 return len(self._key_list) 1120 1121 ## "in" test support 1122 def __contains__(self, key): 1123 return key in self._key_list 1124 1125 ## indexof support 1126 def index(self, key): 1127 return self._key_list.index(key) 1128 1129 ## insert support 1130 def insert(self, key, newkey, newvalue, order): 1131 index = self._key_list.index(key) 1132 if order == 'BEFORE': 1133 self._key_list.insert(index, newkey) 1134 IterableUserDict.__setitem__(self, newkey, newvalue) 1135 elif order == 'AFTER': 1136 self._key_list.insert(index + 1, newkey) 1137 IterableUserDict.__setitem__(self, newkey, newvalue) 1138 1139 ## append support 1140 def append(self, sdict): 1141 for key in sdict: 1142 if key not in self._key_list: 1143 self._key_list.append(key) 1144 IterableUserDict.__setitem__(self, key, sdict[key]) 1145 1146 def has_key(self, key): 1147 return key in self._key_list 1148 1149 ## Empty the dict 1150 def clear(self): 1151 self._key_list = [] 1152 IterableUserDict.clear(self) 1153 1154 ## Return a copy of keys 1155 def keys(self): 1156 keys = [] 1157 for key in self._key_list: 1158 keys.append(key) 1159 return keys 1160 1161 ## Return a copy of values 1162 def values(self): 1163 values = [] 1164 for key in self._key_list: 1165 values.append(self[key]) 1166 return values 1167 1168 ## Return a copy of (key, value) list 1169 def items(self): 1170 items = [] 1171 for key in self._key_list: 1172 items.append((key, self[key])) 1173 return items 1174 1175 ## Iteration support 1176 def iteritems(self): 1177 return iter(self.items()) 1178 1179 ## Keys interation support 1180 def iterkeys(self): 1181 return iter(self.keys()) 1182 1183 ## Values interation support 1184 def itervalues(self): 1185 return iter(self.values()) 1186 1187 ## Return value related to a key, and remove the (key, value) from the dict 1188 def pop(self, key, *dv): 1189 value = None 1190 if key in self._key_list: 1191 value = self[key] 1192 self.__delitem__(key) 1193 elif len(dv) != 0 : 1194 value = kv[0] 1195 return value 1196 1197 ## Return (key, value) pair, and remove the (key, value) from the dict 1198 def popitem(self): 1199 key = self._key_list[-1] 1200 value = self[key] 1201 self.__delitem__(key) 1202 return key, value 1203 1204 def update(self, dict=None, **kwargs): 1205 if dict != None: 1206 for k, v in dict.items(): 1207 self[k] = v 1208 if len(kwargs): 1209 for k, v in kwargs.items(): 1210 self[k] = v 1211 1212## Dictionary with restricted keys 1213# 1214class rdict(dict): 1215 ## Constructor 1216 def __init__(self, KeyList): 1217 for Key in KeyList: 1218 dict.__setitem__(self, Key, "") 1219 1220 ## []= operator 1221 def __setitem__(self, key, value): 1222 if key not in self: 1223 EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key, 1224 ExtraData=", ".join(dict.keys(self))) 1225 dict.__setitem__(self, key, value) 1226 1227 ## =[] operator 1228 def __getitem__(self, key): 1229 if key not in self: 1230 return "" 1231 return dict.__getitem__(self, key) 1232 1233 ## del operator 1234 def __delitem__(self, key): 1235 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del") 1236 1237 ## Empty the dict 1238 def clear(self): 1239 for Key in self: 1240 self.__setitem__(Key, "") 1241 1242 ## Return value related to a key, and remove the (key, value) from the dict 1243 def pop(self, key, *dv): 1244 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop") 1245 1246 ## Return (key, value) pair, and remove the (key, value) from the dict 1247 def popitem(self): 1248 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem") 1249 1250## Dictionary using prioritized list as key 1251# 1252class tdict: 1253 _ListType = type([]) 1254 _TupleType = type(()) 1255 _Wildcard = 'COMMON' 1256 _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM'] 1257 1258 def __init__(self, _Single_=False, _Level_=2): 1259 self._Level_ = _Level_ 1260 self.data = {} 1261 self._Single_ = _Single_ 1262 1263 # =[] operator 1264 def __getitem__(self, key): 1265 KeyType = type(key) 1266 RestKeys = None 1267 if KeyType == self._ListType or KeyType == self._TupleType: 1268 FirstKey = key[0] 1269 if len(key) > 1: 1270 RestKeys = key[1:] 1271 elif self._Level_ > 1: 1272 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)] 1273 else: 1274 FirstKey = key 1275 if self._Level_ > 1: 1276 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)] 1277 1278 if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList: 1279 FirstKey = self._Wildcard 1280 1281 if self._Single_: 1282 return self._GetSingleValue(FirstKey, RestKeys) 1283 else: 1284 return self._GetAllValues(FirstKey, RestKeys) 1285 1286 def _GetSingleValue(self, FirstKey, RestKeys): 1287 Value = None 1288 #print "%s-%s" % (FirstKey, self._Level_) , 1289 if self._Level_ > 1: 1290 if FirstKey == self._Wildcard: 1291 if FirstKey in self.data: 1292 Value = self.data[FirstKey][RestKeys] 1293 if Value == None: 1294 for Key in self.data: 1295 Value = self.data[Key][RestKeys] 1296 if Value != None: break 1297 else: 1298 if FirstKey in self.data: 1299 Value = self.data[FirstKey][RestKeys] 1300 if Value == None and self._Wildcard in self.data: 1301 #print "Value=None" 1302 Value = self.data[self._Wildcard][RestKeys] 1303 else: 1304 if FirstKey == self._Wildcard: 1305 if FirstKey in self.data: 1306 Value = self.data[FirstKey] 1307 if Value == None: 1308 for Key in self.data: 1309 Value = self.data[Key] 1310 if Value != None: break 1311 else: 1312 if FirstKey in self.data: 1313 Value = self.data[FirstKey] 1314 elif self._Wildcard in self.data: 1315 Value = self.data[self._Wildcard] 1316 return Value 1317 1318 def _GetAllValues(self, FirstKey, RestKeys): 1319 Value = [] 1320 if self._Level_ > 1: 1321 if FirstKey == self._Wildcard: 1322 for Key in self.data: 1323 Value += self.data[Key][RestKeys] 1324 else: 1325 if FirstKey in self.data: 1326 Value += self.data[FirstKey][RestKeys] 1327 if self._Wildcard in self.data: 1328 Value += self.data[self._Wildcard][RestKeys] 1329 else: 1330 if FirstKey == self._Wildcard: 1331 for Key in self.data: 1332 Value.append(self.data[Key]) 1333 else: 1334 if FirstKey in self.data: 1335 Value.append(self.data[FirstKey]) 1336 if self._Wildcard in self.data: 1337 Value.append(self.data[self._Wildcard]) 1338 return Value 1339 1340 ## []= operator 1341 def __setitem__(self, key, value): 1342 KeyType = type(key) 1343 RestKeys = None 1344 if KeyType == self._ListType or KeyType == self._TupleType: 1345 FirstKey = key[0] 1346 if len(key) > 1: 1347 RestKeys = key[1:] 1348 else: 1349 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)] 1350 else: 1351 FirstKey = key 1352 if self._Level_ > 1: 1353 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)] 1354 1355 if FirstKey in self._ValidWildcardList: 1356 FirstKey = self._Wildcard 1357 1358 if FirstKey not in self.data and self._Level_ > 0: 1359 self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1) 1360 1361 if self._Level_ > 1: 1362 self.data[FirstKey][RestKeys] = value 1363 else: 1364 self.data[FirstKey] = value 1365 1366 def SetGreedyMode(self): 1367 self._Single_ = False 1368 if self._Level_ > 1: 1369 for Key in self.data: 1370 self.data[Key].SetGreedyMode() 1371 1372 def SetSingleMode(self): 1373 self._Single_ = True 1374 if self._Level_ > 1: 1375 for Key in self.data: 1376 self.data[Key].SetSingleMode() 1377 1378 def GetKeys(self, KeyIndex=0): 1379 assert KeyIndex >= 0 1380 if KeyIndex == 0: 1381 return set(self.data.keys()) 1382 else: 1383 keys = set() 1384 for Key in self.data: 1385 keys |= self.data[Key].GetKeys(KeyIndex - 1) 1386 return keys 1387 1388## Boolean chain list 1389# 1390class Blist(UserList): 1391 def __init__(self, initlist=None): 1392 UserList.__init__(self, initlist) 1393 def __setitem__(self, i, item): 1394 if item not in [True, False]: 1395 if item == 0: 1396 item = False 1397 else: 1398 item = True 1399 self.data[i] = item 1400 def _GetResult(self): 1401 Value = True 1402 for item in self.data: 1403 Value &= item 1404 return Value 1405 Result = property(_GetResult) 1406 1407def ParseConsoleLog(Filename): 1408 Opr = open(os.path.normpath(Filename), 'r') 1409 Opw = open(os.path.normpath(Filename + '.New'), 'w+') 1410 for Line in Opr.readlines(): 1411 if Line.find('.efi') > -1: 1412 Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip() 1413 Opw.write('%s\n' % Line) 1414 1415 Opr.close() 1416 Opw.close() 1417 1418def AnalyzePcdExpression(Setting): 1419 Setting = Setting.strip() 1420 # There might be escaped quote in a string: \", \\\" 1421 Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'') 1422 # There might be '|' in string and in ( ... | ... ), replace it with '-' 1423 NewStr = '' 1424 InStr = False 1425 Pair = 0 1426 for ch in Data: 1427 if ch == '"': 1428 InStr = not InStr 1429 elif ch == '(' and not InStr: 1430 Pair += 1 1431 elif ch == ')' and not InStr: 1432 Pair -= 1 1433 1434 if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT: 1435 NewStr += '-' 1436 else: 1437 NewStr += ch 1438 FieldList = [] 1439 StartPos = 0 1440 while True: 1441 Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos) 1442 if Pos < 0: 1443 FieldList.append(Setting[StartPos:].strip()) 1444 break 1445 FieldList.append(Setting[StartPos:Pos].strip()) 1446 StartPos = Pos + 1 1447 1448 return FieldList 1449 1450## AnalyzeDscPcd 1451# 1452# Analyze DSC PCD value, since there is no data type info in DSC 1453# This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database 1454# 1. Feature flag: TokenSpace.PcdCName|PcdValue 1455# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize] 1456# 3. Dynamic default: 1457# TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]] 1458# TokenSpace.PcdCName|PcdValue 1459# 4. Dynamic VPD: 1460# TokenSpace.PcdCName|VpdOffset[|VpdValue] 1461# TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]] 1462# 5. Dynamic HII: 1463# TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue] 1464# PCD value needs to be located in such kind of string, and the PCD value might be an expression in which 1465# there might have "|" operator, also in string value. 1466# 1467# @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped 1468# @param PcdType: PCD type: feature, fixed, dynamic default VPD HII 1469# @param DataType: The datum type of PCD: VOID*, UNIT, BOOL 1470# @retval: 1471# ValueList: A List contain fields described above 1472# IsValid: True if conforming EBNF, otherwise False 1473# Index: The index where PcdValue is in ValueList 1474# 1475def AnalyzeDscPcd(Setting, PcdType, DataType=''): 1476 FieldList = AnalyzePcdExpression(Setting) 1477 1478 IsValid = True 1479 if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG): 1480 Value = FieldList[0] 1481 Size = '' 1482 if len(FieldList) > 1: 1483 Type = FieldList[1] 1484 # Fix the PCD type when no DataType input 1485 if Type == 'VOID*': 1486 DataType = 'VOID*' 1487 else: 1488 Size = FieldList[1] 1489 if len(FieldList) > 2: 1490 Size = FieldList[2] 1491 if DataType == 'VOID*': 1492 IsValid = (len(FieldList) <= 3) 1493 else: 1494 IsValid = (len(FieldList) <= 1) 1495 return [Value, '', Size], IsValid, 0 1496 elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT): 1497 Value = FieldList[0] 1498 Size = Type = '' 1499 if len(FieldList) > 1: 1500 Type = FieldList[1] 1501 else: 1502 Type = DataType 1503 if len(FieldList) > 2: 1504 Size = FieldList[2] 1505 else: 1506 if Type == 'VOID*': 1507 if Value.startswith("L"): 1508 Size = str((len(Value)- 3 + 1) * 2) 1509 elif Value.startswith("{"): 1510 Size = str(len(Value.split(","))) 1511 else: 1512 Size = str(len(Value) -2 + 1 ) 1513 if DataType == 'VOID*': 1514 IsValid = (len(FieldList) <= 3) 1515 else: 1516 IsValid = (len(FieldList) <= 1) 1517 return [Value, Type, Size], IsValid, 0 1518 elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD): 1519 VpdOffset = FieldList[0] 1520 Value = Size = '' 1521 if not DataType == 'VOID*': 1522 if len(FieldList) > 1: 1523 Value = FieldList[1] 1524 else: 1525 if len(FieldList) > 1: 1526 Size = FieldList[1] 1527 if len(FieldList) > 2: 1528 Value = FieldList[2] 1529 if DataType == 'VOID*': 1530 IsValid = (len(FieldList) <= 3) 1531 else: 1532 IsValid = (len(FieldList) <= 2) 1533 return [VpdOffset, Size, Value], IsValid, 2 1534 elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII): 1535 HiiString = FieldList[0] 1536 Guid = Offset = Value = Attribute = '' 1537 if len(FieldList) > 1: 1538 Guid = FieldList[1] 1539 if len(FieldList) > 2: 1540 Offset = FieldList[2] 1541 if len(FieldList) > 3: 1542 Value = FieldList[3] 1543 if len(FieldList) > 4: 1544 Attribute = FieldList[4] 1545 IsValid = (3 <= len(FieldList) <= 5) 1546 return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3 1547 return [], False, 0 1548 1549## AnalyzePcdData 1550# 1551# Analyze the pcd Value, Datum type and TokenNumber. 1552# Used to avoid split issue while the value string contain "|" character 1553# 1554# @param[in] Setting: A String contain value/datum type/token number information; 1555# 1556# @retval ValueList: A List contain value, datum type and toke number. 1557# 1558def AnalyzePcdData(Setting): 1559 ValueList = ['', '', ''] 1560 1561 ValueRe = re.compile(r'^\s*L?\".*\|.*\"') 1562 PtrValue = ValueRe.findall(Setting) 1563 1564 ValueUpdateFlag = False 1565 1566 if len(PtrValue) >= 1: 1567 Setting = re.sub(ValueRe, '', Setting) 1568 ValueUpdateFlag = True 1569 1570 TokenList = Setting.split(TAB_VALUE_SPLIT) 1571 ValueList[0:len(TokenList)] = TokenList 1572 1573 if ValueUpdateFlag: 1574 ValueList[0] = PtrValue[0] 1575 1576 return ValueList 1577 1578## AnalyzeHiiPcdData 1579# 1580# Analyze the pcd Value, variable name, variable Guid and variable offset. 1581# Used to avoid split issue while the value string contain "|" character 1582# 1583# @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information; 1584# 1585# @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue. 1586# 1587def AnalyzeHiiPcdData(Setting): 1588 ValueList = ['', '', '', ''] 1589 1590 TokenList = GetSplitValueList(Setting) 1591 ValueList[0:len(TokenList)] = TokenList 1592 1593 return ValueList 1594 1595## AnalyzeVpdPcdData 1596# 1597# Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue. 1598# Used to avoid split issue while the value string contain "|" character 1599# 1600# @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information; 1601# 1602# @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue. 1603# 1604def AnalyzeVpdPcdData(Setting): 1605 ValueList = ['', '', ''] 1606 1607 ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$') 1608 PtrValue = ValueRe.findall(Setting) 1609 1610 ValueUpdateFlag = False 1611 1612 if len(PtrValue) >= 1: 1613 Setting = re.sub(ValueRe, '', Setting) 1614 ValueUpdateFlag = True 1615 1616 TokenList = Setting.split(TAB_VALUE_SPLIT) 1617 ValueList[0:len(TokenList)] = TokenList 1618 1619 if ValueUpdateFlag: 1620 ValueList[2] = PtrValue[0] 1621 1622 return ValueList 1623 1624## check format of PCD value against its the datum type 1625# 1626# For PCD value setting 1627# 1628def CheckPcdDatum(Type, Value): 1629 if Type == "VOID*": 1630 ValueRe = re.compile(r'\s*L?\".*\"\s*$') 1631 if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"')) 1632 or (Value.startswith('{') and Value.endswith('}')) 1633 ): 1634 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\ 1635 ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type) 1636 elif ValueRe.match(Value): 1637 # Check the chars in UnicodeString or CString is printable 1638 if Value.startswith("L"): 1639 Value = Value[2:-1] 1640 else: 1641 Value = Value[1:-1] 1642 Printset = set(string.printable) 1643 Printset.remove(TAB_PRINTCHAR_VT) 1644 Printset.add(TAB_PRINTCHAR_BS) 1645 Printset.add(TAB_PRINTCHAR_NUL) 1646 if not set(Value).issubset(Printset): 1647 PrintList = list(Printset) 1648 PrintList.sort() 1649 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList) 1650 elif Type == 'BOOLEAN': 1651 if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']: 1652 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\ 1653 ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type) 1654 elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]: 1655 try: 1656 Value = long(Value, 0) 1657 except: 1658 return False, "Invalid value [%s] of type [%s];"\ 1659 " must be a hexadecimal, decimal or octal in C language format." % (Value, Type) 1660 else: 1661 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type) 1662 1663 return True, "" 1664 1665## Split command line option string to list 1666# 1667# subprocess.Popen needs the args to be a sequence. Otherwise there's problem 1668# in non-windows platform to launch command 1669# 1670def SplitOption(OptionString): 1671 OptionList = [] 1672 LastChar = " " 1673 OptionStart = 0 1674 QuotationMark = "" 1675 for Index in range(0, len(OptionString)): 1676 CurrentChar = OptionString[Index] 1677 if CurrentChar in ['"', "'"]: 1678 if QuotationMark == CurrentChar: 1679 QuotationMark = "" 1680 elif QuotationMark == "": 1681 QuotationMark = CurrentChar 1682 continue 1683 elif QuotationMark: 1684 continue 1685 1686 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]: 1687 if Index > OptionStart: 1688 OptionList.append(OptionString[OptionStart:Index - 1]) 1689 OptionStart = Index 1690 LastChar = CurrentChar 1691 OptionList.append(OptionString[OptionStart:]) 1692 return OptionList 1693 1694def CommonPath(PathList): 1695 P1 = min(PathList).split(os.path.sep) 1696 P2 = max(PathList).split(os.path.sep) 1697 for Index in xrange(min(len(P1), len(P2))): 1698 if P1[Index] != P2[Index]: 1699 return os.path.sep.join(P1[:Index]) 1700 return os.path.sep.join(P1) 1701 1702# 1703# Convert string to C format array 1704# 1705def ConvertStringToByteArray(Value): 1706 Value = Value.strip() 1707 if not Value: 1708 return None 1709 if Value[0] == '{': 1710 if not Value.endswith('}'): 1711 return None 1712 Value = Value.replace(' ', '').replace('{', '').replace('}', '') 1713 ValFields = Value.split(',') 1714 try: 1715 for Index in range(len(ValFields)): 1716 ValFields[Index] = str(int(ValFields[Index], 0)) 1717 except ValueError: 1718 return None 1719 Value = '{' + ','.join(ValFields) + '}' 1720 return Value 1721 1722 Unicode = False 1723 if Value.startswith('L"'): 1724 if not Value.endswith('"'): 1725 return None 1726 Value = Value[1:] 1727 Unicode = True 1728 elif not Value.startswith('"') or not Value.endswith('"'): 1729 return None 1730 1731 Value = eval(Value) # translate escape character 1732 NewValue = '{' 1733 for Index in range(0,len(Value)): 1734 if Unicode: 1735 NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ',' 1736 else: 1737 NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ',' 1738 Value = NewValue + '0}' 1739 return Value 1740 1741class PathClass(object): 1742 def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False, 1743 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''): 1744 self.Arch = Arch 1745 self.File = str(File) 1746 if os.path.isabs(self.File): 1747 self.Root = '' 1748 self.AlterRoot = '' 1749 else: 1750 self.Root = str(Root) 1751 self.AlterRoot = str(AlterRoot) 1752 1753 # Remove any '.' and '..' in path 1754 if self.Root: 1755 self.Root = mws.getWs(self.Root, self.File) 1756 self.Path = os.path.normpath(os.path.join(self.Root, self.File)) 1757 self.Root = os.path.normpath(CommonPath([self.Root, self.Path])) 1758 # eliminate the side-effect of 'C:' 1759 if self.Root[-1] == ':': 1760 self.Root += os.path.sep 1761 # file path should not start with path separator 1762 if self.Root[-1] == os.path.sep: 1763 self.File = self.Path[len(self.Root):] 1764 else: 1765 self.File = self.Path[len(self.Root) + 1:] 1766 else: 1767 self.Path = os.path.normpath(self.File) 1768 1769 self.SubDir, self.Name = os.path.split(self.File) 1770 self.BaseName, self.Ext = os.path.splitext(self.Name) 1771 1772 if self.Root: 1773 if self.SubDir: 1774 self.Dir = os.path.join(self.Root, self.SubDir) 1775 else: 1776 self.Dir = self.Root 1777 else: 1778 self.Dir = self.SubDir 1779 1780 if IsBinary: 1781 self.Type = Type 1782 else: 1783 self.Type = self.Ext.lower() 1784 1785 self.IsBinary = IsBinary 1786 self.Target = Target 1787 self.TagName = TagName 1788 self.ToolCode = ToolCode 1789 self.ToolChainFamily = ToolChainFamily 1790 1791 self._Key = None 1792 1793 ## Convert the object of this class to a string 1794 # 1795 # Convert member Path of the class to a string 1796 # 1797 # @retval string Formatted String 1798 # 1799 def __str__(self): 1800 return self.Path 1801 1802 ## Override __eq__ function 1803 # 1804 # Check whether PathClass are the same 1805 # 1806 # @retval False The two PathClass are different 1807 # @retval True The two PathClass are the same 1808 # 1809 def __eq__(self, Other): 1810 if type(Other) == type(self): 1811 return self.Path == Other.Path 1812 else: 1813 return self.Path == str(Other) 1814 1815 ## Override __cmp__ function 1816 # 1817 # Customize the comparsion operation of two PathClass 1818 # 1819 # @retval 0 The two PathClass are different 1820 # @retval -1 The first PathClass is less than the second PathClass 1821 # @retval 1 The first PathClass is Bigger than the second PathClass 1822 def __cmp__(self, Other): 1823 if type(Other) == type(self): 1824 OtherKey = Other.Path 1825 else: 1826 OtherKey = str(Other) 1827 1828 SelfKey = self.Path 1829 if SelfKey == OtherKey: 1830 return 0 1831 elif SelfKey > OtherKey: 1832 return 1 1833 else: 1834 return -1 1835 1836 ## Override __hash__ function 1837 # 1838 # Use Path as key in hash table 1839 # 1840 # @retval string Key for hash table 1841 # 1842 def __hash__(self): 1843 return hash(self.Path) 1844 1845 def _GetFileKey(self): 1846 if self._Key == None: 1847 self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target 1848 return self._Key 1849 1850 def _GetTimeStamp(self): 1851 return os.stat(self.Path)[8] 1852 1853 def Validate(self, Type='', CaseSensitive=True): 1854 if GlobalData.gCaseInsensitive: 1855 CaseSensitive = False 1856 if Type and Type.lower() != self.Type: 1857 return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type) 1858 1859 RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot) 1860 if not RealRoot and not RealFile: 1861 RealFile = self.File 1862 if self.AlterRoot: 1863 RealFile = os.path.join(self.AlterRoot, self.File) 1864 elif self.Root: 1865 RealFile = os.path.join(self.Root, self.File) 1866 if len (mws.getPkgPath()) == 0: 1867 return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile) 1868 else: 1869 return FILE_NOT_FOUND, "%s is not found in packages path:\n\t%s" % (self.File, '\n\t'.join(mws.getPkgPath())) 1870 1871 ErrorCode = 0 1872 ErrorInfo = '' 1873 if RealRoot != self.Root or RealFile != self.File: 1874 if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)): 1875 ErrorCode = FILE_CASE_MISMATCH 1876 ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]" 1877 1878 self.SubDir, self.Name = os.path.split(RealFile) 1879 self.BaseName, self.Ext = os.path.splitext(self.Name) 1880 if self.SubDir: 1881 self.Dir = os.path.join(RealRoot, self.SubDir) 1882 else: 1883 self.Dir = RealRoot 1884 self.File = RealFile 1885 self.Root = RealRoot 1886 self.Path = os.path.join(RealRoot, RealFile) 1887 return ErrorCode, ErrorInfo 1888 1889 Key = property(_GetFileKey) 1890 TimeStamp = property(_GetTimeStamp) 1891 1892## Parse PE image to get the required PE informaion. 1893# 1894class PeImageClass(): 1895 ## Constructor 1896 # 1897 # @param File FilePath of PeImage 1898 # 1899 def __init__(self, PeFile): 1900 self.FileName = PeFile 1901 self.IsValid = False 1902 self.Size = 0 1903 self.EntryPoint = 0 1904 self.SectionAlignment = 0 1905 self.SectionHeaderList = [] 1906 self.ErrorInfo = '' 1907 try: 1908 PeObject = open(PeFile, 'rb') 1909 except: 1910 self.ErrorInfo = self.FileName + ' can not be found\n' 1911 return 1912 # Read DOS header 1913 ByteArray = array.array('B') 1914 ByteArray.fromfile(PeObject, 0x3E) 1915 ByteList = ByteArray.tolist() 1916 # DOS signature should be 'MZ' 1917 if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ': 1918 self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ' 1919 return 1920 1921 # Read 4 byte PE Signature 1922 PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E]) 1923 PeObject.seek(PeOffset) 1924 ByteArray = array.array('B') 1925 ByteArray.fromfile(PeObject, 4) 1926 # PE signature should be 'PE\0\0' 1927 if ByteArray.tostring() != 'PE\0\0': 1928 self.ErrorInfo = self.FileName + ' has no valid PE signature PE00' 1929 return 1930 1931 # Read PE file header 1932 ByteArray = array.array('B') 1933 ByteArray.fromfile(PeObject, 0x14) 1934 ByteList = ByteArray.tolist() 1935 SecNumber = self._ByteListToInt(ByteList[0x2:0x4]) 1936 if SecNumber == 0: 1937 self.ErrorInfo = self.FileName + ' has no section header' 1938 return 1939 1940 # Read PE optional header 1941 OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12]) 1942 ByteArray = array.array('B') 1943 ByteArray.fromfile(PeObject, OptionalHeaderSize) 1944 ByteList = ByteArray.tolist() 1945 self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14]) 1946 self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24]) 1947 self.Size = self._ByteListToInt(ByteList[0x38:0x3C]) 1948 1949 # Read each Section Header 1950 for Index in range(SecNumber): 1951 ByteArray = array.array('B') 1952 ByteArray.fromfile(PeObject, 0x28) 1953 ByteList = ByteArray.tolist() 1954 SecName = self._ByteListToStr(ByteList[0:8]) 1955 SecVirtualSize = self._ByteListToInt(ByteList[8:12]) 1956 SecRawAddress = self._ByteListToInt(ByteList[20:24]) 1957 SecVirtualAddress = self._ByteListToInt(ByteList[12:16]) 1958 self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize)) 1959 self.IsValid = True 1960 PeObject.close() 1961 1962 def _ByteListToStr(self, ByteList): 1963 String = '' 1964 for index in range(len(ByteList)): 1965 if ByteList[index] == 0: 1966 break 1967 String += chr(ByteList[index]) 1968 return String 1969 1970 def _ByteListToInt(self, ByteList): 1971 Value = 0 1972 for index in range(len(ByteList) - 1, -1, -1): 1973 Value = (Value << 8) | int(ByteList[index]) 1974 return Value 1975 1976 1977class SkuClass(): 1978 1979 DEFAULT = 0 1980 SINGLE = 1 1981 MULTIPLE =2 1982 1983 def __init__(self,SkuIdentifier='', SkuIds={}): 1984 1985 self.AvailableSkuIds = sdict() 1986 self.SkuIdSet = [] 1987 self.SkuIdNumberSet = [] 1988 if SkuIdentifier == '' or SkuIdentifier is None: 1989 self.SkuIdSet = ['DEFAULT'] 1990 self.SkuIdNumberSet = ['0U'] 1991 elif SkuIdentifier == 'ALL': 1992 self.SkuIdSet = SkuIds.keys() 1993 self.SkuIdNumberSet = [num.strip() + 'U' for num in SkuIds.values()] 1994 else: 1995 r = SkuIdentifier.split('|') 1996 self.SkuIdSet=[r[k].strip() for k in range(len(r))] 1997 k = None 1998 try: 1999 self.SkuIdNumberSet = [SkuIds[k].strip() + 'U' for k in self.SkuIdSet] 2000 except Exception: 2001 EdkLogger.error("build", PARAMETER_INVALID, 2002 ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]" 2003 % (k, " ".join(SkuIds.keys()))) 2004 if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL': 2005 self.SkuIdSet.remove('DEFAULT') 2006 self.SkuIdNumberSet.remove('0U') 2007 for each in self.SkuIdSet: 2008 if each in SkuIds: 2009 self.AvailableSkuIds[each] = SkuIds[each] 2010 else: 2011 EdkLogger.error("build", PARAMETER_INVALID, 2012 ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]" 2013 % (each, " ".join(SkuIds.keys()))) 2014 2015 def __SkuUsageType(self): 2016 2017 if len(self.SkuIdSet) == 1: 2018 if self.SkuIdSet[0] == 'DEFAULT': 2019 return SkuClass.DEFAULT 2020 else: 2021 return SkuClass.SINGLE 2022 else: 2023 return SkuClass.MULTIPLE 2024 2025 def __GetAvailableSkuIds(self): 2026 return self.AvailableSkuIds 2027 2028 def __GetSystemSkuID(self): 2029 if self.__SkuUsageType() == SkuClass.SINGLE: 2030 return self.SkuIdSet[0] 2031 else: 2032 return 'DEFAULT' 2033 def __GetAvailableSkuIdNumber(self): 2034 return self.SkuIdNumberSet 2035 SystemSkuId = property(__GetSystemSkuID) 2036 AvailableSkuIdSet = property(__GetAvailableSkuIds) 2037 SkuUsageType = property(__SkuUsageType) 2038 AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber) 2039 2040# 2041# Pack a registry format GUID 2042# 2043def PackRegistryFormatGuid(Guid): 2044 Guid = Guid.split('-') 2045 return pack('=LHHBBBBBBBB', 2046 int(Guid[0], 16), 2047 int(Guid[1], 16), 2048 int(Guid[2], 16), 2049 int(Guid[3][-4:-2], 16), 2050 int(Guid[3][-2:], 16), 2051 int(Guid[4][-12:-10], 16), 2052 int(Guid[4][-10:-8], 16), 2053 int(Guid[4][-8:-6], 16), 2054 int(Guid[4][-6:-4], 16), 2055 int(Guid[4][-4:-2], 16), 2056 int(Guid[4][-2:], 16) 2057 ) 2058 2059## 2060# 2061# This acts like the main() function for the script, unless it is 'import'ed into another 2062# script. 2063# 2064if __name__ == '__main__': 2065 pass 2066 2067