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