]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
BaseTools/Build: Add SDL support
[mirror_edk2.git] / BaseTools / Source / Python / Common / Misc.py
1 ## @file
2 # Common routines used by all tools
3 #
4 # Copyright (c) 2007 - 2015, 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
9 #
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.
12 #
13
14 ##
15 # Import Modules
16 #
17 import Common.LongFilePathOs as os
18 import sys
19 import string
20 import thread
21 import threading
22 import time
23 import re
24 import cPickle
25 import array
26 import shutil
27 from UserDict import IterableUserDict
28 from UserList import UserList
29
30 from Common import EdkLogger as EdkLogger
31 from Common import GlobalData as GlobalData
32 from DataType import *
33 from BuildToolError import *
34 from CommonDataClass.DataClass import *
35 from Parsing import GetSplitValueList
36 from Common.LongFilePathSupport import OpenLongFilePath as open
37
38 ## Regular expression used to find out place holders in string template
39 gPlaceholderPattern = re.compile("\$\{([^$()\s]+)\}", re.MULTILINE|re.UNICODE)
40
41 ## Dictionary used to store file time stamp for quick re-access
42 gFileTimeStampCache = {} # {file path : file time stamp}
43
44 ## Dictionary used to store dependencies of files
45 gDependencyDatabase = {} # arch : {file path : [dependent files list]}
46
47 def GetVariableOffset(mapfilepath, efifilepath, varnames):
48 """ Parse map file to get variable offset in current EFI file
49 @param mapfilepath Map file absolution path
50 @param efifilepath: EFI binary file full path
51 @param varnames iteratable container whose elements are variable names to be searched
52
53 @return List whos elements are tuple with variable name and raw offset
54 """
55 lines = []
56 try:
57 f = open(mapfilepath, 'r')
58 lines = f.readlines()
59 f.close()
60 except:
61 return None
62
63 if len(lines) == 0: return None
64 firstline = lines[0].strip()
65 if (firstline.startswith("Archive member included ") and
66 firstline.endswith(" file (symbol)")):
67 return _parseForGCC(lines, efifilepath, varnames)
68 return _parseGeneral(lines, efifilepath, varnames)
69
70 def _parseForGCC(lines, efifilepath, varnames):
71 """ Parse map file generated by GCC linker """
72 status = 0
73 sections = []
74 varoffset = []
75 for line in lines:
76 line = line.strip()
77 # status machine transection
78 if status == 0 and line == "Memory Configuration":
79 status = 1
80 continue
81 elif status == 1 and line == 'Linker script and memory map':
82 status = 2
83 continue
84 elif status ==2 and line == 'START GROUP':
85 status = 3
86 continue
87
88 # status handler
89 if status == 2:
90 m = re.match('^([\w_\.]+) +([\da-fA-Fx]+) +([\da-fA-Fx]+)$', line)
91 if m != None:
92 sections.append(m.groups(0))
93 for varname in varnames:
94 m = re.match("^([\da-fA-Fx]+) +[_]*(%s)$" % varname, line)
95 if m != None:
96 varoffset.append((varname, int(m.groups(0)[0], 16) , int(sections[-1][1], 16), sections[-1][0]))
97
98 if not varoffset:
99 return []
100 # get section information from efi file
101 efisecs = PeImageClass(efifilepath).SectionHeaderList
102 if efisecs == None or len(efisecs) == 0:
103 return []
104 #redirection
105 redirection = 0
106 for efisec in efisecs:
107 for section in sections:
108 if section[0].strip() == efisec[0].strip() and section[0].strip() == '.text':
109 redirection = int(section[1], 16) - efisec[1]
110
111 ret = []
112 for var in varoffset:
113 for efisec in efisecs:
114 if var[1] >= efisec[1] and var[1] < efisec[1]+efisec[3]:
115 ret.append((var[0], hex(efisec[2] + var[1] - efisec[1] - redirection)))
116 return ret
117
118 def _parseGeneral(lines, efifilepath, varnames):
119 status = 0 #0 - beginning of file; 1 - PE section definition; 2 - symbol table
120 secs = [] # key = section name
121 varoffset = []
122 secRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\da-fA-F]+)[Hh]? +([.\w\$]+) +(\w+)', re.UNICODE)
123 symRe = re.compile('^([\da-fA-F]+):([\da-fA-F]+) +([\.:\\\\\w\?@\$]+) +([\da-fA-F]+)', re.UNICODE)
124
125 for line in lines:
126 line = line.strip()
127 if re.match("^Start[' ']+Length[' ']+Name[' ']+Class", line):
128 status = 1
129 continue
130 if re.match("^Address[' ']+Publics by Value[' ']+Rva\+Base", line):
131 status = 2
132 continue
133 if re.match("^entry point at", line):
134 status = 3
135 continue
136 if status == 1 and len(line) != 0:
137 m = secRe.match(line)
138 assert m != None, "Fail to parse the section in map file , line is %s" % line
139 sec_no, sec_start, sec_length, sec_name, sec_class = m.groups(0)
140 secs.append([int(sec_no, 16), int(sec_start, 16), int(sec_length, 16), sec_name, sec_class])
141 if status == 2 and len(line) != 0:
142 for varname in varnames:
143 m = symRe.match(line)
144 assert m != None, "Fail to parse the symbol in map file, line is %s" % line
145 sec_no, sym_offset, sym_name, vir_addr = m.groups(0)
146 sec_no = int(sec_no, 16)
147 sym_offset = int(sym_offset, 16)
148 vir_addr = int(vir_addr, 16)
149 m2 = re.match('^[_]*(%s)' % varname, sym_name)
150 if m2 != None:
151 # fond a binary pcd entry in map file
152 for sec in secs:
153 if sec[0] == sec_no and (sym_offset >= sec[1] and sym_offset < sec[1] + sec[2]):
154 varoffset.append([varname, sec[3], sym_offset, vir_addr, sec_no])
155
156 if not varoffset: return []
157
158 # get section information from efi file
159 efisecs = PeImageClass(efifilepath).SectionHeaderList
160 if efisecs == None or len(efisecs) == 0:
161 return []
162
163 ret = []
164 for var in varoffset:
165 index = 0
166 for efisec in efisecs:
167 index = index + 1
168 if var[1].strip() == efisec[0].strip():
169 ret.append((var[0], hex(efisec[2] + var[2])))
170 elif var[4] == index:
171 ret.append((var[0], hex(efisec[2] + var[2])))
172
173 return ret
174
175 ## Routine to process duplicated INF
176 #
177 # This function is called by following two cases:
178 # Case 1 in DSC:
179 # [components.arch]
180 # Pkg/module/module.inf
181 # Pkg/module/module.inf {
182 # <Defines>
183 # FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836
184 # }
185 # Case 2 in FDF:
186 # INF Pkg/module/module.inf
187 # INF FILE_GUID = 0D1B936F-68F3-4589-AFCC-FB8B7AEBC836 Pkg/module/module.inf
188 #
189 # This function copies Pkg/module/module.inf to
190 # Conf/.cache/0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf
191 #
192 # @param Path Original PathClass object
193 # @param BaseName New file base name
194 #
195 # @retval return the new PathClass object
196 #
197 def ProcessDuplicatedInf(Path, BaseName, Workspace):
198 Filename = os.path.split(Path.File)[1]
199 if '.' in Filename:
200 Filename = BaseName + Path.BaseName + Filename[Filename.rfind('.'):]
201 else:
202 Filename = BaseName + Path.BaseName
203
204 #
205 # If -N is specified on command line, cache is disabled
206 # The directory has to be created
207 #
208 DbDir = os.path.split(GlobalData.gDatabasePath)[0]
209 if not os.path.exists(DbDir):
210 os.makedirs(DbDir)
211 #
212 # A temporary INF is copied to database path which must have write permission
213 # The temporary will be removed at the end of build
214 # In case of name conflict, the file name is
215 # FILE_GUIDBaseName (0D1B936F-68F3-4589-AFCC-FB8B7AEBC836module.inf)
216 #
217 TempFullPath = os.path.join(DbDir,
218 Filename)
219 RtPath = PathClass(Path.File, Workspace)
220 #
221 # Modify the full path to temporary path, keep other unchanged
222 #
223 # To build same module more than once, the module path with FILE_GUID overridden has
224 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the real path
225 # in DSC which is used as relative path by C files and other files in INF.
226 # A trick was used: all module paths are PathClass instances, after the initialization
227 # of PathClass, the PathClass.Path is overridden by the temporary INF path.
228 #
229 # The reason for creating a temporary INF is:
230 # Platform.Modules which is the base to create ModuleAutoGen objects is a dictionary,
231 # the key is the full path of INF, the value is an object to save overridden library instances, PCDs.
232 # A different key for the same module is needed to create different output directory,
233 # retrieve overridden PCDs, library instances.
234 #
235 # The BaseName is the FILE_GUID which is also the output directory name.
236 #
237 #
238 RtPath.Path = TempFullPath
239 RtPath.BaseName = BaseName
240 #
241 # If file exists, compare contents
242 #
243 if os.path.exists(TempFullPath):
244 with open(str(Path), 'rb') as f1: Src = f1.read()
245 with open(TempFullPath, 'rb') as f2: Dst = f2.read()
246 if Src == Dst:
247 return RtPath
248 GlobalData.gTempInfs.append(TempFullPath)
249 shutil.copy2(str(Path), TempFullPath)
250 return RtPath
251
252 ## Remove temporary created INFs whose paths were saved in gTempInfs
253 #
254 def ClearDuplicatedInf():
255 for File in GlobalData.gTempInfs:
256 if os.path.exists(File):
257 os.remove(File)
258
259 ## callback routine for processing variable option
260 #
261 # This function can be used to process variable number of option values. The
262 # typical usage of it is specify architecure list on command line.
263 # (e.g. <tool> -a IA32 X64 IPF)
264 #
265 # @param Option Standard callback function parameter
266 # @param OptionString Standard callback function parameter
267 # @param Value Standard callback function parameter
268 # @param Parser Standard callback function parameter
269 #
270 # @retval
271 #
272 def ProcessVariableArgument(Option, OptionString, Value, Parser):
273 assert Value is None
274 Value = []
275 RawArgs = Parser.rargs
276 while RawArgs:
277 Arg = RawArgs[0]
278 if (Arg[:2] == "--" and len(Arg) > 2) or \
279 (Arg[:1] == "-" and len(Arg) > 1 and Arg[1] != "-"):
280 break
281 Value.append(Arg)
282 del RawArgs[0]
283 setattr(Parser.values, Option.dest, Value)
284
285 ## Convert GUID string in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx style to C structure style
286 #
287 # @param Guid The GUID string
288 #
289 # @retval string The GUID string in C structure style
290 #
291 def GuidStringToGuidStructureString(Guid):
292 GuidList = Guid.split('-')
293 Result = '{'
294 for Index in range(0,3,1):
295 Result = Result + '0x' + GuidList[Index] + ', '
296 Result = Result + '{0x' + GuidList[3][0:2] + ', 0x' + GuidList[3][2:4]
297 for Index in range(0,12,2):
298 Result = Result + ', 0x' + GuidList[4][Index:Index+2]
299 Result += '}}'
300 return Result
301
302 ## Convert GUID structure in byte array to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
303 #
304 # @param GuidValue The GUID value in byte array
305 #
306 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
307 #
308 def GuidStructureByteArrayToGuidString(GuidValue):
309 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
310 guidValueList = guidValueString.split(",")
311 if len(guidValueList) != 16:
312 return ''
313 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
314 try:
315 return "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
316 int(guidValueList[3], 16),
317 int(guidValueList[2], 16),
318 int(guidValueList[1], 16),
319 int(guidValueList[0], 16),
320 int(guidValueList[5], 16),
321 int(guidValueList[4], 16),
322 int(guidValueList[7], 16),
323 int(guidValueList[6], 16),
324 int(guidValueList[8], 16),
325 int(guidValueList[9], 16),
326 int(guidValueList[10], 16),
327 int(guidValueList[11], 16),
328 int(guidValueList[12], 16),
329 int(guidValueList[13], 16),
330 int(guidValueList[14], 16),
331 int(guidValueList[15], 16)
332 )
333 except:
334 return ''
335
336 ## Convert GUID string in C structure style to xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
337 #
338 # @param GuidValue The GUID value in C structure format
339 #
340 # @retval string The GUID value in xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
341 #
342 def GuidStructureStringToGuidString(GuidValue):
343 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "").replace(";", "")
344 guidValueList = guidValueString.split(",")
345 if len(guidValueList) != 11:
346 return ''
347 #EdkLogger.error(None, None, "Invalid GUID value string %s" % GuidValue)
348 try:
349 return "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" % (
350 int(guidValueList[0], 16),
351 int(guidValueList[1], 16),
352 int(guidValueList[2], 16),
353 int(guidValueList[3], 16),
354 int(guidValueList[4], 16),
355 int(guidValueList[5], 16),
356 int(guidValueList[6], 16),
357 int(guidValueList[7], 16),
358 int(guidValueList[8], 16),
359 int(guidValueList[9], 16),
360 int(guidValueList[10], 16)
361 )
362 except:
363 return ''
364
365 ## Convert GUID string in C structure style to xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx
366 #
367 # @param GuidValue The GUID value in C structure format
368 #
369 # @retval string The GUID value in xxxxxxxx_xxxx_xxxx_xxxx_xxxxxxxxxxxx format
370 #
371 def GuidStructureStringToGuidValueName(GuidValue):
372 guidValueString = GuidValue.lower().replace("{", "").replace("}", "").replace(" ", "")
373 guidValueList = guidValueString.split(",")
374 if len(guidValueList) != 11:
375 EdkLogger.error(None, FORMAT_INVALID, "Invalid GUID value string [%s]" % GuidValue)
376 return "%08x_%04x_%04x_%02x%02x_%02x%02x%02x%02x%02x%02x" % (
377 int(guidValueList[0], 16),
378 int(guidValueList[1], 16),
379 int(guidValueList[2], 16),
380 int(guidValueList[3], 16),
381 int(guidValueList[4], 16),
382 int(guidValueList[5], 16),
383 int(guidValueList[6], 16),
384 int(guidValueList[7], 16),
385 int(guidValueList[8], 16),
386 int(guidValueList[9], 16),
387 int(guidValueList[10], 16)
388 )
389
390 ## Create directories
391 #
392 # @param Directory The directory name
393 #
394 def CreateDirectory(Directory):
395 if Directory == None or Directory.strip() == "":
396 return True
397 try:
398 if not os.access(Directory, os.F_OK):
399 os.makedirs(Directory)
400 except:
401 return False
402 return True
403
404 ## Remove directories, including files and sub-directories in it
405 #
406 # @param Directory The directory name
407 #
408 def RemoveDirectory(Directory, Recursively=False):
409 if Directory == None or Directory.strip() == "" or not os.path.exists(Directory):
410 return
411 if Recursively:
412 CurrentDirectory = os.getcwd()
413 os.chdir(Directory)
414 for File in os.listdir("."):
415 if os.path.isdir(File):
416 RemoveDirectory(File, Recursively)
417 else:
418 os.remove(File)
419 os.chdir(CurrentDirectory)
420 os.rmdir(Directory)
421
422 ## Check if given file is changed or not
423 #
424 # This method is used to check if a file is changed or not between two build
425 # actions. It makes use a cache to store files timestamp.
426 #
427 # @param File The path of file
428 #
429 # @retval True If the given file is changed, doesn't exist, or can't be
430 # found in timestamp cache
431 # @retval False If the given file is changed
432 #
433 def IsChanged(File):
434 if not os.path.exists(File):
435 return True
436
437 FileState = os.stat(File)
438 TimeStamp = FileState[-2]
439
440 if File in gFileTimeStampCache and TimeStamp == gFileTimeStampCache[File]:
441 FileChanged = False
442 else:
443 FileChanged = True
444 gFileTimeStampCache[File] = TimeStamp
445
446 return FileChanged
447
448 ## Store content in file
449 #
450 # This method is used to save file only when its content is changed. This is
451 # quite useful for "make" system to decide what will be re-built and what won't.
452 #
453 # @param File The path of file
454 # @param Content The new content of the file
455 # @param IsBinaryFile The flag indicating if the file is binary file or not
456 #
457 # @retval True If the file content is changed and the file is renewed
458 # @retval False If the file content is the same
459 #
460 def SaveFileOnChange(File, Content, IsBinaryFile=True):
461 if not IsBinaryFile:
462 Content = Content.replace("\n", os.linesep)
463
464 if os.path.exists(File):
465 try:
466 if Content == open(File, "rb").read():
467 return False
468 except:
469 EdkLogger.error(None, FILE_OPEN_FAILURE, ExtraData=File)
470
471 DirName = os.path.dirname(File)
472 if not CreateDirectory(DirName):
473 EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)
474 else:
475 if DirName == '':
476 DirName = os.getcwd()
477 if not os.access(DirName, os.W_OK):
478 EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)
479
480 try:
481 if GlobalData.gIsWindows:
482 try:
483 from PyUtility import SaveFileToDisk
484 if not SaveFileToDisk(File, Content):
485 EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData=File)
486 except:
487 Fd = open(File, "wb")
488 Fd.write(Content)
489 Fd.close()
490 else:
491 Fd = open(File, "wb")
492 Fd.write(Content)
493 Fd.close()
494 except IOError, X:
495 EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s'%X)
496
497 return True
498
499 ## Make a Python object persistent on file system
500 #
501 # @param Data The object to be stored in file
502 # @param File The path of file to store the object
503 #
504 def DataDump(Data, File):
505 Fd = None
506 try:
507 Fd = open(File, 'wb')
508 cPickle.dump(Data, Fd, cPickle.HIGHEST_PROTOCOL)
509 except:
510 EdkLogger.error("", FILE_OPEN_FAILURE, ExtraData=File, RaiseError=False)
511 finally:
512 if Fd != None:
513 Fd.close()
514
515 ## Restore a Python object from a file
516 #
517 # @param File The path of file stored the object
518 #
519 # @retval object A python object
520 # @retval None If failure in file operation
521 #
522 def DataRestore(File):
523 Data = None
524 Fd = None
525 try:
526 Fd = open(File, 'rb')
527 Data = cPickle.load(Fd)
528 except Exception, e:
529 EdkLogger.verbose("Failed to load [%s]\n\t%s" % (File, str(e)))
530 Data = None
531 finally:
532 if Fd != None:
533 Fd.close()
534 return Data
535
536 ## Retrieve and cache the real path name in file system
537 #
538 # @param Root The root directory of path relative to
539 #
540 # @retval str The path string if the path exists
541 # @retval None If path doesn't exist
542 #
543 class DirCache:
544 _CACHE_ = set()
545 _UPPER_CACHE_ = {}
546
547 def __init__(self, Root):
548 self._Root = Root
549 for F in os.listdir(Root):
550 self._CACHE_.add(F)
551 self._UPPER_CACHE_[F.upper()] = F
552
553 # =[] operator
554 def __getitem__(self, Path):
555 Path = Path[len(os.path.commonprefix([Path, self._Root])):]
556 if not Path:
557 return self._Root
558 if Path and Path[0] == os.path.sep:
559 Path = Path[1:]
560 if Path in self._CACHE_:
561 return os.path.join(self._Root, Path)
562 UpperPath = Path.upper()
563 if UpperPath in self._UPPER_CACHE_:
564 return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])
565
566 IndexList = []
567 LastSepIndex = -1
568 SepIndex = Path.find(os.path.sep)
569 while SepIndex > -1:
570 Parent = UpperPath[:SepIndex]
571 if Parent not in self._UPPER_CACHE_:
572 break
573 LastSepIndex = SepIndex
574 SepIndex = Path.find(os.path.sep, LastSepIndex + 1)
575
576 if LastSepIndex == -1:
577 return None
578
579 Cwd = os.getcwd()
580 os.chdir(self._Root)
581 SepIndex = LastSepIndex
582 while SepIndex > -1:
583 Parent = Path[:SepIndex]
584 ParentKey = UpperPath[:SepIndex]
585 if ParentKey not in self._UPPER_CACHE_:
586 os.chdir(Cwd)
587 return None
588
589 if Parent in self._CACHE_:
590 ParentDir = Parent
591 else:
592 ParentDir = self._UPPER_CACHE_[ParentKey]
593 for F in os.listdir(ParentDir):
594 Dir = os.path.join(ParentDir, F)
595 self._CACHE_.add(Dir)
596 self._UPPER_CACHE_[Dir.upper()] = Dir
597
598 SepIndex = Path.find(os.path.sep, SepIndex + 1)
599
600 os.chdir(Cwd)
601 if Path in self._CACHE_:
602 return os.path.join(self._Root, Path)
603 elif UpperPath in self._UPPER_CACHE_:
604 return os.path.join(self._Root, self._UPPER_CACHE_[UpperPath])
605 return None
606
607 ## Get all files of a directory
608 #
609 # @param Root: Root dir
610 # @param SkipList : The files need be skipped
611 #
612 # @retval A list of all files
613 #
614 def GetFiles(Root, SkipList=None, FullPath = True):
615 OriPath = Root
616 FileList = []
617 for Root, Dirs, Files in os.walk(Root):
618 if SkipList:
619 for Item in SkipList:
620 if Item in Dirs:
621 Dirs.remove(Item)
622
623 for File in Files:
624 File = os.path.normpath(os.path.join(Root, File))
625 if not FullPath:
626 File = File[len(OriPath) + 1:]
627 FileList.append(File)
628
629 return FileList
630
631 ## Check if gvien file exists or not
632 #
633 # @param File File name or path to be checked
634 # @param Dir The directory the file is relative to
635 #
636 # @retval True if file exists
637 # @retval False if file doesn't exists
638 #
639 def ValidFile(File, Ext=None):
640 if Ext != None:
641 Dummy, FileExt = os.path.splitext(File)
642 if FileExt.lower() != Ext.lower():
643 return False
644 if not os.path.exists(File):
645 return False
646 return True
647
648 def RealPath(File, Dir='', OverrideDir=''):
649 NewFile = os.path.normpath(os.path.join(Dir, File))
650 NewFile = GlobalData.gAllFiles[NewFile]
651 if not NewFile and OverrideDir:
652 NewFile = os.path.normpath(os.path.join(OverrideDir, File))
653 NewFile = GlobalData.gAllFiles[NewFile]
654 return NewFile
655
656 def RealPath2(File, Dir='', OverrideDir=''):
657 NewFile = None
658 if OverrideDir:
659 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
660 if NewFile:
661 if OverrideDir[-1] == os.path.sep:
662 return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]
663 else:
664 return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)]
665 if GlobalData.gAllFiles:
666 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))]
667 if not NewFile:
668 NewFile = os.path.normpath(os.path.join(Dir, File))
669 if not os.path.exists(NewFile):
670 return None, None
671 if NewFile:
672 if Dir:
673 if Dir[-1] == os.path.sep:
674 return NewFile[len(Dir):], NewFile[0:len(Dir)]
675 else:
676 return NewFile[len(Dir)+1:], NewFile[0:len(Dir)]
677 else:
678 return NewFile, ''
679
680 return None, None
681
682 ## Check if gvien file exists or not
683 #
684 #
685 def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):
686 NewFile = File
687 if Ext != None:
688 Dummy, FileExt = os.path.splitext(File)
689 if FileExt.lower() != Ext.lower():
690 return False, File
691
692 # Replace the Edk macros
693 if OverrideDir != '' and OverrideDir != None:
694 if OverrideDir.find('$(EFI_SOURCE)') > -1:
695 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)
696 if OverrideDir.find('$(EDK_SOURCE)') > -1:
697 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)
698
699 # Replace the default dir to current dir
700 if Dir == '.':
701 Dir = os.getcwd()
702 Dir = Dir[len(Workspace)+1:]
703
704 # First check if File has Edk definition itself
705 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:
706 NewFile = File.replace('$(EFI_SOURCE)', EfiSource)
707 NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource)
708 NewFile = AllFiles[os.path.normpath(NewFile)]
709 if NewFile != None:
710 return True, NewFile
711
712 # Second check the path with override value
713 if OverrideDir != '' and OverrideDir != None:
714 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
715 if NewFile != None:
716 return True, NewFile
717
718 # Last check the path with normal definitions
719 File = os.path.join(Dir, File)
720 NewFile = AllFiles[os.path.normpath(File)]
721 if NewFile != None:
722 return True, NewFile
723
724 return False, File
725
726 ## Check if gvien file exists or not
727 #
728 #
729 def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):
730 # Replace the Edk macros
731 if OverrideDir != '' and OverrideDir != None:
732 if OverrideDir.find('$(EFI_SOURCE)') > -1:
733 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)
734 if OverrideDir.find('$(EDK_SOURCE)') > -1:
735 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)
736
737 # Replace the default dir to current dir
738 # Dir is current module dir related to workspace
739 if Dir == '.':
740 Dir = os.getcwd()
741 Dir = Dir[len(Workspace)+1:]
742
743 NewFile = File
744 RelaPath = AllFiles[os.path.normpath(Dir)]
745 NewRelaPath = RelaPath
746
747 while(True):
748 # First check if File has Edk definition itself
749 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:
750 File = File.replace('$(EFI_SOURCE)', EfiSource)
751 File = File.replace('$(EDK_SOURCE)', EdkSource)
752 NewFile = AllFiles[os.path.normpath(File)]
753 if NewFile != None:
754 NewRelaPath = os.path.dirname(NewFile)
755 File = os.path.basename(NewFile)
756 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
757 break
758
759 # Second check the path with override value
760 if OverrideDir != '' and OverrideDir != None:
761 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]
762 if NewFile != None:
763 #NewRelaPath = os.path.dirname(NewFile)
764 NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]
765 break
766
767 # Last check the path with normal definitions
768 NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))]
769 if NewFile != None:
770 break
771
772 # No file found
773 break
774
775 return NewRelaPath, RelaPath, File
776
777
778 def GetRelPath(Path1, Path2):
779 FileName = os.path.basename(Path2)
780 L1 = os.path.normpath(Path1).split(os.path.normpath('/'))
781 L2 = os.path.normpath(Path2).split(os.path.normpath('/'))
782 for Index in range(0, len(L1)):
783 if L1[Index] != L2[Index]:
784 FileName = '../' * (len(L1) - Index)
785 for Index2 in range(Index, len(L2)):
786 FileName = os.path.join(FileName, L2[Index2])
787 break
788 return os.path.normpath(FileName)
789
790
791 ## Get GUID value from given packages
792 #
793 # @param CName The CName of the GUID
794 # @param PackageList List of packages looking-up in
795 #
796 # @retval GuidValue if the CName is found in any given package
797 # @retval None if the CName is not found in all given packages
798 #
799 def GuidValue(CName, PackageList):
800 for P in PackageList:
801 if CName in P.Guids:
802 return P.Guids[CName]
803 return None
804
805 ## Get Protocol value from given packages
806 #
807 # @param CName The CName of the GUID
808 # @param PackageList List of packages looking-up in
809 #
810 # @retval GuidValue if the CName is found in any given package
811 # @retval None if the CName is not found in all given packages
812 #
813 def ProtocolValue(CName, PackageList):
814 for P in PackageList:
815 if CName in P.Protocols:
816 return P.Protocols[CName]
817 return None
818
819 ## Get PPI value from given packages
820 #
821 # @param CName The CName of the GUID
822 # @param PackageList List of packages looking-up in
823 #
824 # @retval GuidValue if the CName is found in any given package
825 # @retval None if the CName is not found in all given packages
826 #
827 def PpiValue(CName, PackageList):
828 for P in PackageList:
829 if CName in P.Ppis:
830 return P.Ppis[CName]
831 return None
832
833 ## A string template class
834 #
835 # This class implements a template for string replacement. A string template
836 # looks like following
837 #
838 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
839 #
840 # The string between ${BEGIN} and ${END} will be repeated as many times as the
841 # length of "placeholder_name", which is a list passed through a dict. The
842 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
843 # be not used and, in this case, the "placeholder_name" must not a list and it
844 # will just be replaced once.
845 #
846 class TemplateString(object):
847 _REPEAT_START_FLAG = "BEGIN"
848 _REPEAT_END_FLAG = "END"
849
850 class Section(object):
851 _LIST_TYPES = [type([]), type(set()), type((0,))]
852
853 def __init__(self, TemplateSection, PlaceHolderList):
854 self._Template = TemplateSection
855 self._PlaceHolderList = []
856
857 # Split the section into sub-sections according to the position of placeholders
858 if PlaceHolderList:
859 self._SubSectionList = []
860 SubSectionStart = 0
861 #
862 # The placeholders passed in must be in the format of
863 #
864 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
865 #
866 for PlaceHolder,Start,End in PlaceHolderList:
867 self._SubSectionList.append(TemplateSection[SubSectionStart:Start])
868 self._SubSectionList.append(TemplateSection[Start:End])
869 self._PlaceHolderList.append(PlaceHolder)
870 SubSectionStart = End
871 if SubSectionStart < len(TemplateSection):
872 self._SubSectionList.append(TemplateSection[SubSectionStart:])
873 else:
874 self._SubSectionList = [TemplateSection]
875
876 def __str__(self):
877 return self._Template + " : " + str(self._PlaceHolderList)
878
879 def Instantiate(self, PlaceHolderValues):
880 RepeatTime = -1
881 RepeatPlaceHolders = {}
882 NonRepeatPlaceHolders = {}
883
884 for PlaceHolder in self._PlaceHolderList:
885 if PlaceHolder not in PlaceHolderValues:
886 continue
887 Value = PlaceHolderValues[PlaceHolder]
888 if type(Value) in self._LIST_TYPES:
889 if RepeatTime < 0:
890 RepeatTime = len(Value)
891 elif RepeatTime != len(Value):
892 EdkLogger.error(
893 "TemplateString",
894 PARAMETER_INVALID,
895 "${%s} has different repeat time from others!" % PlaceHolder,
896 ExtraData=str(self._Template)
897 )
898 RepeatPlaceHolders["${%s}" % PlaceHolder] = Value
899 else:
900 NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value
901
902 if NonRepeatPlaceHolders:
903 StringList = []
904 for S in self._SubSectionList:
905 if S not in NonRepeatPlaceHolders:
906 StringList.append(S)
907 else:
908 StringList.append(str(NonRepeatPlaceHolders[S]))
909 else:
910 StringList = self._SubSectionList
911
912 if RepeatPlaceHolders:
913 TempStringList = []
914 for Index in range(RepeatTime):
915 for S in StringList:
916 if S not in RepeatPlaceHolders:
917 TempStringList.append(S)
918 else:
919 TempStringList.append(str(RepeatPlaceHolders[S][Index]))
920 StringList = TempStringList
921
922 return "".join(StringList)
923
924 ## Constructor
925 def __init__(self, Template=None):
926 self.String = ''
927 self.IsBinary = False
928 self._Template = Template
929 self._TemplateSectionList = self._Parse(Template)
930
931 ## str() operator
932 #
933 # @retval string The string replaced
934 #
935 def __str__(self):
936 return self.String
937
938 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
939 #
940 # @retval list A list of TemplateString.Section objects
941 #
942 def _Parse(self, Template):
943 SectionStart = 0
944 SearchFrom = 0
945 MatchEnd = 0
946 PlaceHolderList = []
947 TemplateSectionList = []
948 while Template:
949 MatchObj = gPlaceholderPattern.search(Template, SearchFrom)
950 if not MatchObj:
951 if MatchEnd <= len(Template):
952 TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList)
953 TemplateSectionList.append(TemplateSection)
954 break
955
956 MatchString = MatchObj.group(1)
957 MatchStart = MatchObj.start()
958 MatchEnd = MatchObj.end()
959
960 if MatchString == self._REPEAT_START_FLAG:
961 if MatchStart > SectionStart:
962 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
963 TemplateSectionList.append(TemplateSection)
964 SectionStart = MatchEnd
965 PlaceHolderList = []
966 elif MatchString == self._REPEAT_END_FLAG:
967 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
968 TemplateSectionList.append(TemplateSection)
969 SectionStart = MatchEnd
970 PlaceHolderList = []
971 else:
972 PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart))
973 SearchFrom = MatchEnd
974 return TemplateSectionList
975
976 ## Replace the string template with dictionary of placeholders and append it to previous one
977 #
978 # @param AppendString The string template to append
979 # @param Dictionary The placeholder dictionaries
980 #
981 def Append(self, AppendString, Dictionary=None):
982 if Dictionary:
983 SectionList = self._Parse(AppendString)
984 self.String += "".join([S.Instantiate(Dictionary) for S in SectionList])
985 else:
986 self.String += AppendString
987
988 ## Replace the string template with dictionary of placeholders
989 #
990 # @param Dictionary The placeholder dictionaries
991 #
992 # @retval str The string replaced with placeholder values
993 #
994 def Replace(self, Dictionary=None):
995 return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList])
996
997 ## Progress indicator class
998 #
999 # This class makes use of thread to print progress on console.
1000 #
1001 class Progressor:
1002 # for avoiding deadloop
1003 _StopFlag = None
1004 _ProgressThread = None
1005 _CheckInterval = 0.25
1006
1007 ## Constructor
1008 #
1009 # @param OpenMessage The string printed before progress charaters
1010 # @param CloseMessage The string printed after progress charaters
1011 # @param ProgressChar The charater used to indicate the progress
1012 # @param Interval The interval in seconds between two progress charaters
1013 #
1014 def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0):
1015 self.PromptMessage = OpenMessage
1016 self.CodaMessage = CloseMessage
1017 self.ProgressChar = ProgressChar
1018 self.Interval = Interval
1019 if Progressor._StopFlag == None:
1020 Progressor._StopFlag = threading.Event()
1021
1022 ## Start to print progress charater
1023 #
1024 # @param OpenMessage The string printed before progress charaters
1025 #
1026 def Start(self, OpenMessage=None):
1027 if OpenMessage != None:
1028 self.PromptMessage = OpenMessage
1029 Progressor._StopFlag.clear()
1030 if Progressor._ProgressThread == None:
1031 Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)
1032 Progressor._ProgressThread.setDaemon(False)
1033 Progressor._ProgressThread.start()
1034
1035 ## Stop printing progress charater
1036 #
1037 # @param CloseMessage The string printed after progress charaters
1038 #
1039 def Stop(self, CloseMessage=None):
1040 OriginalCodaMessage = self.CodaMessage
1041 if CloseMessage != None:
1042 self.CodaMessage = CloseMessage
1043 self.Abort()
1044 self.CodaMessage = OriginalCodaMessage
1045
1046 ## Thread entry method
1047 def _ProgressThreadEntry(self):
1048 sys.stdout.write(self.PromptMessage + " ")
1049 sys.stdout.flush()
1050 TimeUp = 0.0
1051 while not Progressor._StopFlag.isSet():
1052 if TimeUp <= 0.0:
1053 sys.stdout.write(self.ProgressChar)
1054 sys.stdout.flush()
1055 TimeUp = self.Interval
1056 time.sleep(self._CheckInterval)
1057 TimeUp -= self._CheckInterval
1058 sys.stdout.write(" " + self.CodaMessage + "\n")
1059 sys.stdout.flush()
1060
1061 ## Abort the progress display
1062 @staticmethod
1063 def Abort():
1064 if Progressor._StopFlag != None:
1065 Progressor._StopFlag.set()
1066 if Progressor._ProgressThread != None:
1067 Progressor._ProgressThread.join()
1068 Progressor._ProgressThread = None
1069
1070 ## A dict which can access its keys and/or values orderly
1071 #
1072 # The class implements a new kind of dict which its keys or values can be
1073 # accessed in the order they are added into the dict. It guarantees the order
1074 # by making use of an internal list to keep a copy of keys.
1075 #
1076 class sdict(IterableUserDict):
1077 ## Constructor
1078 def __init__(self):
1079 IterableUserDict.__init__(self)
1080 self._key_list = []
1081
1082 ## [] operator
1083 def __setitem__(self, key, value):
1084 if key not in self._key_list:
1085 self._key_list.append(key)
1086 IterableUserDict.__setitem__(self, key, value)
1087
1088 ## del operator
1089 def __delitem__(self, key):
1090 self._key_list.remove(key)
1091 IterableUserDict.__delitem__(self, key)
1092
1093 ## used in "for k in dict" loop to ensure the correct order
1094 def __iter__(self):
1095 return self.iterkeys()
1096
1097 ## len() support
1098 def __len__(self):
1099 return len(self._key_list)
1100
1101 ## "in" test support
1102 def __contains__(self, key):
1103 return key in self._key_list
1104
1105 ## indexof support
1106 def index(self, key):
1107 return self._key_list.index(key)
1108
1109 ## insert support
1110 def insert(self, key, newkey, newvalue, order):
1111 index = self._key_list.index(key)
1112 if order == 'BEFORE':
1113 self._key_list.insert(index, newkey)
1114 IterableUserDict.__setitem__(self, newkey, newvalue)
1115 elif order == 'AFTER':
1116 self._key_list.insert(index + 1, newkey)
1117 IterableUserDict.__setitem__(self, newkey, newvalue)
1118
1119 ## append support
1120 def append(self, sdict):
1121 for key in sdict:
1122 if key not in self._key_list:
1123 self._key_list.append(key)
1124 IterableUserDict.__setitem__(self, key, sdict[key])
1125
1126 def has_key(self, key):
1127 return key in self._key_list
1128
1129 ## Empty the dict
1130 def clear(self):
1131 self._key_list = []
1132 IterableUserDict.clear(self)
1133
1134 ## Return a copy of keys
1135 def keys(self):
1136 keys = []
1137 for key in self._key_list:
1138 keys.append(key)
1139 return keys
1140
1141 ## Return a copy of values
1142 def values(self):
1143 values = []
1144 for key in self._key_list:
1145 values.append(self[key])
1146 return values
1147
1148 ## Return a copy of (key, value) list
1149 def items(self):
1150 items = []
1151 for key in self._key_list:
1152 items.append((key, self[key]))
1153 return items
1154
1155 ## Iteration support
1156 def iteritems(self):
1157 return iter(self.items())
1158
1159 ## Keys interation support
1160 def iterkeys(self):
1161 return iter(self.keys())
1162
1163 ## Values interation support
1164 def itervalues(self):
1165 return iter(self.values())
1166
1167 ## Return value related to a key, and remove the (key, value) from the dict
1168 def pop(self, key, *dv):
1169 value = None
1170 if key in self._key_list:
1171 value = self[key]
1172 self.__delitem__(key)
1173 elif len(dv) != 0 :
1174 value = kv[0]
1175 return value
1176
1177 ## Return (key, value) pair, and remove the (key, value) from the dict
1178 def popitem(self):
1179 key = self._key_list[-1]
1180 value = self[key]
1181 self.__delitem__(key)
1182 return key, value
1183
1184 def update(self, dict=None, **kwargs):
1185 if dict != None:
1186 for k, v in dict.items():
1187 self[k] = v
1188 if len(kwargs):
1189 for k, v in kwargs.items():
1190 self[k] = v
1191
1192 ## Dictionary with restricted keys
1193 #
1194 class rdict(dict):
1195 ## Constructor
1196 def __init__(self, KeyList):
1197 for Key in KeyList:
1198 dict.__setitem__(self, Key, "")
1199
1200 ## []= operator
1201 def __setitem__(self, key, value):
1202 if key not in self:
1203 EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key,
1204 ExtraData=", ".join(dict.keys(self)))
1205 dict.__setitem__(self, key, value)
1206
1207 ## =[] operator
1208 def __getitem__(self, key):
1209 if key not in self:
1210 return ""
1211 return dict.__getitem__(self, key)
1212
1213 ## del operator
1214 def __delitem__(self, key):
1215 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")
1216
1217 ## Empty the dict
1218 def clear(self):
1219 for Key in self:
1220 self.__setitem__(Key, "")
1221
1222 ## Return value related to a key, and remove the (key, value) from the dict
1223 def pop(self, key, *dv):
1224 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")
1225
1226 ## Return (key, value) pair, and remove the (key, value) from the dict
1227 def popitem(self):
1228 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")
1229
1230 ## Dictionary using prioritized list as key
1231 #
1232 class tdict:
1233 _ListType = type([])
1234 _TupleType = type(())
1235 _Wildcard = 'COMMON'
1236 _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1237
1238 def __init__(self, _Single_=False, _Level_=2):
1239 self._Level_ = _Level_
1240 self.data = {}
1241 self._Single_ = _Single_
1242
1243 # =[] operator
1244 def __getitem__(self, key):
1245 KeyType = type(key)
1246 RestKeys = None
1247 if KeyType == self._ListType or KeyType == self._TupleType:
1248 FirstKey = key[0]
1249 if len(key) > 1:
1250 RestKeys = key[1:]
1251 elif self._Level_ > 1:
1252 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1253 else:
1254 FirstKey = key
1255 if self._Level_ > 1:
1256 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1257
1258 if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:
1259 FirstKey = self._Wildcard
1260
1261 if self._Single_:
1262 return self._GetSingleValue(FirstKey, RestKeys)
1263 else:
1264 return self._GetAllValues(FirstKey, RestKeys)
1265
1266 def _GetSingleValue(self, FirstKey, RestKeys):
1267 Value = None
1268 #print "%s-%s" % (FirstKey, self._Level_) ,
1269 if self._Level_ > 1:
1270 if FirstKey == self._Wildcard:
1271 if FirstKey in self.data:
1272 Value = self.data[FirstKey][RestKeys]
1273 if Value == None:
1274 for Key in self.data:
1275 Value = self.data[Key][RestKeys]
1276 if Value != None: break
1277 else:
1278 if FirstKey in self.data:
1279 Value = self.data[FirstKey][RestKeys]
1280 if Value == None and self._Wildcard in self.data:
1281 #print "Value=None"
1282 Value = self.data[self._Wildcard][RestKeys]
1283 else:
1284 if FirstKey == self._Wildcard:
1285 if FirstKey in self.data:
1286 Value = self.data[FirstKey]
1287 if Value == None:
1288 for Key in self.data:
1289 Value = self.data[Key]
1290 if Value != None: break
1291 else:
1292 if FirstKey in self.data:
1293 Value = self.data[FirstKey]
1294 elif self._Wildcard in self.data:
1295 Value = self.data[self._Wildcard]
1296 return Value
1297
1298 def _GetAllValues(self, FirstKey, RestKeys):
1299 Value = []
1300 if self._Level_ > 1:
1301 if FirstKey == self._Wildcard:
1302 for Key in self.data:
1303 Value += self.data[Key][RestKeys]
1304 else:
1305 if FirstKey in self.data:
1306 Value += self.data[FirstKey][RestKeys]
1307 if self._Wildcard in self.data:
1308 Value += self.data[self._Wildcard][RestKeys]
1309 else:
1310 if FirstKey == self._Wildcard:
1311 for Key in self.data:
1312 Value.append(self.data[Key])
1313 else:
1314 if FirstKey in self.data:
1315 Value.append(self.data[FirstKey])
1316 if self._Wildcard in self.data:
1317 Value.append(self.data[self._Wildcard])
1318 return Value
1319
1320 ## []= operator
1321 def __setitem__(self, key, value):
1322 KeyType = type(key)
1323 RestKeys = None
1324 if KeyType == self._ListType or KeyType == self._TupleType:
1325 FirstKey = key[0]
1326 if len(key) > 1:
1327 RestKeys = key[1:]
1328 else:
1329 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1330 else:
1331 FirstKey = key
1332 if self._Level_ > 1:
1333 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]
1334
1335 if FirstKey in self._ValidWildcardList:
1336 FirstKey = self._Wildcard
1337
1338 if FirstKey not in self.data and self._Level_ > 0:
1339 self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)
1340
1341 if self._Level_ > 1:
1342 self.data[FirstKey][RestKeys] = value
1343 else:
1344 self.data[FirstKey] = value
1345
1346 def SetGreedyMode(self):
1347 self._Single_ = False
1348 if self._Level_ > 1:
1349 for Key in self.data:
1350 self.data[Key].SetGreedyMode()
1351
1352 def SetSingleMode(self):
1353 self._Single_ = True
1354 if self._Level_ > 1:
1355 for Key in self.data:
1356 self.data[Key].SetSingleMode()
1357
1358 def GetKeys(self, KeyIndex=0):
1359 assert KeyIndex >= 0
1360 if KeyIndex == 0:
1361 return set(self.data.keys())
1362 else:
1363 keys = set()
1364 for Key in self.data:
1365 keys |= self.data[Key].GetKeys(KeyIndex - 1)
1366 return keys
1367
1368 ## Boolean chain list
1369 #
1370 class Blist(UserList):
1371 def __init__(self, initlist=None):
1372 UserList.__init__(self, initlist)
1373 def __setitem__(self, i, item):
1374 if item not in [True, False]:
1375 if item == 0:
1376 item = False
1377 else:
1378 item = True
1379 self.data[i] = item
1380 def _GetResult(self):
1381 Value = True
1382 for item in self.data:
1383 Value &= item
1384 return Value
1385 Result = property(_GetResult)
1386
1387 def ParseConsoleLog(Filename):
1388 Opr = open(os.path.normpath(Filename), 'r')
1389 Opw = open(os.path.normpath(Filename + '.New'), 'w+')
1390 for Line in Opr.readlines():
1391 if Line.find('.efi') > -1:
1392 Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip()
1393 Opw.write('%s\n' % Line)
1394
1395 Opr.close()
1396 Opw.close()
1397
1398 ## AnalyzeDscPcd
1399 #
1400 # Analyze DSC PCD value, since there is no data type info in DSC
1401 # This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
1402 # 1. Feature flag: TokenSpace.PcdCName|PcdValue
1403 # 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
1404 # 3. Dynamic default:
1405 # TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
1406 # TokenSpace.PcdCName|PcdValue
1407 # 4. Dynamic VPD:
1408 # TokenSpace.PcdCName|VpdOffset[|VpdValue]
1409 # TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
1410 # 5. Dynamic HII:
1411 # TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
1412 # PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
1413 # there might have "|" operator, also in string value.
1414 #
1415 # @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
1416 # @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
1417 # @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
1418 # @retval:
1419 # ValueList: A List contain fields described above
1420 # IsValid: True if conforming EBNF, otherwise False
1421 # Index: The index where PcdValue is in ValueList
1422 #
1423 def AnalyzeDscPcd(Setting, PcdType, DataType=''):
1424 Setting = Setting.strip()
1425 # There might be escaped quote in a string: \", \\\"
1426 Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')
1427 # There might be '|' in string and in ( ... | ... ), replace it with '-'
1428 NewStr = ''
1429 InStr = False
1430 Pair = 0
1431 for ch in Data:
1432 if ch == '"':
1433 InStr = not InStr
1434 elif ch == '(' and not InStr:
1435 Pair += 1
1436 elif ch == ')' and not InStr:
1437 Pair -= 1
1438
1439 if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT:
1440 NewStr += '-'
1441 else:
1442 NewStr += ch
1443 FieldList = []
1444 StartPos = 0
1445 while True:
1446 Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)
1447 if Pos < 0:
1448 FieldList.append(Setting[StartPos:].strip())
1449 break
1450 FieldList.append(Setting[StartPos:Pos].strip())
1451 StartPos = Pos + 1
1452
1453 IsValid = True
1454 if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):
1455 Value = FieldList[0]
1456 Size = ''
1457 if len(FieldList) > 1:
1458 Type = FieldList[1]
1459 # Fix the PCD type when no DataType input
1460 if Type == 'VOID*':
1461 DataType = 'VOID*'
1462 else:
1463 Size = FieldList[1]
1464 if len(FieldList) > 2:
1465 Size = FieldList[2]
1466 if DataType == 'VOID*':
1467 IsValid = (len(FieldList) <= 3)
1468 else:
1469 IsValid = (len(FieldList) <= 1)
1470 return [Value, '', Size], IsValid, 0
1471 elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1472 Value = FieldList[0]
1473 Size = Type = ''
1474 if len(FieldList) > 1:
1475 Type = FieldList[1]
1476 else:
1477 Type = DataType
1478 if len(FieldList) > 2:
1479 Size = FieldList[2]
1480 else:
1481 if Type == 'VOID*':
1482 if Value.startswith("L"):
1483 Size = str((len(Value)- 3 + 1) * 2)
1484 elif Value.startswith("{"):
1485 Size = str(len(Value.split(",")))
1486 else:
1487 Size = str(len(Value) -2 + 1 )
1488 if DataType == 'VOID*':
1489 IsValid = (len(FieldList) <= 3)
1490 else:
1491 IsValid = (len(FieldList) <= 1)
1492 return [Value, Type, Size], IsValid, 0
1493 elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):
1494 VpdOffset = FieldList[0]
1495 Value = Size = ''
1496 if not DataType == 'VOID*':
1497 if len(FieldList) > 1:
1498 Value = FieldList[1]
1499 else:
1500 if len(FieldList) > 1:
1501 Size = FieldList[1]
1502 if len(FieldList) > 2:
1503 Value = FieldList[2]
1504 if DataType == 'VOID*':
1505 IsValid = (len(FieldList) <= 3)
1506 else:
1507 IsValid = (len(FieldList) <= 2)
1508 return [VpdOffset, Size, Value], IsValid, 2
1509 elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):
1510 HiiString = FieldList[0]
1511 Guid = Offset = Value = Attribute = ''
1512 if len(FieldList) > 1:
1513 Guid = FieldList[1]
1514 if len(FieldList) > 2:
1515 Offset = FieldList[2]
1516 if len(FieldList) > 3:
1517 Value = FieldList[3]
1518 if len(FieldList) > 4:
1519 Attribute = FieldList[4]
1520 IsValid = (3 <= len(FieldList) <= 5)
1521 return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3
1522 return [], False, 0
1523
1524 ## AnalyzePcdData
1525 #
1526 # Analyze the pcd Value, Datum type and TokenNumber.
1527 # Used to avoid split issue while the value string contain "|" character
1528 #
1529 # @param[in] Setting: A String contain value/datum type/token number information;
1530 #
1531 # @retval ValueList: A List contain value, datum type and toke number.
1532 #
1533 def AnalyzePcdData(Setting):
1534 ValueList = ['', '', '']
1535
1536 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1537 PtrValue = ValueRe.findall(Setting)
1538
1539 ValueUpdateFlag = False
1540
1541 if len(PtrValue) >= 1:
1542 Setting = re.sub(ValueRe, '', Setting)
1543 ValueUpdateFlag = True
1544
1545 TokenList = Setting.split(TAB_VALUE_SPLIT)
1546 ValueList[0:len(TokenList)] = TokenList
1547
1548 if ValueUpdateFlag:
1549 ValueList[0] = PtrValue[0]
1550
1551 return ValueList
1552
1553 ## AnalyzeHiiPcdData
1554 #
1555 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1556 # Used to avoid split issue while the value string contain "|" character
1557 #
1558 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1559 #
1560 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1561 #
1562 def AnalyzeHiiPcdData(Setting):
1563 ValueList = ['', '', '', '']
1564
1565 TokenList = GetSplitValueList(Setting)
1566 ValueList[0:len(TokenList)] = TokenList
1567
1568 return ValueList
1569
1570 ## AnalyzeVpdPcdData
1571 #
1572 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1573 # Used to avoid split issue while the value string contain "|" character
1574 #
1575 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1576 #
1577 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1578 #
1579 def AnalyzeVpdPcdData(Setting):
1580 ValueList = ['', '', '']
1581
1582 ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')
1583 PtrValue = ValueRe.findall(Setting)
1584
1585 ValueUpdateFlag = False
1586
1587 if len(PtrValue) >= 1:
1588 Setting = re.sub(ValueRe, '', Setting)
1589 ValueUpdateFlag = True
1590
1591 TokenList = Setting.split(TAB_VALUE_SPLIT)
1592 ValueList[0:len(TokenList)] = TokenList
1593
1594 if ValueUpdateFlag:
1595 ValueList[2] = PtrValue[0]
1596
1597 return ValueList
1598
1599 ## check format of PCD value against its the datum type
1600 #
1601 # For PCD value setting
1602 #
1603 def CheckPcdDatum(Type, Value):
1604 if Type == "VOID*":
1605 ValueRe = re.compile(r'\s*L?\".*\"\s*$')
1606 if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))
1607 or (Value.startswith('{') and Value.endswith('}'))
1608 ):
1609 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1610 ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type)
1611 elif ValueRe.match(Value):
1612 # Check the chars in UnicodeString or CString is printable
1613 if Value.startswith("L"):
1614 Value = Value[2:-1]
1615 else:
1616 Value = Value[1:-1]
1617 Printset = set(string.printable)
1618 Printset.remove(TAB_PRINTCHAR_VT)
1619 Printset.add(TAB_PRINTCHAR_BS)
1620 Printset.add(TAB_PRINTCHAR_NUL)
1621 if not set(Value).issubset(Printset):
1622 PrintList = list(Printset)
1623 PrintList.sort()
1624 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList)
1625 elif Type == 'BOOLEAN':
1626 if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1627 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1628 ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type)
1629 elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]:
1630 try:
1631 Value = long(Value, 0)
1632 except:
1633 return False, "Invalid value [%s] of type [%s];"\
1634 " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)
1635 else:
1636 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type)
1637
1638 return True, ""
1639
1640 ## Split command line option string to list
1641 #
1642 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1643 # in non-windows platform to launch command
1644 #
1645 def SplitOption(OptionString):
1646 OptionList = []
1647 LastChar = " "
1648 OptionStart = 0
1649 QuotationMark = ""
1650 for Index in range(0, len(OptionString)):
1651 CurrentChar = OptionString[Index]
1652 if CurrentChar in ['"', "'"]:
1653 if QuotationMark == CurrentChar:
1654 QuotationMark = ""
1655 elif QuotationMark == "":
1656 QuotationMark = CurrentChar
1657 continue
1658 elif QuotationMark:
1659 continue
1660
1661 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
1662 if Index > OptionStart:
1663 OptionList.append(OptionString[OptionStart:Index-1])
1664 OptionStart = Index
1665 LastChar = CurrentChar
1666 OptionList.append(OptionString[OptionStart:])
1667 return OptionList
1668
1669 def CommonPath(PathList):
1670 P1 = min(PathList).split(os.path.sep)
1671 P2 = max(PathList).split(os.path.sep)
1672 for Index in xrange(min(len(P1), len(P2))):
1673 if P1[Index] != P2[Index]:
1674 return os.path.sep.join(P1[:Index])
1675 return os.path.sep.join(P1)
1676
1677 #
1678 # Convert string to C format array
1679 #
1680 def ConvertStringToByteArray(Value):
1681 Value = Value.strip()
1682 if not Value:
1683 return None
1684 if Value[0] == '{':
1685 if not Value.endswith('}'):
1686 return None
1687 Value = Value.replace(' ', '').replace('{', '').replace('}', '')
1688 ValFields = Value.split(',')
1689 try:
1690 for Index in range(len(ValFields)):
1691 ValFields[Index] = str(int(ValFields[Index], 0))
1692 except ValueError:
1693 return None
1694 Value = '{' + ','.join(ValFields) + '}'
1695 return Value
1696
1697 Unicode = False
1698 if Value.startswith('L"'):
1699 if not Value.endswith('"'):
1700 return None
1701 Value = Value[1:]
1702 Unicode = True
1703 elif not Value.startswith('"') or not Value.endswith('"'):
1704 return None
1705
1706 Value = eval(Value) # translate escape character
1707 NewValue = '{'
1708 for Index in range(0,len(Value)):
1709 if Unicode:
1710 NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','
1711 else:
1712 NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','
1713 Value = NewValue + '0}'
1714 return Value
1715
1716 class PathClass(object):
1717 def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
1718 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):
1719 self.Arch = Arch
1720 self.File = str(File)
1721 if os.path.isabs(self.File):
1722 self.Root = ''
1723 self.AlterRoot = ''
1724 else:
1725 self.Root = str(Root)
1726 self.AlterRoot = str(AlterRoot)
1727
1728 # Remove any '.' and '..' in path
1729 if self.Root:
1730 self.Path = os.path.normpath(os.path.join(self.Root, self.File))
1731 self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
1732 # eliminate the side-effect of 'C:'
1733 if self.Root[-1] == ':':
1734 self.Root += os.path.sep
1735 # file path should not start with path separator
1736 if self.Root[-1] == os.path.sep:
1737 self.File = self.Path[len(self.Root):]
1738 else:
1739 self.File = self.Path[len(self.Root)+1:]
1740 else:
1741 self.Path = os.path.normpath(self.File)
1742
1743 self.SubDir, self.Name = os.path.split(self.File)
1744 self.BaseName, self.Ext = os.path.splitext(self.Name)
1745
1746 if self.Root:
1747 if self.SubDir:
1748 self.Dir = os.path.join(self.Root, self.SubDir)
1749 else:
1750 self.Dir = self.Root
1751 else:
1752 self.Dir = self.SubDir
1753
1754 if IsBinary:
1755 self.Type = Type
1756 else:
1757 self.Type = self.Ext.lower()
1758
1759 self.IsBinary = IsBinary
1760 self.Target = Target
1761 self.TagName = TagName
1762 self.ToolCode = ToolCode
1763 self.ToolChainFamily = ToolChainFamily
1764
1765 self._Key = None
1766
1767 ## Convert the object of this class to a string
1768 #
1769 # Convert member Path of the class to a string
1770 #
1771 # @retval string Formatted String
1772 #
1773 def __str__(self):
1774 return self.Path
1775
1776 ## Override __eq__ function
1777 #
1778 # Check whether PathClass are the same
1779 #
1780 # @retval False The two PathClass are different
1781 # @retval True The two PathClass are the same
1782 #
1783 def __eq__(self, Other):
1784 if type(Other) == type(self):
1785 return self.Path == Other.Path
1786 else:
1787 return self.Path == str(Other)
1788
1789 ## Override __cmp__ function
1790 #
1791 # Customize the comparsion operation of two PathClass
1792 #
1793 # @retval 0 The two PathClass are different
1794 # @retval -1 The first PathClass is less than the second PathClass
1795 # @retval 1 The first PathClass is Bigger than the second PathClass
1796 def __cmp__(self, Other):
1797 if type(Other) == type(self):
1798 OtherKey = Other.Path
1799 else:
1800 OtherKey = str(Other)
1801
1802 SelfKey = self.Path
1803 if SelfKey == OtherKey:
1804 return 0
1805 elif SelfKey > OtherKey:
1806 return 1
1807 else:
1808 return -1
1809
1810 ## Override __hash__ function
1811 #
1812 # Use Path as key in hash table
1813 #
1814 # @retval string Key for hash table
1815 #
1816 def __hash__(self):
1817 return hash(self.Path)
1818
1819 def _GetFileKey(self):
1820 if self._Key == None:
1821 self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1822 return self._Key
1823
1824 def _GetTimeStamp(self):
1825 return os.stat(self.Path)[8]
1826
1827 def Validate(self, Type='', CaseSensitive=True):
1828 if GlobalData.gCaseInsensitive:
1829 CaseSensitive = False
1830 if Type and Type.lower() != self.Type:
1831 return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)
1832
1833 RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
1834 if not RealRoot and not RealFile:
1835 RealFile = self.File
1836 if self.AlterRoot:
1837 RealFile = os.path.join(self.AlterRoot, self.File)
1838 elif self.Root:
1839 RealFile = os.path.join(self.Root, self.File)
1840 return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
1841
1842 ErrorCode = 0
1843 ErrorInfo = ''
1844 if RealRoot != self.Root or RealFile != self.File:
1845 if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):
1846 ErrorCode = FILE_CASE_MISMATCH
1847 ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"
1848
1849 self.SubDir, self.Name = os.path.split(RealFile)
1850 self.BaseName, self.Ext = os.path.splitext(self.Name)
1851 if self.SubDir:
1852 self.Dir = os.path.join(RealRoot, self.SubDir)
1853 else:
1854 self.Dir = RealRoot
1855 self.File = RealFile
1856 self.Root = RealRoot
1857 self.Path = os.path.join(RealRoot, RealFile)
1858 return ErrorCode, ErrorInfo
1859
1860 Key = property(_GetFileKey)
1861 TimeStamp = property(_GetTimeStamp)
1862
1863 ## Parse PE image to get the required PE informaion.
1864 #
1865 class PeImageClass():
1866 ## Constructor
1867 #
1868 # @param File FilePath of PeImage
1869 #
1870 def __init__(self, PeFile):
1871 self.FileName = PeFile
1872 self.IsValid = False
1873 self.Size = 0
1874 self.EntryPoint = 0
1875 self.SectionAlignment = 0
1876 self.SectionHeaderList = []
1877 self.ErrorInfo = ''
1878 try:
1879 PeObject = open(PeFile, 'rb')
1880 except:
1881 self.ErrorInfo = self.FileName + ' can not be found\n'
1882 return
1883 # Read DOS header
1884 ByteArray = array.array('B')
1885 ByteArray.fromfile(PeObject, 0x3E)
1886 ByteList = ByteArray.tolist()
1887 # DOS signature should be 'MZ'
1888 if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':
1889 self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'
1890 return
1891
1892 # Read 4 byte PE Signature
1893 PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])
1894 PeObject.seek(PeOffset)
1895 ByteArray = array.array('B')
1896 ByteArray.fromfile(PeObject, 4)
1897 # PE signature should be 'PE\0\0'
1898 if ByteArray.tostring() != 'PE\0\0':
1899 self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'
1900 return
1901
1902 # Read PE file header
1903 ByteArray = array.array('B')
1904 ByteArray.fromfile(PeObject, 0x14)
1905 ByteList = ByteArray.tolist()
1906 SecNumber = self._ByteListToInt(ByteList[0x2:0x4])
1907 if SecNumber == 0:
1908 self.ErrorInfo = self.FileName + ' has no section header'
1909 return
1910
1911 # Read PE optional header
1912 OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])
1913 ByteArray = array.array('B')
1914 ByteArray.fromfile(PeObject, OptionalHeaderSize)
1915 ByteList = ByteArray.tolist()
1916 self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14])
1917 self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])
1918 self.Size = self._ByteListToInt(ByteList[0x38:0x3C])
1919
1920 # Read each Section Header
1921 for Index in range(SecNumber):
1922 ByteArray = array.array('B')
1923 ByteArray.fromfile(PeObject, 0x28)
1924 ByteList = ByteArray.tolist()
1925 SecName = self._ByteListToStr(ByteList[0:8])
1926 SecVirtualSize = self._ByteListToInt(ByteList[8:12])
1927 SecRawAddress = self._ByteListToInt(ByteList[20:24])
1928 SecVirtualAddress = self._ByteListToInt(ByteList[12:16])
1929 self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))
1930 self.IsValid = True
1931 PeObject.close()
1932
1933 def _ByteListToStr(self, ByteList):
1934 String = ''
1935 for index in range(len(ByteList)):
1936 if ByteList[index] == 0:
1937 break
1938 String += chr(ByteList[index])
1939 return String
1940
1941 def _ByteListToInt(self, ByteList):
1942 Value = 0
1943 for index in range(len(ByteList) - 1, -1, -1):
1944 Value = (Value << 8) | int(ByteList[index])
1945 return Value
1946
1947
1948 class SkuClass():
1949
1950 DEFAULT = 0
1951 SINGLE = 1
1952 MULTIPLE =2
1953
1954 def __init__(self,SkuIdentifier='', SkuIds={}):
1955
1956 self.AvailableSkuIds = sdict()
1957 self.SkuIdSet = []
1958
1959 if SkuIdentifier == '' or SkuIdentifier is None:
1960 self.SkuIdSet = ['DEFAULT']
1961 elif SkuIdentifier == 'ALL':
1962 self.SkuIdSet = SkuIds.keys()
1963 else:
1964 r = SkuIdentifier.split('|')
1965 self.SkuIdSet=[r[k].strip() for k in range(len(r))]
1966 if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':
1967 self.SkuIdSet.remove('DEFAULT')
1968
1969 for each in self.SkuIdSet:
1970 if each in SkuIds:
1971 self.AvailableSkuIds[each] = SkuIds[each]
1972 else:
1973 EdkLogger.error("build", PARAMETER_INVALID,
1974 ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
1975 % (each, " ".join(SkuIds.keys())))
1976
1977 def __SkuUsageType(self):
1978
1979 if len(self.SkuIdSet) == 1:
1980 if self.SkuIdSet[0] == 'DEFAULT':
1981 return SkuClass.DEFAULT
1982 else:
1983 return SkuClass.SINGLE
1984 else:
1985 return SkuClass.MULTIPLE
1986
1987 def __GetAvailableSkuIds(self):
1988 return self.AvailableSkuIds
1989
1990 def __GetSystemSkuID(self):
1991 if self.__SkuUsageType() == SkuClass.SINGLE:
1992 return self.SkuIdSet[0]
1993 else:
1994 return 'DEFAULT'
1995
1996 SystemSkuId = property(__GetSystemSkuID)
1997 AvailableSkuIdSet = property(__GetAvailableSkuIds)
1998 SkuUsageType = property(__SkuUsageType)
1999
2000 ##
2001 #
2002 # This acts like the main() function for the script, unless it is 'import'ed into another
2003 # script.
2004 #
2005 if __name__ == '__main__':
2006 pass
2007