]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
2 # Common routines used by all tools
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
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.
26 from UserDict
import IterableUserDict
27 from UserList
import UserList
29 from Common
import EdkLogger
as EdkLogger
30 from Common
import GlobalData
as GlobalData
31 from DataType
import *
32 from BuildToolError
import *
34 ## Regular expression used to find out place holders in string template
35 gPlaceholderPattern
= re
.compile("\$\{([^$()\s]+)\}", re
.MULTILINE|re
.UNICODE
)
37 ## Dictionary used to store file time stamp for quick re-access
38 gFileTimeStampCache
= {} # {file path : file time stamp}
40 ## Dictionary used to store dependencies of files
41 gDependencyDatabase
= {} # arch : {file path : [dependent files list]}
43 ## callback routine for processing variable option
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)
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
56 def ProcessVariableArgument(Option
, OptionString
, Value
, Parser
):
59 RawArgs
= Parser
.rargs
62 if (Arg
[:2] == "--" and len(Arg
) > 2) or \
63 (Arg
[:1] == "-" and len(Arg
) > 1 and Arg
[1] != "-"):
67 setattr(Parser
.values
, Option
.dest
, Value
)
69 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
71 # @param Guid The GUID string
73 # @retval string The GUID string in C structure style
75 def GuidStringToGuidStructureString(Guid
):
76 GuidList
= Guid
.split('-')
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]
86 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
88 # @param GuidValue The GUID value in byte array
90 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
92 def GuidStructureByteArrayToGuidString(GuidValue
):
93 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
94 guidValueList
= guidValueString
.split(",")
95 if len(guidValueList
) != 16:
97 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
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)
120 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
122 # @param GuidValue The GUID value in C structure format
124 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
126 def GuidStructureStringToGuidString(GuidValue
):
127 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
128 guidValueList
= guidValueString
.split(",")
129 if len(guidValueList
) != 11:
131 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
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)
149 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
151 # @param GuidValue The GUID value in C structure format
153 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
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)
174 ## Create directories
176 # @param Directory The directory name
178 def CreateDirectory(Directory
):
179 if Directory
== None or Directory
.strip() == "":
182 if not os
.access(Directory
, os
.F_OK
):
183 os
.makedirs(Directory
)
188 ## Remove directories, including files and sub-directories in it
190 # @param Directory The directory name
192 def RemoveDirectory(Directory
, Recursively
=False):
193 if Directory
== None or Directory
.strip() == "" or not os
.path
.exists(Directory
):
196 CurrentDirectory
= os
.getcwd()
198 for File
in os
.listdir("."):
199 if os
.path
.isdir(File
):
200 RemoveDirectory(File
, Recursively
)
203 os
.chdir(CurrentDirectory
)
206 ## Check if given file is changed or not
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.
211 # @param File The path of file
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
218 if not os
.path
.exists(File
):
221 FileState
= os
.stat(File
)
222 TimeStamp
= FileState
[-2]
224 if File
in gFileTimeStampCache
and TimeStamp
== gFileTimeStampCache
[File
]:
228 gFileTimeStampCache
[File
] = TimeStamp
232 ## Store content in file
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.
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
241 # @retval True If the file content is changed and the file is renewed
242 # @retval False If the file content is the same
244 def SaveFileOnChange(File
, Content
, IsBinaryFile
=True):
246 Content
= Content
.replace("\n", os
.linesep
)
248 if os
.path
.exists(File
):
250 if Content
== open(File
, "rb").read():
253 EdkLogger
.error(None, FILE_OPEN_FAILURE
, ExtraData
=File
)
255 DirName
= os
.path
.dirname(File
)
256 if not CreateDirectory(DirName
):
257 EdkLogger
.error(None, FILE_CREATE_FAILURE
, "Could not create directory %s" % 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
)
265 if GlobalData
.gIsWindows
:
267 from PyUtility
import SaveFileToDisk
268 if not SaveFileToDisk(File
, Content
):
269 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
271 Fd
= open(File
, "wb")
275 Fd
= open(File
, "wb")
279 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
='IOError %s'%X)
283 ## Make a Python object persistent on file system
285 # @param Data The object to be stored in file
286 # @param File The path of file to store the object
288 def DataDump(Data
, File
):
291 Fd
= open(File
, 'wb')
292 cPickle
.dump(Data
, Fd
, cPickle
.HIGHEST_PROTOCOL
)
294 EdkLogger
.error("", FILE_OPEN_FAILURE
, ExtraData
=File
, RaiseError
=False)
299 ## Restore a Python object from a file
301 # @param File The path of file stored the object
303 # @retval object A python object
304 # @retval None If failure in file operation
306 def DataRestore(File
):
310 Fd
= open(File
, 'rb')
311 Data
= cPickle
.load(Fd
)
313 EdkLogger
.verbose("Failed to load [%s]\n\t%s" % (File
, str(e
)))
320 ## Retrieve and cache the real path name in file system
322 # @param Root The root directory of path relative to
324 # @retval str The path string if the path exists
325 # @retval None If path doesn't exist
331 def __init__(self
, Root
):
333 for F
in os
.listdir(Root
):
335 self
._UPPER
_CACHE
_[F
.upper()] = F
338 def __getitem__(self
, Path
):
339 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
342 if Path
and Path
[0] == os
.path
.sep
:
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
])
352 SepIndex
= Path
.find(os
.path
.sep
)
354 Parent
= UpperPath
[:SepIndex
]
355 if Parent
not in self
._UPPER
_CACHE
_:
357 LastSepIndex
= SepIndex
358 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
360 if LastSepIndex
== -1:
365 SepIndex
= LastSepIndex
367 Parent
= Path
[:SepIndex
]
368 ParentKey
= UpperPath
[:SepIndex
]
369 if ParentKey
not in self
._UPPER
_CACHE
_:
373 if Parent
in self
._CACHE
_:
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
382 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
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
])
391 ## Get all files of a directory
393 # @param Root: Root dir
394 # @param SkipList : The files need be skipped
396 # @retval A list of all files
398 def GetFiles(Root
, SkipList
=None, FullPath
= True):
401 for Root
, Dirs
, Files
in os
.walk(Root
):
403 for Item
in SkipList
:
408 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
410 File
= File
[len(OriPath
) + 1:]
411 FileList
.append(File
)
415 ## Check if gvien file exists or not
417 # @param File File name or path to be checked
418 # @param Dir The directory the file is relative to
420 # @retval True if file exists
421 # @retval False if file doesn't exists
423 def ValidFile(File
, Ext
=None):
425 Dummy
, FileExt
= os
.path
.splitext(File
)
426 if FileExt
.lower() != Ext
.lower():
428 if not os
.path
.exists(File
):
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
]
440 def RealPath2(File
, Dir
='', OverrideDir
=''):
442 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
444 if OverrideDir
[-1] == os
.path
.sep
:
445 return NewFile
[len(OverrideDir
):], NewFile
[0:len(OverrideDir
)]
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
))]
451 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
454 if Dir
[-1] == os
.path
.sep
:
455 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
457 return NewFile
[len(Dir
)+1:], NewFile
[0:len(Dir
)]
463 ## Check if gvien file exists or not
466 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
469 Dummy
, FileExt
= os
.path
.splitext(File
)
470 if FileExt
.lower() != Ext
.lower():
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
)
480 # Replace the default dir to current dir
483 Dir
= Dir
[len(Workspace
)+1:]
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
)]
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
))]
499 # Last check the path with normal definitions
500 File
= os
.path
.join(Dir
, File
)
501 NewFile
= AllFiles
[os
.path
.normpath(File
)]
507 ## Check if gvien file exists or not
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
)
518 # Replace the default dir to current dir
519 # Dir is current module dir related to workspace
522 Dir
= Dir
[len(Workspace
)+1:]
525 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
526 NewRelaPath
= RelaPath
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
)]
535 NewRelaPath
= os
.path
.dirname(NewFile
)
536 File
= os
.path
.basename(NewFile
)
537 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
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
))]
544 #NewRelaPath = os.path.dirname(NewFile)
545 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
548 # Last check the path with normal definitions
549 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
556 return NewRelaPath
, RelaPath
, File
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
])
569 return os
.path
.normpath(FileName
)
572 ## Get GUID value from given packages
574 # @param CName The CName of the GUID
575 # @param PackageList List of packages looking-up in
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
580 def GuidValue(CName
, PackageList
):
581 for P
in PackageList
:
583 return P
.Guids
[CName
]
586 ## Get Protocol value from given packages
588 # @param CName The CName of the GUID
589 # @param PackageList List of packages looking-up in
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
594 def ProtocolValue(CName
, PackageList
):
595 for P
in PackageList
:
596 if CName
in P
.Protocols
:
597 return P
.Protocols
[CName
]
600 ## Get PPI value from given packages
602 # @param CName The CName of the GUID
603 # @param PackageList List of packages looking-up in
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
608 def PpiValue(CName
, PackageList
):
609 for P
in PackageList
:
614 ## A string template class
616 # This class implements a template for string replacement. A string template
617 # looks like following
619 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
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.
627 class TemplateString(object):
628 _REPEAT_START_FLAG
= "BEGIN"
629 _REPEAT_END_FLAG
= "END"
631 class Section(object):
632 _LIST_TYPES
= [type([]), type(set()), type((0,))]
634 def __init__(self
, TemplateSection
, PlaceHolderList
):
635 self
._Template
= TemplateSection
636 self
._PlaceHolderList
= []
638 # Split the section into sub-sections according to the position of placeholders
640 self
._SubSectionList
= []
643 # The placeholders passed in must be in the format of
645 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
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
:])
655 self
._SubSectionList
= [TemplateSection
]
658 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
660 def Instantiate(self
, PlaceHolderValues
):
662 RepeatPlaceHolders
= {}
663 NonRepeatPlaceHolders
= {}
665 for PlaceHolder
in self
._PlaceHolderList
:
666 if PlaceHolder
not in PlaceHolderValues
:
668 Value
= PlaceHolderValues
[PlaceHolder
]
669 if type(Value
) in self
._LIST
_TYPES
:
671 RepeatTime
= len(Value
)
672 elif RepeatTime
!= len(Value
):
676 "${%s} has different repeat time from others!" % PlaceHolder
,
677 ExtraData
=str(self
._Template
)
679 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
681 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
683 if NonRepeatPlaceHolders
:
685 for S
in self
._SubSectionList
:
686 if S
not in NonRepeatPlaceHolders
:
689 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
691 StringList
= self
._SubSectionList
693 if RepeatPlaceHolders
:
695 for Index
in range(RepeatTime
):
697 if S
not in RepeatPlaceHolders
:
698 TempStringList
.append(S
)
700 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
701 StringList
= TempStringList
703 return "".join(StringList
)
706 def __init__(self
, Template
=None):
708 self
.IsBinary
= False
709 self
._Template
= Template
710 self
._TemplateSectionList
= self
._Parse
(Template
)
714 # @retval string The string replaced
719 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
721 # @retval list A list of TemplateString.Section objects
723 def _Parse(self
, Template
):
728 TemplateSectionList
= []
730 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
732 if MatchEnd
<= len(Template
):
733 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
734 TemplateSectionList
.append(TemplateSection
)
737 MatchString
= MatchObj
.group(1)
738 MatchStart
= MatchObj
.start()
739 MatchEnd
= MatchObj
.end()
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
747 elif MatchString
== self
._REPEAT
_END
_FLAG
:
748 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
749 TemplateSectionList
.append(TemplateSection
)
750 SectionStart
= MatchEnd
753 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
754 SearchFrom
= MatchEnd
755 return TemplateSectionList
757 ## Replace the string template with dictionary of placeholders and append it to previous one
759 # @param AppendString The string template to append
760 # @param Dictionary The placeholder dictionaries
762 def Append(self
, AppendString
, Dictionary
=None):
764 SectionList
= self
._Parse
(AppendString
)
765 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
767 self
.String
+= AppendString
769 ## Replace the string template with dictionary of placeholders
771 # @param Dictionary The placeholder dictionaries
773 # @retval str The string replaced with placeholder values
775 def Replace(self
, Dictionary
=None):
776 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
778 ## Progress indicator class
780 # This class makes use of thread to print progress on console.
783 # for avoiding deadloop
785 _ProgressThread
= None
786 _CheckInterval
= 0.25
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
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()
803 ## Start to print progress charater
805 # @param OpenMessage The string printed before progress charaters
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()
816 ## Stop printing progress charater
818 # @param CloseMessage The string printed after progress charaters
820 def Stop(self
, CloseMessage
=None):
821 OriginalCodaMessage
= self
.CodaMessage
822 if CloseMessage
!= None:
823 self
.CodaMessage
= CloseMessage
825 self
.CodaMessage
= OriginalCodaMessage
827 ## Thread entry method
828 def _ProgressThreadEntry(self
):
829 sys
.stdout
.write(self
.PromptMessage
+ " ")
832 while not Progressor
._StopFlag
.isSet():
834 sys
.stdout
.write(self
.ProgressChar
)
836 TimeUp
= self
.Interval
837 time
.sleep(self
._CheckInterval
)
838 TimeUp
-= self
._CheckInterval
839 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
842 ## Abort the progress display
845 if Progressor
._StopFlag
!= None:
846 Progressor
._StopFlag
.set()
847 if Progressor
._ProgressThread
!= None:
848 Progressor
._ProgressThread
.join()
849 Progressor
._ProgressThread
= None
851 ## A dict which can access its keys and/or values orderly
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.
857 class sdict(IterableUserDict
):
860 IterableUserDict
.__init
__(self
)
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
)
870 def __delitem__(self
, key
):
871 self
._key
_list
.remove(key
)
872 IterableUserDict
.__delitem
__(self
, key
)
874 ## used in "for k in dict" loop to ensure the correct order
876 return self
.iterkeys()
880 return len(self
._key
_list
)
883 def __contains__(self
, key
):
884 return key
in self
._key
_list
887 def index(self
, key
):
888 return self
._key
_list
.index(key
)
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
)
901 def append(self
, sdict
):
903 if key
not in self
._key
_list
:
904 self
._key
_list
.append(key
)
905 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
907 def has_key(self
, key
):
908 return key
in self
._key
_list
913 IterableUserDict
.clear(self
)
915 ## Return a copy of keys
918 for key
in self
._key
_list
:
922 ## Return a copy of values
925 for key
in self
._key
_list
:
926 values
.append(self
[key
])
929 ## Return a copy of (key, value) list
932 for key
in self
._key
_list
:
933 items
.append((key
, self
[key
]))
938 return iter(self
.items())
940 ## Keys interation support
942 return iter(self
.keys())
944 ## Values interation support
945 def itervalues(self
):
946 return iter(self
.values())
948 ## Return value related to a key, and remove the (key, value) from the dict
949 def pop(self
, key
, *dv
):
951 if key
in self
._key
_list
:
953 self
.__delitem
__(key
)
958 ## Return (key, value) pair, and remove the (key, value) from the dict
960 key
= self
._key
_list
[-1]
962 self
.__delitem
__(key
)
965 def update(self
, dict=None, **kwargs
):
967 for k
, v
in dict.items():
970 for k
, v
in kwargs
.items():
973 ## Dictionary with restricted keys
977 def __init__(self
, KeyList
):
979 dict.__setitem
__(self
, Key
, "")
982 def __setitem__(self
, key
, value
):
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
)
989 def __getitem__(self
, key
):
992 return dict.__getitem
__(self
, key
)
995 def __delitem__(self
, key
):
996 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
1001 self
.__setitem
__(Key
, "")
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")
1007 ## Return (key, value) pair, and remove the (key, value) from the dict
1009 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
1011 ## Dictionary using prioritized list as key
1014 _ListType
= type([])
1015 _TupleType
= type(())
1016 _Wildcard
= 'COMMON'
1017 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1019 def __init__(self
, _Single_
=False, _Level_
=2):
1020 self
._Level
_ = _Level_
1022 self
._Single
_ = _Single_
1025 def __getitem__(self
, key
):
1028 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1032 elif self
._Level
_ > 1:
1033 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1036 if self
._Level
_ > 1:
1037 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1039 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1040 FirstKey
= self
._Wildcard
1043 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1045 return self
._GetAllValues
(FirstKey
, RestKeys
)
1047 def _GetSingleValue(self
, FirstKey
, RestKeys
):
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
]
1055 for Key
in self
.data
:
1056 Value
= self
.data
[Key
][RestKeys
]
1057 if Value
!= None: break
1059 if FirstKey
in self
.data
:
1060 Value
= self
.data
[FirstKey
][RestKeys
]
1061 if Value
== None and self
._Wildcard
in self
.data
:
1063 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1065 if FirstKey
== self
._Wildcard
:
1066 if FirstKey
in self
.data
:
1067 Value
= self
.data
[FirstKey
]
1069 for Key
in self
.data
:
1070 Value
= self
.data
[Key
]
1071 if Value
!= None: break
1073 if FirstKey
in self
.data
:
1074 Value
= self
.data
[FirstKey
]
1075 elif self
._Wildcard
in self
.data
:
1076 Value
= self
.data
[self
._Wildcard
]
1079 def _GetAllValues(self
, FirstKey
, RestKeys
):
1081 if self
._Level
_ > 1:
1082 if FirstKey
== self
._Wildcard
:
1083 for Key
in self
.data
:
1084 Value
+= self
.data
[Key
][RestKeys
]
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
]
1091 if FirstKey
== self
._Wildcard
:
1092 for Key
in self
.data
:
1093 Value
.append(self
.data
[Key
])
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
])
1102 def __setitem__(self
, key
, value
):
1105 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1110 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1113 if self
._Level
_ > 1:
1114 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1116 if FirstKey
in self
._ValidWildcardList
:
1117 FirstKey
= self
._Wildcard
1119 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1120 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1122 if self
._Level
_ > 1:
1123 self
.data
[FirstKey
][RestKeys
] = value
1125 self
.data
[FirstKey
] = value
1127 def SetGreedyMode(self
):
1128 self
._Single
_ = False
1129 if self
._Level
_ > 1:
1130 for Key
in self
.data
:
1131 self
.data
[Key
].SetGreedyMode()
1133 def SetSingleMode(self
):
1134 self
._Single
_ = True
1135 if self
._Level
_ > 1:
1136 for Key
in self
.data
:
1137 self
.data
[Key
].SetSingleMode()
1139 def GetKeys(self
, KeyIndex
=0):
1140 assert KeyIndex
>= 0
1142 return set(self
.data
.keys())
1145 for Key
in self
.data
:
1146 keys |
= self
.data
[Key
].GetKeys(KeyIndex
- 1)
1149 ## Boolean chain list
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]:
1161 def _GetResult(self
):
1163 for item
in self
.data
:
1166 Result
= property(_GetResult
)
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
)
1181 # Analyze the pcd Value, Datum type and TokenNumber.
1182 # Used to avoid split issue while the value string contain "|" character
1184 # @param[in] Setting: A String contain value/datum type/token number information;
1186 # @retval ValueList: A List contain value, datum type and toke number.
1188 def AnalyzePcdData(Setting
):
1189 ValueList
= ['', '', '']
1191 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1192 PtrValue
= ValueRe
.findall(Setting
)
1194 ValueUpdateFlag
= False
1196 if len(PtrValue
) >= 1:
1197 Setting
= re
.sub(ValueRe
, '', Setting
)
1198 ValueUpdateFlag
= True
1200 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1201 ValueList
[0:len(TokenList
)] = TokenList
1204 ValueList
[0] = PtrValue
[0]
1208 ## AnalyzeHiiPcdData
1210 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1211 # Used to avoid split issue while the value string contain "|" character
1213 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1215 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1217 def AnalyzeHiiPcdData(Setting
):
1218 ValueList
= ['', '', '', '']
1220 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1221 PtrValue
= ValueRe
.findall(Setting
)
1223 ValueUpdateFlag
= False
1225 if len(PtrValue
) >= 1:
1226 Setting
= re
.sub(ValueRe
, '', Setting
)
1227 ValueUpdateFlag
= True
1229 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1230 ValueList
[0:len(TokenList
)] = TokenList
1233 ValueList
[0] = PtrValue
[0]
1237 ## AnalyzeVpdPcdData
1239 # Analyze the vpd pcd Value, Datum type and TokenNumber.
1240 # Used to avoid split issue while the value string contain "|" character
1242 # @param[in] Setting: A String contain value/datum type/token number information;
1244 # @retval ValueList: A List contain value, datum type and toke number.
1246 def AnalyzeVpdPcdData(Setting
):
1247 ValueList
= ['', '', '']
1249 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
1250 PtrValue
= ValueRe
.findall(Setting
)
1252 ValueUpdateFlag
= False
1254 if len(PtrValue
) >= 1:
1255 Setting
= re
.sub(ValueRe
, '', Setting
)
1256 ValueUpdateFlag
= True
1258 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1259 ValueList
[0:len(TokenList
)] = TokenList
1262 ValueList
[2] = PtrValue
[0]
1266 ## check format of PCD value against its the datum type
1268 # For PCD value setting
1270 def CheckPcdDatum(Type
, Value
):
1272 if not (((Value
.startswith('L"') or Value
.startswith('"')) and Value
.endswith('"'))
1273 or (Value
.startswith('{') and Value
.endswith('}'))
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(""):
1283 Value
= long(Value
, 0)
1285 return False, "Invalid value [%s] of type [%s];"\
1286 " must be a hexadecimal, decimal or octal in C language format."\
1291 ## Split command line option string to list
1293 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1294 # in non-windows platform to launch command
1296 def SplitOption(OptionString
):
1301 for Index
in range(0, len(OptionString
)):
1302 CurrentChar
= OptionString
[Index
]
1303 if CurrentChar
in ['"', "'"]:
1304 if QuotationMark
== CurrentChar
:
1306 elif QuotationMark
== "":
1307 QuotationMark
= CurrentChar
1312 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1313 if Index
> OptionStart
:
1314 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1316 LastChar
= CurrentChar
1317 OptionList
.append(OptionString
[OptionStart
:])
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
)
1328 class PathClass(object):
1329 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1330 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1332 self
.File
= str(File
)
1333 if os
.path
.isabs(self
.File
):
1337 self
.Root
= str(Root
)
1338 self
.AlterRoot
= str(AlterRoot
)
1340 # Remove any '.' and '..' in path
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
):]
1351 self
.File
= self
.Path
[len(self
.Root
)+1:]
1353 self
.Path
= os
.path
.normpath(self
.File
)
1355 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1356 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1360 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1362 self
.Dir
= self
.Root
1364 self
.Dir
= self
.SubDir
1369 self
.Type
= self
.Ext
.lower()
1371 self
.IsBinary
= IsBinary
1372 self
.Target
= Target
1373 self
.TagName
= TagName
1374 self
.ToolCode
= ToolCode
1375 self
.ToolChainFamily
= ToolChainFamily
1379 ## Convert the object of this class to a string
1381 # Convert member Path of the class to a string
1383 # @retval string Formatted String
1388 ## Override __eq__ function
1390 # Check whether PathClass are the same
1392 # @retval False The two PathClass are different
1393 # @retval True The two PathClass are the same
1395 def __eq__(self
, Other
):
1396 if type(Other
) == type(self
):
1397 return self
.Path
== Other
.Path
1399 return self
.Path
== str(Other
)
1401 ## Override __cmp__ function
1403 # Customize the comparsion operation of two PathClass
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
1412 OtherKey
= str(Other
)
1415 if SelfKey
== OtherKey
:
1417 elif SelfKey
> OtherKey
:
1422 ## Override __hash__ function
1424 # Use Path as key in hash table
1426 # @retval string Key for hash table
1429 return hash(self
.Path
)
1431 def _GetFileKey(self
):
1432 if self
._Key
== None:
1433 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1436 def _GetTimeStamp(self
):
1437 return os
.stat(self
.Path
)[8]
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
)
1445 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1446 if not RealRoot
and not RealFile
:
1447 RealFile
= self
.File
1449 RealFile
= os
.path
.join(self
.AlterRoot
, self
.File
)
1451 RealFile
= os
.path
.join(self
.Root
, self
.File
)
1452 return FILE_NOT_FOUND
, os
.path
.join(self
.AlterRoot
, RealFile
)
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]"
1461 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1462 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1464 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1467 self
.File
= RealFile
1468 self
.Root
= RealRoot
1469 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1470 return ErrorCode
, ErrorInfo
1472 Key
= property(_GetFileKey
)
1473 TimeStamp
= property(_GetTimeStamp
)
1475 ## Parse PE image to get the required PE informaion.
1477 class PeImageClass():
1480 # @param File FilePath of PeImage
1482 def __init__(self
, PeFile
):
1483 self
.FileName
= PeFile
1484 self
.IsValid
= False
1487 self
.SectionAlignment
= 0
1488 self
.SectionHeaderList
= []
1491 PeObject
= open(PeFile
, 'rb')
1493 self
.ErrorInfo
= self
.FileName
+ ' can not be found\n'
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'
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'
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])
1520 self
.ErrorInfo
= self
.FileName
+ ' has no section header'
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])
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
))
1545 def _ByteListToStr(self
, ByteList
):
1547 for index
in range(len(ByteList
)):
1548 if ByteList
[index
] == 0:
1550 String
+= chr(ByteList
[index
])
1553 def _ByteListToInt(self
, ByteList
):
1555 for index
in range(len(ByteList
) - 1, -1, -1):
1556 Value
= (Value
<< 8) |
int(ByteList
[index
])
1561 # This acts like the main() function for the script, unless it is 'import'ed into another
1564 if __name__
== '__main__':