2 # Common routines used by all tools
4 # Copyright (c) 2007 - 2014, 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.
17 import Common
.LongFilePathOs
as os
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 *
33 from CommonDataClass
.DataClass
import *
34 from Parsing
import GetSplitValueList
35 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
37 ## Regular expression used to find out place holders in string template
38 gPlaceholderPattern
= re
.compile("\$\{([^$()\s]+)\}", re
.MULTILINE|re
.UNICODE
)
40 ## Dictionary used to store file time stamp for quick re-access
41 gFileTimeStampCache
= {} # {file path : file time stamp}
43 ## Dictionary used to store dependencies of files
44 gDependencyDatabase
= {} # arch : {file path : [dependent files list]}
46 ## callback routine for processing variable option
48 # This function can be used to process variable number of option values. The
49 # typical usage of it is specify architecure list on command line.
50 # (e.g. <tool> -a IA32 X64 IPF)
52 # @param Option Standard callback function parameter
53 # @param OptionString Standard callback function parameter
54 # @param Value Standard callback function parameter
55 # @param Parser Standard callback function parameter
59 def ProcessVariableArgument(Option
, OptionString
, Value
, Parser
):
62 RawArgs
= Parser
.rargs
65 if (Arg
[:2] == "--" and len(Arg
) > 2) or \
66 (Arg
[:1] == "-" and len(Arg
) > 1 and Arg
[1] != "-"):
70 setattr(Parser
.values
, Option
.dest
, Value
)
72 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
74 # @param Guid The GUID string
76 # @retval string The GUID string in C structure style
78 def GuidStringToGuidStructureString(Guid
):
79 GuidList
= Guid
.split('-')
81 for Index
in range(0,3,1):
82 Result
= Result
+ '0x' + GuidList
[Index
] + ', '
83 Result
= Result
+ '{0x' + GuidList
[3][0:2] + ', 0x' + GuidList
[3][2:4]
84 for Index
in range(0,12,2):
85 Result
= Result
+ ', 0x' + GuidList
[4][Index
:Index
+2]
89 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
91 # @param GuidValue The GUID value in byte array
93 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
95 def GuidStructureByteArrayToGuidString(GuidValue
):
96 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
97 guidValueList
= guidValueString
.split(",")
98 if len(guidValueList
) != 16:
100 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
102 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
103 int(guidValueList
[3], 16),
104 int(guidValueList
[2], 16),
105 int(guidValueList
[1], 16),
106 int(guidValueList
[0], 16),
107 int(guidValueList
[5], 16),
108 int(guidValueList
[4], 16),
109 int(guidValueList
[7], 16),
110 int(guidValueList
[6], 16),
111 int(guidValueList
[8], 16),
112 int(guidValueList
[9], 16),
113 int(guidValueList
[10], 16),
114 int(guidValueList
[11], 16),
115 int(guidValueList
[12], 16),
116 int(guidValueList
[13], 16),
117 int(guidValueList
[14], 16),
118 int(guidValueList
[15], 16)
123 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
125 # @param GuidValue The GUID value in C structure format
127 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
129 def GuidStructureStringToGuidString(GuidValue
):
130 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
131 guidValueList
= guidValueString
.split(",")
132 if len(guidValueList
) != 11:
134 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
136 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
137 int(guidValueList
[0], 16),
138 int(guidValueList
[1], 16),
139 int(guidValueList
[2], 16),
140 int(guidValueList
[3], 16),
141 int(guidValueList
[4], 16),
142 int(guidValueList
[5], 16),
143 int(guidValueList
[6], 16),
144 int(guidValueList
[7], 16),
145 int(guidValueList
[8], 16),
146 int(guidValueList
[9], 16),
147 int(guidValueList
[10], 16)
152 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
154 # @param GuidValue The GUID value in C structure format
156 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
158 def GuidStructureStringToGuidValueName(GuidValue
):
159 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "")
160 guidValueList
= guidValueString
.split(",")
161 if len(guidValueList
) != 11:
162 EdkLogger
.error(None, FORMAT_INVALID
, "Invalid GUID value string [%s]" % GuidValue
)
163 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
164 int(guidValueList
[0], 16),
165 int(guidValueList
[1], 16),
166 int(guidValueList
[2], 16),
167 int(guidValueList
[3], 16),
168 int(guidValueList
[4], 16),
169 int(guidValueList
[5], 16),
170 int(guidValueList
[6], 16),
171 int(guidValueList
[7], 16),
172 int(guidValueList
[8], 16),
173 int(guidValueList
[9], 16),
174 int(guidValueList
[10], 16)
177 ## Create directories
179 # @param Directory The directory name
181 def CreateDirectory(Directory
):
182 if Directory
== None or Directory
.strip() == "":
185 if not os
.access(Directory
, os
.F_OK
):
186 os
.makedirs(Directory
)
191 ## Remove directories, including files and sub-directories in it
193 # @param Directory The directory name
195 def RemoveDirectory(Directory
, Recursively
=False):
196 if Directory
== None or Directory
.strip() == "" or not os
.path
.exists(Directory
):
199 CurrentDirectory
= os
.getcwd()
201 for File
in os
.listdir("."):
202 if os
.path
.isdir(File
):
203 RemoveDirectory(File
, Recursively
)
206 os
.chdir(CurrentDirectory
)
209 ## Check if given file is changed or not
211 # This method is used to check if a file is changed or not between two build
212 # actions. It makes use a cache to store files timestamp.
214 # @param File The path of file
216 # @retval True If the given file is changed, doesn't exist, or can't be
217 # found in timestamp cache
218 # @retval False If the given file is changed
221 if not os
.path
.exists(File
):
224 FileState
= os
.stat(File
)
225 TimeStamp
= FileState
[-2]
227 if File
in gFileTimeStampCache
and TimeStamp
== gFileTimeStampCache
[File
]:
231 gFileTimeStampCache
[File
] = TimeStamp
235 ## Store content in file
237 # This method is used to save file only when its content is changed. This is
238 # quite useful for "make" system to decide what will be re-built and what won't.
240 # @param File The path of file
241 # @param Content The new content of the file
242 # @param IsBinaryFile The flag indicating if the file is binary file or not
244 # @retval True If the file content is changed and the file is renewed
245 # @retval False If the file content is the same
247 def SaveFileOnChange(File
, Content
, IsBinaryFile
=True):
249 Content
= Content
.replace("\n", os
.linesep
)
251 if os
.path
.exists(File
):
253 if Content
== open(File
, "rb").read():
256 EdkLogger
.error(None, FILE_OPEN_FAILURE
, ExtraData
=File
)
258 DirName
= os
.path
.dirname(File
)
259 if not CreateDirectory(DirName
):
260 EdkLogger
.error(None, FILE_CREATE_FAILURE
, "Could not create directory %s" % DirName
)
263 DirName
= os
.getcwd()
264 if not os
.access(DirName
, os
.W_OK
):
265 EdkLogger
.error(None, PERMISSION_FAILURE
, "Do not have write permission on directory %s" % DirName
)
268 if GlobalData
.gIsWindows
:
270 from PyUtility
import SaveFileToDisk
271 if not SaveFileToDisk(File
, Content
):
272 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
274 Fd
= open(File
, "wb")
278 Fd
= open(File
, "wb")
282 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
='IOError %s'%X)
286 ## Make a Python object persistent on file system
288 # @param Data The object to be stored in file
289 # @param File The path of file to store the object
291 def DataDump(Data
, File
):
294 Fd
= open(File
, 'wb')
295 cPickle
.dump(Data
, Fd
, cPickle
.HIGHEST_PROTOCOL
)
297 EdkLogger
.error("", FILE_OPEN_FAILURE
, ExtraData
=File
, RaiseError
=False)
302 ## Restore a Python object from a file
304 # @param File The path of file stored the object
306 # @retval object A python object
307 # @retval None If failure in file operation
309 def DataRestore(File
):
313 Fd
= open(File
, 'rb')
314 Data
= cPickle
.load(Fd
)
316 EdkLogger
.verbose("Failed to load [%s]\n\t%s" % (File
, str(e
)))
323 ## Retrieve and cache the real path name in file system
325 # @param Root The root directory of path relative to
327 # @retval str The path string if the path exists
328 # @retval None If path doesn't exist
334 def __init__(self
, Root
):
336 for F
in os
.listdir(Root
):
338 self
._UPPER
_CACHE
_[F
.upper()] = F
341 def __getitem__(self
, Path
):
342 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
345 if Path
and Path
[0] == os
.path
.sep
:
347 if Path
in self
._CACHE
_:
348 return os
.path
.join(self
._Root
, Path
)
349 UpperPath
= Path
.upper()
350 if UpperPath
in self
._UPPER
_CACHE
_:
351 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
355 SepIndex
= Path
.find(os
.path
.sep
)
357 Parent
= UpperPath
[:SepIndex
]
358 if Parent
not in self
._UPPER
_CACHE
_:
360 LastSepIndex
= SepIndex
361 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
363 if LastSepIndex
== -1:
368 SepIndex
= LastSepIndex
370 Parent
= Path
[:SepIndex
]
371 ParentKey
= UpperPath
[:SepIndex
]
372 if ParentKey
not in self
._UPPER
_CACHE
_:
376 if Parent
in self
._CACHE
_:
379 ParentDir
= self
._UPPER
_CACHE
_[ParentKey
]
380 for F
in os
.listdir(ParentDir
):
381 Dir
= os
.path
.join(ParentDir
, F
)
382 self
._CACHE
_.add(Dir
)
383 self
._UPPER
_CACHE
_[Dir
.upper()] = Dir
385 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
388 if Path
in self
._CACHE
_:
389 return os
.path
.join(self
._Root
, Path
)
390 elif UpperPath
in self
._UPPER
_CACHE
_:
391 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
394 ## Get all files of a directory
396 # @param Root: Root dir
397 # @param SkipList : The files need be skipped
399 # @retval A list of all files
401 def GetFiles(Root
, SkipList
=None, FullPath
= True):
404 for Root
, Dirs
, Files
in os
.walk(Root
):
406 for Item
in SkipList
:
411 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
413 File
= File
[len(OriPath
) + 1:]
414 FileList
.append(File
)
418 ## Check if gvien file exists or not
420 # @param File File name or path to be checked
421 # @param Dir The directory the file is relative to
423 # @retval True if file exists
424 # @retval False if file doesn't exists
426 def ValidFile(File
, Ext
=None):
428 Dummy
, FileExt
= os
.path
.splitext(File
)
429 if FileExt
.lower() != Ext
.lower():
431 if not os
.path
.exists(File
):
435 def RealPath(File
, Dir
='', OverrideDir
=''):
436 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
437 NewFile
= GlobalData
.gAllFiles
[NewFile
]
438 if not NewFile
and OverrideDir
:
439 NewFile
= os
.path
.normpath(os
.path
.join(OverrideDir
, File
))
440 NewFile
= GlobalData
.gAllFiles
[NewFile
]
443 def RealPath2(File
, Dir
='', OverrideDir
=''):
445 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
447 if OverrideDir
[-1] == os
.path
.sep
:
448 return NewFile
[len(OverrideDir
):], NewFile
[0:len(OverrideDir
)]
450 return NewFile
[len(OverrideDir
)+1:], NewFile
[0:len(OverrideDir
)]
451 if GlobalData
.gAllFiles
:
452 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
454 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
457 if Dir
[-1] == os
.path
.sep
:
458 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
460 return NewFile
[len(Dir
)+1:], NewFile
[0:len(Dir
)]
466 ## Check if gvien file exists or not
469 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
472 Dummy
, FileExt
= os
.path
.splitext(File
)
473 if FileExt
.lower() != Ext
.lower():
476 # Replace the Edk macros
477 if OverrideDir
!= '' and OverrideDir
!= None:
478 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
479 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
480 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
481 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
483 # Replace the default dir to current dir
486 Dir
= Dir
[len(Workspace
)+1:]
488 # First check if File has Edk definition itself
489 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
490 NewFile
= File
.replace('$(EFI_SOURCE)', EfiSource
)
491 NewFile
= NewFile
.replace('$(EDK_SOURCE)', EdkSource
)
492 NewFile
= AllFiles
[os
.path
.normpath(NewFile
)]
496 # Second check the path with override value
497 if OverrideDir
!= '' and OverrideDir
!= None:
498 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
502 # Last check the path with normal definitions
503 File
= os
.path
.join(Dir
, File
)
504 NewFile
= AllFiles
[os
.path
.normpath(File
)]
510 ## Check if gvien file exists or not
513 def ValidFile3(AllFiles
, File
, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
514 # Replace the Edk macros
515 if OverrideDir
!= '' and OverrideDir
!= None:
516 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
517 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
518 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
519 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
521 # Replace the default dir to current dir
522 # Dir is current module dir related to workspace
525 Dir
= Dir
[len(Workspace
)+1:]
528 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
529 NewRelaPath
= RelaPath
532 # First check if File has Edk definition itself
533 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
534 File
= File
.replace('$(EFI_SOURCE)', EfiSource
)
535 File
= File
.replace('$(EDK_SOURCE)', EdkSource
)
536 NewFile
= AllFiles
[os
.path
.normpath(File
)]
538 NewRelaPath
= os
.path
.dirname(NewFile
)
539 File
= os
.path
.basename(NewFile
)
540 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
543 # Second check the path with override value
544 if OverrideDir
!= '' and OverrideDir
!= None:
545 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
547 #NewRelaPath = os.path.dirname(NewFile)
548 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
551 # Last check the path with normal definitions
552 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
559 return NewRelaPath
, RelaPath
, File
562 def GetRelPath(Path1
, Path2
):
563 FileName
= os
.path
.basename(Path2
)
564 L1
= os
.path
.normpath(Path1
).split(os
.path
.normpath('/'))
565 L2
= os
.path
.normpath(Path2
).split(os
.path
.normpath('/'))
566 for Index
in range(0, len(L1
)):
567 if L1
[Index
] != L2
[Index
]:
568 FileName
= '../' * (len(L1
) - Index
)
569 for Index2
in range(Index
, len(L2
)):
570 FileName
= os
.path
.join(FileName
, L2
[Index2
])
572 return os
.path
.normpath(FileName
)
575 ## Get GUID value from given packages
577 # @param CName The CName of the GUID
578 # @param PackageList List of packages looking-up in
580 # @retval GuidValue if the CName is found in any given package
581 # @retval None if the CName is not found in all given packages
583 def GuidValue(CName
, PackageList
):
584 for P
in PackageList
:
586 return P
.Guids
[CName
]
589 ## Get Protocol value from given packages
591 # @param CName The CName of the GUID
592 # @param PackageList List of packages looking-up in
594 # @retval GuidValue if the CName is found in any given package
595 # @retval None if the CName is not found in all given packages
597 def ProtocolValue(CName
, PackageList
):
598 for P
in PackageList
:
599 if CName
in P
.Protocols
:
600 return P
.Protocols
[CName
]
603 ## Get PPI value from given packages
605 # @param CName The CName of the GUID
606 # @param PackageList List of packages looking-up in
608 # @retval GuidValue if the CName is found in any given package
609 # @retval None if the CName is not found in all given packages
611 def PpiValue(CName
, PackageList
):
612 for P
in PackageList
:
617 ## A string template class
619 # This class implements a template for string replacement. A string template
620 # looks like following
622 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
624 # The string between ${BEGIN} and ${END} will be repeated as many times as the
625 # length of "placeholder_name", which is a list passed through a dict. The
626 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
627 # be not used and, in this case, the "placeholder_name" must not a list and it
628 # will just be replaced once.
630 class TemplateString(object):
631 _REPEAT_START_FLAG
= "BEGIN"
632 _REPEAT_END_FLAG
= "END"
634 class Section(object):
635 _LIST_TYPES
= [type([]), type(set()), type((0,))]
637 def __init__(self
, TemplateSection
, PlaceHolderList
):
638 self
._Template
= TemplateSection
639 self
._PlaceHolderList
= []
641 # Split the section into sub-sections according to the position of placeholders
643 self
._SubSectionList
= []
646 # The placeholders passed in must be in the format of
648 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
650 for PlaceHolder
,Start
,End
in PlaceHolderList
:
651 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:Start
])
652 self
._SubSectionList
.append(TemplateSection
[Start
:End
])
653 self
._PlaceHolderList
.append(PlaceHolder
)
654 SubSectionStart
= End
655 if SubSectionStart
< len(TemplateSection
):
656 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:])
658 self
._SubSectionList
= [TemplateSection
]
661 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
663 def Instantiate(self
, PlaceHolderValues
):
665 RepeatPlaceHolders
= {}
666 NonRepeatPlaceHolders
= {}
668 for PlaceHolder
in self
._PlaceHolderList
:
669 if PlaceHolder
not in PlaceHolderValues
:
671 Value
= PlaceHolderValues
[PlaceHolder
]
672 if type(Value
) in self
._LIST
_TYPES
:
674 RepeatTime
= len(Value
)
675 elif RepeatTime
!= len(Value
):
679 "${%s} has different repeat time from others!" % PlaceHolder
,
680 ExtraData
=str(self
._Template
)
682 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
684 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
686 if NonRepeatPlaceHolders
:
688 for S
in self
._SubSectionList
:
689 if S
not in NonRepeatPlaceHolders
:
692 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
694 StringList
= self
._SubSectionList
696 if RepeatPlaceHolders
:
698 for Index
in range(RepeatTime
):
700 if S
not in RepeatPlaceHolders
:
701 TempStringList
.append(S
)
703 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
704 StringList
= TempStringList
706 return "".join(StringList
)
709 def __init__(self
, Template
=None):
711 self
.IsBinary
= False
712 self
._Template
= Template
713 self
._TemplateSectionList
= self
._Parse
(Template
)
717 # @retval string The string replaced
722 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
724 # @retval list A list of TemplateString.Section objects
726 def _Parse(self
, Template
):
731 TemplateSectionList
= []
733 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
735 if MatchEnd
<= len(Template
):
736 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
737 TemplateSectionList
.append(TemplateSection
)
740 MatchString
= MatchObj
.group(1)
741 MatchStart
= MatchObj
.start()
742 MatchEnd
= MatchObj
.end()
744 if MatchString
== self
._REPEAT
_START
_FLAG
:
745 if MatchStart
> SectionStart
:
746 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
747 TemplateSectionList
.append(TemplateSection
)
748 SectionStart
= MatchEnd
750 elif MatchString
== self
._REPEAT
_END
_FLAG
:
751 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
752 TemplateSectionList
.append(TemplateSection
)
753 SectionStart
= MatchEnd
756 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
757 SearchFrom
= MatchEnd
758 return TemplateSectionList
760 ## Replace the string template with dictionary of placeholders and append it to previous one
762 # @param AppendString The string template to append
763 # @param Dictionary The placeholder dictionaries
765 def Append(self
, AppendString
, Dictionary
=None):
767 SectionList
= self
._Parse
(AppendString
)
768 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
770 self
.String
+= AppendString
772 ## Replace the string template with dictionary of placeholders
774 # @param Dictionary The placeholder dictionaries
776 # @retval str The string replaced with placeholder values
778 def Replace(self
, Dictionary
=None):
779 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
781 ## Progress indicator class
783 # This class makes use of thread to print progress on console.
786 # for avoiding deadloop
788 _ProgressThread
= None
789 _CheckInterval
= 0.25
793 # @param OpenMessage The string printed before progress charaters
794 # @param CloseMessage The string printed after progress charaters
795 # @param ProgressChar The charater used to indicate the progress
796 # @param Interval The interval in seconds between two progress charaters
798 def __init__(self
, OpenMessage
="", CloseMessage
="", ProgressChar
='.', Interval
=1.0):
799 self
.PromptMessage
= OpenMessage
800 self
.CodaMessage
= CloseMessage
801 self
.ProgressChar
= ProgressChar
802 self
.Interval
= Interval
803 if Progressor
._StopFlag
== None:
804 Progressor
._StopFlag
= threading
.Event()
806 ## Start to print progress charater
808 # @param OpenMessage The string printed before progress charaters
810 def Start(self
, OpenMessage
=None):
811 if OpenMessage
!= None:
812 self
.PromptMessage
= OpenMessage
813 Progressor
._StopFlag
.clear()
814 if Progressor
._ProgressThread
== None:
815 Progressor
._ProgressThread
= threading
.Thread(target
=self
._ProgressThreadEntry
)
816 Progressor
._ProgressThread
.setDaemon(False)
817 Progressor
._ProgressThread
.start()
819 ## Stop printing progress charater
821 # @param CloseMessage The string printed after progress charaters
823 def Stop(self
, CloseMessage
=None):
824 OriginalCodaMessage
= self
.CodaMessage
825 if CloseMessage
!= None:
826 self
.CodaMessage
= CloseMessage
828 self
.CodaMessage
= OriginalCodaMessage
830 ## Thread entry method
831 def _ProgressThreadEntry(self
):
832 sys
.stdout
.write(self
.PromptMessage
+ " ")
835 while not Progressor
._StopFlag
.isSet():
837 sys
.stdout
.write(self
.ProgressChar
)
839 TimeUp
= self
.Interval
840 time
.sleep(self
._CheckInterval
)
841 TimeUp
-= self
._CheckInterval
842 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
845 ## Abort the progress display
848 if Progressor
._StopFlag
!= None:
849 Progressor
._StopFlag
.set()
850 if Progressor
._ProgressThread
!= None:
851 Progressor
._ProgressThread
.join()
852 Progressor
._ProgressThread
= None
854 ## A dict which can access its keys and/or values orderly
856 # The class implements a new kind of dict which its keys or values can be
857 # accessed in the order they are added into the dict. It guarantees the order
858 # by making use of an internal list to keep a copy of keys.
860 class sdict(IterableUserDict
):
863 IterableUserDict
.__init
__(self
)
867 def __setitem__(self
, key
, value
):
868 if key
not in self
._key
_list
:
869 self
._key
_list
.append(key
)
870 IterableUserDict
.__setitem
__(self
, key
, value
)
873 def __delitem__(self
, key
):
874 self
._key
_list
.remove(key
)
875 IterableUserDict
.__delitem
__(self
, key
)
877 ## used in "for k in dict" loop to ensure the correct order
879 return self
.iterkeys()
883 return len(self
._key
_list
)
886 def __contains__(self
, key
):
887 return key
in self
._key
_list
890 def index(self
, key
):
891 return self
._key
_list
.index(key
)
894 def insert(self
, key
, newkey
, newvalue
, order
):
895 index
= self
._key
_list
.index(key
)
896 if order
== 'BEFORE':
897 self
._key
_list
.insert(index
, newkey
)
898 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
899 elif order
== 'AFTER':
900 self
._key
_list
.insert(index
+ 1, newkey
)
901 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
904 def append(self
, sdict
):
906 if key
not in self
._key
_list
:
907 self
._key
_list
.append(key
)
908 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
910 def has_key(self
, key
):
911 return key
in self
._key
_list
916 IterableUserDict
.clear(self
)
918 ## Return a copy of keys
921 for key
in self
._key
_list
:
925 ## Return a copy of values
928 for key
in self
._key
_list
:
929 values
.append(self
[key
])
932 ## Return a copy of (key, value) list
935 for key
in self
._key
_list
:
936 items
.append((key
, self
[key
]))
941 return iter(self
.items())
943 ## Keys interation support
945 return iter(self
.keys())
947 ## Values interation support
948 def itervalues(self
):
949 return iter(self
.values())
951 ## Return value related to a key, and remove the (key, value) from the dict
952 def pop(self
, key
, *dv
):
954 if key
in self
._key
_list
:
956 self
.__delitem
__(key
)
961 ## Return (key, value) pair, and remove the (key, value) from the dict
963 key
= self
._key
_list
[-1]
965 self
.__delitem
__(key
)
968 def update(self
, dict=None, **kwargs
):
970 for k
, v
in dict.items():
973 for k
, v
in kwargs
.items():
976 ## Dictionary with restricted keys
980 def __init__(self
, KeyList
):
982 dict.__setitem
__(self
, Key
, "")
985 def __setitem__(self
, key
, value
):
987 EdkLogger
.error("RestrictedDict", ATTRIBUTE_SET_FAILURE
, "Key [%s] is not allowed" % key
,
988 ExtraData
=", ".join(dict.keys(self
)))
989 dict.__setitem
__(self
, key
, value
)
992 def __getitem__(self
, key
):
995 return dict.__getitem
__(self
, key
)
998 def __delitem__(self
, key
):
999 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
1004 self
.__setitem
__(Key
, "")
1006 ## Return value related to a key, and remove the (key, value) from the dict
1007 def pop(self
, key
, *dv
):
1008 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="pop")
1010 ## Return (key, value) pair, and remove the (key, value) from the dict
1012 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
1014 ## Dictionary using prioritized list as key
1017 _ListType
= type([])
1018 _TupleType
= type(())
1019 _Wildcard
= 'COMMON'
1020 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1022 def __init__(self
, _Single_
=False, _Level_
=2):
1023 self
._Level
_ = _Level_
1025 self
._Single
_ = _Single_
1028 def __getitem__(self
, key
):
1031 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1035 elif self
._Level
_ > 1:
1036 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1039 if self
._Level
_ > 1:
1040 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1042 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1043 FirstKey
= self
._Wildcard
1046 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1048 return self
._GetAllValues
(FirstKey
, RestKeys
)
1050 def _GetSingleValue(self
, FirstKey
, RestKeys
):
1052 #print "%s-%s" % (FirstKey, self._Level_) ,
1053 if self
._Level
_ > 1:
1054 if FirstKey
== self
._Wildcard
:
1055 if FirstKey
in self
.data
:
1056 Value
= self
.data
[FirstKey
][RestKeys
]
1058 for Key
in self
.data
:
1059 Value
= self
.data
[Key
][RestKeys
]
1060 if Value
!= None: break
1062 if FirstKey
in self
.data
:
1063 Value
= self
.data
[FirstKey
][RestKeys
]
1064 if Value
== None and self
._Wildcard
in self
.data
:
1066 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1068 if FirstKey
== self
._Wildcard
:
1069 if FirstKey
in self
.data
:
1070 Value
= self
.data
[FirstKey
]
1072 for Key
in self
.data
:
1073 Value
= self
.data
[Key
]
1074 if Value
!= None: break
1076 if FirstKey
in self
.data
:
1077 Value
= self
.data
[FirstKey
]
1078 elif self
._Wildcard
in self
.data
:
1079 Value
= self
.data
[self
._Wildcard
]
1082 def _GetAllValues(self
, FirstKey
, RestKeys
):
1084 if self
._Level
_ > 1:
1085 if FirstKey
== self
._Wildcard
:
1086 for Key
in self
.data
:
1087 Value
+= self
.data
[Key
][RestKeys
]
1089 if FirstKey
in self
.data
:
1090 Value
+= self
.data
[FirstKey
][RestKeys
]
1091 if self
._Wildcard
in self
.data
:
1092 Value
+= self
.data
[self
._Wildcard
][RestKeys
]
1094 if FirstKey
== self
._Wildcard
:
1095 for Key
in self
.data
:
1096 Value
.append(self
.data
[Key
])
1098 if FirstKey
in self
.data
:
1099 Value
.append(self
.data
[FirstKey
])
1100 if self
._Wildcard
in self
.data
:
1101 Value
.append(self
.data
[self
._Wildcard
])
1105 def __setitem__(self
, key
, value
):
1108 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1113 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1116 if self
._Level
_ > 1:
1117 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1119 if FirstKey
in self
._ValidWildcardList
:
1120 FirstKey
= self
._Wildcard
1122 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1123 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1125 if self
._Level
_ > 1:
1126 self
.data
[FirstKey
][RestKeys
] = value
1128 self
.data
[FirstKey
] = value
1130 def SetGreedyMode(self
):
1131 self
._Single
_ = False
1132 if self
._Level
_ > 1:
1133 for Key
in self
.data
:
1134 self
.data
[Key
].SetGreedyMode()
1136 def SetSingleMode(self
):
1137 self
._Single
_ = True
1138 if self
._Level
_ > 1:
1139 for Key
in self
.data
:
1140 self
.data
[Key
].SetSingleMode()
1142 def GetKeys(self
, KeyIndex
=0):
1143 assert KeyIndex
>= 0
1145 return set(self
.data
.keys())
1148 for Key
in self
.data
:
1149 keys |
= self
.data
[Key
].GetKeys(KeyIndex
- 1)
1152 ## Boolean chain list
1154 class Blist(UserList
):
1155 def __init__(self
, initlist
=None):
1156 UserList
.__init
__(self
, initlist
)
1157 def __setitem__(self
, i
, item
):
1158 if item
not in [True, False]:
1164 def _GetResult(self
):
1166 for item
in self
.data
:
1169 Result
= property(_GetResult
)
1171 def ParseConsoleLog(Filename
):
1172 Opr
= open(os
.path
.normpath(Filename
), 'r')
1173 Opw
= open(os
.path
.normpath(Filename
+ '.New'), 'w+')
1174 for Line
in Opr
.readlines():
1175 if Line
.find('.efi') > -1:
1176 Line
= Line
[Line
.rfind(' ') : Line
.rfind('.efi')].strip()
1177 Opw
.write('%s\n' % Line
)
1184 # Analyze DSC PCD value, since there is no data type info in DSC
1185 # This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
1186 # 1. Feature flag: TokenSpace.PcdCName|PcdValue
1187 # 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
1188 # 3. Dynamic default:
1189 # TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
1190 # TokenSpace.PcdCName|PcdValue
1192 # TokenSpace.PcdCName|VpdOffset[|VpdValue]
1193 # TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
1195 # TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
1196 # PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
1197 # there might have "|" operator, also in string value.
1199 # @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
1200 # @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
1201 # @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
1203 # ValueList: A List contain fields described above
1204 # IsValid: True if conforming EBNF, otherwise False
1205 # Index: The index where PcdValue is in ValueList
1207 def AnalyzeDscPcd(Setting
, PcdType
, DataType
=''):
1208 Setting
= Setting
.strip()
1209 # There might be escaped quote in a string: \", \\\"
1210 Data
= Setting
.replace('\\\\', '//').replace('\\\"', '\\\'')
1211 # There might be '|' in string and in ( ... | ... ), replace it with '-'
1218 elif ch
== '(' and not InStr
:
1220 elif ch
== ')' and not InStr
:
1223 if (Pair
> 0 or InStr
) and ch
== TAB_VALUE_SPLIT
:
1230 Pos
= NewStr
.find(TAB_VALUE_SPLIT
, StartPos
)
1232 FieldList
.append(Setting
[StartPos
:].strip())
1234 FieldList
.append(Setting
[StartPos
:Pos
].strip())
1238 if PcdType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_FEATURE_FLAG
):
1239 Value
= FieldList
[0]
1241 if len(FieldList
) > 1:
1243 # Fix the PCD type when no DataType input
1248 if len(FieldList
) > 2:
1250 if DataType
== 'VOID*':
1251 IsValid
= (len(FieldList
) <= 3)
1253 IsValid
= (len(FieldList
) <= 1)
1254 return [Value
, '', Size
], IsValid
, 0
1255 elif PcdType
in (MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
):
1256 Value
= FieldList
[0]
1258 if len(FieldList
) > 1:
1262 if len(FieldList
) > 2:
1266 if Value
.startswith("L"):
1267 Size
= str((len(Value
)- 3 + 1) * 2)
1268 elif Value
.startswith("{"):
1269 Size
= str(len(Value
.split(",")))
1271 Size
= str(len(Value
) -2 + 1 )
1272 if DataType
== 'VOID*':
1273 IsValid
= (len(FieldList
) <= 3)
1275 IsValid
= (len(FieldList
) <= 1)
1276 return [Value
, Type
, Size
], IsValid
, 0
1277 elif PcdType
in (MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_VPD
):
1278 VpdOffset
= FieldList
[0]
1280 if not DataType
== 'VOID*':
1281 if len(FieldList
) > 1:
1282 Value
= FieldList
[1]
1284 if len(FieldList
) > 1:
1286 if len(FieldList
) > 2:
1287 Value
= FieldList
[2]
1288 if DataType
== 'VOID*':
1289 IsValid
= (len(FieldList
) <= 3)
1291 IsValid
= (len(FieldList
) <= 2)
1292 return [VpdOffset
, Size
, Value
], IsValid
, 2
1293 elif PcdType
in (MODEL_PCD_DYNAMIC_HII
, MODEL_PCD_DYNAMIC_EX_HII
):
1294 HiiString
= FieldList
[0]
1295 Guid
= Offset
= Value
= ''
1296 if len(FieldList
) > 1:
1298 if len(FieldList
) > 2:
1299 Offset
= FieldList
[2]
1300 if len(FieldList
) > 3:
1301 Value
= FieldList
[3]
1302 IsValid
= (3 <= len(FieldList
) <= 4)
1303 return [HiiString
, Guid
, Offset
, Value
], IsValid
, 3
1308 # Analyze the pcd Value, Datum type and TokenNumber.
1309 # Used to avoid split issue while the value string contain "|" character
1311 # @param[in] Setting: A String contain value/datum type/token number information;
1313 # @retval ValueList: A List contain value, datum type and toke number.
1315 def AnalyzePcdData(Setting
):
1316 ValueList
= ['', '', '']
1318 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1319 PtrValue
= ValueRe
.findall(Setting
)
1321 ValueUpdateFlag
= False
1323 if len(PtrValue
) >= 1:
1324 Setting
= re
.sub(ValueRe
, '', Setting
)
1325 ValueUpdateFlag
= True
1327 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1328 ValueList
[0:len(TokenList
)] = TokenList
1331 ValueList
[0] = PtrValue
[0]
1335 ## AnalyzeHiiPcdData
1337 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1338 # Used to avoid split issue while the value string contain "|" character
1340 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1342 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1344 def AnalyzeHiiPcdData(Setting
):
1345 ValueList
= ['', '', '', '']
1347 TokenList
= GetSplitValueList(Setting
)
1348 ValueList
[0:len(TokenList
)] = TokenList
1352 ## AnalyzeVpdPcdData
1354 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1355 # Used to avoid split issue while the value string contain "|" character
1357 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1359 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1361 def AnalyzeVpdPcdData(Setting
):
1362 ValueList
= ['', '', '']
1364 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
1365 PtrValue
= ValueRe
.findall(Setting
)
1367 ValueUpdateFlag
= False
1369 if len(PtrValue
) >= 1:
1370 Setting
= re
.sub(ValueRe
, '', Setting
)
1371 ValueUpdateFlag
= True
1373 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1374 ValueList
[0:len(TokenList
)] = TokenList
1377 ValueList
[2] = PtrValue
[0]
1381 ## check format of PCD value against its the datum type
1383 # For PCD value setting
1385 def CheckPcdDatum(Type
, Value
):
1387 ValueRe
= re
.compile(r
'\s*L?\".*\"\s*$')
1388 if not (((Value
.startswith('L"') or Value
.startswith('"')) and Value
.endswith('"'))
1389 or (Value
.startswith('{') and Value
.endswith('}'))
1391 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1392 ", or \"...\" for string, or L\"...\" for unicode string" % (Value
, Type
)
1393 elif ValueRe
.match(Value
):
1394 # Check the chars in UnicodeString or CString is printable
1395 if Value
.startswith("L"):
1399 Printset
= set(string
.printable
)
1400 Printset
.remove(TAB_PRINTCHAR_VT
)
1401 Printset
.add(TAB_PRINTCHAR_BS
)
1402 Printset
.add(TAB_PRINTCHAR_NUL
)
1403 if not set(Value
).issubset(Printset
):
1404 PrintList
= list(Printset
)
1406 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type
, PrintList
)
1407 elif Type
== 'BOOLEAN':
1408 if Value
not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1409 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1410 ", FALSE, False, false, 0x0, 0x00, 0" % (Value
, Type
)
1411 elif Type
in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
]:
1413 Value
= long(Value
, 0)
1415 return False, "Invalid value [%s] of type [%s];"\
1416 " must be a hexadecimal, decimal or octal in C language format." % (Value
, Type
)
1418 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type
)
1422 ## Split command line option string to list
1424 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1425 # in non-windows platform to launch command
1427 def SplitOption(OptionString
):
1432 for Index
in range(0, len(OptionString
)):
1433 CurrentChar
= OptionString
[Index
]
1434 if CurrentChar
in ['"', "'"]:
1435 if QuotationMark
== CurrentChar
:
1437 elif QuotationMark
== "":
1438 QuotationMark
= CurrentChar
1443 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1444 if Index
> OptionStart
:
1445 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1447 LastChar
= CurrentChar
1448 OptionList
.append(OptionString
[OptionStart
:])
1451 def CommonPath(PathList
):
1452 P1
= min(PathList
).split(os
.path
.sep
)
1453 P2
= max(PathList
).split(os
.path
.sep
)
1454 for Index
in xrange(min(len(P1
), len(P2
))):
1455 if P1
[Index
] != P2
[Index
]:
1456 return os
.path
.sep
.join(P1
[:Index
])
1457 return os
.path
.sep
.join(P1
)
1459 class PathClass(object):
1460 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1461 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1463 self
.File
= str(File
)
1464 if os
.path
.isabs(self
.File
):
1468 self
.Root
= str(Root
)
1469 self
.AlterRoot
= str(AlterRoot
)
1471 # Remove any '.' and '..' in path
1473 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1474 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1475 # eliminate the side-effect of 'C:'
1476 if self
.Root
[-1] == ':':
1477 self
.Root
+= os
.path
.sep
1478 # file path should not start with path separator
1479 if self
.Root
[-1] == os
.path
.sep
:
1480 self
.File
= self
.Path
[len(self
.Root
):]
1482 self
.File
= self
.Path
[len(self
.Root
)+1:]
1484 self
.Path
= os
.path
.normpath(self
.File
)
1486 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1487 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1491 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1493 self
.Dir
= self
.Root
1495 self
.Dir
= self
.SubDir
1500 self
.Type
= self
.Ext
.lower()
1502 self
.IsBinary
= IsBinary
1503 self
.Target
= Target
1504 self
.TagName
= TagName
1505 self
.ToolCode
= ToolCode
1506 self
.ToolChainFamily
= ToolChainFamily
1510 ## Convert the object of this class to a string
1512 # Convert member Path of the class to a string
1514 # @retval string Formatted String
1519 ## Override __eq__ function
1521 # Check whether PathClass are the same
1523 # @retval False The two PathClass are different
1524 # @retval True The two PathClass are the same
1526 def __eq__(self
, Other
):
1527 if type(Other
) == type(self
):
1528 return self
.Path
== Other
.Path
1530 return self
.Path
== str(Other
)
1532 ## Override __cmp__ function
1534 # Customize the comparsion operation of two PathClass
1536 # @retval 0 The two PathClass are different
1537 # @retval -1 The first PathClass is less than the second PathClass
1538 # @retval 1 The first PathClass is Bigger than the second PathClass
1539 def __cmp__(self
, Other
):
1540 if type(Other
) == type(self
):
1541 OtherKey
= Other
.Path
1543 OtherKey
= str(Other
)
1546 if SelfKey
== OtherKey
:
1548 elif SelfKey
> OtherKey
:
1553 ## Override __hash__ function
1555 # Use Path as key in hash table
1557 # @retval string Key for hash table
1560 return hash(self
.Path
)
1562 def _GetFileKey(self
):
1563 if self
._Key
== None:
1564 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1567 def _GetTimeStamp(self
):
1568 return os
.stat(self
.Path
)[8]
1570 def Validate(self
, Type
='', CaseSensitive
=True):
1571 if GlobalData
.gCaseInsensitive
:
1572 CaseSensitive
= False
1573 if Type
and Type
.lower() != self
.Type
:
1574 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
1576 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1577 if not RealRoot
and not RealFile
:
1578 RealFile
= self
.File
1580 RealFile
= os
.path
.join(self
.AlterRoot
, self
.File
)
1582 RealFile
= os
.path
.join(self
.Root
, self
.File
)
1583 return FILE_NOT_FOUND
, os
.path
.join(self
.AlterRoot
, RealFile
)
1587 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
1588 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
1589 ErrorCode
= FILE_CASE_MISMATCH
1590 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
1592 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1593 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1595 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1598 self
.File
= RealFile
1599 self
.Root
= RealRoot
1600 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1601 return ErrorCode
, ErrorInfo
1603 Key
= property(_GetFileKey
)
1604 TimeStamp
= property(_GetTimeStamp
)
1606 ## Parse PE image to get the required PE informaion.
1608 class PeImageClass():
1611 # @param File FilePath of PeImage
1613 def __init__(self
, PeFile
):
1614 self
.FileName
= PeFile
1615 self
.IsValid
= False
1618 self
.SectionAlignment
= 0
1619 self
.SectionHeaderList
= []
1622 PeObject
= open(PeFile
, 'rb')
1624 self
.ErrorInfo
= self
.FileName
+ ' can not be found\n'
1627 ByteArray
= array
.array('B')
1628 ByteArray
.fromfile(PeObject
, 0x3E)
1629 ByteList
= ByteArray
.tolist()
1630 # DOS signature should be 'MZ'
1631 if self
._ByteListToStr
(ByteList
[0x0:0x2]) != 'MZ':
1632 self
.ErrorInfo
= self
.FileName
+ ' has no valid DOS signature MZ'
1635 # Read 4 byte PE Signature
1636 PeOffset
= self
._ByteListToInt
(ByteList
[0x3C:0x3E])
1637 PeObject
.seek(PeOffset
)
1638 ByteArray
= array
.array('B')
1639 ByteArray
.fromfile(PeObject
, 4)
1640 # PE signature should be 'PE\0\0'
1641 if ByteArray
.tostring() != 'PE\0\0':
1642 self
.ErrorInfo
= self
.FileName
+ ' has no valid PE signature PE00'
1645 # Read PE file header
1646 ByteArray
= array
.array('B')
1647 ByteArray
.fromfile(PeObject
, 0x14)
1648 ByteList
= ByteArray
.tolist()
1649 SecNumber
= self
._ByteListToInt
(ByteList
[0x2:0x4])
1651 self
.ErrorInfo
= self
.FileName
+ ' has no section header'
1654 # Read PE optional header
1655 OptionalHeaderSize
= self
._ByteListToInt
(ByteArray
[0x10:0x12])
1656 ByteArray
= array
.array('B')
1657 ByteArray
.fromfile(PeObject
, OptionalHeaderSize
)
1658 ByteList
= ByteArray
.tolist()
1659 self
.EntryPoint
= self
._ByteListToInt
(ByteList
[0x10:0x14])
1660 self
.SectionAlignment
= self
._ByteListToInt
(ByteList
[0x20:0x24])
1661 self
.Size
= self
._ByteListToInt
(ByteList
[0x38:0x3C])
1663 # Read each Section Header
1664 for Index
in range(SecNumber
):
1665 ByteArray
= array
.array('B')
1666 ByteArray
.fromfile(PeObject
, 0x28)
1667 ByteList
= ByteArray
.tolist()
1668 SecName
= self
._ByteListToStr
(ByteList
[0:8])
1669 SecVirtualSize
= self
._ByteListToInt
(ByteList
[8:12])
1670 SecRawAddress
= self
._ByteListToInt
(ByteList
[20:24])
1671 SecVirtualAddress
= self
._ByteListToInt
(ByteList
[12:16])
1672 self
.SectionHeaderList
.append((SecName
, SecVirtualAddress
, SecRawAddress
, SecVirtualSize
))
1676 def _ByteListToStr(self
, ByteList
):
1678 for index
in range(len(ByteList
)):
1679 if ByteList
[index
] == 0:
1681 String
+= chr(ByteList
[index
])
1684 def _ByteListToInt(self
, ByteList
):
1686 for index
in range(len(ByteList
) - 1, -1, -1):
1687 Value
= (Value
<< 8) |
int(ByteList
[index
])
1697 def __init__(self
,SkuIdentifier
='', SkuIds
={}):
1699 self
.AvailableSkuIds
= sdict()
1702 if SkuIdentifier
== '' or SkuIdentifier
is None:
1703 self
.SkuIdSet
= ['DEFAULT']
1704 elif SkuIdentifier
== 'ALL':
1705 self
.SkuIdSet
= SkuIds
.keys()
1707 r
= SkuIdentifier
.split('|')
1708 self
.SkuIdSet
=[r
[k
].strip() for k
in range(len(r
))]
1709 if len(self
.SkuIdSet
) == 2 and 'DEFAULT' in self
.SkuIdSet
and SkuIdentifier
!= 'ALL':
1710 self
.SkuIdSet
.remove('DEFAULT')
1712 for each
in self
.SkuIdSet
:
1714 self
.AvailableSkuIds
[each
] = SkuIds
[each
]
1716 EdkLogger
.error("build", PARAMETER_INVALID
,
1717 ExtraData
="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
1718 % (each
, " ".join(SkuIds
.keys())))
1720 def __SkuUsageType(self
):
1722 if len(self
.SkuIdSet
) == 1:
1723 if self
.SkuIdSet
[0] == 'DEFAULT':
1724 return SkuClass
.DEFAULT
1726 return SkuClass
.SINGLE
1728 return SkuClass
.MULTIPLE
1730 def __GetAvailableSkuIds(self
):
1731 return self
.AvailableSkuIds
1733 def __GetSystemSkuID(self
):
1734 if self
.__SkuUsageType
() == SkuClass
.SINGLE
:
1735 return self
.SkuIdSet
[0]
1739 SystemSkuId
= property(__GetSystemSkuID
)
1740 AvailableSkuIdSet
= property(__GetAvailableSkuIds
)
1741 SkuUsageType
= property(__SkuUsageType
)
1745 # This acts like the main() function for the script, unless it is 'import'ed into another
1748 if __name__
== '__main__':