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