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 if DataType
== 'VOID*':
1243 IsValid
= (len(FieldList
) <= 2)
1245 IsValid
= (len(FieldList
) <= 1)
1246 return [Value
, '', Size
], IsValid
, 0
1247 elif PcdType
in (MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
):
1248 Value
= FieldList
[0]
1250 if len(FieldList
) > 1:
1254 if len(FieldList
) > 2:
1258 Size
= str(len(Value
))
1259 if DataType
== 'VOID*':
1260 IsValid
= (len(FieldList
) <= 3)
1262 IsValid
= (len(FieldList
) <= 1)
1263 return [Value
, Type
, Size
], IsValid
, 0
1264 elif PcdType
in (MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_VPD
):
1265 VpdOffset
= FieldList
[0]
1267 if not DataType
== 'VOID*':
1268 if len(FieldList
) > 1:
1269 Value
= FieldList
[1]
1271 if len(FieldList
) > 1:
1273 if len(FieldList
) > 2:
1274 Value
= FieldList
[2]
1275 if DataType
== 'VOID*':
1276 IsValid
= (len(FieldList
) <= 3)
1278 IsValid
= (len(FieldList
) <= 2)
1279 return [VpdOffset
, Size
, Value
], IsValid
, 2
1280 elif PcdType
in (MODEL_PCD_DYNAMIC_HII
, MODEL_PCD_DYNAMIC_EX_HII
):
1281 HiiString
= FieldList
[0]
1282 Guid
= Offset
= Value
= ''
1283 if len(FieldList
) > 1:
1285 if len(FieldList
) > 2:
1286 Offset
= FieldList
[2]
1287 if len(FieldList
) > 3:
1288 Value
= FieldList
[3]
1289 IsValid
= (3 <= len(FieldList
) <= 4)
1290 return [HiiString
, Guid
, Offset
, Value
], IsValid
, 3
1295 # Analyze the pcd Value, Datum type and TokenNumber.
1296 # Used to avoid split issue while the value string contain "|" character
1298 # @param[in] Setting: A String contain value/datum type/token number information;
1300 # @retval ValueList: A List contain value, datum type and toke number.
1302 def AnalyzePcdData(Setting
):
1303 ValueList
= ['', '', '']
1305 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1306 PtrValue
= ValueRe
.findall(Setting
)
1308 ValueUpdateFlag
= False
1310 if len(PtrValue
) >= 1:
1311 Setting
= re
.sub(ValueRe
, '', Setting
)
1312 ValueUpdateFlag
= True
1314 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1315 ValueList
[0:len(TokenList
)] = TokenList
1318 ValueList
[0] = PtrValue
[0]
1322 ## AnalyzeHiiPcdData
1324 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1325 # Used to avoid split issue while the value string contain "|" character
1327 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1329 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1331 def AnalyzeHiiPcdData(Setting
):
1332 ValueList
= ['', '', '', '']
1334 TokenList
= GetSplitValueList(Setting
)
1335 ValueList
[0:len(TokenList
)] = TokenList
1339 ## AnalyzeVpdPcdData
1341 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1342 # Used to avoid split issue while the value string contain "|" character
1344 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1346 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1348 def AnalyzeVpdPcdData(Setting
):
1349 ValueList
= ['', '', '']
1351 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
1352 PtrValue
= ValueRe
.findall(Setting
)
1354 ValueUpdateFlag
= False
1356 if len(PtrValue
) >= 1:
1357 Setting
= re
.sub(ValueRe
, '', Setting
)
1358 ValueUpdateFlag
= True
1360 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1361 ValueList
[0:len(TokenList
)] = TokenList
1364 ValueList
[2] = PtrValue
[0]
1368 ## check format of PCD value against its the datum type
1370 # For PCD value setting
1372 def CheckPcdDatum(Type
, Value
):
1374 ValueRe
= re
.compile(r
'\s*L?\".*\"\s*$')
1375 if not (((Value
.startswith('L"') or Value
.startswith('"')) and Value
.endswith('"'))
1376 or (Value
.startswith('{') and Value
.endswith('}'))
1378 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1379 ", or \"...\" for string, or L\"...\" for unicode string" % (Value
, Type
)
1380 elif ValueRe
.match(Value
):
1381 # Check the chars in UnicodeString or CString is printable
1382 if Value
.startswith("L"):
1386 Printset
= set(string
.printable
)
1387 Printset
.remove(TAB_PRINTCHAR_VT
)
1388 Printset
.add(TAB_PRINTCHAR_BS
)
1389 Printset
.add(TAB_PRINTCHAR_NUL
)
1390 if not set(Value
).issubset(Printset
):
1391 PrintList
= list(Printset
)
1393 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type
, PrintList
)
1394 elif Type
== 'BOOLEAN':
1395 if Value
not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1396 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1397 ", FALSE, False, false, 0x0, 0x00, 0" % (Value
, Type
)
1398 elif Type
in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
]:
1400 Value
= long(Value
, 0)
1402 return False, "Invalid value [%s] of type [%s];"\
1403 " must be a hexadecimal, decimal or octal in C language format." % (Value
, Type
)
1405 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type
)
1409 ## Split command line option string to list
1411 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1412 # in non-windows platform to launch command
1414 def SplitOption(OptionString
):
1419 for Index
in range(0, len(OptionString
)):
1420 CurrentChar
= OptionString
[Index
]
1421 if CurrentChar
in ['"', "'"]:
1422 if QuotationMark
== CurrentChar
:
1424 elif QuotationMark
== "":
1425 QuotationMark
= CurrentChar
1430 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1431 if Index
> OptionStart
:
1432 OptionList
.append(OptionString
[OptionStart
:Index
-1])
1434 LastChar
= CurrentChar
1435 OptionList
.append(OptionString
[OptionStart
:])
1438 def CommonPath(PathList
):
1439 P1
= min(PathList
).split(os
.path
.sep
)
1440 P2
= max(PathList
).split(os
.path
.sep
)
1441 for Index
in xrange(min(len(P1
), len(P2
))):
1442 if P1
[Index
] != P2
[Index
]:
1443 return os
.path
.sep
.join(P1
[:Index
])
1444 return os
.path
.sep
.join(P1
)
1446 class PathClass(object):
1447 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1448 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1450 self
.File
= str(File
)
1451 if os
.path
.isabs(self
.File
):
1455 self
.Root
= str(Root
)
1456 self
.AlterRoot
= str(AlterRoot
)
1458 # Remove any '.' and '..' in path
1460 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1461 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1462 # eliminate the side-effect of 'C:'
1463 if self
.Root
[-1] == ':':
1464 self
.Root
+= os
.path
.sep
1465 # file path should not start with path separator
1466 if self
.Root
[-1] == os
.path
.sep
:
1467 self
.File
= self
.Path
[len(self
.Root
):]
1469 self
.File
= self
.Path
[len(self
.Root
)+1:]
1471 self
.Path
= os
.path
.normpath(self
.File
)
1473 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1474 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1478 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1480 self
.Dir
= self
.Root
1482 self
.Dir
= self
.SubDir
1487 self
.Type
= self
.Ext
.lower()
1489 self
.IsBinary
= IsBinary
1490 self
.Target
= Target
1491 self
.TagName
= TagName
1492 self
.ToolCode
= ToolCode
1493 self
.ToolChainFamily
= ToolChainFamily
1497 ## Convert the object of this class to a string
1499 # Convert member Path of the class to a string
1501 # @retval string Formatted String
1506 ## Override __eq__ function
1508 # Check whether PathClass are the same
1510 # @retval False The two PathClass are different
1511 # @retval True The two PathClass are the same
1513 def __eq__(self
, Other
):
1514 if type(Other
) == type(self
):
1515 return self
.Path
== Other
.Path
1517 return self
.Path
== str(Other
)
1519 ## Override __cmp__ function
1521 # Customize the comparsion operation of two PathClass
1523 # @retval 0 The two PathClass are different
1524 # @retval -1 The first PathClass is less than the second PathClass
1525 # @retval 1 The first PathClass is Bigger than the second PathClass
1526 def __cmp__(self
, Other
):
1527 if type(Other
) == type(self
):
1528 OtherKey
= Other
.Path
1530 OtherKey
= str(Other
)
1533 if SelfKey
== OtherKey
:
1535 elif SelfKey
> OtherKey
:
1540 ## Override __hash__ function
1542 # Use Path as key in hash table
1544 # @retval string Key for hash table
1547 return hash(self
.Path
)
1549 def _GetFileKey(self
):
1550 if self
._Key
== None:
1551 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1554 def _GetTimeStamp(self
):
1555 return os
.stat(self
.Path
)[8]
1557 def Validate(self
, Type
='', CaseSensitive
=True):
1558 if GlobalData
.gCaseInsensitive
:
1559 CaseSensitive
= False
1560 if Type
and Type
.lower() != self
.Type
:
1561 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
1563 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
1564 if not RealRoot
and not RealFile
:
1565 RealFile
= self
.File
1567 RealFile
= os
.path
.join(self
.AlterRoot
, self
.File
)
1569 RealFile
= os
.path
.join(self
.Root
, self
.File
)
1570 return FILE_NOT_FOUND
, os
.path
.join(self
.AlterRoot
, RealFile
)
1574 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
1575 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
1576 ErrorCode
= FILE_CASE_MISMATCH
1577 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
1579 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
1580 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1582 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
1585 self
.File
= RealFile
1586 self
.Root
= RealRoot
1587 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
1588 return ErrorCode
, ErrorInfo
1590 Key
= property(_GetFileKey
)
1591 TimeStamp
= property(_GetTimeStamp
)
1593 ## Parse PE image to get the required PE informaion.
1595 class PeImageClass():
1598 # @param File FilePath of PeImage
1600 def __init__(self
, PeFile
):
1601 self
.FileName
= PeFile
1602 self
.IsValid
= False
1605 self
.SectionAlignment
= 0
1606 self
.SectionHeaderList
= []
1609 PeObject
= open(PeFile
, 'rb')
1611 self
.ErrorInfo
= self
.FileName
+ ' can not be found\n'
1614 ByteArray
= array
.array('B')
1615 ByteArray
.fromfile(PeObject
, 0x3E)
1616 ByteList
= ByteArray
.tolist()
1617 # DOS signature should be 'MZ'
1618 if self
._ByteListToStr
(ByteList
[0x0:0x2]) != 'MZ':
1619 self
.ErrorInfo
= self
.FileName
+ ' has no valid DOS signature MZ'
1622 # Read 4 byte PE Signature
1623 PeOffset
= self
._ByteListToInt
(ByteList
[0x3C:0x3E])
1624 PeObject
.seek(PeOffset
)
1625 ByteArray
= array
.array('B')
1626 ByteArray
.fromfile(PeObject
, 4)
1627 # PE signature should be 'PE\0\0'
1628 if ByteArray
.tostring() != 'PE\0\0':
1629 self
.ErrorInfo
= self
.FileName
+ ' has no valid PE signature PE00'
1632 # Read PE file header
1633 ByteArray
= array
.array('B')
1634 ByteArray
.fromfile(PeObject
, 0x14)
1635 ByteList
= ByteArray
.tolist()
1636 SecNumber
= self
._ByteListToInt
(ByteList
[0x2:0x4])
1638 self
.ErrorInfo
= self
.FileName
+ ' has no section header'
1641 # Read PE optional header
1642 OptionalHeaderSize
= self
._ByteListToInt
(ByteArray
[0x10:0x12])
1643 ByteArray
= array
.array('B')
1644 ByteArray
.fromfile(PeObject
, OptionalHeaderSize
)
1645 ByteList
= ByteArray
.tolist()
1646 self
.EntryPoint
= self
._ByteListToInt
(ByteList
[0x10:0x14])
1647 self
.SectionAlignment
= self
._ByteListToInt
(ByteList
[0x20:0x24])
1648 self
.Size
= self
._ByteListToInt
(ByteList
[0x38:0x3C])
1650 # Read each Section Header
1651 for Index
in range(SecNumber
):
1652 ByteArray
= array
.array('B')
1653 ByteArray
.fromfile(PeObject
, 0x28)
1654 ByteList
= ByteArray
.tolist()
1655 SecName
= self
._ByteListToStr
(ByteList
[0:8])
1656 SecVirtualSize
= self
._ByteListToInt
(ByteList
[8:12])
1657 SecRawAddress
= self
._ByteListToInt
(ByteList
[20:24])
1658 SecVirtualAddress
= self
._ByteListToInt
(ByteList
[12:16])
1659 self
.SectionHeaderList
.append((SecName
, SecVirtualAddress
, SecRawAddress
, SecVirtualSize
))
1663 def _ByteListToStr(self
, ByteList
):
1665 for index
in range(len(ByteList
)):
1666 if ByteList
[index
] == 0:
1668 String
+= chr(ByteList
[index
])
1671 def _ByteListToInt(self
, ByteList
):
1673 for index
in range(len(ByteList
) - 1, -1, -1):
1674 Value
= (Value
<< 8) |
int(ByteList
[index
])
1684 def __init__(self
,SkuIdentifier
='', SkuIds
={}):
1686 self
.AvailableSkuIds
= sdict()
1689 if SkuIdentifier
== '' or SkuIdentifier
is None:
1690 self
.SkuIdSet
= ['DEFAULT']
1691 elif SkuIdentifier
== 'ALL':
1692 self
.SkuIdSet
= SkuIds
.keys()
1694 r
= SkuIdentifier
.split('|')
1695 self
.SkuIdSet
=[r
[k
].strip() for k
in range(len(r
))]
1696 if len(self
.SkuIdSet
) == 2 and 'DEFAULT' in self
.SkuIdSet
and SkuIdentifier
!= 'ALL':
1697 self
.SkuIdSet
.remove('DEFAULT')
1699 for each
in self
.SkuIdSet
:
1701 self
.AvailableSkuIds
[each
] = SkuIds
[each
]
1703 EdkLogger
.error("build", PARAMETER_INVALID
,
1704 ExtraData
="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
1705 % (each
, " ".join(SkuIds
.keys())))
1707 def __SkuUsageType(self
):
1709 if len(self
.SkuIdSet
) == 1:
1710 if self
.SkuIdSet
[0] == 'DEFAULT':
1711 return SkuClass
.DEFAULT
1713 return SkuClass
.SINGLE
1715 return SkuClass
.MULTIPLE
1717 def __GetAvailableSkuIds(self
):
1718 return self
.AvailableSkuIds
1720 def __GetSystemSkuID(self
):
1721 if self
.__SkuUsageType
() == SkuClass
.SINGLE
:
1722 return self
.SkuIdSet
[0]
1726 SystemSkuId
= property(__GetSystemSkuID
)
1727 AvailableSkuIdSet
= property(__GetAvailableSkuIds
)
1728 SkuUsageType
= property(__SkuUsageType
)
1732 # This acts like the main() function for the script, unless it is 'import'ed into another
1735 if __name__
== '__main__':