]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
Sync BaseTool trunk (version r2460) into EDKII BaseTools. The change mainly includes:
[mirror_edk2.git] / BaseTools / Source / Python / Common / Misc.py
1 ## @file
2 # Common routines used by all tools
3 #
4 # Copyright (c) 2007 - 2010, 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 #
17 import os
18 import sys
19 import string
20 import thread
21 import threading
22 import time
23 import re
24 import cPickle
25 import array
26 from UserDict import IterableUserDict
27 from UserList import UserList
28
29 from Common import EdkLogger as EdkLogger
30 from Common import GlobalData as GlobalData
31 from DataType import *
32 from BuildToolError import *
33
34 ## Regular expression used to find out place holders in string template
35 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE)
36
37 ## Dictionary used to store file time stamp for quick re-access
38 gFileTimeStampCache = {} # {file path : file time stamp}
39
40 ## Dictionary used to store dependencies of files
41 gDependencyDatabase = {} # arch : {file path : [dependent files list]}
42
43 ## callback routine for processing variable option
44 #
45 # This function can be used to process variable number of option values. The
46 # typical usage of it is specify architecure list on command line.
47 # (e.g. <tool> -a IA32 X64 IPF)
48 #
49 # @param Option Standard callback function parameter
50 # @param OptionString Standard callback function parameter
51 # @param Value Standard callback function parameter
52 # @param Parser Standard callback function parameter
53 #
54 # @retval
55 #
56 def ProcessVariableArgument(Option, OptionString, Value, Parser):
57 assert Value is None
58 Value = []
59 RawArgs = Parser.rargs
60 while RawArgs:
61 Arg = RawArgs[0]
62 if (Arg[:2] == "--" and len(Arg) > 2) or \
63 (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"):
64 break
65 Value.append(Arg)
66 del RawArgs[0]
67 setattr(Parser.values, Option.dest, Value)
68
69 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
70 #
71 # @param Guid The GUID string
72 #
73 # @retval string The GUID string in C structure style
74 #
75 def GuidStringToGuidStructureString(Guid):
76 GuidList = Guid.split('-')
77 Result = '{'
78 for Index in range(0,3,1):
79 Result = Result + '0x' + GuidList[Index] + ', '
80 Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]
81 for Index in range(0,12,2):
82 Result = Result + ', 0x' + GuidList[4][Index:Index+2]
83 Result += '}}'
84 return Result
85
86 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
87 #
88 # @param GuidValue The GUID value in byte array
89 #
90 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
91 #
92 def GuidStructureByteArrayToGuidString(GuidValue):
93 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
94 guidValueList = guidValueString.split(",")
95 if len(guidValueList) != 16:
96 return ''
97 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
98 try:
99 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
100 int(guidValueList[3], 16),
101 int(guidValueList[2], 16),
102 int(guidValueList[1], 16),
103 int(guidValueList[0], 16),
104 int(guidValueList[5], 16),
105 int(guidValueList[4], 16),
106 int(guidValueList[7], 16),
107 int(guidValueList[6], 16),
108 int(guidValueList[8], 16),
109 int(guidValueList[9], 16),
110 int(guidValueList[10], 16),
111 int(guidValueList[11], 16),
112 int(guidValueList[12], 16),
113 int(guidValueList[13], 16),
114 int(guidValueList[14], 16),
115 int(guidValueList[15], 16)
116 )
117 except:
118 return ''
119
120 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
121 #
122 # @param GuidValue The GUID value in C structure format
123 #
124 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
125 #
126 def GuidStructureStringToGuidString(GuidValue):
127 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
128 guidValueList = guidValueString.split(",")
129 if len(guidValueList) != 11:
130 return ''
131 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
132 try:
133 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
134 int(guidValueList[0], 16),
135 int(guidValueList[1], 16),
136 int(guidValueList[2], 16),
137 int(guidValueList[3], 16),
138 int(guidValueList[4], 16),
139 int(guidValueList[5], 16),
140 int(guidValueList[6], 16),
141 int(guidValueList[7], 16),
142 int(guidValueList[8], 16),
143 int(guidValueList[9], 16),
144 int(guidValueList[10], 16)
145 )
146 except:
147 return ''
148
149 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
150 #
151 # @param GuidValue The GUID value in C structure format
152 #
153 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
154 #
155 def GuidStructureStringToGuidValueName(GuidValue):
156 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")
157 guidValueList = guidValueString.split(",")
158 if len(guidValueList) != 11:
159 EdkLogger.error(None, FORMAT_INVALID, "Invalid GUID value string [%s]" % GuidValue)
160 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
161 int(guidValueList[0], 16),
162 int(guidValueList[1], 16),
163 int(guidValueList[2], 16),
164 int(guidValueList[3], 16),
165 int(guidValueList[4], 16),
166 int(guidValueList[5], 16),
167 int(guidValueList[6], 16),
168 int(guidValueList[7], 16),
169 int(guidValueList[8], 16),
170 int(guidValueList[9], 16),
171 int(guidValueList[10], 16)
172 )
173
174 ## Create directories
175 #
176 # @param Directory The directory name
177 #
178 def CreateDirectory(Directory):
179 if Directory == None or Directory.strip() == "":
180 return True
181 try:
182 if not os.access(Directory, os.F_OK):
183 os.makedirs(Directory)
184 except:
185 return False
186 return True
187
188 ## Remove directories, including files and sub-directories in it
189 #
190 # @param Directory The directory name
191 #
192 def RemoveDirectory(Directory, Recursively=False):
193 if Directory == None or Directory.strip() == "" or not os.path.exists(Directory):
194 return
195 if Recursively:
196 CurrentDirectory = os.getcwd()
197 os.chdir(Directory)
198 for File in os.listdir("."):
199 if os.path.isdir(File):
200 RemoveDirectory(File, Recursively)
201 else:
202 os.remove(File)
203 os.chdir(CurrentDirectory)
204 os.rmdir(Directory)
205
206 ## Check if given file is changed or not
207 #
208 # This method is used to check if a file is changed or not between two build
209 # actions. It makes use a cache to store files timestamp.
210 #
211 # @param File The path of file
212 #
213 # @retval True If the given file is changed, doesn't exist, or can't be
214 # found in timestamp cache
215 # @retval False If the given file is changed
216 #
217 def IsChanged(File):
218 if not os.path.exists(File):
219 return True
220
221 FileState = os.stat(File)
222 TimeStamp = FileState[-2]
223
224 if File in gFileTimeStampCache and TimeStamp == gFileTimeStampCache[File]:
225 FileChanged = False
226 else:
227 FileChanged = True
228 gFileTimeStampCache[File] = TimeStamp
229
230 return FileChanged
231
232 ## Store content in file
233 #
234 # This method is used to save file only when its content is changed. This is
235 # quite useful for "make" system to decide what will be re-built and what won't.
236 #
237 # @param File The path of file
238 # @param Content The new content of the file
239 # @param IsBinaryFile The flag indicating if the file is binary file or not
240 #
241 # @retval True If the file content is changed and the file is renewed
242 # @retval False If the file content is the same
243 #
244 def SaveFileOnChange(File, Content, IsBinaryFile=True):
245 if not IsBinaryFile:
246 Content = Content.replace("\n", os.linesep)
247
248 if os.path.exists(File):
249 try:
250 if Content == open(File, "rb").read():
251 return False
252 except:
253 EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File)
254
255 DirName = os.path.dirname(File)
256 if not CreateDirectory(DirName):
257 EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)
258 else:
259 if DirName == '':
260 DirName = os.getcwd()
261 if not os.access(DirName, os.W_OK):
262 EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)
263
264 try:
265 if GlobalData.gIsWindows:
266 try:
267 from PyUtility import SaveFileToDisk
268 if not SaveFileToDisk(File, Content):
269 EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)
270 except:
271 Fd = open(File, "wb")
272 Fd.write(Content)
273 Fd.close()
274 else:
275 Fd = open(File, "wb")
276 Fd.write(Content)
277 Fd.close()
278 except IOError, X:
279 EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s'%X)
280
281 return True
282
283 ## Make a Python object persistent on file system
284 #
285 # @param Data The object to be stored in file
286 # @param File The path of file to store the object
287 #
288 def DataDump(Data, File):
289 Fd = None
290 try:
291 Fd = open(File, 'wb')
292 cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL)
293 except:
294 EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False)
295 finally:
296 if Fd != None:
297 Fd.close()
298
299 ## Restore a Python object from a file
300 #
301 # @param File The path of file stored the object
302 #
303 # @retval object A python object
304 # @retval None If failure in file operation
305 #
306 def DataRestore(File):
307 Data = None
308 Fd = None
309 try:
310 Fd = open(File, 'rb')
311 Data = cPickle.load(Fd)
312 except Exception, e:
313 EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e)))
314 Data = None
315 finally:
316 if Fd != None:
317 Fd.close()
318 return Data
319
320 ## Retrieve and cache the real path name in file system
321 #
322 # @param Root The root directory of path relative to
323 #
324 # @retval str The path string if the path exists
325 # @retval None If path doesn't exist
326 #
327 class DirCache:
328 _CACHE_ = set()
329 _UPPER_CACHE_ = {}
330
331 def __init__(self, Root):
332 self._Root = Root
333 for F in os.listdir(Root):
334 self._CACHE_.add(F)
335 self._UPPER_CACHE_[F.upper()] = F
336
337 # =[] operator
338 def __getitem__(self, Path):
339 Path = Path[len(os.path.commonprefix([Path, self._Root])):]
340 if not Path:
341 return self._Root
342 if Path and Path[0] == os.path.sep:
343 Path = Path[1:]
344 if Path in self._CACHE_:
345 return os.path.join(self._Root, Path)
346 UpperPath = Path.upper()
347 if UpperPath in self._UPPER_CACHE_:
348 return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])
349
350 IndexList = []
351 LastSepIndex = -1
352 SepIndex = Path.find(os.path.sep)
353 while SepIndex > -1:
354 Parent = UpperPath[:SepIndex]
355 if Parent not in self._UPPER_CACHE_:
356 break
357 LastSepIndex = SepIndex
358 SepIndex = Path.find(os.path.sep, LastSepIndex + 1)
359
360 if LastSepIndex == -1:
361 return None
362
363 Cwd = os.getcwd()
364 os.chdir(self._Root)
365 SepIndex = LastSepIndex
366 while SepIndex > -1:
367 Parent = Path[:SepIndex]
368 ParentKey = UpperPath[:SepIndex]
369 if ParentKey not in self._UPPER_CACHE_:
370 os.chdir(Cwd)
371 return None
372
373 if Parent in self._CACHE_:
374 ParentDir = Parent
375 else:
376 ParentDir = self._UPPER_CACHE_[ParentKey]
377 for F in os.listdir(ParentDir):
378 Dir = os.path.join(ParentDir, F)
379 self._CACHE_.add(Dir)
380 self._UPPER_CACHE_[Dir.upper()] = Dir
381
382 SepIndex = Path.find(os.path.sep, SepIndex + 1)
383
384 os.chdir(Cwd)
385 if Path in self._CACHE_:
386 return os.path.join(self._Root, Path)
387 elif UpperPath in self._UPPER_CACHE_:
388 return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])
389 return None
390
391 ## Get all files of a directory
392 #
393 # @param Root: Root dir
394 # @param SkipList : The files need be skipped
395 #
396 # @retval A list of all files
397 #
398 def GetFiles(Root, SkipList=None, FullPath = True):
399 OriPath = Root
400 FileList = []
401 for Root, Dirs, Files in os.walk(Root):
402 if SkipList:
403 for Item in SkipList:
404 if Item in Dirs:
405 Dirs.remove(Item)
406
407 for File in Files:
408 File = os.path.normpath(os.path.join(Root, File))
409 if not FullPath:
410 File = File[len(OriPath) + 1:]
411 FileList.append(File)
412
413 return FileList
414
415 ## Check if gvien file exists or not
416 #
417 # @param File File name or path to be checked
418 # @param Dir The directory the file is relative to
419 #
420 # @retval True if file exists
421 # @retval False if file doesn't exists
422 #
423 def ValidFile(File, Ext=None):
424 if Ext != None:
425 Dummy, FileExt = os.path.splitext(File)
426 if FileExt.lower() != Ext.lower():
427 return False
428 if not os.path.exists(File):
429 return False
430 return True
431
432 def RealPath(File, Dir='', OverrideDir=''):
433 NewFile = os.path.normpath(os.path.join(Dir, File))
434 NewFile = GlobalData.gAllFiles[NewFile]
435 if not NewFile and OverrideDir:
436 NewFile = os.path.normpath(os.path.join(OverrideDir, File))
437 NewFile = GlobalData.gAllFiles[NewFile]
438 return NewFile
439
440 def RealPath2(File, Dir='', OverrideDir=''):
441 if OverrideDir:
442 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
443 if NewFile:
444 if OverrideDir[-1] == os.path.sep:
445 return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
446 else:
447 return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)]
448 if GlobalData.gAllFiles:
449 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))]
450 else:
451 NewFile = os.path.normpath(os.path.join(Dir, File))
452 if NewFile:
453 if Dir:
454 if Dir[-1] == os.path.sep:
455 return NewFile[len(Dir):], NewFile[0:len(Dir)]
456 else:
457 return NewFile[len(Dir)+1:], NewFile[0:len(Dir)]
458 else:
459 return NewFile, ''
460
461 return None, None
462
463 ## Check if gvien file exists or not
464 #
465 #
466 def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):
467 NewFile = File
468 if Ext != None:
469 Dummy, FileExt = os.path.splitext(File)
470 if FileExt.lower() != Ext.lower():
471 return False, File
472
473 # Replace the Edk macros
474 if OverrideDir != '' and OverrideDir != None:
475 if OverrideDir.find('$(EFI_SOURCE)') > -1:
476 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)
477 if OverrideDir.find('$(EDK_SOURCE)') > -1:
478 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)
479
480 # Replace the default dir to current dir
481 if Dir == '.':
482 Dir = os.getcwd()
483 Dir = Dir[len(Workspace)+1:]
484
485 # First check if File has Edk definition itself
486 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:
487 NewFile = File.replace('$(EFI_SOURCE)', EfiSource)
488 NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource)
489 NewFile = AllFiles[os.path.normpath(NewFile)]
490 if NewFile != None:
491 return True, NewFile
492
493 # Second check the path with override value
494 if OverrideDir != '' and OverrideDir != None:
495 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
496 if NewFile != None:
497 return True, NewFile
498
499 # Last check the path with normal definitions
500 File = os.path.join(Dir, File)
501 NewFile = AllFiles[os.path.normpath(File)]
502 if NewFile != None:
503 return True, NewFile
504
505 return False, File
506
507 ## Check if gvien file exists or not
508 #
509 #
510 def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):
511 # Replace the Edk macros
512 if OverrideDir != '' and OverrideDir != None:
513 if OverrideDir.find('$(EFI_SOURCE)') > -1:
514 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)
515 if OverrideDir.find('$(EDK_SOURCE)') > -1:
516 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)
517
518 # Replace the default dir to current dir
519 # Dir is current module dir related to workspace
520 if Dir == '.':
521 Dir = os.getcwd()
522 Dir = Dir[len(Workspace)+1:]
523
524 NewFile = File
525 RelaPath = AllFiles[os.path.normpath(Dir)]
526 NewRelaPath = RelaPath
527
528 while(True):
529 # First check if File has Edk definition itself
530 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:
531 File = File.replace('$(EFI_SOURCE)', EfiSource)
532 File = File.replace('$(EDK_SOURCE)', EdkSource)
533 NewFile = AllFiles[os.path.normpath(File)]
534 if NewFile != None:
535 NewRelaPath = os.path.dirname(NewFile)
536 File = os.path.basename(NewFile)
537 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
538 break
539
540 # Second check the path with override value
541 if OverrideDir != '' and OverrideDir != None:
542 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
543 if NewFile != None:
544 #NewRelaPath = os.path.dirname(NewFile)
545 NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
546 break
547
548 # Last check the path with normal definitions
549 NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))]
550 if NewFile != None:
551 break
552
553 # No file found
554 break
555
556 return NewRelaPath, RelaPath, File
557
558
559 def GetRelPath(Path1, Path2):
560 FileName = os.path.basename(Path2)
561 L1 = os.path.normpath(Path1).split(os.path.normpath('/'))
562 L2 = os.path.normpath(Path2).split(os.path.normpath('/'))
563 for Index in range(0, len(L1)):
564 if L1[Index] != L2[Index]:
565 FileName = '../' * (len(L1) - Index)
566 for Index2 in range(Index, len(L2)):
567 FileName = os.path.join(FileName, L2[Index2])
568 break
569 return os.path.normpath(FileName)
570
571
572 ## Get GUID value from given packages
573 #
574 # @param CName The CName of the GUID
575 # @param PackageList List of packages looking-up in
576 #
577 # @retval GuidValue if the CName is found in any given package
578 # @retval None if the CName is not found in all given packages
579 #
580 def GuidValue(CName, PackageList):
581 for P in PackageList:
582 if CName in P.Guids:
583 return P.Guids[CName]
584 return None
585
586 ## Get Protocol value from given packages
587 #
588 # @param CName The CName of the GUID
589 # @param PackageList List of packages looking-up in
590 #
591 # @retval GuidValue if the CName is found in any given package
592 # @retval None if the CName is not found in all given packages
593 #
594 def ProtocolValue(CName, PackageList):
595 for P in PackageList:
596 if CName in P.Protocols:
597 return P.Protocols[CName]
598 return None
599
600 ## Get PPI value from given packages
601 #
602 # @param CName The CName of the GUID
603 # @param PackageList List of packages looking-up in
604 #
605 # @retval GuidValue if the CName is found in any given package
606 # @retval None if the CName is not found in all given packages
607 #
608 def PpiValue(CName, PackageList):
609 for P in PackageList:
610 if CName in P.Ppis:
611 return P.Ppis[CName]
612 return None
613
614 ## A string template class
615 #
616 # This class implements a template for string replacement. A string template
617 # looks like following
618 #
619 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
620 #
621 # The string between ${BEGIN} and ${END} will be repeated as many times as the
622 # length of "placeholder_name", which is a list passed through a dict. The
623 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
624 # be not used and, in this case, the "placeholder_name" must not a list and it
625 # will just be replaced once.
626 #
627 class TemplateString(object):
628 _REPEAT_START_FLAG = "BEGIN"
629 _REPEAT_END_FLAG = "END"
630
631 class Section(object):
632 _LIST_TYPES = [type([]), type(set()), type((0,))]
633
634 def __init__(self, TemplateSection, PlaceHolderList):
635 self._Template = TemplateSection
636 self._PlaceHolderList = []
637
638 # Split the section into sub-sections according to the position of placeholders
639 if PlaceHolderList:
640 self._SubSectionList = []
641 SubSectionStart = 0
642 #
643 # The placeholders passed in must be in the format of
644 #
645 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
646 #
647 for PlaceHolder,Start,End in PlaceHolderList:
648 self._SubSectionList.append(TemplateSection[SubSectionStart:Start])
649 self._SubSectionList.append(TemplateSection[Start:End])
650 self._PlaceHolderList.append(PlaceHolder)
651 SubSectionStart = End
652 if SubSectionStart < len(TemplateSection):
653 self._SubSectionList.append(TemplateSection[SubSectionStart:])
654 else:
655 self._SubSectionList = [TemplateSection]
656
657 def __str__(self):
658 return self._Template + " : " + str(self._PlaceHolderList)
659
660 def Instantiate(self, PlaceHolderValues):
661 RepeatTime = -1
662 RepeatPlaceHolders = {}
663 NonRepeatPlaceHolders = {}
664
665 for PlaceHolder in self._PlaceHolderList:
666 if PlaceHolder not in PlaceHolderValues:
667 continue
668 Value = PlaceHolderValues[PlaceHolder]
669 if type(Value) in self._LIST_TYPES:
670 if RepeatTime < 0:
671 RepeatTime = len(Value)
672 elif RepeatTime != len(Value):
673 EdkLogger.error(
674 "TemplateString",
675 PARAMETER_INVALID,
676 "${%s} has different repeat time from others!" % PlaceHolder,
677 ExtraData=str(self._Template)
678 )
679 RepeatPlaceHolders["${%s}" % PlaceHolder] = Value
680 else:
681 NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value
682
683 if NonRepeatPlaceHolders:
684 StringList = []
685 for S in self._SubSectionList:
686 if S not in NonRepeatPlaceHolders:
687 StringList.append(S)
688 else:
689 StringList.append(str(NonRepeatPlaceHolders[S]))
690 else:
691 StringList = self._SubSectionList
692
693 if RepeatPlaceHolders:
694 TempStringList = []
695 for Index in range(RepeatTime):
696 for S in StringList:
697 if S not in RepeatPlaceHolders:
698 TempStringList.append(S)
699 else:
700 TempStringList.append(str(RepeatPlaceHolders[S][Index]))
701 StringList = TempStringList
702
703 return "".join(StringList)
704
705 ## Constructor
706 def __init__(self, Template=None):
707 self.String = ''
708 self.IsBinary = False
709 self._Template = Template
710 self._TemplateSectionList = self._Parse(Template)
711
712 ## str() operator
713 #
714 # @retval string The string replaced
715 #
716 def __str__(self):
717 return self.String
718
719 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
720 #
721 # @retval list A list of TemplateString.Section objects
722 #
723 def _Parse(self, Template):
724 SectionStart = 0
725 SearchFrom = 0
726 MatchEnd = 0
727 PlaceHolderList = []
728 TemplateSectionList = []
729 while Template:
730 MatchObj = gPlaceholderPattern.search(Template, SearchFrom)
731 if not MatchObj:
732 if MatchEnd <= len(Template):
733 TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList)
734 TemplateSectionList.append(TemplateSection)
735 break
736
737 MatchString = MatchObj.group(1)
738 MatchStart = MatchObj.start()
739 MatchEnd = MatchObj.end()
740
741 if MatchString == self._REPEAT_START_FLAG:
742 if MatchStart > SectionStart:
743 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
744 TemplateSectionList.append(TemplateSection)
745 SectionStart = MatchEnd
746 PlaceHolderList = []
747 elif MatchString == self._REPEAT_END_FLAG:
748 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
749 TemplateSectionList.append(TemplateSection)
750 SectionStart = MatchEnd
751 PlaceHolderList = []
752 else:
753 PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart))
754 SearchFrom = MatchEnd
755 return TemplateSectionList
756
757 ## Replace the string template with dictionary of placeholders and append it to previous one
758 #
759 # @param AppendString The string template to append
760 # @param Dictionary The placeholder dictionaries
761 #
762 def Append(self, AppendString, Dictionary=None):
763 if Dictionary:
764 SectionList = self._Parse(AppendString)
765 self.String += "".join([S.Instantiate(Dictionary) for S in SectionList])
766 else:
767 self.String += AppendString
768
769 ## Replace the string template with dictionary of placeholders
770 #
771 # @param Dictionary The placeholder dictionaries
772 #
773 # @retval str The string replaced with placeholder values
774 #
775 def Replace(self, Dictionary=None):
776 return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList])
777
778 ## Progress indicator class
779 #
780 # This class makes use of thread to print progress on console.
781 #
782 class Progressor:
783 # for avoiding deadloop
784 _StopFlag = None
785 _ProgressThread = None
786 _CheckInterval = 0.25
787
788 ## Constructor
789 #
790 # @param OpenMessage The string printed before progress charaters
791 # @param CloseMessage The string printed after progress charaters
792 # @param ProgressChar The charater used to indicate the progress
793 # @param Interval The interval in seconds between two progress charaters
794 #
795 def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0):
796 self.PromptMessage = OpenMessage
797 self.CodaMessage = CloseMessage
798 self.ProgressChar = ProgressChar
799 self.Interval = Interval
800 if Progressor._StopFlag == None:
801 Progressor._StopFlag = threading.Event()
802
803 ## Start to print progress charater
804 #
805 # @param OpenMessage The string printed before progress charaters
806 #
807 def Start(self, OpenMessage=None):
808 if OpenMessage != None:
809 self.PromptMessage = OpenMessage
810 Progressor._StopFlag.clear()
811 if Progressor._ProgressThread == None:
812 Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)
813 Progressor._ProgressThread.setDaemon(False)
814 Progressor._ProgressThread.start()
815
816 ## Stop printing progress charater
817 #
818 # @param CloseMessage The string printed after progress charaters
819 #
820 def Stop(self, CloseMessage=None):
821 OriginalCodaMessage = self.CodaMessage
822 if CloseMessage != None:
823 self.CodaMessage = CloseMessage
824 self.Abort()
825 self.CodaMessage = OriginalCodaMessage
826
827 ## Thread entry method
828 def _ProgressThreadEntry(self):
829 sys.stdout.write(self.PromptMessage + " ")
830 sys.stdout.flush()
831 TimeUp = 0.0
832 while not Progressor._StopFlag.isSet():
833 if TimeUp <= 0.0:
834 sys.stdout.write(self.ProgressChar)
835 sys.stdout.flush()
836 TimeUp = self.Interval
837 time.sleep(self._CheckInterval)
838 TimeUp -= self._CheckInterval
839 sys.stdout.write(" " + self.CodaMessage + "\n")
840 sys.stdout.flush()
841
842 ## Abort the progress display
843 @staticmethod
844 def Abort():
845 if Progressor._StopFlag != None:
846 Progressor._StopFlag.set()
847 if Progressor._ProgressThread != None:
848 Progressor._ProgressThread.join()
849 Progressor._ProgressThread = None
850
851 ## A dict which can access its keys and/or values orderly
852 #
853 # The class implements a new kind of dict which its keys or values can be
854 # accessed in the order they are added into the dict. It guarantees the order
855 # by making use of an internal list to keep a copy of keys.
856 #
857 class sdict(IterableUserDict):
858 ## Constructor
859 def __init__(self):
860 IterableUserDict.__init__(self)
861 self._key_list = []
862
863 ## [] operator
864 def __setitem__(self, key, value):
865 if key not in self._key_list:
866 self._key_list.append(key)
867 IterableUserDict.__setitem__(self, key, value)
868
869 ## del operator
870 def __delitem__(self, key):
871 self._key_list.remove(key)
872 IterableUserDict.__delitem__(self, key)
873
874 ## used in "for k in dict" loop to ensure the correct order
875 def __iter__(self):
876 return self.iterkeys()
877
878 ## len() support
879 def __len__(self):
880 return len(self._key_list)
881
882 ## "in" test support
883 def __contains__(self, key):
884 return key in self._key_list
885
886 ## indexof support
887 def index(self, key):
888 return self._key_list.index(key)
889
890 ## insert support
891 def insert(self, key, newkey, newvalue, order):
892 index = self._key_list.index(key)
893 if order == 'BEFORE':
894 self._key_list.insert(index, newkey)
895 IterableUserDict.__setitem__(self, newkey, newvalue)
896 elif order == 'AFTER':
897 self._key_list.insert(index + 1, newkey)
898 IterableUserDict.__setitem__(self, newkey, newvalue)
899
900 ## append support
901 def append(self, sdict):
902 for key in sdict:
903 if key not in self._key_list:
904 self._key_list.append(key)
905 IterableUserDict.__setitem__(self, key, sdict[key])
906
907 def has_key(self, key):
908 return key in self._key_list
909
910 ## Empty the dict
911 def clear(self):
912 self._key_list = []
913 IterableUserDict.clear(self)
914
915 ## Return a copy of keys
916 def keys(self):
917 keys = []
918 for key in self._key_list:
919 keys.append(key)
920 return keys
921
922 ## Return a copy of values
923 def values(self):
924 values = []
925 for key in self._key_list:
926 values.append(self[key])
927 return values
928
929 ## Return a copy of (key, value) list
930 def items(self):
931 items = []
932 for key in self._key_list:
933 items.append((key, self[key]))
934 return items
935
936 ## Iteration support
937 def iteritems(self):
938 return iter(self.items())
939
940 ## Keys interation support
941 def iterkeys(self):
942 return iter(self.keys())
943
944 ## Values interation support
945 def itervalues(self):
946 return iter(self.values())
947
948 ## Return value related to a key, and remove the (key, value) from the dict
949 def pop(self, key, *dv):
950 value = None
951 if key in self._key_list:
952 value = self[key]
953 self.__delitem__(key)
954 elif len(dv) != 0 :
955 value = kv[0]
956 return value
957
958 ## Return (key, value) pair, and remove the (key, value) from the dict
959 def popitem(self):
960 key = self._key_list[-1]
961 value = self[key]
962 self.__delitem__(key)
963 return key, value
964
965 def update(self, dict=None, **kwargs):
966 if dict != None:
967 for k, v in dict.items():
968 self[k] = v
969 if len(kwargs):
970 for k, v in kwargs.items():
971 self[k] = v
972
973 ## Dictionary with restricted keys
974 #
975 class rdict(dict):
976 ## Constructor
977 def __init__(self, KeyList):
978 for Key in KeyList:
979 dict.__setitem__(self, Key, "")
980
981 ## []= operator
982 def __setitem__(self, key, value):
983 if key not in self:
984 EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key,
985 ExtraData=", ".join(dict.keys(self)))
986 dict.__setitem__(self, key, value)
987
988 ## =[] operator
989 def __getitem__(self, key):
990 if key not in self:
991 return ""
992 return dict.__getitem__(self, key)
993
994 ## del operator
995 def __delitem__(self, key):
996 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")
997
998 ## Empty the dict
999 def clear(self):
1000 for Key in self:
1001 self.__setitem__(Key, "")
1002
1003 ## Return value related to a key, and remove the (key, value) from the dict
1004 def pop(self, key, *dv):
1005 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")
1006
1007 ## Return (key, value) pair, and remove the (key, value) from the dict
1008 def popitem(self):
1009 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")
1010
1011 ## Dictionary using prioritized list as key
1012 #
1013 class tdict:
1014 _ListType = type([])
1015 _TupleType = type(())
1016 _Wildcard = 'COMMON'
1017 _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1018
1019 def __init__(self, _Single_=False, _Level_=2):
1020 self._Level_ = _Level_
1021 self.data = {}
1022 self._Single_ = _Single_
1023
1024 # =[] operator
1025 def __getitem__(self, key):
1026 KeyType = type(key)
1027 RestKeys = None
1028 if KeyType == self._ListType or KeyType == self._TupleType:
1029 FirstKey = key[0]
1030 if len(key) > 1:
1031 RestKeys = key[1:]
1032 elif self._Level_ > 1:
1033 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1034 else:
1035 FirstKey = key
1036 if self._Level_ > 1:
1037 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1038
1039 if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:
1040 FirstKey = self._Wildcard
1041
1042 if self._Single_:
1043 return self._GetSingleValue(FirstKey, RestKeys)
1044 else:
1045 return self._GetAllValues(FirstKey, RestKeys)
1046
1047 def _GetSingleValue(self, FirstKey, RestKeys):
1048 Value = None
1049 #print "%s-%s" % (FirstKey, self._Level_) ,
1050 if self._Level_ > 1:
1051 if FirstKey == self._Wildcard:
1052 if FirstKey in self.data:
1053 Value = self.data[FirstKey][RestKeys]
1054 if Value == None:
1055 for Key in self.data:
1056 Value = self.data[Key][RestKeys]
1057 if Value != None: break
1058 else:
1059 if FirstKey in self.data:
1060 Value = self.data[FirstKey][RestKeys]
1061 if Value == None and self._Wildcard in self.data:
1062 #print "Value=None"
1063 Value = self.data[self._Wildcard][RestKeys]
1064 else:
1065 if FirstKey == self._Wildcard:
1066 if FirstKey in self.data:
1067 Value = self.data[FirstKey]
1068 if Value == None:
1069 for Key in self.data:
1070 Value = self.data[Key]
1071 if Value != None: break
1072 else:
1073 if FirstKey in self.data:
1074 Value = self.data[FirstKey]
1075 elif self._Wildcard in self.data:
1076 Value = self.data[self._Wildcard]
1077 return Value
1078
1079 def _GetAllValues(self, FirstKey, RestKeys):
1080 Value = []
1081 if self._Level_ > 1:
1082 if FirstKey == self._Wildcard:
1083 for Key in self.data:
1084 Value += self.data[Key][RestKeys]
1085 else:
1086 if FirstKey in self.data:
1087 Value += self.data[FirstKey][RestKeys]
1088 if self._Wildcard in self.data:
1089 Value += self.data[self._Wildcard][RestKeys]
1090 else:
1091 if FirstKey == self._Wildcard:
1092 for Key in self.data:
1093 Value.append(self.data[Key])
1094 else:
1095 if FirstKey in self.data:
1096 Value.append(self.data[FirstKey])
1097 if self._Wildcard in self.data:
1098 Value.append(self.data[self._Wildcard])
1099 return Value
1100
1101 ## []= operator
1102 def __setitem__(self, key, value):
1103 KeyType = type(key)
1104 RestKeys = None
1105 if KeyType == self._ListType or KeyType == self._TupleType:
1106 FirstKey = key[0]
1107 if len(key) > 1:
1108 RestKeys = key[1:]
1109 else:
1110 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1111 else:
1112 FirstKey = key
1113 if self._Level_ > 1:
1114 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1115
1116 if FirstKey in self._ValidWildcardList:
1117 FirstKey = self._Wildcard
1118
1119 if FirstKey not in self.data and self._Level_ > 0:
1120 self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)
1121
1122 if self._Level_ > 1:
1123 self.data[FirstKey][RestKeys] = value
1124 else:
1125 self.data[FirstKey] = value
1126
1127 def SetGreedyMode(self):
1128 self._Single_ = False
1129 if self._Level_ > 1:
1130 for Key in self.data:
1131 self.data[Key].SetGreedyMode()
1132
1133 def SetSingleMode(self):
1134 self._Single_ = True
1135 if self._Level_ > 1:
1136 for Key in self.data:
1137 self.data[Key].SetSingleMode()
1138
1139 def GetKeys(self, KeyIndex=0):
1140 assert KeyIndex >= 0
1141 if KeyIndex == 0:
1142 return set(self.data.keys())
1143 else:
1144 keys = set()
1145 for Key in self.data:
1146 keys |= self.data[Key].GetKeys(KeyIndex - 1)
1147 return keys
1148
1149 ## Boolean chain list
1150 #
1151 class Blist(UserList):
1152 def __init__(self, initlist=None):
1153 UserList.__init__(self, initlist)
1154 def __setitem__(self, i, item):
1155 if item not in [True, False]:
1156 if item == 0:
1157 item = False
1158 else:
1159 item = True
1160 self.data[i] = item
1161 def _GetResult(self):
1162 Value = True
1163 for item in self.data:
1164 Value &= item
1165 return Value
1166 Result = property(_GetResult)
1167
1168 def ParseConsoleLog(Filename):
1169 Opr = open(os.path.normpath(Filename), 'r')
1170 Opw = open(os.path.normpath(Filename + '.New'), 'w+')
1171 for Line in Opr.readlines():
1172 if Line.find('.efi') > -1:
1173 Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip()
1174 Opw.write('%s\n' % Line)
1175
1176 Opr.close()
1177 Opw.close()
1178
1179 ## AnalyzePcdData
1180 #
1181 # Analyze the pcd Value, Datum type and TokenNumber.
1182 # Used to avoid split issue while the value string contain "|" character
1183 #
1184 # @param[in] Setting: A String contain value/datum type/token number information;
1185 #
1186 # @retval ValueList: A List contain value, datum type and toke number.
1187 #
1188 def AnalyzePcdData(Setting):
1189 ValueList = ['', '', '']
1190
1191 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1192 PtrValue = ValueRe.findall(Setting)
1193
1194 ValueUpdateFlag = False
1195
1196 if len(PtrValue) >= 1:
1197 Setting = re.sub(ValueRe, '', Setting)
1198 ValueUpdateFlag = True
1199
1200 TokenList = Setting.split(TAB_VALUE_SPLIT)
1201 ValueList[0:len(TokenList)] = TokenList
1202
1203 if ValueUpdateFlag:
1204 ValueList[0] = PtrValue[0]
1205
1206 return ValueList
1207
1208 ## AnalyzeHiiPcdData
1209 #
1210 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1211 # Used to avoid split issue while the value string contain "|" character
1212 #
1213 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1214 #
1215 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1216 #
1217 def AnalyzeHiiPcdData(Setting):
1218 ValueList = ['', '', '', '']
1219
1220 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1221 PtrValue = ValueRe.findall(Setting)
1222
1223 ValueUpdateFlag = False
1224
1225 if len(PtrValue) >= 1:
1226 Setting = re.sub(ValueRe, '', Setting)
1227 ValueUpdateFlag = True
1228
1229 TokenList = Setting.split(TAB_VALUE_SPLIT)
1230 ValueList[0:len(TokenList)] = TokenList
1231
1232 if ValueUpdateFlag:
1233 ValueList[0] = PtrValue[0]
1234
1235 return ValueList
1236
1237 ## AnalyzeVpdPcdData
1238 #
1239 # Analyze the vpd pcd Value, Datum type and TokenNumber.
1240 # Used to avoid split issue while the value string contain "|" character
1241 #
1242 # @param[in] Setting: A String contain value/datum type/token number information;
1243 #
1244 # @retval ValueList: A List contain value, datum type and toke number.
1245 #
1246 def AnalyzeVpdPcdData(Setting):
1247 ValueList = ['', '', '']
1248
1249 ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')
1250 PtrValue = ValueRe.findall(Setting)
1251
1252 ValueUpdateFlag = False
1253
1254 if len(PtrValue) >= 1:
1255 Setting = re.sub(ValueRe, '', Setting)
1256 ValueUpdateFlag = True
1257
1258 TokenList = Setting.split(TAB_VALUE_SPLIT)
1259 ValueList[0:len(TokenList)] = TokenList
1260
1261 if ValueUpdateFlag:
1262 ValueList[2] = PtrValue[0]
1263
1264 return ValueList
1265
1266 ## check format of PCD value against its the datum type
1267 #
1268 # For PCD value setting
1269 #
1270 def CheckPcdDatum(Type, Value):
1271 if Type == "VOID*":
1272 if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))
1273 or (Value.startswith('{') and Value.endswith('}'))
1274 ):
1275 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1276 ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type)
1277 elif Type == 'BOOLEAN':
1278 if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1279 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1280 ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type)
1281 elif type(Value) == type(""):
1282 try:
1283 Value = long(Value, 0)
1284 except:
1285 return False, "Invalid value [%s] of type [%s];"\
1286 " must be a hexadecimal, decimal or octal in C language format."\
1287 % (Value, Type)
1288
1289 return True, ""
1290
1291 ## Split command line option string to list
1292 #
1293 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1294 # in non-windows platform to launch command
1295 #
1296 def SplitOption(OptionString):
1297 OptionList = []
1298 LastChar = " "
1299 OptionStart = 0
1300 QuotationMark = ""
1301 for Index in range(0, len(OptionString)):
1302 CurrentChar = OptionString[Index]
1303 if CurrentChar in ['"', "'"]:
1304 if QuotationMark == CurrentChar:
1305 QuotationMark = ""
1306 elif QuotationMark == "":
1307 QuotationMark = CurrentChar
1308 continue
1309 elif QuotationMark:
1310 continue
1311
1312 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
1313 if Index > OptionStart:
1314 OptionList.append(OptionString[OptionStart:Index-1])
1315 OptionStart = Index
1316 LastChar = CurrentChar
1317 OptionList.append(OptionString[OptionStart:])
1318 return OptionList
1319
1320 def CommonPath(PathList):
1321 P1 = min(PathList).split(os.path.sep)
1322 P2 = max(PathList).split(os.path.sep)
1323 for Index in xrange(min(len(P1), len(P2))):
1324 if P1[Index] != P2[Index]:
1325 return os.path.sep.join(P1[:Index])
1326 return os.path.sep.join(P1)
1327
1328 class PathClass(object):
1329 def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
1330 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):
1331 self.Arch = Arch
1332 self.File = str(File)
1333 if os.path.isabs(self.File):
1334 self.Root = ''
1335 self.AlterRoot = ''
1336 else:
1337 self.Root = str(Root)
1338 self.AlterRoot = str(AlterRoot)
1339
1340 # Remove any '.' and '..' in path
1341 if self.Root:
1342 self.Path = os.path.normpath(os.path.join(self.Root, self.File))
1343 self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
1344 # eliminate the side-effect of 'C:'
1345 if self.Root[-1] == ':':
1346 self.Root += os.path.sep
1347 # file path should not start with path separator
1348 if self.Root[-1] == os.path.sep:
1349 self.File = self.Path[len(self.Root):]
1350 else:
1351 self.File = self.Path[len(self.Root)+1:]
1352 else:
1353 self.Path = os.path.normpath(self.File)
1354
1355 self.SubDir, self.Name = os.path.split(self.File)
1356 self.BaseName, self.Ext = os.path.splitext(self.Name)
1357
1358 if self.Root:
1359 if self.SubDir:
1360 self.Dir = os.path.join(self.Root, self.SubDir)
1361 else:
1362 self.Dir = self.Root
1363 else:
1364 self.Dir = self.SubDir
1365
1366 if IsBinary:
1367 self.Type = Type
1368 else:
1369 self.Type = self.Ext.lower()
1370
1371 self.IsBinary = IsBinary
1372 self.Target = Target
1373 self.TagName = TagName
1374 self.ToolCode = ToolCode
1375 self.ToolChainFamily = ToolChainFamily
1376
1377 self._Key = None
1378
1379 ## Convert the object of this class to a string
1380 #
1381 # Convert member Path of the class to a string
1382 #
1383 # @retval string Formatted String
1384 #
1385 def __str__(self):
1386 return self.Path
1387
1388 ## Override __eq__ function
1389 #
1390 # Check whether PathClass are the same
1391 #
1392 # @retval False The two PathClass are different
1393 # @retval True The two PathClass are the same
1394 #
1395 def __eq__(self, Other):
1396 if type(Other) == type(self):
1397 return self.Path == Other.Path
1398 else:
1399 return self.Path == str(Other)
1400
1401 ## Override __cmp__ function
1402 #
1403 # Customize the comparsion operation of two PathClass
1404 #
1405 # @retval 0 The two PathClass are different
1406 # @retval -1 The first PathClass is less than the second PathClass
1407 # @retval 1 The first PathClass is Bigger than the second PathClass
1408 def __cmp__(self, Other):
1409 if type(Other) == type(self):
1410 OtherKey = Other.Path
1411 else:
1412 OtherKey = str(Other)
1413
1414 SelfKey = self.Path
1415 if SelfKey == OtherKey:
1416 return 0
1417 elif SelfKey > OtherKey:
1418 return 1
1419 else:
1420 return -1
1421
1422 ## Override __hash__ function
1423 #
1424 # Use Path as key in hash table
1425 #
1426 # @retval string Key for hash table
1427 #
1428 def __hash__(self):
1429 return hash(self.Path)
1430
1431 def _GetFileKey(self):
1432 if self._Key == None:
1433 self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1434 return self._Key
1435
1436 def _GetTimeStamp(self):
1437 return os.stat(self.Path)[8]
1438
1439 def Validate(self, Type='', CaseSensitive=True):
1440 if GlobalData.gCaseInsensitive:
1441 CaseSensitive = False
1442 if Type and Type.lower() != self.Type:
1443 return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)
1444
1445 RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
1446 if not RealRoot and not RealFile:
1447 RealFile = self.File
1448 if self.AlterRoot:
1449 RealFile = os.path.join(self.AlterRoot, self.File)
1450 elif self.Root:
1451 RealFile = os.path.join(self.Root, self.File)
1452 return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
1453
1454 ErrorCode = 0
1455 ErrorInfo = ''
1456 if RealRoot != self.Root or RealFile != self.File:
1457 if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):
1458 ErrorCode = FILE_CASE_MISMATCH
1459 ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"
1460
1461 self.SubDir, self.Name = os.path.split(RealFile)
1462 self.BaseName, self.Ext = os.path.splitext(self.Name)
1463 if self.SubDir:
1464 self.Dir = os.path.join(RealRoot, self.SubDir)
1465 else:
1466 self.Dir = RealRoot
1467 self.File = RealFile
1468 self.Root = RealRoot
1469 self.Path = os.path.join(RealRoot, RealFile)
1470 return ErrorCode, ErrorInfo
1471
1472 Key = property(_GetFileKey)
1473 TimeStamp = property(_GetTimeStamp)
1474
1475 ## Parse PE image to get the required PE informaion.
1476 #
1477 class PeImageClass():
1478 ## Constructor
1479 #
1480 # @param File FilePath of PeImage
1481 #
1482 def __init__(self, PeFile):
1483 self.FileName = PeFile
1484 self.IsValid = False
1485 self.Size = 0
1486 self.EntryPoint = 0
1487 self.SectionAlignment = 0
1488 self.SectionHeaderList = []
1489 self.ErrorInfo = ''
1490 try:
1491 PeObject = open(PeFile, 'rb')
1492 except:
1493 self.ErrorInfo = self.FileName + ' can not be found\n'
1494 return
1495 # Read DOS header
1496 ByteArray = array.array('B')
1497 ByteArray.fromfile(PeObject, 0x3E)
1498 ByteList = ByteArray.tolist()
1499 # DOS signature should be 'MZ'
1500 if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':
1501 self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'
1502 return
1503
1504 # Read 4 byte PE Signature
1505 PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])
1506 PeObject.seek(PeOffset)
1507 ByteArray = array.array('B')
1508 ByteArray.fromfile(PeObject, 4)
1509 # PE signature should be 'PE\0\0'
1510 if ByteArray.tostring() != 'PE\0\0':
1511 self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'
1512 return
1513
1514 # Read PE file header
1515 ByteArray = array.array('B')
1516 ByteArray.fromfile(PeObject, 0x14)
1517 ByteList = ByteArray.tolist()
1518 SecNumber = self._ByteListToInt(ByteList[0x2:0x4])
1519 if SecNumber == 0:
1520 self.ErrorInfo = self.FileName + ' has no section header'
1521 return
1522
1523 # Read PE optional header
1524 OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])
1525 ByteArray = array.array('B')
1526 ByteArray.fromfile(PeObject, OptionalHeaderSize)
1527 ByteList = ByteArray.tolist()
1528 self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14])
1529 self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])
1530 self.Size = self._ByteListToInt(ByteList[0x38:0x3C])
1531
1532 # Read each Section Header
1533 for Index in range(SecNumber):
1534 ByteArray = array.array('B')
1535 ByteArray.fromfile(PeObject, 0x28)
1536 ByteList = ByteArray.tolist()
1537 SecName = self._ByteListToStr(ByteList[0:8])
1538 SecVirtualSize = self._ByteListToInt(ByteList[8:12])
1539 SecRawAddress = self._ByteListToInt(ByteList[20:24])
1540 SecVirtualAddress = self._ByteListToInt(ByteList[12:16])
1541 self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))
1542 self.IsValid = True
1543 PeObject.close()
1544
1545 def _ByteListToStr(self, ByteList):
1546 String = ''
1547 for index in range(len(ByteList)):
1548 if ByteList[index] == 0:
1549 break
1550 String += chr(ByteList[index])
1551 return String
1552
1553 def _ByteListToInt(self, ByteList):
1554 Value = 0
1555 for index in range(len(ByteList) - 1, -1, -1):
1556 Value = (Value << 8) | int(ByteList[index])
1557 return Value
1558
1559 ##
1560 #
1561 # This acts like the main() function for the script, unless it is 'import'ed into another
1562 # script.
1563 #
1564 if __name__ == '__main__':
1565 pass
1566