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 *
33 from CommonDataClass
.DataClass
import *
34 from Parsing
import GetSplitValueList
36 ## Regular expression used to find out place holders in string template
37 gPlaceholderPattern
= re
.compile("\$\{([^$()\s]+)\}", re
.MULTILINE|re
.UNICODE
)
39 ## Dictionary used to store file time stamp for quick re-access
40 gFileTimeStampCache
= {} # {file path : file time stamp}
42 ## Dictionary used to store dependencies of files
43 gDependencyDatabase
= {} # arch : {file path : [dependent files list]}
45 ## callback routine for processing variable option
47 # This function can be used to process variable number of option values. The
48 # typical usage of it is specify architecure list on command line.
49 # (e.g. <tool> -a IA32 X64 IPF)
51 # @param Option Standard callback function parameter
52 # @param OptionString Standard callback function parameter
53 # @param Value Standard callback function parameter
54 # @param Parser Standard callback function parameter
58 def ProcessVariableArgument(Option
, OptionString
, Value
, Parser
):
61 RawArgs
= Parser
.rargs
64 if (Arg
[:2] == "--" and len(Arg
) > 2) or \
65 (Arg
[:1] == "-" and len(Arg
) > 1 and Arg
[1] != "-"):
69 setattr(Parser
.values
, Option
.dest
, Value
)
71 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
73 # @param Guid The GUID string
75 # @retval string The GUID string in C structure style
77 def GuidStringToGuidStructureString(Guid
):
78 GuidList
= Guid
.split('-')
80 for Index
in range(0,3,1):
81 Result
= Result
+ '0x' + GuidList
[Index
] + ', '
82 Result
= Result
+ '{0x' + GuidList
[3][0:2] + ', 0x' + GuidList
[3][2:4]
83 for Index
in range(0,12,2):
84 Result
= Result
+ ', 0x' + GuidList
[4][Index
:Index
+2]
88 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
90 # @param GuidValue The GUID value in byte array
92 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
94 def GuidStructureByteArrayToGuidString(GuidValue
):
95 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
96 guidValueList
= guidValueString
.split(",")
97 if len(guidValueList
) != 16:
99 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
101 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
102 int(guidValueList
[3], 16),
103 int(guidValueList
[2], 16),
104 int(guidValueList
[1], 16),
105 int(guidValueList
[0], 16),
106 int(guidValueList
[5], 16),
107 int(guidValueList
[4], 16),
108 int(guidValueList
[7], 16),
109 int(guidValueList
[6], 16),
110 int(guidValueList
[8], 16),
111 int(guidValueList
[9], 16),
112 int(guidValueList
[10], 16),
113 int(guidValueList
[11], 16),
114 int(guidValueList
[12], 16),
115 int(guidValueList
[13], 16),
116 int(guidValueList
[14], 16),
117 int(guidValueList
[15], 16)
122 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
124 # @param GuidValue The GUID value in C structure format
126 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
128 def GuidStructureStringToGuidString(GuidValue
):
129 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
130 guidValueList
= guidValueString
.split(",")
131 if len(guidValueList
) != 11:
133 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
135 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
136 int(guidValueList
[0], 16),
137 int(guidValueList
[1], 16),
138 int(guidValueList
[2], 16),
139 int(guidValueList
[3], 16),
140 int(guidValueList
[4], 16),
141 int(guidValueList
[5], 16),
142 int(guidValueList
[6], 16),
143 int(guidValueList
[7], 16),
144 int(guidValueList
[8], 16),
145 int(guidValueList
[9], 16),
146 int(guidValueList
[10], 16)
151 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
153 # @param GuidValue The GUID value in C structure format
155 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
157 def GuidStructureStringToGuidValueName(GuidValue
):
158 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "")
159 guidValueList
= guidValueString
.split(",")
160 if len(guidValueList
) != 11:
161 EdkLogger
.error(None, FORMAT_INVALID
, "Invalid GUID value string [%s]" % GuidValue
)
162 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
163 int(guidValueList
[0], 16),
164 int(guidValueList
[1], 16),
165 int(guidValueList
[2], 16),
166 int(guidValueList
[3], 16),
167 int(guidValueList
[4], 16),
168 int(guidValueList
[5], 16),
169 int(guidValueList
[6], 16),
170 int(guidValueList
[7], 16),
171 int(guidValueList
[8], 16),
172 int(guidValueList
[9], 16),
173 int(guidValueList
[10], 16)
176 ## Create directories
178 # @param Directory The directory name
180 def CreateDirectory(Directory
):
181 if Directory
== None or Directory
.strip() == "":
184 if not os
.access(Directory
, os
.F_OK
):
185 os
.makedirs(Directory
)
190 ## Remove directories, including files and sub-directories in it
192 # @param Directory The directory name
194 def RemoveDirectory(Directory
, Recursively
=False):
195 if Directory
== None or Directory
.strip() == "" or not os
.path
.exists(Directory
):
198 CurrentDirectory
= os
.getcwd()
200 for File
in os
.listdir("."):
201 if os
.path
.isdir(File
):
202 RemoveDirectory(File
, Recursively
)
205 os
.chdir(CurrentDirectory
)
208 ## Check if given file is changed or not
210 # This method is used to check if a file is changed or not between two build
211 # actions. It makes use a cache to store files timestamp.
213 # @param File The path of file
215 # @retval True If the given file is changed, doesn't exist, or can't be
216 # found in timestamp cache
217 # @retval False If the given file is changed
220 if not os
.path
.exists(File
):
223 FileState
= os
.stat(File
)
224 TimeStamp
= FileState
[-2]
226 if File
in gFileTimeStampCache
and TimeStamp
== gFileTimeStampCache
[File
]:
230 gFileTimeStampCache
[File
] = TimeStamp
234 ## Store content in file
236 # This method is used to save file only when its content is changed. This is
237 # quite useful for "make" system to decide what will be re-built and what won't.
239 # @param File The path of file
240 # @param Content The new content of the file
241 # @param IsBinaryFile The flag indicating if the file is binary file or not
243 # @retval True If the file content is changed and the file is renewed
244 # @retval False If the file content is the same
246 def SaveFileOnChange(File
, Content
, IsBinaryFile
=True):
248 Content
= Content
.replace("\n", os
.linesep
)
250 if os
.path
.exists(File
):
252 if Content
== open(File
, "rb").read():
255 EdkLogger
.error(None, FILE_OPEN_FAILURE
, ExtraData
=File
)
257 DirName
= os
.path
.dirname(File
)
258 if not CreateDirectory(DirName
):
259 EdkLogger
.error(None, FILE_CREATE_FAILURE
, "Could not create directory %s" % DirName
)
262 DirName
= os
.getcwd()
263 if not os
.access(DirName
, os
.W_OK
):
264 EdkLogger
.error(None, PERMISSION_FAILURE
, "Do not have write permission on directory %s" % DirName
)
267 if GlobalData
.gIsWindows
:
269 from PyUtility
import SaveFileToDisk
270 if not SaveFileToDisk(File
, Content
):
271 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
273 Fd
= open(File
, "wb")
277 Fd
= open(File
, "wb")
281 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
='IOError %s'%X)
285 ## Make a Python object persistent on file system
287 # @param Data The object to be stored in file
288 # @param File The path of file to store the object
290 def DataDump(Data
, File
):
293 Fd
= open(File
, 'wb')
294 cPickle
.dump(Data
, Fd
, cPickle
.HIGHEST_PROTOCOL
)
296 EdkLogger
.error("", FILE_OPEN_FAILURE
, ExtraData
=File
, RaiseError
=False)
301 ## Restore a Python object from a file
303 # @param File The path of file stored the object
305 # @retval object A python object
306 # @retval None If failure in file operation
308 def DataRestore(File
):
312 Fd
= open(File
, 'rb')
313 Data
= cPickle
.load(Fd
)
315 EdkLogger
.verbose("Failed to load [%s]\n\t%s" % (File
, str(e
)))
322 ## Retrieve and cache the real path name in file system
324 # @param Root The root directory of path relative to
326 # @retval str The path string if the path exists
327 # @retval None If path doesn't exist
333 def __init__(self
, Root
):
335 for F
in os
.listdir(Root
):
337 self
._UPPER
_CACHE
_[F
.upper()] = F
340 def __getitem__(self
, Path
):
341 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
344 if Path
and Path
[0] == os
.path
.sep
:
346 if Path
in self
._CACHE
_:
347 return os
.path
.join(self
._Root
, Path
)
348 UpperPath
= Path
.upper()
349 if UpperPath
in self
._UPPER
_CACHE
_:
350 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
354 SepIndex
= Path
.find(os
.path
.sep
)
356 Parent
= UpperPath
[:SepIndex
]
357 if Parent
not in self
._UPPER
_CACHE
_:
359 LastSepIndex
= SepIndex
360 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
362 if LastSepIndex
== -1:
367 SepIndex
= LastSepIndex
369 Parent
= Path
[:SepIndex
]
370 ParentKey
= UpperPath
[:SepIndex
]
371 if ParentKey
not in self
._UPPER
_CACHE
_:
375 if Parent
in self
._CACHE
_:
378 ParentDir
= self
._UPPER
_CACHE
_[ParentKey
]
379 for F
in os
.listdir(ParentDir
):
380 Dir
= os
.path
.join(ParentDir
, F
)
381 self
._CACHE
_.add(Dir
)
382 self
._UPPER
_CACHE
_[Dir
.upper()] = Dir
384 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
387 if Path
in self
._CACHE
_:
388 return os
.path
.join(self
._Root
, Path
)
389 elif UpperPath
in self
._UPPER
_CACHE
_:
390 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
393 ## Get all files of a directory
395 # @param Root: Root dir
396 # @param SkipList : The files need be skipped
398 # @retval A list of all files
400 def GetFiles(Root
, SkipList
=None, FullPath
= True):
403 for Root
, Dirs
, Files
in os
.walk(Root
):
405 for Item
in SkipList
:
410 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
412 File
= File
[len(OriPath
) + 1:]
413 FileList
.append(File
)
417 ## Check if gvien file exists or not
419 # @param File File name or path to be checked
420 # @param Dir The directory the file is relative to
422 # @retval True if file exists
423 # @retval False if file doesn't exists
425 def ValidFile(File
, Ext
=None):
427 Dummy
, FileExt
= os
.path
.splitext(File
)
428 if FileExt
.lower() != Ext
.lower():
430 if not os
.path
.exists(File
):
434 def RealPath(File
, Dir
='', OverrideDir
=''):
435 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
436 NewFile
= GlobalData
.gAllFiles
[NewFile
]
437 if not NewFile
and OverrideDir
:
438 NewFile
= os
.path
.normpath(os
.path
.join(OverrideDir
, File
))
439 NewFile
= GlobalData
.gAllFiles
[NewFile
]
442 def RealPath2(File
, Dir
='', OverrideDir
=''):
444 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
446 if OverrideDir
[-1] == os
.path
.sep
:
447 return NewFile
[len(OverrideDir
):], NewFile
[0:len(OverrideDir
)]
449 return NewFile
[len(OverrideDir
)+1:], NewFile
[0:len(OverrideDir
)]
450 if GlobalData
.gAllFiles
:
451 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
453 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
456 if Dir
[-1] == os
.path
.sep
:
457 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
459 return NewFile
[len(Dir
)+1:], NewFile
[0:len(Dir
)]
465 ## Check if gvien file exists or not
468 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
471 Dummy
, FileExt
= os
.path
.splitext(File
)
472 if FileExt
.lower() != Ext
.lower():
475 # Replace the Edk macros
476 if OverrideDir
!= '' and OverrideDir
!= None:
477 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
478 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
479 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
480 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
482 # Replace the default dir to current dir
485 Dir
= Dir
[len(Workspace
)+1:]
487 # First check if File has Edk definition itself
488 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
489 NewFile
= File
.replace('$(EFI_SOURCE)', EfiSource
)
490 NewFile
= NewFile
.replace('$(EDK_SOURCE)', EdkSource
)
491 NewFile
= AllFiles
[os
.path
.normpath(NewFile
)]
495 # Second check the path with override value
496 if OverrideDir
!= '' and OverrideDir
!= None:
497 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
501 # Last check the path with normal definitions
502 File
= os
.path
.join(Dir
, File
)
503 NewFile
= AllFiles
[os
.path
.normpath(File
)]
509 ## Check if gvien file exists or not
512 def ValidFile3(AllFiles
, File
, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
513 # Replace the Edk macros
514 if OverrideDir
!= '' and OverrideDir
!= None:
515 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
516 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
517 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
518 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
520 # Replace the default dir to current dir
521 # Dir is current module dir related to workspace
524 Dir
= Dir
[len(Workspace
)+1:]
527 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
528 NewRelaPath
= RelaPath
531 # First check if File has Edk definition itself
532 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
533 File
= File
.replace('$(EFI_SOURCE)', EfiSource
)
534 File
= File
.replace('$(EDK_SOURCE)', EdkSource
)
535 NewFile
= AllFiles
[os
.path
.normpath(File
)]
537 NewRelaPath
= os
.path
.dirname(NewFile
)
538 File
= os
.path
.basename(NewFile
)
539 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
542 # Second check the path with override value
543 if OverrideDir
!= '' and OverrideDir
!= None:
544 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
546 #NewRelaPath = os.path.dirname(NewFile)
547 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
550 # Last check the path with normal definitions
551 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
558 return NewRelaPath
, RelaPath
, File
561 def GetRelPath(Path1
, Path2
):
562 FileName
= os
.path
.basename(Path2
)
563 L1
= os
.path
.normpath(Path1
).split(os
.path
.normpath('/'))
564 L2
= os
.path
.normpath(Path2
).split(os
.path
.normpath('/'))
565 for Index
in range(0, len(L1
)):
566 if L1
[Index
] != L2
[Index
]:
567 FileName
= '../' * (len(L1
) - Index
)
568 for Index2
in range(Index
, len(L2
)):
569 FileName
= os
.path
.join(FileName
, L2
[Index2
])
571 return os
.path
.normpath(FileName
)
574 ## Get GUID value from given packages
576 # @param CName The CName of the GUID
577 # @param PackageList List of packages looking-up in
579 # @retval GuidValue if the CName is found in any given package
580 # @retval None if the CName is not found in all given packages
582 def GuidValue(CName
, PackageList
):
583 for P
in PackageList
:
585 return P
.Guids
[CName
]
588 ## Get Protocol value from given packages
590 # @param CName The CName of the GUID
591 # @param PackageList List of packages looking-up in
593 # @retval GuidValue if the CName is found in any given package
594 # @retval None if the CName is not found in all given packages
596 def ProtocolValue(CName
, PackageList
):
597 for P
in PackageList
:
598 if CName
in P
.Protocols
:
599 return P
.Protocols
[CName
]
602 ## Get PPI value from given packages
604 # @param CName The CName of the GUID
605 # @param PackageList List of packages looking-up in
607 # @retval GuidValue if the CName is found in any given package
608 # @retval None if the CName is not found in all given packages
610 def PpiValue(CName
, PackageList
):
611 for P
in PackageList
:
616 ## A string template class
618 # This class implements a template for string replacement. A string template
619 # looks like following
621 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
623 # The string between ${BEGIN} and ${END} will be repeated as many times as the
624 # length of "placeholder_name", which is a list passed through a dict. The
625 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
626 # be not used and, in this case, the "placeholder_name" must not a list and it
627 # will just be replaced once.
629 class TemplateString(object):
630 _REPEAT_START_FLAG
= "BEGIN"
631 _REPEAT_END_FLAG
= "END"
633 class Section(object):
634 _LIST_TYPES
= [type([]), type(set()), type((0,))]
636 def __init__(self
, TemplateSection
, PlaceHolderList
):
637 self
._Template
= TemplateSection
638 self
._PlaceHolderList
= []
640 # Split the section into sub-sections according to the position of placeholders
642 self
._SubSectionList
= []
645 # The placeholders passed in must be in the format of
647 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
649 for PlaceHolder
,Start
,End
in PlaceHolderList
:
650 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:Start
])
651 self
._SubSectionList
.append(TemplateSection
[Start
:End
])
652 self
._PlaceHolderList
.append(PlaceHolder
)
653 SubSectionStart
= End
654 if SubSectionStart
< len(TemplateSection
):
655 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:])
657 self
._SubSectionList
= [TemplateSection
]
660 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
662 def Instantiate(self
, PlaceHolderValues
):
664 RepeatPlaceHolders
= {}
665 NonRepeatPlaceHolders
= {}
667 for PlaceHolder
in self
._PlaceHolderList
:
668 if PlaceHolder
not in PlaceHolderValues
:
670 Value
= PlaceHolderValues
[PlaceHolder
]
671 if type(Value
) in self
._LIST
_TYPES
:
673 RepeatTime
= len(Value
)
674 elif RepeatTime
!= len(Value
):
678 "${%s} has different repeat time from others!" % PlaceHolder
,
679 ExtraData
=str(self
._Template
)
681 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
683 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
685 if NonRepeatPlaceHolders
:
687 for S
in self
._SubSectionList
:
688 if S
not in NonRepeatPlaceHolders
:
691 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
693 StringList
= self
._SubSectionList
695 if RepeatPlaceHolders
:
697 for Index
in range(RepeatTime
):
699 if S
not in RepeatPlaceHolders
:
700 TempStringList
.append(S
)
702 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
703 StringList
= TempStringList
705 return "".join(StringList
)
708 def __init__(self
, Template
=None):
710 self
.IsBinary
= False
711 self
._Template
= Template
712 self
._TemplateSectionList
= self
._Parse
(Template
)
716 # @retval string The string replaced
721 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
723 # @retval list A list of TemplateString.Section objects
725 def _Parse(self
, Template
):
730 TemplateSectionList
= []
732 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
734 if MatchEnd
<= len(Template
):
735 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
736 TemplateSectionList
.append(TemplateSection
)
739 MatchString
= MatchObj
.group(1)
740 MatchStart
= MatchObj
.start()
741 MatchEnd
= MatchObj
.end()
743 if MatchString
== self
._REPEAT
_START
_FLAG
:
744 if MatchStart
> SectionStart
:
745 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
746 TemplateSectionList
.append(TemplateSection
)
747 SectionStart
= MatchEnd
749 elif MatchString
== self
._REPEAT
_END
_FLAG
:
750 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
751 TemplateSectionList
.append(TemplateSection
)
752 SectionStart
= MatchEnd
755 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
756 SearchFrom
= MatchEnd
757 return TemplateSectionList
759 ## Replace the string template with dictionary of placeholders and append it to previous one
761 # @param AppendString The string template to append
762 # @param Dictionary The placeholder dictionaries
764 def Append(self
, AppendString
, Dictionary
=None):
766 SectionList
= self
._Parse
(AppendString
)
767 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
769 self
.String
+= AppendString
771 ## Replace the string template with dictionary of placeholders
773 # @param Dictionary The placeholder dictionaries
775 # @retval str The string replaced with placeholder values
777 def Replace(self
, Dictionary
=None):
778 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
780 ## Progress indicator class
782 # This class makes use of thread to print progress on console.
785 # for avoiding deadloop
787 _ProgressThread
= None
788 _CheckInterval
= 0.25
792 # @param OpenMessage The string printed before progress charaters
793 # @param CloseMessage The string printed after progress charaters
794 # @param ProgressChar The charater used to indicate the progress
795 # @param Interval The interval in seconds between two progress charaters
797 def __init__(self
, OpenMessage
="", CloseMessage
="", ProgressChar
='.', Interval
=1.0):
798 self
.PromptMessage
= OpenMessage
799 self
.CodaMessage
= CloseMessage
800 self
.ProgressChar
= ProgressChar
801 self
.Interval
= Interval
802 if Progressor
._StopFlag
== None:
803 Progressor
._StopFlag
= threading
.Event()
805 ## Start to print progress charater
807 # @param OpenMessage The string printed before progress charaters
809 def Start(self
, OpenMessage
=None):
810 if OpenMessage
!= None:
811 self
.PromptMessage
= OpenMessage
812 Progressor
._StopFlag
.clear()
813 if Progressor
._ProgressThread
== None:
814 Progressor
._ProgressThread
= threading
.Thread(target
=self
._ProgressThreadEntry
)
815 Progressor
._ProgressThread
.setDaemon(False)
816 Progressor
._ProgressThread
.start()
818 ## Stop printing progress charater
820 # @param CloseMessage The string printed after progress charaters
822 def Stop(self
, CloseMessage
=None):
823 OriginalCodaMessage
= self
.CodaMessage
824 if CloseMessage
!= None:
825 self
.CodaMessage
= CloseMessage
827 self
.CodaMessage
= OriginalCodaMessage
829 ## Thread entry method
830 def _ProgressThreadEntry(self
):
831 sys
.stdout
.write(self
.PromptMessage
+ " ")
834 while not Progressor
._StopFlag
.isSet():
836 sys
.stdout
.write(self
.ProgressChar
)
838 TimeUp
= self
.Interval
839 time
.sleep(self
._CheckInterval
)
840 TimeUp
-= self
._CheckInterval
841 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
844 ## Abort the progress display
847 if Progressor
._StopFlag
!= None:
848 Progressor
._StopFlag
.set()
849 if Progressor
._ProgressThread
!= None:
850 Progressor
._ProgressThread
.join()
851 Progressor
._ProgressThread
= None
853 ## A dict which can access its keys and/or values orderly
855 # The class implements a new kind of dict which its keys or values can be
856 # accessed in the order they are added into the dict. It guarantees the order
857 # by making use of an internal list to keep a copy of keys.
859 class sdict(IterableUserDict
):
862 IterableUserDict
.__init
__(self
)
866 def __setitem__(self
, key
, value
):
867 if key
not in self
._key
_list
:
868 self
._key
_list
.append(key
)
869 IterableUserDict
.__setitem
__(self
, key
, value
)
872 def __delitem__(self
, key
):
873 self
._key
_list
.remove(key
)
874 IterableUserDict
.__delitem
__(self
, key
)
876 ## used in "for k in dict" loop to ensure the correct order
878 return self
.iterkeys()
882 return len(self
._key
_list
)
885 def __contains__(self
, key
):
886 return key
in self
._key
_list
889 def index(self
, key
):
890 return self
._key
_list
.index(key
)
893 def insert(self
, key
, newkey
, newvalue
, order
):
894 index
= self
._key
_list
.index(key
)
895 if order
== 'BEFORE':
896 self
._key
_list
.insert(index
, newkey
)
897 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
898 elif order
== 'AFTER':
899 self
._key
_list
.insert(index
+ 1, newkey
)
900 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
903 def append(self
, sdict
):
905 if key
not in self
._key
_list
:
906 self
._key
_list
.append(key
)
907 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
909 def has_key(self
, key
):
910 return key
in self
._key
_list
915 IterableUserDict
.clear(self
)
917 ## Return a copy of keys
920 for key
in self
._key
_list
:
924 ## Return a copy of values
927 for key
in self
._key
_list
:
928 values
.append(self
[key
])
931 ## Return a copy of (key, value) list
934 for key
in self
._key
_list
:
935 items
.append((key
, self
[key
]))
940 return iter(self
.items())
942 ## Keys interation support
944 return iter(self
.keys())
946 ## Values interation support
947 def itervalues(self
):
948 return iter(self
.values())
950 ## Return value related to a key, and remove the (key, value) from the dict
951 def pop(self
, key
, *dv
):
953 if key
in self
._key
_list
:
955 self
.__delitem
__(key
)
960 ## Return (key, value) pair, and remove the (key, value) from the dict
962 key
= self
._key
_list
[-1]
964 self
.__delitem
__(key
)
967 def update(self
, dict=None, **kwargs
):
969 for k
, v
in dict.items():
972 for k
, v
in kwargs
.items():
975 ## Dictionary with restricted keys
979 def __init__(self
, KeyList
):
981 dict.__setitem
__(self
, Key
, "")
984 def __setitem__(self
, key
, value
):
986 EdkLogger
.error("RestrictedDict", ATTRIBUTE_SET_FAILURE
, "Key [%s] is not allowed" % key
,
987 ExtraData
=", ".join(dict.keys(self
)))
988 dict.__setitem
__(self
, key
, value
)
991 def __getitem__(self
, key
):
994 return dict.__getitem
__(self
, key
)
997 def __delitem__(self
, key
):
998 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
1003 self
.__setitem
__(Key
, "")
1005 ## Return value related to a key, and remove the (key, value) from the dict
1006 def pop(self
, key
, *dv
):
1007 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="pop")
1009 ## Return (key, value) pair, and remove the (key, value) from the dict
1011 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
1013 ## Dictionary using prioritized list as key
1016 _ListType
= type([])
1017 _TupleType
= type(())
1018 _Wildcard
= 'COMMON'
1019 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1021 def __init__(self
, _Single_
=False, _Level_
=2):
1022 self
._Level
_ = _Level_
1024 self
._Single
_ = _Single_
1027 def __getitem__(self
, key
):
1030 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1034 elif self
._Level
_ > 1:
1035 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1038 if self
._Level
_ > 1:
1039 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1041 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1042 FirstKey
= self
._Wildcard
1045 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1047 return self
._GetAllValues
(FirstKey
, RestKeys
)
1049 def _GetSingleValue(self
, FirstKey
, RestKeys
):
1051 #print "%s-%s" % (FirstKey, self._Level_) ,
1052 if self
._Level
_ > 1:
1053 if FirstKey
== self
._Wildcard
:
1054 if FirstKey
in self
.data
:
1055 Value
= self
.data
[FirstKey
][RestKeys
]
1057 for Key
in self
.data
:
1058 Value
= self
.data
[Key
][RestKeys
]
1059 if Value
!= None: break
1061 if FirstKey
in self
.data
:
1062 Value
= self
.data
[FirstKey
][RestKeys
]
1063 if Value
== None and self
._Wildcard
in self
.data
:
1065 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1067 if FirstKey
== self
._Wildcard
:
1068 if FirstKey
in self
.data
:
1069 Value
= self
.data
[FirstKey
]
1071 for Key
in self
.data
:
1072 Value
= self
.data
[Key
]
1073 if Value
!= None: break
1075 if FirstKey
in self
.data
:
1076 Value
= self
.data
[FirstKey
]
1077 elif self
._Wildcard
in self
.data
:
1078 Value
= self
.data
[self
._Wildcard
]
1081 def _GetAllValues(self
, FirstKey
, RestKeys
):
1083 if self
._Level
_ > 1:
1084 if FirstKey
== self
._Wildcard
:
1085 for Key
in self
.data
:
1086 Value
+= self
.data
[Key
][RestKeys
]
1088 if FirstKey
in self
.data
:
1089 Value
+= self
.data
[FirstKey
][RestKeys
]
1090 if self
._Wildcard
in self
.data
:
1091 Value
+= self
.data
[self
._Wildcard
][RestKeys
]
1093 if FirstKey
== self
._Wildcard
:
1094 for Key
in self
.data
:
1095 Value
.append(self
.data
[Key
])
1097 if FirstKey
in self
.data
:
1098 Value
.append(self
.data
[FirstKey
])
1099 if self
._Wildcard
in self
.data
:
1100 Value
.append(self
.data
[self
._Wildcard
])
1104 def __setitem__(self
, key
, value
):
1107 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1112 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1115 if self
._Level
_ > 1:
1116 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_-1)]
1118 if FirstKey
in self
._ValidWildcardList
:
1119 FirstKey
= self
._Wildcard
1121 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1122 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1124 if self
._Level
_ > 1:
1125 self
.data
[FirstKey
][RestKeys
] = value
1127 self
.data
[FirstKey
] = value
1129 def SetGreedyMode(self
):
1130 self
._Single
_ = False
1131 if self
._Level
_ > 1:
1132 for Key
in self
.data
:
1133 self
.data
[Key
].SetGreedyMode()
1135 def SetSingleMode(self
):
1136 self
._Single
_ = True
1137 if self
._Level
_ > 1:
1138 for Key
in self
.data
:
1139 self
.data
[Key
].SetSingleMode()
1141 def GetKeys(self
, KeyIndex
=0):
1142 assert KeyIndex
>= 0
1144 return set(self
.data
.keys())
1147 for Key
in self
.data
:
1148 keys |
= self
.data
[Key
].GetKeys(KeyIndex
- 1)
1151 ## Boolean chain list
1153 class Blist(UserList
):
1154 def __init__(self
, initlist
=None):
1155 UserList
.__init
__(self
, initlist
)
1156 def __setitem__(self
, i
, item
):
1157 if item
not in [True, False]:
1163 def _GetResult(self
):
1165 for item
in self
.data
:
1168 Result
= property(_GetResult
)
1170 def ParseConsoleLog(Filename
):
1171 Opr
= open(os
.path
.normpath(Filename
), 'r')
1172 Opw
= open(os
.path
.normpath(Filename
+ '.New'), 'w+')
1173 for Line
in Opr
.readlines():
1174 if Line
.find('.efi') > -1:
1175 Line
= Line
[Line
.rfind(' ') : Line
.rfind('.efi')].strip()
1176 Opw
.write('%s\n' % Line
)
1183 # Analyze DSC PCD value, since there is no data type info in DSC
1184 # This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
1185 # 1. Feature flag: TokenSpace.PcdCName|PcdValue
1186 # 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
1187 # 3. Dynamic default:
1188 # TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
1189 # TokenSpace.PcdCName|PcdValue
1191 # TokenSpace.PcdCName|VpdOffset[|VpdValue]
1192 # TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
1194 # TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
1195 # PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
1196 # there might have "|" operator, also in string value.
1198 # @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
1199 # @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
1200 # @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
1202 # ValueList: A List contain fields described above
1203 # IsValid: True if conforming EBNF, otherwise False
1204 # Index: The index where PcdValue is in ValueList
1206 def AnalyzeDscPcd(Setting
, PcdType
, DataType
=''):
1207 Setting
= Setting
.strip()
1208 # There might be escaped quote in a string: \", \\\"
1209 Data
= Setting
.replace('\\\\', '//').replace('\\\"', '\\\'')
1210 # There might be '|' in string and in ( ... | ... ), replace it with '-'
1217 elif ch
== '(' and not InStr
:
1219 elif ch
== ')' and not InStr
:
1222 if (Pair
> 0 or InStr
) and ch
== TAB_VALUE_SPLIT
:
1229 Pos
= NewStr
.find(TAB_VALUE_SPLIT
, StartPos
)
1231 FieldList
.append(Setting
[StartPos
:].strip())
1233 FieldList
.append(Setting
[StartPos
:Pos
].strip())
1237 if PcdType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_FEATURE_FLAG
):
1238 Value
= FieldList
[0]
1240 if len(FieldList
) > 1:
1242 # Fix the PCD type when no DataType input
1247 if len(FieldList
) > 2:
1249 if DataType
== 'VOID*':
1250 IsValid
= (len(FieldList
) <= 3)
1252 IsValid
= (len(FieldList
) <= 1)
1253 return [Value
, '', Size
], IsValid
, 0
1254 elif PcdType
in (MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
):
1255 Value
= FieldList
[0]
1257 if len(FieldList
) > 1:
1261 if len(FieldList
) > 2:
1265 if Value
.startswith("L"):
1266 Size
= str((len(Value
)- 3 + 1) * 2)
1267 elif Value
.startswith("{"):
1268 Size
= str(len(Value
.split(",")))
1270 Size
= str(len(Value
) -2 + 1 )
1271 if DataType
== 'VOID*':
1272 IsValid
= (len(FieldList
) <= 3)
1274 IsValid
= (len(FieldList
) <= 1)
1275 return [Value
, Type
, Size
], IsValid
, 0
1276 elif PcdType
in (MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_VPD
):
1277 VpdOffset
= FieldList
[0]
1279 if not DataType
== 'VOID*':
1280 if len(FieldList
) > 1:
1281 Value
= FieldList
[1]
1283 if len(FieldList
) > 1:
1285 if len(FieldList
) > 2:
1286 Value
= FieldList
[2]
1287 if DataType
== 'VOID*':
1288 IsValid
= (len(FieldList
) <= 3)
1290 IsValid
= (len(FieldList
) <= 2)
1291 return [VpdOffset
, Size
, Value
], IsValid
, 2
1292 elif PcdType
in (MODEL_PCD_DYNAMIC_HII
, MODEL_PCD_DYNAMIC_EX_HII
):
1293 HiiString
= FieldList
[0]
1294 Guid
= Offset
= Value
= ''
1295 if len(FieldList
) > 1:
1297 if len(FieldList
) > 2:
1298 Offset
= FieldList
[2]
1299 if len(FieldList
) > 3:
1300 Value
= FieldList
[3]
1301 IsValid
= (3 <= len(FieldList
) <= 4)
1302 return [HiiString
, Guid
, Offset
, Value
], IsValid
, 3
1307 # Analyze the pcd Value, Datum type and TokenNumber.
1308 # Used to avoid split issue while the value string contain "|" character
1310 # @param[in] Setting: A String contain value/datum type/token number information;
1312 # @retval ValueList: A List contain value, datum type and toke number.
1314 def AnalyzePcdData(Setting
):
1315 ValueList
= ['', '', '']
1317 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1318 PtrValue
= ValueRe
.findall(Setting
)
1320 ValueUpdateFlag
= False
1322 if len(PtrValue
) >= 1:
1323 Setting
= re
.sub(ValueRe
, '', Setting
)
1324 ValueUpdateFlag
= True
1326 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1327 ValueList
[0:len(TokenList
)] = TokenList
1330 ValueList
[0] = PtrValue
[0]
1334 ## AnalyzeHiiPcdData
1336 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1337 # Used to avoid split issue while the value string contain "|" character
1339 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1341 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1343 def AnalyzeHiiPcdData(Setting
):
1344 ValueList
= ['', '', '', '']
1346 TokenList
= GetSplitValueList(Setting
)
1347 ValueList
[0:len(TokenList
)] = TokenList
1351 ## AnalyzeVpdPcdData
1353 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1354 # Used to avoid split issue while the value string contain "|" character
1356 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1358 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1360 def AnalyzeVpdPcdData(Setting
):
1361 ValueList
= ['', '', '']
1363 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
1364 PtrValue
= ValueRe
.findall(Setting
)
1366 ValueUpdateFlag
= False
1368 if len(PtrValue
) >= 1:
1369 Setting
= re
.sub(ValueRe
, '', Setting
)
1370 ValueUpdateFlag
= True
1372 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1373 ValueList
[0:len(TokenList
)] = TokenList
1376 ValueList
[2] = PtrValue
[0]
1380 ## check format of PCD value against its the datum type
1382 # For PCD value setting
1384 def CheckPcdDatum(Type
, Value
):
1386 ValueRe
= re
.compile(r
'\s*L?\".*\"\s*$')
1387 if not (((Value
.startswith('L"') or Value
.startswith('"')) and Value
.endswith('"'))
1388 or (Value
.startswith('{') and Value
.endswith('}'))
1390 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1391 ", or \"...\" for string, or L\"...\" for unicode string" % (Value
, Type
)
1392 elif ValueRe
.match(Value
):
1393 # Check the chars in UnicodeString or CString is printable
1394 if Value
.startswith("L"):
1398 Printset
= set(string
.printable
)
1399 Printset
.remove(TAB_PRINTCHAR_VT
)
1400 Printset
.add(TAB_PRINTCHAR_BS
)
1401 Printset
.add(TAB_PRINTCHAR_NUL
)
1402 if not set(Value
).issubset(Printset
):
1403 PrintList
= list(Printset
)
1405 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type
, PrintList
)
1406 elif Type
== 'BOOLEAN':
1407 if Value
not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1408 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1409 ", FALSE, False, false, 0x0, 0x00, 0" % (Value
, Type
)
1410 elif Type
in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
]:
1412 Value
= long(Value
, 0)
1414 return False, "Invalid value [%s] of type [%s];"\
1415 " must be a hexadecimal, decimal or octal in C language format." % (Value
, Type
)
1417 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type
)
1421 ## Split command line option string to list
1423 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1424 # in non-windows platform to launch command
1426 def SplitOption(OptionString
):
1431 for Index
in range(0, len(OptionString
)):
1432 CurrentChar
= OptionString
[Index
]
1433 if CurrentChar
in ['"', "'"]:
1434 if QuotationMark
== CurrentChar
:
1436 elif QuotationMark
== "":
1437 QuotationMark
= CurrentChar
1442 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1443 if Index
> OptionStart
:
1444 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1446 LastChar
= CurrentChar
1447 OptionList
.append(OptionString
[OptionStart
:])
1450 def CommonPath(PathList
):
1451 P1
= min(PathList
).split(os
.path
.sep
)
1452 P2
= max(PathList
).split(os
.path
.sep
)
1453 for Index
in xrange(min(len(P1
), len(P2
))):
1454 if P1
[Index
] != P2
[Index
]:
1455 return os
.path
.sep
.join(P1
[:Index
])
1456 return os
.path
.sep
.join(P1
)
1458 class PathClass(object):
1459 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1460 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1462 self
.File
= str(File
)
1463 if os
.path
.isabs(self
.File
):
1467 self
.Root
= str(Root
)
1468 self
.AlterRoot
= str(AlterRoot
)
1470 # Remove any '.' and '..' in path
1472 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1473 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1474 # eliminate the side-effect of 'C:'
1475 if self
.Root
[-1] == ':':
1476 self
.Root
+= os
.path
.sep
1477 # file path should not start with path separator
1478 if self
.Root
[-1] == os
.path
.sep
:
1479 self
.File
= self
.Path
[len(self
.Root
):]
1481 self
.File
= self
.Path
[len(self
.Root
)+1:]
1483 self
.Path
= os
.path
.normpath(self
.File
)
1485 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1486 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1490 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1492 self
.Dir
= self
.Root
1494 self
.Dir
= self
.SubDir
1499 self
.Type
= self
.Ext
.lower()
1501 self
.IsBinary
= IsBinary
1502 self
.Target
= Target
1503 self
.TagName
= TagName
1504 self
.ToolCode
= ToolCode
1505 self
.ToolChainFamily
= ToolChainFamily
1509 ## Convert the object of this class to a string
1511 # Convert member Path of the class to a string
1513 # @retval string Formatted String
1518 ## Override __eq__ function
1520 # Check whether PathClass are the same
1522 # @retval False The two PathClass are different
1523 # @retval True The two PathClass are the same
1525 def __eq__(self
, Other
):
1526 if type(Other
) == type(self
):
1527 return self
.Path
== Other
.Path
1529 return self
.Path
== str(Other
)
1531 ## Override __cmp__ function
1533 # Customize the comparsion operation of two PathClass
1535 # @retval 0 The two PathClass are different
1536 # @retval -1 The first PathClass is less than the second PathClass
1537 # @retval 1 The first PathClass is Bigger than the second PathClass
1538 def __cmp__(self
, Other
):
1539 if type(Other
) == type(self
):
1540 OtherKey
= Other
.Path
1542 OtherKey
= str(Other
)
1545 if SelfKey
== OtherKey
:
1547 elif SelfKey
> OtherKey
:
1552 ## Override __hash__ function
1554 # Use Path as key in hash table
1556 # @retval string Key for hash table
1559 return hash(self
.Path
)
1561 def _GetFileKey(self
):
1562 if self
._Key
== None:
1563 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1566 def _GetTimeStamp(self
):
1567 return os
.stat(self
.Path
)[8]
1569 def Validate(self
, Type
='', CaseSensitive
=True):
1570 if GlobalData
.gCaseInsensitive
:
1571 CaseSensitive
= False
1572 if Type
and Type
.lower() != self
.Type
:
1573 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
1575 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1576 if not RealRoot
and not RealFile
:
1577 RealFile
= self
.File
1579 RealFile
= os
.path
.join(self
.AlterRoot
, self
.File
)
1581 RealFile
= os
.path
.join(self
.Root
, self
.File
)
1582 return FILE_NOT_FOUND
, os
.path
.join(self
.AlterRoot
, RealFile
)
1586 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
1587 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
1588 ErrorCode
= FILE_CASE_MISMATCH
1589 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
1591 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1592 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1594 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1597 self
.File
= RealFile
1598 self
.Root
= RealRoot
1599 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1600 return ErrorCode
, ErrorInfo
1602 Key
= property(_GetFileKey
)
1603 TimeStamp
= property(_GetTimeStamp
)
1605 ## Parse PE image to get the required PE informaion.
1607 class PeImageClass():
1610 # @param File FilePath of PeImage
1612 def __init__(self
, PeFile
):
1613 self
.FileName
= PeFile
1614 self
.IsValid
= False
1617 self
.SectionAlignment
= 0
1618 self
.SectionHeaderList
= []
1621 PeObject
= open(PeFile
, 'rb')
1623 self
.ErrorInfo
= self
.FileName
+ ' can not be found\n'
1626 ByteArray
= array
.array('B')
1627 ByteArray
.fromfile(PeObject
, 0x3E)
1628 ByteList
= ByteArray
.tolist()
1629 # DOS signature should be 'MZ'
1630 if self
._ByteListToStr
(ByteList
[0x0:0x2]) != 'MZ':
1631 self
.ErrorInfo
= self
.FileName
+ ' has no valid DOS signature MZ'
1634 # Read 4 byte PE Signature
1635 PeOffset
= self
._ByteListToInt
(ByteList
[0x3C:0x3E])
1636 PeObject
.seek(PeOffset
)
1637 ByteArray
= array
.array('B')
1638 ByteArray
.fromfile(PeObject
, 4)
1639 # PE signature should be 'PE\0\0'
1640 if ByteArray
.tostring() != 'PE\0\0':
1641 self
.ErrorInfo
= self
.FileName
+ ' has no valid PE signature PE00'
1644 # Read PE file header
1645 ByteArray
= array
.array('B')
1646 ByteArray
.fromfile(PeObject
, 0x14)
1647 ByteList
= ByteArray
.tolist()
1648 SecNumber
= self
._ByteListToInt
(ByteList
[0x2:0x4])
1650 self
.ErrorInfo
= self
.FileName
+ ' has no section header'
1653 # Read PE optional header
1654 OptionalHeaderSize
= self
._ByteListToInt
(ByteArray
[0x10:0x12])
1655 ByteArray
= array
.array('B')
1656 ByteArray
.fromfile(PeObject
, OptionalHeaderSize
)
1657 ByteList
= ByteArray
.tolist()
1658 self
.EntryPoint
= self
._ByteListToInt
(ByteList
[0x10:0x14])
1659 self
.SectionAlignment
= self
._ByteListToInt
(ByteList
[0x20:0x24])
1660 self
.Size
= self
._ByteListToInt
(ByteList
[0x38:0x3C])
1662 # Read each Section Header
1663 for Index
in range(SecNumber
):
1664 ByteArray
= array
.array('B')
1665 ByteArray
.fromfile(PeObject
, 0x28)
1666 ByteList
= ByteArray
.tolist()
1667 SecName
= self
._ByteListToStr
(ByteList
[0:8])
1668 SecVirtualSize
= self
._ByteListToInt
(ByteList
[8:12])
1669 SecRawAddress
= self
._ByteListToInt
(ByteList
[20:24])
1670 SecVirtualAddress
= self
._ByteListToInt
(ByteList
[12:16])
1671 self
.SectionHeaderList
.append((SecName
, SecVirtualAddress
, SecRawAddress
, SecVirtualSize
))
1675 def _ByteListToStr(self
, ByteList
):
1677 for index
in range(len(ByteList
)):
1678 if ByteList
[index
] == 0:
1680 String
+= chr(ByteList
[index
])
1683 def _ByteListToInt(self
, ByteList
):
1685 for index
in range(len(ByteList
) - 1, -1, -1):
1686 Value
= (Value
<< 8) |
int(ByteList
[index
])
1696 def __init__(self
,SkuIdentifier
='', SkuIds
={}):
1698 self
.AvailableSkuIds
= sdict()
1701 if SkuIdentifier
== '' or SkuIdentifier
is None:
1702 self
.SkuIdSet
= ['DEFAULT']
1703 elif SkuIdentifier
== 'ALL':
1704 self
.SkuIdSet
= SkuIds
.keys()
1706 r
= SkuIdentifier
.split('|')
1707 self
.SkuIdSet
=[r
[k
].strip() for k
in range(len(r
))]
1708 if len(self
.SkuIdSet
) == 2 and 'DEFAULT' in self
.SkuIdSet
and SkuIdentifier
!= 'ALL':
1709 self
.SkuIdSet
.remove('DEFAULT')
1711 for each
in self
.SkuIdSet
:
1713 self
.AvailableSkuIds
[each
] = SkuIds
[each
]
1715 EdkLogger
.error("build", PARAMETER_INVALID
,
1716 ExtraData
="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
1717 % (each
, " ".join(SkuIds
.keys())))
1719 def __SkuUsageType(self
):
1721 if len(self
.SkuIdSet
) == 1:
1722 if self
.SkuIdSet
[0] == 'DEFAULT':
1723 return SkuClass
.DEFAULT
1725 return SkuClass
.SINGLE
1727 return SkuClass
.MULTIPLE
1729 def __GetAvailableSkuIds(self
):
1730 return self
.AvailableSkuIds
1732 def __GetSystemSkuID(self
):
1733 if self
.__SkuUsageType
() == SkuClass
.SINGLE
:
1734 return self
.SkuIdSet
[0]
1738 SystemSkuId
= property(__GetSystemSkuID
)
1739 AvailableSkuIdSet
= property(__GetAvailableSkuIds
)
1740 SkuUsageType
= property(__SkuUsageType
)
1744 # This acts like the main() function for the script, unless it is 'import'ed into another
1747 if __name__
== '__main__':