2 # Common routines used by all tools
4 # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 import Common
.LongFilePathOs
as os
27 from struct
import pack
28 from UserDict
import IterableUserDict
29 from UserList
import UserList
31 from Common
import EdkLogger
as EdkLogger
32 from Common
import GlobalData
as GlobalData
33 from DataType
import *
34 from BuildToolError
import *
35 from CommonDataClass
.DataClass
import *
36 from Parsing
import GetSplitValueList
37 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
38 from Common
.MultipleWorkspace
import MultipleWorkspace
as mws
40 from CommonDataClass
.Exceptions
import BadExpression
42 ## Regular expression used to find out place holders in string template
43 gPlaceholderPattern
= re
.compile("\$\{([^$()\s]+)\}", re
.MULTILINE | re
.UNICODE
)
45 ## Dictionary used to store file time stamp for quick re-access
46 gFileTimeStampCache
= {} # {file path : file time stamp}
48 ## Dictionary used to store dependencies of files
49 gDependencyDatabase
= {} # arch : {file path : [dependent files list]}
51 def GetVariableOffset(mapfilepath
, efifilepath
, varnames
):
52 """ Parse map file to get variable offset in current EFI file
53 @param mapfilepath Map file absolution path
54 @param efifilepath: EFI binary file full path
55 @param varnames iteratable container whose elements are variable names to be searched
57 @return List whos elements are tuple with variable name and raw offset
61 f
= open(mapfilepath
, 'r')
67 if len(lines
) == 0: return None
68 firstline
= lines
[0].strip()
69 if (firstline
.startswith("Archive member included ") and
70 firstline
.endswith(" file (symbol)")):
71 return _parseForGCC(lines
, efifilepath
, varnames
)
72 if firstline
.startswith("# Path:"):
73 return _parseForXcode(lines
, efifilepath
, varnames
)
74 return _parseGeneral(lines
, efifilepath
, varnames
)
76 def _parseForXcode(lines
, efifilepath
, varnames
):
79 for index
, line
in enumerate(lines
):
81 if status
== 0 and line
== "# Symbols:":
84 if status
== 1 and len(line
) != 0:
85 for varname
in varnames
:
87 m
= re
.match('^([\da-fA-FxX]+)([\s\S]*)([_]*%s)$' % varname
, line
)
89 ret
.append((varname
, m
.group(1)))
92 def _parseForGCC(lines
, efifilepath
, varnames
):
93 """ Parse map file generated by GCC linker """
97 for index
, line
in enumerate(lines
):
99 # status machine transection
100 if status
== 0 and line
== "Memory Configuration":
103 elif status
== 1 and line
== 'Linker script and memory map':
106 elif status
==2 and line
== 'START GROUP':
112 m
= re
.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line
)
114 sections
.append(m
.groups(0))
115 for varname
in varnames
:
117 m
= re
.match("^.data.(%s)" % varname
, line
)
119 m
= re
.match(".data.(%s)$" % varname
, line
)
121 Str
= lines
[index
+ 1]
123 Str
= line
[len(".data.%s" % varname
):]
125 m
= re
.match('^([\da-fA-Fx]+) +([\da-fA-Fx]+)', Str
.strip())
127 varoffset
.append((varname
, int(m
.groups(0)[0], 16) , int(sections
[-1][1], 16), sections
[-1][0]))
131 # get section information from efi file
132 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
133 if efisecs
== None or len(efisecs
) == 0:
137 for efisec
in efisecs
:
138 for section
in sections
:
139 if section
[0].strip() == efisec
[0].strip() and section
[0].strip() == '.text':
140 redirection
= int(section
[1], 16) - efisec
[1]
143 for var
in varoffset
:
144 for efisec
in efisecs
:
145 if var
[1] >= efisec
[1] and var
[1] < efisec
[1]+efisec
[3]:
146 ret
.append((var
[0], hex(efisec
[2] + var
[1] - efisec
[1] - redirection
)))
149 def _parseGeneral(lines
, efifilepath
, varnames
):
150 status
= 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table
151 secs
= [] # key = section name
153 secRe
= re
.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re
.UNICODE
)
154 symRe
= re
.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re
.UNICODE
)
158 if re
.match("^Start[' ']+Length[' ']+Name[' ']+Class", line
):
161 if re
.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line
):
164 if re
.match("^entry point at", line
):
167 if status
== 1 and len(line
) != 0:
168 m
= secRe
.match(line
)
169 assert m
!= None, "Fail to parse the section in map file , line is %s" % line
170 sec_no
, sec_start
, sec_length
, sec_name
, sec_class
= m
.groups(0)
171 secs
.append([int(sec_no
, 16), int(sec_start
, 16), int(sec_length
, 16), sec_name
, sec_class
])
172 if status
== 2 and len(line
) != 0:
173 for varname
in varnames
:
174 m
= symRe
.match(line
)
175 assert m
!= None, "Fail to parse the symbol in map file, line is %s" % line
176 sec_no
, sym_offset
, sym_name
, vir_addr
= m
.groups(0)
177 sec_no
= int(sec_no
, 16)
178 sym_offset
= int(sym_offset
, 16)
179 vir_addr
= int(vir_addr
, 16)
180 m2
= re
.match('^[_]*(%s)' % varname
, sym_name
)
182 # fond a binary pcd entry in map file
184 if sec
[0] == sec_no
and (sym_offset
>= sec
[1] and sym_offset
< sec
[1] + sec
[2]):
185 varoffset
.append([varname
, sec
[3], sym_offset
, vir_addr
, sec_no
])
187 if not varoffset
: return []
189 # get section information from efi file
190 efisecs
= PeImageClass(efifilepath
).SectionHeaderList
191 if efisecs
== None or len(efisecs
) == 0:
195 for var
in varoffset
:
197 for efisec
in efisecs
:
199 if var
[1].strip() == efisec
[0].strip():
200 ret
.append((var
[0], hex(efisec
[2] + var
[2])))
201 elif var
[4] == index
:
202 ret
.append((var
[0], hex(efisec
[2] + var
[2])))
206 ## Routine to process duplicated INF
208 # This function is called by following two cases:
211 # Pkg/module/module.inf
212 # Pkg/module/module.inf {
214 # FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836
217 # INF Pkg/module/module.inf
218 # INF FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836 Pkg/module/module.inf
220 # This function copies Pkg/module/module.inf to
221 # Conf/.cache/0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf
223 # @param Path Original PathClass object
224 # @param BaseName New file base name
226 # @retval return the new PathClass object
228 def ProcessDuplicatedInf(Path
, BaseName
, Workspace
):
229 Filename
= os
.path
.split(Path
.File
)[1]
231 Filename
= BaseName
+ Path
.BaseName
+ Filename
[Filename
.rfind('.'):]
233 Filename
= BaseName
+ Path
.BaseName
236 # If -N is specified on command line, cache is disabled
237 # The directory has to be created
239 DbDir
= os
.path
.split(GlobalData
.gDatabasePath
)[0]
240 if not os
.path
.exists(DbDir
):
243 # A temporary INF is copied to database path which must have write permission
244 # The temporary will be removed at the end of build
245 # In case of name conflict, the file name is
246 # FILE_GUIDBaseName (0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf)
248 TempFullPath
= os
.path
.join(DbDir
,
250 RtPath
= PathClass(Path
.File
, Workspace
)
252 # Modify the full path to temporary path, keep other unchanged
254 # To build same module more than once, the module path with FILE_GUID overridden has
255 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
256 # in DSC which is used as relative path by C files and other files in INF.
257 # A trick was used: all module paths are PathClass instances, after the initialization
258 # of PathClass, the PathClass.Path is overridden by the temporary INF path.
260 # The reason for creating a temporary INF is:
261 # Platform.Modules which is the base to create ModuleAutoGen objects is a dictionary,
262 # the key is the full path of INF, the value is an object to save overridden library instances, PCDs.
263 # A different key for the same module is needed to create different output directory,
264 # retrieve overridden PCDs, library instances.
266 # The BaseName is the FILE_GUID which is also the output directory name.
269 RtPath
.Path
= TempFullPath
270 RtPath
.BaseName
= BaseName
272 # If file exists, compare contents
274 if os
.path
.exists(TempFullPath
):
275 with
open(str(Path
), 'rb') as f1
: Src
= f1
.read()
276 with
open(TempFullPath
, 'rb') as f2
: Dst
= f2
.read()
279 GlobalData
.gTempInfs
.append(TempFullPath
)
280 shutil
.copy2(str(Path
), TempFullPath
)
283 ## Remove temporary created INFs whose paths were saved in gTempInfs
285 def ClearDuplicatedInf():
286 for File
in GlobalData
.gTempInfs
:
287 if os
.path
.exists(File
):
290 ## callback routine for processing variable option
292 # This function can be used to process variable number of option values. The
293 # typical usage of it is specify architecure list on command line.
294 # (e.g. <tool> -a IA32 X64 IPF)
296 # @param Option Standard callback function parameter
297 # @param OptionString Standard callback function parameter
298 # @param Value Standard callback function parameter
299 # @param Parser Standard callback function parameter
303 def ProcessVariableArgument(Option
, OptionString
, Value
, Parser
):
306 RawArgs
= Parser
.rargs
309 if (Arg
[:2] == "--" and len(Arg
) > 2) or \
310 (Arg
[:1] == "-" and len(Arg
) > 1 and Arg
[1] != "-"):
314 setattr(Parser
.values
, Option
.dest
, Value
)
316 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
318 # @param Guid The GUID string
320 # @retval string The GUID string in C structure style
322 def GuidStringToGuidStructureString(Guid
):
323 GuidList
= Guid
.split('-')
325 for Index
in range(0, 3, 1):
326 Result
= Result
+ '0x' + GuidList
[Index
] + ', '
327 Result
= Result
+ '{0x' + GuidList
[3][0:2] + ', 0x' + GuidList
[3][2:4]
328 for Index
in range(0, 12, 2):
329 Result
= Result
+ ', 0x' + GuidList
[4][Index
:Index
+ 2]
333 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
335 # @param GuidValue The GUID value in byte array
337 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
339 def GuidStructureByteArrayToGuidString(GuidValue
):
340 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
341 guidValueList
= guidValueString
.split(",")
342 if len(guidValueList
) != 16:
344 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
346 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
347 int(guidValueList
[3], 16),
348 int(guidValueList
[2], 16),
349 int(guidValueList
[1], 16),
350 int(guidValueList
[0], 16),
351 int(guidValueList
[5], 16),
352 int(guidValueList
[4], 16),
353 int(guidValueList
[7], 16),
354 int(guidValueList
[6], 16),
355 int(guidValueList
[8], 16),
356 int(guidValueList
[9], 16),
357 int(guidValueList
[10], 16),
358 int(guidValueList
[11], 16),
359 int(guidValueList
[12], 16),
360 int(guidValueList
[13], 16),
361 int(guidValueList
[14], 16),
362 int(guidValueList
[15], 16)
367 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
369 # @param GuidValue The GUID value in C structure format
371 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
373 def GuidStructureStringToGuidString(GuidValue
):
374 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
375 guidValueList
= guidValueString
.split(",")
376 if len(guidValueList
) != 11:
378 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
380 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
381 int(guidValueList
[0], 16),
382 int(guidValueList
[1], 16),
383 int(guidValueList
[2], 16),
384 int(guidValueList
[3], 16),
385 int(guidValueList
[4], 16),
386 int(guidValueList
[5], 16),
387 int(guidValueList
[6], 16),
388 int(guidValueList
[7], 16),
389 int(guidValueList
[8], 16),
390 int(guidValueList
[9], 16),
391 int(guidValueList
[10], 16)
396 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
398 # @param GuidValue The GUID value in C structure format
400 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
402 def GuidStructureStringToGuidValueName(GuidValue
):
403 guidValueString
= GuidValue
.lower().replace("{", "").replace("}", "").replace(" ", "")
404 guidValueList
= guidValueString
.split(",")
405 if len(guidValueList
) != 11:
406 EdkLogger
.error(None, FORMAT_INVALID
, "Invalid GUID value string [%s]" % GuidValue
)
407 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
408 int(guidValueList
[0], 16),
409 int(guidValueList
[1], 16),
410 int(guidValueList
[2], 16),
411 int(guidValueList
[3], 16),
412 int(guidValueList
[4], 16),
413 int(guidValueList
[5], 16),
414 int(guidValueList
[6], 16),
415 int(guidValueList
[7], 16),
416 int(guidValueList
[8], 16),
417 int(guidValueList
[9], 16),
418 int(guidValueList
[10], 16)
421 ## Create directories
423 # @param Directory The directory name
425 def CreateDirectory(Directory
):
426 if Directory
== None or Directory
.strip() == "":
429 if not os
.access(Directory
, os
.F_OK
):
430 os
.makedirs(Directory
)
435 ## Remove directories, including files and sub-directories in it
437 # @param Directory The directory name
439 def RemoveDirectory(Directory
, Recursively
=False):
440 if Directory
== None or Directory
.strip() == "" or not os
.path
.exists(Directory
):
443 CurrentDirectory
= os
.getcwd()
445 for File
in os
.listdir("."):
446 if os
.path
.isdir(File
):
447 RemoveDirectory(File
, Recursively
)
450 os
.chdir(CurrentDirectory
)
453 ## Check if given file is changed or not
455 # This method is used to check if a file is changed or not between two build
456 # actions. It makes use a cache to store files timestamp.
458 # @param File The path of file
460 # @retval True If the given file is changed, doesn't exist, or can't be
461 # found in timestamp cache
462 # @retval False If the given file is changed
465 if not os
.path
.exists(File
):
468 FileState
= os
.stat(File
)
469 TimeStamp
= FileState
[-2]
471 if File
in gFileTimeStampCache
and TimeStamp
== gFileTimeStampCache
[File
]:
475 gFileTimeStampCache
[File
] = TimeStamp
479 ## Store content in file
481 # This method is used to save file only when its content is changed. This is
482 # quite useful for "make" system to decide what will be re-built and what won't.
484 # @param File The path of file
485 # @param Content The new content of the file
486 # @param IsBinaryFile The flag indicating if the file is binary file or not
488 # @retval True If the file content is changed and the file is renewed
489 # @retval False If the file content is the same
491 def SaveFileOnChange(File
, Content
, IsBinaryFile
=True):
493 Content
= Content
.replace("\n", os
.linesep
)
495 if os
.path
.exists(File
):
497 if Content
== open(File
, "rb").read():
500 EdkLogger
.error(None, FILE_OPEN_FAILURE
, ExtraData
=File
)
502 DirName
= os
.path
.dirname(File
)
503 if not CreateDirectory(DirName
):
504 EdkLogger
.error(None, FILE_CREATE_FAILURE
, "Could not create directory %s" % DirName
)
507 DirName
= os
.getcwd()
508 if not os
.access(DirName
, os
.W_OK
):
509 EdkLogger
.error(None, PERMISSION_FAILURE
, "Do not have write permission on directory %s" % DirName
)
512 if GlobalData
.gIsWindows
:
514 from PyUtility
import SaveFileToDisk
515 if not SaveFileToDisk(File
, Content
):
516 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
=File
)
518 Fd
= open(File
, "wb")
522 Fd
= open(File
, "wb")
526 EdkLogger
.error(None, FILE_CREATE_FAILURE
, ExtraData
='IOError %s' % X
)
530 ## Make a Python object persistent on file system
532 # @param Data The object to be stored in file
533 # @param File The path of file to store the object
535 def DataDump(Data
, File
):
538 Fd
= open(File
, 'wb')
539 cPickle
.dump(Data
, Fd
, cPickle
.HIGHEST_PROTOCOL
)
541 EdkLogger
.error("", FILE_OPEN_FAILURE
, ExtraData
=File
, RaiseError
=False)
546 ## Restore a Python object from a file
548 # @param File The path of file stored the object
550 # @retval object A python object
551 # @retval None If failure in file operation
553 def DataRestore(File
):
557 Fd
= open(File
, 'rb')
558 Data
= cPickle
.load(Fd
)
560 EdkLogger
.verbose("Failed to load [%s]\n\t%s" % (File
, str(e
)))
567 ## Retrieve and cache the real path name in file system
569 # @param Root The root directory of path relative to
571 # @retval str The path string if the path exists
572 # @retval None If path doesn't exist
578 def __init__(self
, Root
):
580 for F
in os
.listdir(Root
):
582 self
._UPPER
_CACHE
_[F
.upper()] = F
585 def __getitem__(self
, Path
):
586 Path
= Path
[len(os
.path
.commonprefix([Path
, self
._Root
])):]
589 if Path
and Path
[0] == os
.path
.sep
:
591 if Path
in self
._CACHE
_:
592 return os
.path
.join(self
._Root
, Path
)
593 UpperPath
= Path
.upper()
594 if UpperPath
in self
._UPPER
_CACHE
_:
595 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
599 SepIndex
= Path
.find(os
.path
.sep
)
601 Parent
= UpperPath
[:SepIndex
]
602 if Parent
not in self
._UPPER
_CACHE
_:
604 LastSepIndex
= SepIndex
605 SepIndex
= Path
.find(os
.path
.sep
, LastSepIndex
+ 1)
607 if LastSepIndex
== -1:
612 SepIndex
= LastSepIndex
614 Parent
= Path
[:SepIndex
]
615 ParentKey
= UpperPath
[:SepIndex
]
616 if ParentKey
not in self
._UPPER
_CACHE
_:
620 if Parent
in self
._CACHE
_:
623 ParentDir
= self
._UPPER
_CACHE
_[ParentKey
]
624 for F
in os
.listdir(ParentDir
):
625 Dir
= os
.path
.join(ParentDir
, F
)
626 self
._CACHE
_.add(Dir
)
627 self
._UPPER
_CACHE
_[Dir
.upper()] = Dir
629 SepIndex
= Path
.find(os
.path
.sep
, SepIndex
+ 1)
632 if Path
in self
._CACHE
_:
633 return os
.path
.join(self
._Root
, Path
)
634 elif UpperPath
in self
._UPPER
_CACHE
_:
635 return os
.path
.join(self
._Root
, self
._UPPER
_CACHE
_[UpperPath
])
638 ## Get all files of a directory
640 # @param Root: Root dir
641 # @param SkipList : The files need be skipped
643 # @retval A list of all files
645 def GetFiles(Root
, SkipList
=None, FullPath
=True):
648 for Root
, Dirs
, Files
in os
.walk(Root
):
650 for Item
in SkipList
:
655 File
= os
.path
.normpath(os
.path
.join(Root
, File
))
657 File
= File
[len(OriPath
) + 1:]
658 FileList
.append(File
)
662 ## Check if gvien file exists or not
664 # @param File File name or path to be checked
665 # @param Dir The directory the file is relative to
667 # @retval True if file exists
668 # @retval False if file doesn't exists
670 def ValidFile(File
, Ext
=None):
672 Dummy
, FileExt
= os
.path
.splitext(File
)
673 if FileExt
.lower() != Ext
.lower():
675 if not os
.path
.exists(File
):
679 def RealPath(File
, Dir
='', OverrideDir
=''):
680 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
681 NewFile
= GlobalData
.gAllFiles
[NewFile
]
682 if not NewFile
and OverrideDir
:
683 NewFile
= os
.path
.normpath(os
.path
.join(OverrideDir
, File
))
684 NewFile
= GlobalData
.gAllFiles
[NewFile
]
687 def RealPath2(File
, Dir
='', OverrideDir
=''):
690 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
692 if OverrideDir
[-1] == os
.path
.sep
:
693 return NewFile
[len(OverrideDir
):], NewFile
[0:len(OverrideDir
)]
695 return NewFile
[len(OverrideDir
) + 1:], NewFile
[0:len(OverrideDir
)]
696 if GlobalData
.gAllFiles
:
697 NewFile
= GlobalData
.gAllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
699 NewFile
= os
.path
.normpath(os
.path
.join(Dir
, File
))
700 if not os
.path
.exists(NewFile
):
704 if Dir
[-1] == os
.path
.sep
:
705 return NewFile
[len(Dir
):], NewFile
[0:len(Dir
)]
707 return NewFile
[len(Dir
) + 1:], NewFile
[0:len(Dir
)]
713 ## Check if gvien file exists or not
716 def ValidFile2(AllFiles
, File
, Ext
=None, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
719 Dummy
, FileExt
= os
.path
.splitext(File
)
720 if FileExt
.lower() != Ext
.lower():
723 # Replace the Edk macros
724 if OverrideDir
!= '' and OverrideDir
!= None:
725 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
726 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
727 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
728 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
730 # Replace the default dir to current dir
733 Dir
= Dir
[len(Workspace
) + 1:]
735 # First check if File has Edk definition itself
736 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
737 NewFile
= File
.replace('$(EFI_SOURCE)', EfiSource
)
738 NewFile
= NewFile
.replace('$(EDK_SOURCE)', EdkSource
)
739 NewFile
= AllFiles
[os
.path
.normpath(NewFile
)]
743 # Second check the path with override value
744 if OverrideDir
!= '' and OverrideDir
!= None:
745 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
749 # Last check the path with normal definitions
750 File
= os
.path
.join(Dir
, File
)
751 NewFile
= AllFiles
[os
.path
.normpath(File
)]
757 ## Check if gvien file exists or not
760 def ValidFile3(AllFiles
, File
, Workspace
='', EfiSource
='', EdkSource
='', Dir
='.', OverrideDir
=''):
761 # Replace the Edk macros
762 if OverrideDir
!= '' and OverrideDir
!= None:
763 if OverrideDir
.find('$(EFI_SOURCE)') > -1:
764 OverrideDir
= OverrideDir
.replace('$(EFI_SOURCE)', EfiSource
)
765 if OverrideDir
.find('$(EDK_SOURCE)') > -1:
766 OverrideDir
= OverrideDir
.replace('$(EDK_SOURCE)', EdkSource
)
768 # Replace the default dir to current dir
769 # Dir is current module dir related to workspace
772 Dir
= Dir
[len(Workspace
) + 1:]
775 RelaPath
= AllFiles
[os
.path
.normpath(Dir
)]
776 NewRelaPath
= RelaPath
779 # First check if File has Edk definition itself
780 if File
.find('$(EFI_SOURCE)') > -1 or File
.find('$(EDK_SOURCE)') > -1:
781 File
= File
.replace('$(EFI_SOURCE)', EfiSource
)
782 File
= File
.replace('$(EDK_SOURCE)', EdkSource
)
783 NewFile
= AllFiles
[os
.path
.normpath(File
)]
785 NewRelaPath
= os
.path
.dirname(NewFile
)
786 File
= os
.path
.basename(NewFile
)
787 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
790 # Second check the path with override value
791 if OverrideDir
!= '' and OverrideDir
!= None:
792 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(OverrideDir
, File
))]
794 #NewRelaPath = os.path.dirname(NewFile)
795 NewRelaPath
= NewFile
[:len(NewFile
) - len(File
.replace("..\\", '').replace("../", '')) - 1]
798 # Last check the path with normal definitions
799 NewFile
= AllFiles
[os
.path
.normpath(os
.path
.join(Dir
, File
))]
806 return NewRelaPath
, RelaPath
, File
809 def GetRelPath(Path1
, Path2
):
810 FileName
= os
.path
.basename(Path2
)
811 L1
= os
.path
.normpath(Path1
).split(os
.path
.normpath('/'))
812 L2
= os
.path
.normpath(Path2
).split(os
.path
.normpath('/'))
813 for Index
in range(0, len(L1
)):
814 if L1
[Index
] != L2
[Index
]:
815 FileName
= '../' * (len(L1
) - Index
)
816 for Index2
in range(Index
, len(L2
)):
817 FileName
= os
.path
.join(FileName
, L2
[Index2
])
819 return os
.path
.normpath(FileName
)
822 ## Get GUID value from given packages
824 # @param CName The CName of the GUID
825 # @param PackageList List of packages looking-up in
826 # @param Inffile The driver file
828 # @retval GuidValue if the CName is found in any given package
829 # @retval None if the CName is not found in all given packages
831 def GuidValue(CName
, PackageList
, Inffile
= None):
832 for P
in PackageList
:
833 GuidKeys
= P
.Guids
.keys()
834 if Inffile
and P
._PrivateGuids
:
835 if not Inffile
.startswith(P
.MetaFile
.Dir
):
836 GuidKeys
= (dict.fromkeys(x
for x
in P
.Guids
if x
not in P
._PrivateGuids
)).keys()
837 if CName
in GuidKeys
:
838 return P
.Guids
[CName
]
841 ## Get Protocol value from given packages
843 # @param CName The CName of the GUID
844 # @param PackageList List of packages looking-up in
845 # @param Inffile The driver file
847 # @retval GuidValue if the CName is found in any given package
848 # @retval None if the CName is not found in all given packages
850 def ProtocolValue(CName
, PackageList
, Inffile
= None):
851 for P
in PackageList
:
852 ProtocolKeys
= P
.Protocols
.keys()
853 if Inffile
and P
._PrivateProtocols
:
854 if not Inffile
.startswith(P
.MetaFile
.Dir
):
855 ProtocolKeys
= (dict.fromkeys(x
for x
in P
.Protocols
if x
not in P
._PrivateProtocols
)).keys()
856 if CName
in ProtocolKeys
:
857 return P
.Protocols
[CName
]
860 ## Get PPI value from given packages
862 # @param CName The CName of the GUID
863 # @param PackageList List of packages looking-up in
864 # @param Inffile The driver file
866 # @retval GuidValue if the CName is found in any given package
867 # @retval None if the CName is not found in all given packages
869 def PpiValue(CName
, PackageList
, Inffile
= None):
870 for P
in PackageList
:
871 PpiKeys
= P
.Ppis
.keys()
872 if Inffile
and P
._PrivatePpis
:
873 if not Inffile
.startswith(P
.MetaFile
.Dir
):
874 PpiKeys
= (dict.fromkeys(x
for x
in P
.Ppis
if x
not in P
._PrivatePpis
)).keys()
879 ## A string template class
881 # This class implements a template for string replacement. A string template
882 # looks like following
884 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
886 # The string between ${BEGIN} and ${END} will be repeated as many times as the
887 # length of "placeholder_name", which is a list passed through a dict. The
888 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
889 # be not used and, in this case, the "placeholder_name" must not a list and it
890 # will just be replaced once.
892 class TemplateString(object):
893 _REPEAT_START_FLAG
= "BEGIN"
894 _REPEAT_END_FLAG
= "END"
896 class Section(object):
897 _LIST_TYPES
= [type([]), type(set()), type((0,))]
899 def __init__(self
, TemplateSection
, PlaceHolderList
):
900 self
._Template
= TemplateSection
901 self
._PlaceHolderList
= []
903 # Split the section into sub-sections according to the position of placeholders
905 self
._SubSectionList
= []
908 # The placeholders passed in must be in the format of
910 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
912 for PlaceHolder
, Start
, End
in PlaceHolderList
:
913 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:Start
])
914 self
._SubSectionList
.append(TemplateSection
[Start
:End
])
915 self
._PlaceHolderList
.append(PlaceHolder
)
916 SubSectionStart
= End
917 if SubSectionStart
< len(TemplateSection
):
918 self
._SubSectionList
.append(TemplateSection
[SubSectionStart
:])
920 self
._SubSectionList
= [TemplateSection
]
923 return self
._Template
+ " : " + str(self
._PlaceHolderList
)
925 def Instantiate(self
, PlaceHolderValues
):
927 RepeatPlaceHolders
= {}
928 NonRepeatPlaceHolders
= {}
930 for PlaceHolder
in self
._PlaceHolderList
:
931 if PlaceHolder
not in PlaceHolderValues
:
933 Value
= PlaceHolderValues
[PlaceHolder
]
934 if type(Value
) in self
._LIST
_TYPES
:
936 RepeatTime
= len(Value
)
937 elif RepeatTime
!= len(Value
):
941 "${%s} has different repeat time from others!" % PlaceHolder
,
942 ExtraData
=str(self
._Template
)
944 RepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
946 NonRepeatPlaceHolders
["${%s}" % PlaceHolder
] = Value
948 if NonRepeatPlaceHolders
:
950 for S
in self
._SubSectionList
:
951 if S
not in NonRepeatPlaceHolders
:
954 StringList
.append(str(NonRepeatPlaceHolders
[S
]))
956 StringList
= self
._SubSectionList
958 if RepeatPlaceHolders
:
960 for Index
in range(RepeatTime
):
962 if S
not in RepeatPlaceHolders
:
963 TempStringList
.append(S
)
965 TempStringList
.append(str(RepeatPlaceHolders
[S
][Index
]))
966 StringList
= TempStringList
968 return "".join(StringList
)
971 def __init__(self
, Template
=None):
973 self
.IsBinary
= False
974 self
._Template
= Template
975 self
._TemplateSectionList
= self
._Parse
(Template
)
979 # @retval string The string replaced
984 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
986 # @retval list A list of TemplateString.Section objects
988 def _Parse(self
, Template
):
993 TemplateSectionList
= []
995 MatchObj
= gPlaceholderPattern
.search(Template
, SearchFrom
)
997 if MatchEnd
<= len(Template
):
998 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:], PlaceHolderList
)
999 TemplateSectionList
.append(TemplateSection
)
1002 MatchString
= MatchObj
.group(1)
1003 MatchStart
= MatchObj
.start()
1004 MatchEnd
= MatchObj
.end()
1006 if MatchString
== self
._REPEAT
_START
_FLAG
:
1007 if MatchStart
> SectionStart
:
1008 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
1009 TemplateSectionList
.append(TemplateSection
)
1010 SectionStart
= MatchEnd
1011 PlaceHolderList
= []
1012 elif MatchString
== self
._REPEAT
_END
_FLAG
:
1013 TemplateSection
= TemplateString
.Section(Template
[SectionStart
:MatchStart
], PlaceHolderList
)
1014 TemplateSectionList
.append(TemplateSection
)
1015 SectionStart
= MatchEnd
1016 PlaceHolderList
= []
1018 PlaceHolderList
.append((MatchString
, MatchStart
- SectionStart
, MatchEnd
- SectionStart
))
1019 SearchFrom
= MatchEnd
1020 return TemplateSectionList
1022 ## Replace the string template with dictionary of placeholders and append it to previous one
1024 # @param AppendString The string template to append
1025 # @param Dictionary The placeholder dictionaries
1027 def Append(self
, AppendString
, Dictionary
=None):
1029 SectionList
= self
._Parse
(AppendString
)
1030 self
.String
+= "".join([S
.Instantiate(Dictionary
) for S
in SectionList
])
1032 self
.String
+= AppendString
1034 ## Replace the string template with dictionary of placeholders
1036 # @param Dictionary The placeholder dictionaries
1038 # @retval str The string replaced with placeholder values
1040 def Replace(self
, Dictionary
=None):
1041 return "".join([S
.Instantiate(Dictionary
) for S
in self
._TemplateSectionList
])
1043 ## Progress indicator class
1045 # This class makes use of thread to print progress on console.
1048 # for avoiding deadloop
1050 _ProgressThread
= None
1051 _CheckInterval
= 0.25
1055 # @param OpenMessage The string printed before progress charaters
1056 # @param CloseMessage The string printed after progress charaters
1057 # @param ProgressChar The charater used to indicate the progress
1058 # @param Interval The interval in seconds between two progress charaters
1060 def __init__(self
, OpenMessage
="", CloseMessage
="", ProgressChar
='.', Interval
=1.0):
1061 self
.PromptMessage
= OpenMessage
1062 self
.CodaMessage
= CloseMessage
1063 self
.ProgressChar
= ProgressChar
1064 self
.Interval
= Interval
1065 if Progressor
._StopFlag
== None:
1066 Progressor
._StopFlag
= threading
.Event()
1068 ## Start to print progress charater
1070 # @param OpenMessage The string printed before progress charaters
1072 def Start(self
, OpenMessage
=None):
1073 if OpenMessage
!= None:
1074 self
.PromptMessage
= OpenMessage
1075 Progressor
._StopFlag
.clear()
1076 if Progressor
._ProgressThread
== None:
1077 Progressor
._ProgressThread
= threading
.Thread(target
=self
._ProgressThreadEntry
)
1078 Progressor
._ProgressThread
.setDaemon(False)
1079 Progressor
._ProgressThread
.start()
1081 ## Stop printing progress charater
1083 # @param CloseMessage The string printed after progress charaters
1085 def Stop(self
, CloseMessage
=None):
1086 OriginalCodaMessage
= self
.CodaMessage
1087 if CloseMessage
!= None:
1088 self
.CodaMessage
= CloseMessage
1090 self
.CodaMessage
= OriginalCodaMessage
1092 ## Thread entry method
1093 def _ProgressThreadEntry(self
):
1094 sys
.stdout
.write(self
.PromptMessage
+ " ")
1097 while not Progressor
._StopFlag
.isSet():
1099 sys
.stdout
.write(self
.ProgressChar
)
1101 TimeUp
= self
.Interval
1102 time
.sleep(self
._CheckInterval
)
1103 TimeUp
-= self
._CheckInterval
1104 sys
.stdout
.write(" " + self
.CodaMessage
+ "\n")
1107 ## Abort the progress display
1110 if Progressor
._StopFlag
!= None:
1111 Progressor
._StopFlag
.set()
1112 if Progressor
._ProgressThread
!= None:
1113 Progressor
._ProgressThread
.join()
1114 Progressor
._ProgressThread
= None
1116 ## A dict which can access its keys and/or values orderly
1118 # The class implements a new kind of dict which its keys or values can be
1119 # accessed in the order they are added into the dict. It guarantees the order
1120 # by making use of an internal list to keep a copy of keys.
1122 class sdict(IterableUserDict
):
1125 IterableUserDict
.__init
__(self
)
1129 def __setitem__(self
, key
, value
):
1130 if key
not in self
._key
_list
:
1131 self
._key
_list
.append(key
)
1132 IterableUserDict
.__setitem
__(self
, key
, value
)
1135 def __delitem__(self
, key
):
1136 self
._key
_list
.remove(key
)
1137 IterableUserDict
.__delitem
__(self
, key
)
1139 ## used in "for k in dict" loop to ensure the correct order
1141 return self
.iterkeys()
1145 return len(self
._key
_list
)
1147 ## "in" test support
1148 def __contains__(self
, key
):
1149 return key
in self
._key
_list
1152 def index(self
, key
):
1153 return self
._key
_list
.index(key
)
1156 def insert(self
, key
, newkey
, newvalue
, order
):
1157 index
= self
._key
_list
.index(key
)
1158 if order
== 'BEFORE':
1159 self
._key
_list
.insert(index
, newkey
)
1160 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
1161 elif order
== 'AFTER':
1162 self
._key
_list
.insert(index
+ 1, newkey
)
1163 IterableUserDict
.__setitem
__(self
, newkey
, newvalue
)
1166 def append(self
, sdict
):
1168 if key
not in self
._key
_list
:
1169 self
._key
_list
.append(key
)
1170 IterableUserDict
.__setitem
__(self
, key
, sdict
[key
])
1172 def has_key(self
, key
):
1173 return key
in self
._key
_list
1178 IterableUserDict
.clear(self
)
1180 ## Return a copy of keys
1183 for key
in self
._key
_list
:
1187 ## Return a copy of values
1190 for key
in self
._key
_list
:
1191 values
.append(self
[key
])
1194 ## Return a copy of (key, value) list
1197 for key
in self
._key
_list
:
1198 items
.append((key
, self
[key
]))
1201 ## Iteration support
1202 def iteritems(self
):
1203 return iter(self
.items())
1205 ## Keys interation support
1207 return iter(self
.keys())
1209 ## Values interation support
1210 def itervalues(self
):
1211 return iter(self
.values())
1213 ## Return value related to a key, and remove the (key, value) from the dict
1214 def pop(self
, key
, *dv
):
1216 if key
in self
._key
_list
:
1218 self
.__delitem
__(key
)
1223 ## Return (key, value) pair, and remove the (key, value) from the dict
1225 key
= self
._key
_list
[-1]
1227 self
.__delitem
__(key
)
1230 def update(self
, dict=None, **kwargs
):
1232 for k
, v
in dict.items():
1235 for k
, v
in kwargs
.items():
1238 ## Dictionary with restricted keys
1242 def __init__(self
, KeyList
):
1244 dict.__setitem
__(self
, Key
, "")
1247 def __setitem__(self
, key
, value
):
1249 EdkLogger
.error("RestrictedDict", ATTRIBUTE_SET_FAILURE
, "Key [%s] is not allowed" % key
,
1250 ExtraData
=", ".join(dict.keys(self
)))
1251 dict.__setitem
__(self
, key
, value
)
1254 def __getitem__(self
, key
):
1257 return dict.__getitem
__(self
, key
)
1260 def __delitem__(self
, key
):
1261 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="del")
1266 self
.__setitem
__(Key
, "")
1268 ## Return value related to a key, and remove the (key, value) from the dict
1269 def pop(self
, key
, *dv
):
1270 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="pop")
1272 ## Return (key, value) pair, and remove the (key, value) from the dict
1274 EdkLogger
.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED
, ExtraData
="popitem")
1276 ## Dictionary using prioritized list as key
1279 _ListType
= type([])
1280 _TupleType
= type(())
1281 _Wildcard
= 'COMMON'
1282 _ValidWildcardList
= ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1284 def __init__(self
, _Single_
=False, _Level_
=2):
1285 self
._Level
_ = _Level_
1287 self
._Single
_ = _Single_
1290 def __getitem__(self
, key
):
1293 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1297 elif self
._Level
_ > 1:
1298 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_ - 1)]
1301 if self
._Level
_ > 1:
1302 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_ - 1)]
1304 if FirstKey
== None or str(FirstKey
).upper() in self
._ValidWildcardList
:
1305 FirstKey
= self
._Wildcard
1308 return self
._GetSingleValue
(FirstKey
, RestKeys
)
1310 return self
._GetAllValues
(FirstKey
, RestKeys
)
1312 def _GetSingleValue(self
, FirstKey
, RestKeys
):
1314 #print "%s-%s" % (FirstKey, self._Level_) ,
1315 if self
._Level
_ > 1:
1316 if FirstKey
== self
._Wildcard
:
1317 if FirstKey
in self
.data
:
1318 Value
= self
.data
[FirstKey
][RestKeys
]
1320 for Key
in self
.data
:
1321 Value
= self
.data
[Key
][RestKeys
]
1322 if Value
!= None: break
1324 if FirstKey
in self
.data
:
1325 Value
= self
.data
[FirstKey
][RestKeys
]
1326 if Value
== None and self
._Wildcard
in self
.data
:
1328 Value
= self
.data
[self
._Wildcard
][RestKeys
]
1330 if FirstKey
== self
._Wildcard
:
1331 if FirstKey
in self
.data
:
1332 Value
= self
.data
[FirstKey
]
1334 for Key
in self
.data
:
1335 Value
= self
.data
[Key
]
1336 if Value
!= None: break
1338 if FirstKey
in self
.data
:
1339 Value
= self
.data
[FirstKey
]
1340 elif self
._Wildcard
in self
.data
:
1341 Value
= self
.data
[self
._Wildcard
]
1344 def _GetAllValues(self
, FirstKey
, RestKeys
):
1346 if self
._Level
_ > 1:
1347 if FirstKey
== self
._Wildcard
:
1348 for Key
in self
.data
:
1349 Value
+= self
.data
[Key
][RestKeys
]
1351 if FirstKey
in self
.data
:
1352 Value
+= self
.data
[FirstKey
][RestKeys
]
1353 if self
._Wildcard
in self
.data
:
1354 Value
+= self
.data
[self
._Wildcard
][RestKeys
]
1356 if FirstKey
== self
._Wildcard
:
1357 for Key
in self
.data
:
1358 Value
.append(self
.data
[Key
])
1360 if FirstKey
in self
.data
:
1361 Value
.append(self
.data
[FirstKey
])
1362 if self
._Wildcard
in self
.data
:
1363 Value
.append(self
.data
[self
._Wildcard
])
1367 def __setitem__(self
, key
, value
):
1370 if KeyType
== self
._ListType
or KeyType
== self
._TupleType
:
1375 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_ - 1)]
1378 if self
._Level
_ > 1:
1379 RestKeys
= [self
._Wildcard
for i
in range(0, self
._Level
_ - 1)]
1381 if FirstKey
in self
._ValidWildcardList
:
1382 FirstKey
= self
._Wildcard
1384 if FirstKey
not in self
.data
and self
._Level
_ > 0:
1385 self
.data
[FirstKey
] = tdict(self
._Single
_, self
._Level
_ - 1)
1387 if self
._Level
_ > 1:
1388 self
.data
[FirstKey
][RestKeys
] = value
1390 self
.data
[FirstKey
] = value
1392 def SetGreedyMode(self
):
1393 self
._Single
_ = False
1394 if self
._Level
_ > 1:
1395 for Key
in self
.data
:
1396 self
.data
[Key
].SetGreedyMode()
1398 def SetSingleMode(self
):
1399 self
._Single
_ = True
1400 if self
._Level
_ > 1:
1401 for Key
in self
.data
:
1402 self
.data
[Key
].SetSingleMode()
1404 def GetKeys(self
, KeyIndex
=0):
1405 assert KeyIndex
>= 0
1407 return set(self
.data
.keys())
1410 for Key
in self
.data
:
1411 keys |
= self
.data
[Key
].GetKeys(KeyIndex
- 1)
1414 ## Boolean chain list
1416 class Blist(UserList
):
1417 def __init__(self
, initlist
=None):
1418 UserList
.__init
__(self
, initlist
)
1419 def __setitem__(self
, i
, item
):
1420 if item
not in [True, False]:
1426 def _GetResult(self
):
1428 for item
in self
.data
:
1431 Result
= property(_GetResult
)
1433 def ParseConsoleLog(Filename
):
1434 Opr
= open(os
.path
.normpath(Filename
), 'r')
1435 Opw
= open(os
.path
.normpath(Filename
+ '.New'), 'w+')
1436 for Line
in Opr
.readlines():
1437 if Line
.find('.efi') > -1:
1438 Line
= Line
[Line
.rfind(' ') : Line
.rfind('.efi')].strip()
1439 Opw
.write('%s\n' % Line
)
1444 def AnalyzePcdExpression(Setting
):
1445 Setting
= Setting
.strip()
1446 # There might be escaped quote in a string: \", \\\" , \', \\\'
1448 # There might be '|' in string and in ( ... | ... ), replace it with '-'
1450 InSingleQuoteStr
= False
1451 InDoubleQuoteStr
= False
1453 for Index
, ch
in enumerate(Data
):
1454 if ch
== '"' and not InSingleQuoteStr
:
1455 if Data
[Index
- 1] != '\\':
1456 InDoubleQuoteStr
= not InDoubleQuoteStr
1457 elif ch
== "'" and not InDoubleQuoteStr
:
1458 if Data
[Index
- 1] != '\\':
1459 InSingleQuoteStr
= not InSingleQuoteStr
1460 elif ch
== '(' and not (InSingleQuoteStr
or InDoubleQuoteStr
):
1462 elif ch
== ')' and not (InSingleQuoteStr
or InDoubleQuoteStr
):
1465 if (Pair
> 0 or InSingleQuoteStr
or InDoubleQuoteStr
) and ch
== TAB_VALUE_SPLIT
:
1472 Pos
= NewStr
.find(TAB_VALUE_SPLIT
, StartPos
)
1474 FieldList
.append(Setting
[StartPos
:].strip())
1476 FieldList
.append(Setting
[StartPos
:Pos
].strip())
1481 def ParseDevPathValue (Value
):
1482 DevPathList
= [ "Path","HardwarePath","Pci","PcCard","MemoryMapped","VenHw","Ctrl","BMC","AcpiPath","Acpi","PciRoot",
1483 "PcieRoot","Floppy","Keyboard","Serial","ParallelPort","AcpiEx","AcpiExp","AcpiAdr","Msg","Ata","Scsi",
1484 "Fibre","FibreEx","I1394","USB","I2O","Infiniband","VenMsg","VenPcAnsi","VenVt100","VenVt100Plus",
1485 "VenUtf8","UartFlowCtrl","SAS","SasEx","NVMe","UFS","SD","eMMC","DebugPort","MAC","IPv4","IPv6","Uart",
1486 "UsbClass","UsbAudio","UsbCDCControl","UsbHID","UsbImage","UsbPrinter","UsbMassStorage","UsbHub",
1487 "UsbCDCData","UsbSmartCard","UsbVideo","UsbDiagnostic","UsbWireless","UsbDeviceFirmwareUpdate",
1488 "UsbIrdaBridge","UsbTestAndMeasurement","UsbWwid","Unit","iSCSI","Vlan","Uri","Bluetooth","Wi-Fi",
1489 "MediaPath","HD","CDROM","VenMedia","Media","Fv","FvFile","Offset","RamDisk","VirtualDisk","VirtualCD",
1490 "PersistentVirtualDisk","PersistentVirtualCD","BbsPath","BBS","Sata" ]
1492 Value
.replace('\\', '/').replace(' ', '')
1493 for Item
in Value
.split('/'):
1494 Key
= Item
.strip().split('(')[0]
1495 if Key
not in DevPathList
:
1498 Cmd
= 'DevicePath ' + '"' + Value
+ '"'
1500 p
= subprocess
.Popen(Cmd
, stdout
=subprocess
.PIPE
, stderr
=subprocess
.PIPE
, shell
=True)
1501 out
, err
= p
.communicate()
1502 except Exception, X
:
1503 raise BadExpression("DevicePath: %s" % (str(X
)) )
1505 subprocess
._cleanup
()
1509 raise BadExpression("DevicePath: %s" % str(err
))
1510 Size
= len(out
.split())
1511 out
= ','.join(out
.split())
1512 return '{' + out
+ '}', Size
1514 def ParseFieldValue (Value
):
1515 if type(Value
) == type(0):
1516 return Value
, (Value
.bit_length() + 7) / 8
1517 if type(Value
) <> type(''):
1518 raise BadExpression('Type %s is %s' %(Value
, type(Value
)))
1519 Value
= Value
.strip()
1520 if Value
.startswith('UINT8') and Value
.endswith(')'):
1521 Value
, Size
= ParseFieldValue(Value
.split('(', 1)[1][:-1])
1523 raise BadExpression('Value (%s) Size larger than %d' %(Value
, Size
))
1525 if Value
.startswith('UINT16') and Value
.endswith(')'):
1526 Value
, Size
= ParseFieldValue(Value
.split('(', 1)[1][:-1])
1528 raise BadExpression('Value (%s) Size larger than %d' %(Value
, Size
))
1530 if Value
.startswith('UINT32') and Value
.endswith(')'):
1531 Value
, Size
= ParseFieldValue(Value
.split('(', 1)[1][:-1])
1533 raise BadExpression('Value (%s) Size larger than %d' %(Value
, Size
))
1535 if Value
.startswith('UINT64') and Value
.endswith(')'):
1536 Value
, Size
= ParseFieldValue(Value
.split('(', 1)[1][:-1])
1538 raise BadExpression('Value (%s) Size larger than %d' % (Value
, Size
))
1540 if Value
.startswith('GUID') and Value
.endswith(')'):
1541 Value
= Value
.split('(', 1)[1][:-1].strip()
1542 if Value
[0] == '{' and Value
[-1] == '}':
1543 TmpValue
= GuidStructureStringToGuidString(Value
)
1544 if len(TmpValue
) == 0:
1545 raise BadExpression("Invalid GUID value string %s" % Value
)
1547 if Value
[0] == '"' and Value
[-1] == '"':
1550 Value
= "'" + uuid
.UUID(Value
).get_bytes_le() + "'"
1551 except ValueError, Message
:
1552 raise BadExpression('%s' % Message
)
1553 Value
, Size
= ParseFieldValue(Value
)
1555 if Value
.startswith('L"') and Value
.endswith('"'):
1557 # translate escape character
1567 Value
= (Value
<< 16) |
ord(Char
)
1568 return Value
, (len(List
) + 1) * 2
1569 if Value
.startswith('"') and Value
.endswith('"'):
1571 # translate escape character
1580 Value
= (Value
<< 8) |
ord(Char
)
1581 return Value
, len(List
) + 1
1582 if Value
.startswith("L'") and Value
.endswith("'"):
1583 # Unicode Character Constant
1584 # translate escape character
1592 raise BadExpression('Length %s is %s' % (Value
, len(List
)))
1596 Value
= (Value
<< 16) |
ord(Char
)
1597 return Value
, len(List
) * 2
1598 if Value
.startswith("'") and Value
.endswith("'"):
1599 # Character constant
1600 # translate escape character
1607 raise BadExpression('Length %s is %s' % (Value
, len(List
)))
1611 Value
= (Value
<< 8) |
ord(Char
)
1612 return Value
, len(List
)
1613 if Value
.startswith('{') and Value
.endswith('}'):
1616 List
= [Item
.strip() for Item
in Value
.split(',')]
1621 ItemValue
, Size
= ParseFieldValue(Item
)
1623 for I
in range(Size
):
1624 Value
= (Value
<< 8) |
((ItemValue
>> 8 * I
) & 0xff)
1625 return Value
, RetSize
1626 if Value
.startswith('DEVICE_PATH(') and Value
.endswith(')'):
1627 Value
= Value
.replace("DEVICE_PATH(", '').rstrip(')')
1628 Value
= Value
.strip().strip('"')
1629 return ParseDevPathValue(Value
)
1630 if Value
.lower().startswith('0x'):
1631 Value
= int(Value
, 16)
1634 return Value
, (Value
.bit_length() + 7) / 8
1635 if Value
[0].isdigit():
1636 Value
= int(Value
, 10)
1639 return Value
, (Value
.bit_length() + 7) / 8
1640 if Value
.lower() == 'true':
1642 if Value
.lower() == 'false':
1648 # Analyze DSC PCD value, since there is no data type info in DSC
1649 # This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
1650 # 1. Feature flag: TokenSpace.PcdCName|PcdValue
1651 # 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
1652 # 3. Dynamic default:
1653 # TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
1654 # TokenSpace.PcdCName|PcdValue
1656 # TokenSpace.PcdCName|VpdOffset[|VpdValue]
1657 # TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
1659 # TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
1660 # PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
1661 # there might have "|" operator, also in string value.
1663 # @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
1664 # @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
1665 # @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
1667 # ValueList: A List contain fields described above
1668 # IsValid: True if conforming EBNF, otherwise False
1669 # Index: The index where PcdValue is in ValueList
1671 def AnalyzeDscPcd(Setting
, PcdType
, DataType
=''):
1672 FieldList
= AnalyzePcdExpression(Setting
)
1675 if PcdType
in (MODEL_PCD_FIXED_AT_BUILD
, MODEL_PCD_PATCHABLE_IN_MODULE
, MODEL_PCD_FEATURE_FLAG
):
1676 Value
= FieldList
[0]
1678 if len(FieldList
) > 1:
1679 if FieldList
[1].upper().startswith("0X") or FieldList
[1].isdigit():
1682 DataType
= FieldList
[1]
1684 if len(FieldList
) > 2:
1687 IsValid
= (len(FieldList
) <= 1)
1689 IsValid
= (len(FieldList
) <= 3)
1690 # Value, Size = ParseFieldValue(Value)
1693 int(Size
,16) if Size
.upper().startswith("0X") else int(Size
)
1697 return [str(Value
), '', str(Size
)], IsValid
, 0
1698 elif PcdType
in (MODEL_PCD_DYNAMIC_DEFAULT
, MODEL_PCD_DYNAMIC_EX_DEFAULT
):
1699 Value
= FieldList
[0]
1701 if len(FieldList
) > 1:
1705 if len(FieldList
) > 2:
1709 if Value
.startswith("L"):
1710 Size
= str((len(Value
)- 3 + 1) * 2)
1711 elif Value
.startswith("{"):
1712 Size
= str(len(Value
.split(",")))
1714 Size
= str(len(Value
) -2 + 1 )
1716 IsValid
= (len(FieldList
) <= 1)
1718 IsValid
= (len(FieldList
) <= 3)
1722 int(Size
,16) if Size
.upper().startswith("0X") else int(Size
)
1726 return [Value
, Type
, str(Size
)], IsValid
, 0
1727 elif PcdType
in (MODEL_PCD_DYNAMIC_VPD
, MODEL_PCD_DYNAMIC_EX_VPD
):
1728 VpdOffset
= FieldList
[0]
1730 if not DataType
== 'VOID*':
1731 if len(FieldList
) > 1:
1732 Value
= FieldList
[1]
1734 if len(FieldList
) > 1:
1736 if len(FieldList
) > 2:
1737 Value
= FieldList
[2]
1739 IsValid
= (len(FieldList
) <= 1)
1741 IsValid
= (len(FieldList
) <= 3)
1744 int(Size
,16) if Size
.upper().startswith("0X") else int(Size
)
1748 return [VpdOffset
, str(Size
), Value
], IsValid
, 2
1749 elif PcdType
in (MODEL_PCD_DYNAMIC_HII
, MODEL_PCD_DYNAMIC_EX_HII
):
1750 HiiString
= FieldList
[0]
1751 Guid
= Offset
= Value
= Attribute
= ''
1752 if len(FieldList
) > 1:
1754 if len(FieldList
) > 2:
1755 Offset
= FieldList
[2]
1756 if len(FieldList
) > 3:
1757 Value
= FieldList
[3]
1758 if len(FieldList
) > 4:
1759 Attribute
= FieldList
[4]
1760 IsValid
= (3 <= len(FieldList
) <= 5)
1761 return [HiiString
, Guid
, Offset
, Value
, Attribute
], IsValid
, 3
1766 # Analyze the pcd Value, Datum type and TokenNumber.
1767 # Used to avoid split issue while the value string contain "|" character
1769 # @param[in] Setting: A String contain value/datum type/token number information;
1771 # @retval ValueList: A List contain value, datum type and toke number.
1773 def AnalyzePcdData(Setting
):
1774 ValueList
= ['', '', '']
1776 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1777 PtrValue
= ValueRe
.findall(Setting
)
1779 ValueUpdateFlag
= False
1781 if len(PtrValue
) >= 1:
1782 Setting
= re
.sub(ValueRe
, '', Setting
)
1783 ValueUpdateFlag
= True
1785 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1786 ValueList
[0:len(TokenList
)] = TokenList
1789 ValueList
[0] = PtrValue
[0]
1793 ## AnalyzeHiiPcdData
1795 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1796 # Used to avoid split issue while the value string contain "|" character
1798 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1800 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1802 def AnalyzeHiiPcdData(Setting
):
1803 ValueList
= ['', '', '', '']
1805 TokenList
= GetSplitValueList(Setting
)
1806 ValueList
[0:len(TokenList
)] = TokenList
1810 ## AnalyzeVpdPcdData
1812 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1813 # Used to avoid split issue while the value string contain "|" character
1815 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1817 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1819 def AnalyzeVpdPcdData(Setting
):
1820 ValueList
= ['', '', '']
1822 ValueRe
= re
.compile(r
'\s*L?\".*\|.*\"\s*$')
1823 PtrValue
= ValueRe
.findall(Setting
)
1825 ValueUpdateFlag
= False
1827 if len(PtrValue
) >= 1:
1828 Setting
= re
.sub(ValueRe
, '', Setting
)
1829 ValueUpdateFlag
= True
1831 TokenList
= Setting
.split(TAB_VALUE_SPLIT
)
1832 ValueList
[0:len(TokenList
)] = TokenList
1835 ValueList
[2] = PtrValue
[0]
1839 ## check format of PCD value against its the datum type
1841 # For PCD value setting
1843 def CheckPcdDatum(Type
, Value
):
1845 ValueRe
= re
.compile(r
'\s*L?\".*\"\s*$')
1846 if not (((Value
.startswith('L"') or Value
.startswith('"')) and Value
.endswith('"'))
1847 or (Value
.startswith('{') and Value
.endswith('}')) or (Value
.startswith("L'") or Value
.startswith("'") and Value
.endswith("'"))
1849 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1850 ", \"...\" or \'...\' for string, L\"...\" or L\'...\' for unicode string" % (Value
, Type
)
1851 elif ValueRe
.match(Value
):
1852 # Check the chars in UnicodeString or CString is printable
1853 if Value
.startswith("L"):
1857 Printset
= set(string
.printable
)
1858 Printset
.remove(TAB_PRINTCHAR_VT
)
1859 Printset
.add(TAB_PRINTCHAR_BS
)
1860 Printset
.add(TAB_PRINTCHAR_NUL
)
1861 if not set(Value
).issubset(Printset
):
1862 PrintList
= list(Printset
)
1864 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type
, PrintList
)
1865 elif Type
== 'BOOLEAN':
1866 if Value
not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1867 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1868 ", FALSE, False, false, 0x0, 0x00, 0" % (Value
, Type
)
1869 elif Type
in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
]:
1871 Value
= long(Value
, 0)
1873 return False, "Invalid value [%s] of type [%s];"\
1874 " must be a hexadecimal, decimal or octal in C language format." % (Value
, Type
)
1876 return True, "StructurePcd"
1880 ## Split command line option string to list
1882 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1883 # in non-windows platform to launch command
1885 def SplitOption(OptionString
):
1890 for Index
in range(0, len(OptionString
)):
1891 CurrentChar
= OptionString
[Index
]
1892 if CurrentChar
in ['"', "'"]:
1893 if QuotationMark
== CurrentChar
:
1895 elif QuotationMark
== "":
1896 QuotationMark
= CurrentChar
1901 if CurrentChar
in ["/", "-"] and LastChar
in [" ", "\t", "\r", "\n"]:
1902 if Index
> OptionStart
:
1903 OptionList
.append(OptionString
[OptionStart
:Index
- 1])
1905 LastChar
= CurrentChar
1906 OptionList
.append(OptionString
[OptionStart
:])
1909 def CommonPath(PathList
):
1910 P1
= min(PathList
).split(os
.path
.sep
)
1911 P2
= max(PathList
).split(os
.path
.sep
)
1912 for Index
in xrange(min(len(P1
), len(P2
))):
1913 if P1
[Index
] != P2
[Index
]:
1914 return os
.path
.sep
.join(P1
[:Index
])
1915 return os
.path
.sep
.join(P1
)
1918 # Convert string to C format array
1920 def ConvertStringToByteArray(Value
):
1921 Value
= Value
.strip()
1925 if not Value
.endswith('}'):
1927 Value
= Value
.replace(' ', '').replace('{', '').replace('}', '')
1928 ValFields
= Value
.split(',')
1930 for Index
in range(len(ValFields
)):
1931 ValFields
[Index
] = str(int(ValFields
[Index
], 0))
1934 Value
= '{' + ','.join(ValFields
) + '}'
1938 if Value
.startswith('L"'):
1939 if not Value
.endswith('"'):
1943 elif not Value
.startswith('"') or not Value
.endswith('"'):
1946 Value
= eval(Value
) # translate escape character
1948 for Index
in range(0,len(Value
)):
1950 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x10000) + ','
1952 NewValue
= NewValue
+ str(ord(Value
[Index
]) % 0x100) + ','
1953 Value
= NewValue
+ '0}'
1956 class PathClass(object):
1957 def __init__(self
, File
='', Root
='', AlterRoot
='', Type
='', IsBinary
=False,
1958 Arch
='COMMON', ToolChainFamily
='', Target
='', TagName
='', ToolCode
=''):
1960 self
.File
= str(File
)
1961 if os
.path
.isabs(self
.File
):
1965 self
.Root
= str(Root
)
1966 self
.AlterRoot
= str(AlterRoot
)
1968 # Remove any '.' and '..' in path
1970 self
.Root
= mws
.getWs(self
.Root
, self
.File
)
1971 self
.Path
= os
.path
.normpath(os
.path
.join(self
.Root
, self
.File
))
1972 self
.Root
= os
.path
.normpath(CommonPath([self
.Root
, self
.Path
]))
1973 # eliminate the side-effect of 'C:'
1974 if self
.Root
[-1] == ':':
1975 self
.Root
+= os
.path
.sep
1976 # file path should not start with path separator
1977 if self
.Root
[-1] == os
.path
.sep
:
1978 self
.File
= self
.Path
[len(self
.Root
):]
1980 self
.File
= self
.Path
[len(self
.Root
) + 1:]
1982 self
.Path
= os
.path
.normpath(self
.File
)
1984 self
.SubDir
, self
.Name
= os
.path
.split(self
.File
)
1985 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
1989 self
.Dir
= os
.path
.join(self
.Root
, self
.SubDir
)
1991 self
.Dir
= self
.Root
1993 self
.Dir
= self
.SubDir
1998 self
.Type
= self
.Ext
.lower()
2000 self
.IsBinary
= IsBinary
2001 self
.Target
= Target
2002 self
.TagName
= TagName
2003 self
.ToolCode
= ToolCode
2004 self
.ToolChainFamily
= ToolChainFamily
2008 ## Convert the object of this class to a string
2010 # Convert member Path of the class to a string
2012 # @retval string Formatted String
2017 ## Override __eq__ function
2019 # Check whether PathClass are the same
2021 # @retval False The two PathClass are different
2022 # @retval True The two PathClass are the same
2024 def __eq__(self
, Other
):
2025 if type(Other
) == type(self
):
2026 return self
.Path
== Other
.Path
2028 return self
.Path
== str(Other
)
2030 ## Override __cmp__ function
2032 # Customize the comparsion operation of two PathClass
2034 # @retval 0 The two PathClass are different
2035 # @retval -1 The first PathClass is less than the second PathClass
2036 # @retval 1 The first PathClass is Bigger than the second PathClass
2037 def __cmp__(self
, Other
):
2038 if type(Other
) == type(self
):
2039 OtherKey
= Other
.Path
2041 OtherKey
= str(Other
)
2044 if SelfKey
== OtherKey
:
2046 elif SelfKey
> OtherKey
:
2051 ## Override __hash__ function
2053 # Use Path as key in hash table
2055 # @retval string Key for hash table
2058 return hash(self
.Path
)
2060 def _GetFileKey(self
):
2061 if self
._Key
== None:
2062 self
._Key
= self
.Path
.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
2065 def _GetTimeStamp(self
):
2066 return os
.stat(self
.Path
)[8]
2068 def Validate(self
, Type
='', CaseSensitive
=True):
2069 if GlobalData
.gCaseInsensitive
:
2070 CaseSensitive
= False
2071 if Type
and Type
.lower() != self
.Type
:
2072 return FILE_TYPE_MISMATCH
, '%s (expect %s but got %s)' % (self
.File
, Type
, self
.Type
)
2074 RealFile
, RealRoot
= RealPath2(self
.File
, self
.Root
, self
.AlterRoot
)
2075 if not RealRoot
and not RealFile
:
2076 RealFile
= self
.File
2078 RealFile
= os
.path
.join(self
.AlterRoot
, self
.File
)
2080 RealFile
= os
.path
.join(self
.Root
, self
.File
)
2081 if len (mws
.getPkgPath()) == 0:
2082 return FILE_NOT_FOUND
, os
.path
.join(self
.AlterRoot
, RealFile
)
2084 return FILE_NOT_FOUND
, "%s is not found in packages path:\n\t%s" % (self
.File
, '\n\t'.join(mws
.getPkgPath()))
2088 if RealRoot
!= self
.Root
or RealFile
!= self
.File
:
2089 if CaseSensitive
and (RealFile
!= self
.File
or (RealRoot
!= self
.Root
and RealRoot
!= self
.AlterRoot
)):
2090 ErrorCode
= FILE_CASE_MISMATCH
2091 ErrorInfo
= self
.File
+ '\n\t' + RealFile
+ " [in file system]"
2093 self
.SubDir
, self
.Name
= os
.path
.split(RealFile
)
2094 self
.BaseName
, self
.Ext
= os
.path
.splitext(self
.Name
)
2096 self
.Dir
= os
.path
.join(RealRoot
, self
.SubDir
)
2099 self
.File
= RealFile
2100 self
.Root
= RealRoot
2101 self
.Path
= os
.path
.join(RealRoot
, RealFile
)
2102 return ErrorCode
, ErrorInfo
2104 Key
= property(_GetFileKey
)
2105 TimeStamp
= property(_GetTimeStamp
)
2107 ## Parse PE image to get the required PE informaion.
2109 class PeImageClass():
2112 # @param File FilePath of PeImage
2114 def __init__(self
, PeFile
):
2115 self
.FileName
= PeFile
2116 self
.IsValid
= False
2119 self
.SectionAlignment
= 0
2120 self
.SectionHeaderList
= []
2123 PeObject
= open(PeFile
, 'rb')
2125 self
.ErrorInfo
= self
.FileName
+ ' can not be found\n'
2128 ByteArray
= array
.array('B')
2129 ByteArray
.fromfile(PeObject
, 0x3E)
2130 ByteList
= ByteArray
.tolist()
2131 # DOS signature should be 'MZ'
2132 if self
._ByteListToStr
(ByteList
[0x0:0x2]) != 'MZ':
2133 self
.ErrorInfo
= self
.FileName
+ ' has no valid DOS signature MZ'
2136 # Read 4 byte PE Signature
2137 PeOffset
= self
._ByteListToInt
(ByteList
[0x3C:0x3E])
2138 PeObject
.seek(PeOffset
)
2139 ByteArray
= array
.array('B')
2140 ByteArray
.fromfile(PeObject
, 4)
2141 # PE signature should be 'PE\0\0'
2142 if ByteArray
.tostring() != 'PE\0\0':
2143 self
.ErrorInfo
= self
.FileName
+ ' has no valid PE signature PE00'
2146 # Read PE file header
2147 ByteArray
= array
.array('B')
2148 ByteArray
.fromfile(PeObject
, 0x14)
2149 ByteList
= ByteArray
.tolist()
2150 SecNumber
= self
._ByteListToInt
(ByteList
[0x2:0x4])
2152 self
.ErrorInfo
= self
.FileName
+ ' has no section header'
2155 # Read PE optional header
2156 OptionalHeaderSize
= self
._ByteListToInt
(ByteArray
[0x10:0x12])
2157 ByteArray
= array
.array('B')
2158 ByteArray
.fromfile(PeObject
, OptionalHeaderSize
)
2159 ByteList
= ByteArray
.tolist()
2160 self
.EntryPoint
= self
._ByteListToInt
(ByteList
[0x10:0x14])
2161 self
.SectionAlignment
= self
._ByteListToInt
(ByteList
[0x20:0x24])
2162 self
.Size
= self
._ByteListToInt
(ByteList
[0x38:0x3C])
2164 # Read each Section Header
2165 for Index
in range(SecNumber
):
2166 ByteArray
= array
.array('B')
2167 ByteArray
.fromfile(PeObject
, 0x28)
2168 ByteList
= ByteArray
.tolist()
2169 SecName
= self
._ByteListToStr
(ByteList
[0:8])
2170 SecVirtualSize
= self
._ByteListToInt
(ByteList
[8:12])
2171 SecRawAddress
= self
._ByteListToInt
(ByteList
[20:24])
2172 SecVirtualAddress
= self
._ByteListToInt
(ByteList
[12:16])
2173 self
.SectionHeaderList
.append((SecName
, SecVirtualAddress
, SecRawAddress
, SecVirtualSize
))
2177 def _ByteListToStr(self
, ByteList
):
2179 for index
in range(len(ByteList
)):
2180 if ByteList
[index
] == 0:
2182 String
+= chr(ByteList
[index
])
2185 def _ByteListToInt(self
, ByteList
):
2187 for index
in range(len(ByteList
) - 1, -1, -1):
2188 Value
= (Value
<< 8) |
int(ByteList
[index
])
2191 class DefaultStore():
2192 def __init__(self
,DefaultStores
):
2194 self
.DefaultStores
= DefaultStores
2195 def DefaultStoreID(self
,DefaultStoreName
):
2196 for key
,value
in self
.DefaultStores
.items():
2197 if value
== DefaultStoreName
:
2200 def GetDefaultDefault(self
):
2201 if not self
.DefaultStores
or "0" in self
.DefaultStores
:
2202 return "0",TAB_DEFAULT_STORES_DEFAULT
2204 minvalue
= min([int(value_str
) for value_str
in self
.DefaultStores
.keys()])
2205 return (str(minvalue
), self
.DefaultStores
[str(minvalue
)])
2206 def GetMin(self
,DefaultSIdList
):
2207 if not DefaultSIdList
:
2209 storeidset
= {storeid
for storeid
, storename
in self
.DefaultStores
.values() if storename
in DefaultSIdList
}
2212 minid
= min(storeidset
)
2213 for sid
,name
in self
.DefaultStores
.values():
2222 def __init__(self
,SkuIdentifier
='', SkuIds
=None):
2226 for SkuName
in SkuIds
:
2227 SkuId
= SkuIds
[SkuName
][0]
2228 skuid_num
= int(SkuId
,16) if SkuId
.upper().startswith("0X") else int(SkuId
)
2229 if skuid_num
> 0xFFFFFFFFFFFFFFFF:
2230 EdkLogger
.error("build", PARAMETER_INVALID
,
2231 ExtraData
= "SKU-ID [%s] value %s exceeds the max value of UINT64"
2234 self
.AvailableSkuIds
= sdict()
2236 self
.SkuIdNumberSet
= []
2237 self
.SkuData
= SkuIds
2238 self
.__SkuInherit
= {}
2239 self
.__SkuIdentifier
= SkuIdentifier
2240 if SkuIdentifier
== '' or SkuIdentifier
is None:
2241 self
.SkuIdSet
= ['DEFAULT']
2242 self
.SkuIdNumberSet
= ['0U']
2243 elif SkuIdentifier
== 'ALL':
2244 self
.SkuIdSet
= SkuIds
.keys()
2245 self
.SkuIdNumberSet
= [num
[0].strip() + 'U' for num
in SkuIds
.values()]
2247 r
= SkuIdentifier
.split('|')
2248 self
.SkuIdSet
=[(r
[k
].strip()).upper() for k
in range(len(r
))]
2251 self
.SkuIdNumberSet
= [SkuIds
[k
][0].strip() + 'U' for k
in self
.SkuIdSet
]
2253 EdkLogger
.error("build", PARAMETER_INVALID
,
2254 ExtraData
= "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
2255 % (k
, " | ".join(SkuIds
.keys())))
2256 for each
in self
.SkuIdSet
:
2258 self
.AvailableSkuIds
[each
] = SkuIds
[each
][0]
2260 EdkLogger
.error("build", PARAMETER_INVALID
,
2261 ExtraData
="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
2262 % (each
, " | ".join(SkuIds
.keys())))
2263 if self
.SkuUsageType
!= self
.SINGLE
:
2264 self
.AvailableSkuIds
.update({'DEFAULT':0, 'COMMON':0})
2266 GlobalData
.gSkuids
= (self
.SkuIdSet
)
2267 if 'COMMON' in GlobalData
.gSkuids
:
2268 GlobalData
.gSkuids
.remove('COMMON')
2269 if self
.SkuUsageType
== self
.SINGLE
:
2270 if len(GlobalData
.gSkuids
) != 1:
2271 if 'DEFAULT' in GlobalData
.gSkuids
:
2272 GlobalData
.gSkuids
.remove('DEFAULT')
2273 if GlobalData
.gSkuids
:
2274 GlobalData
.gSkuids
.sort()
2276 def GetNextSkuId(self
, skuname
):
2277 if not self
.__SkuInherit
:
2278 self
.__SkuInherit
= {}
2279 for item
in self
.SkuData
.values():
2280 self
.__SkuInherit
[item
[1]]=item
[2] if item
[2] else "DEFAULT"
2281 return self
.__SkuInherit
.get(skuname
,"DEFAULT")
2283 def GetSkuChain(self
,sku
):
2284 if sku
== "DEFAULT":
2289 nextsku
= self
.GetNextSkuId(nextsku
)
2290 skulist
.append(nextsku
)
2291 if nextsku
== "DEFAULT":
2295 def SkuOverrideOrder(self
):
2297 for skuname
in self
.SkuIdSet
:
2298 skuorderset
.append(self
.GetSkuChain(skuname
))
2301 for index
in range(max([len(item
) for item
in skuorderset
])):
2302 for subset
in skuorderset
:
2303 if index
> len(subset
)-1:
2305 if subset
[index
] in skuorder
:
2307 skuorder
.append(subset
[index
])
2311 def __SkuUsageType(self
):
2313 if self
.__SkuIdentifier
.upper() == "ALL":
2314 return SkuClass
.MULTIPLE
2316 if len(self
.SkuIdSet
) == 1:
2317 if self
.SkuIdSet
[0] == 'DEFAULT':
2318 return SkuClass
.DEFAULT
2320 return SkuClass
.SINGLE
2321 elif len(self
.SkuIdSet
) == 2:
2322 if 'DEFAULT' in self
.SkuIdSet
:
2323 return SkuClass
.SINGLE
2325 return SkuClass
.MULTIPLE
2327 return SkuClass
.MULTIPLE
2328 def DumpSkuIdArrary(self
):
2331 if self
.SkuUsageType
== SkuClass
.SINGLE
:
2334 for skuname
in self
.AvailableSkuIds
:
2335 if skuname
== "COMMON":
2337 while skuname
!= "DEFAULT":
2338 ArrayStrList
.append(hex(int(self
.AvailableSkuIds
[skuname
])))
2339 skuname
= self
.GetNextSkuId(skuname
)
2340 ArrayStrList
.append("0x0")
2341 ArrayStr
= "{" + ",".join(ArrayStrList
) + "}"
2343 def __GetAvailableSkuIds(self
):
2344 return self
.AvailableSkuIds
2346 def __GetSystemSkuID(self
):
2347 if self
.__SkuUsageType
() == SkuClass
.SINGLE
:
2348 if len(self
.SkuIdSet
) == 1:
2349 return self
.SkuIdSet
[0]
2351 return self
.SkuIdSet
[0] if self
.SkuIdSet
[0] != 'DEFAULT' else self
.SkuIdSet
[1]
2354 def __GetAvailableSkuIdNumber(self
):
2355 return self
.SkuIdNumberSet
2356 SystemSkuId
= property(__GetSystemSkuID
)
2357 AvailableSkuIdSet
= property(__GetAvailableSkuIds
)
2358 SkuUsageType
= property(__SkuUsageType
)
2359 AvailableSkuIdNumSet
= property(__GetAvailableSkuIdNumber
)
2362 # Pack a registry format GUID
2364 def PackRegistryFormatGuid(Guid
):
2365 Guid
= Guid
.split('-')
2366 return pack('=LHHBBBBBBBB',
2370 int(Guid
[3][-4:-2], 16),
2371 int(Guid
[3][-2:], 16),
2372 int(Guid
[4][-12:-10], 16),
2373 int(Guid
[4][-10:-8], 16),
2374 int(Guid
[4][-8:-6], 16),
2375 int(Guid
[4][-6:-4], 16),
2376 int(Guid
[4][-4:-2], 16),
2377 int(Guid
[4][-2:], 16)
2380 def BuildOptionPcdValueFormat(TokenSpaceGuidCName
, TokenCName
, PcdDatumType
, Value
):
2381 if PcdDatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
,'BOOLEAN']:
2382 if Value
.startswith('L') or Value
.startswith('"'):
2384 EdkLogger
.error("build", FORMAT_INVALID
, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
2386 elif Value
.startswith('H'):
2388 EdkLogger
.error("build", FORMAT_INVALID
, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
2392 EdkLogger
.error("build", FORMAT_INVALID
, 'For Void* type PCD, when specify the Value in the command line, please use the following format: "string", L"string", H"{...}"')
2393 Value
= '"' + Value
+ '"'
2395 IsValid
, Cause
= CheckPcdDatum(PcdDatumType
, Value
)
2397 EdkLogger
.error("build", FORMAT_INVALID
, Cause
, ExtraData
="%s.%s" % (TokenSpaceGuidCName
, TokenCName
))
2398 if PcdDatumType
== 'BOOLEAN':
2399 Value
= Value
.upper()
2400 if Value
== 'TRUE' or Value
== '1':
2402 elif Value
== 'FALSE' or Value
== '0':
2405 ## Get the integer value from string like "14U" or integer like 2
2407 # @param Input The object that may be either a integer value or a string
2409 # @retval Value The integer value that the input represents
2411 def GetIntegerValue(Input
):
2412 if type(Input
) in (int, long):
2415 if String
.endswith("U"):
2416 String
= String
[:-1]
2417 if String
.endswith("ULL"):
2418 String
= String
[:-3]
2419 if String
.endswith("LL"):
2420 String
= String
[:-2]
2422 if String
.startswith("0x") or String
.startswith("0X"):
2423 return int(String
, 16)
2431 # This acts like the main() function for the script, unless it is 'import'ed into another
2434 if __name__
== '__main__':