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