]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
BaseTools: support private package definition
[mirror_edk2.git] / BaseTools / Source / Python / Common / Misc.py
1 ## @file
2 # Common routines used by all tools
3 #
4 # Copyright (c) 2007 - 2016, 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 # @param Inffile The driver file
798 #
799 # @retval GuidValue if the CName is found in any given package
800 # @retval None if the CName is not found in all given packages
801 #
802 def GuidValue(CName, PackageList, Inffile = None):
803 for P in PackageList:
804 GuidKeys = P.Guids.keys()
805 if Inffile and P._PrivateGuids:
806 if not Inffile.startswith(P.MetaFile.Dir):
807 GuidKeys = (dict.fromkeys(x for x in P.Guids if x not in P._PrivateGuids)).keys()
808 if CName in GuidKeys:
809 return P.Guids[CName]
810 return None
811
812 ## Get Protocol value from given packages
813 #
814 # @param CName The CName of the GUID
815 # @param PackageList List of packages looking-up in
816 # @param Inffile The driver file
817 #
818 # @retval GuidValue if the CName is found in any given package
819 # @retval None if the CName is not found in all given packages
820 #
821 def ProtocolValue(CName, PackageList, Inffile = None):
822 for P in PackageList:
823 ProtocolKeys = P.Protocols.keys()
824 if Inffile and P._PrivateProtocols:
825 if not Inffile.startswith(P.MetaFile.Dir):
826 ProtocolKeys = (dict.fromkeys(x for x in P.Protocols if x not in P._PrivateProtocols)).keys()
827 if CName in ProtocolKeys:
828 return P.Protocols[CName]
829 return None
830
831 ## Get PPI value from given packages
832 #
833 # @param CName The CName of the GUID
834 # @param PackageList List of packages looking-up in
835 # @param Inffile The driver file
836 #
837 # @retval GuidValue if the CName is found in any given package
838 # @retval None if the CName is not found in all given packages
839 #
840 def PpiValue(CName, PackageList, Inffile = None):
841 for P in PackageList:
842 PpiKeys = P.Ppis.keys()
843 if Inffile and P._PrivatePpis:
844 if not Inffile.startswith(P.MetaFile.Dir):
845 PpiKeys = (dict.fromkeys(x for x in P.Ppis if x not in P._PrivatePpis)).keys()
846 if CName in PpiKeys:
847 return P.Ppis[CName]
848 return None
849
850 ## A string template class
851 #
852 # This class implements a template for string replacement. A string template
853 # looks like following
854 #
855 # ${BEGIN} other_string ${placeholder_name} other_string ${END}
856 #
857 # The string between ${BEGIN} and ${END} will be repeated as many times as the
858 # length of "placeholder_name", which is a list passed through a dict. The
859 # "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can
860 # be not used and, in this case, the "placeholder_name" must not a list and it
861 # will just be replaced once.
862 #
863 class TemplateString(object):
864 _REPEAT_START_FLAG = "BEGIN"
865 _REPEAT_END_FLAG = "END"
866
867 class Section(object):
868 _LIST_TYPES = [type([]), type(set()), type((0,))]
869
870 def __init__(self, TemplateSection, PlaceHolderList):
871 self._Template = TemplateSection
872 self._PlaceHolderList = []
873
874 # Split the section into sub-sections according to the position of placeholders
875 if PlaceHolderList:
876 self._SubSectionList = []
877 SubSectionStart = 0
878 #
879 # The placeholders passed in must be in the format of
880 #
881 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint
882 #
883 for PlaceHolder, Start, End in PlaceHolderList:
884 self._SubSectionList.append(TemplateSection[SubSectionStart:Start])
885 self._SubSectionList.append(TemplateSection[Start:End])
886 self._PlaceHolderList.append(PlaceHolder)
887 SubSectionStart = End
888 if SubSectionStart < len(TemplateSection):
889 self._SubSectionList.append(TemplateSection[SubSectionStart:])
890 else:
891 self._SubSectionList = [TemplateSection]
892
893 def __str__(self):
894 return self._Template + " : " + str(self._PlaceHolderList)
895
896 def Instantiate(self, PlaceHolderValues):
897 RepeatTime = -1
898 RepeatPlaceHolders = {}
899 NonRepeatPlaceHolders = {}
900
901 for PlaceHolder in self._PlaceHolderList:
902 if PlaceHolder not in PlaceHolderValues:
903 continue
904 Value = PlaceHolderValues[PlaceHolder]
905 if type(Value) in self._LIST_TYPES:
906 if RepeatTime < 0:
907 RepeatTime = len(Value)
908 elif RepeatTime != len(Value):
909 EdkLogger.error(
910 "TemplateString",
911 PARAMETER_INVALID,
912 "${%s} has different repeat time from others!" % PlaceHolder,
913 ExtraData=str(self._Template)
914 )
915 RepeatPlaceHolders["${%s}" % PlaceHolder] = Value
916 else:
917 NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value
918
919 if NonRepeatPlaceHolders:
920 StringList = []
921 for S in self._SubSectionList:
922 if S not in NonRepeatPlaceHolders:
923 StringList.append(S)
924 else:
925 StringList.append(str(NonRepeatPlaceHolders[S]))
926 else:
927 StringList = self._SubSectionList
928
929 if RepeatPlaceHolders:
930 TempStringList = []
931 for Index in range(RepeatTime):
932 for S in StringList:
933 if S not in RepeatPlaceHolders:
934 TempStringList.append(S)
935 else:
936 TempStringList.append(str(RepeatPlaceHolders[S][Index]))
937 StringList = TempStringList
938
939 return "".join(StringList)
940
941 ## Constructor
942 def __init__(self, Template=None):
943 self.String = ''
944 self.IsBinary = False
945 self._Template = Template
946 self._TemplateSectionList = self._Parse(Template)
947
948 ## str() operator
949 #
950 # @retval string The string replaced
951 #
952 def __str__(self):
953 return self.String
954
955 ## Split the template string into fragments per the ${BEGIN} and ${END} flags
956 #
957 # @retval list A list of TemplateString.Section objects
958 #
959 def _Parse(self, Template):
960 SectionStart = 0
961 SearchFrom = 0
962 MatchEnd = 0
963 PlaceHolderList = []
964 TemplateSectionList = []
965 while Template:
966 MatchObj = gPlaceholderPattern.search(Template, SearchFrom)
967 if not MatchObj:
968 if MatchEnd <= len(Template):
969 TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList)
970 TemplateSectionList.append(TemplateSection)
971 break
972
973 MatchString = MatchObj.group(1)
974 MatchStart = MatchObj.start()
975 MatchEnd = MatchObj.end()
976
977 if MatchString == self._REPEAT_START_FLAG:
978 if MatchStart > SectionStart:
979 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
980 TemplateSectionList.append(TemplateSection)
981 SectionStart = MatchEnd
982 PlaceHolderList = []
983 elif MatchString == self._REPEAT_END_FLAG:
984 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)
985 TemplateSectionList.append(TemplateSection)
986 SectionStart = MatchEnd
987 PlaceHolderList = []
988 else:
989 PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart))
990 SearchFrom = MatchEnd
991 return TemplateSectionList
992
993 ## Replace the string template with dictionary of placeholders and append it to previous one
994 #
995 # @param AppendString The string template to append
996 # @param Dictionary The placeholder dictionaries
997 #
998 def Append(self, AppendString, Dictionary=None):
999 if Dictionary:
1000 SectionList = self._Parse(AppendString)
1001 self.String += "".join([S.Instantiate(Dictionary) for S in SectionList])
1002 else:
1003 self.String += AppendString
1004
1005 ## Replace the string template with dictionary of placeholders
1006 #
1007 # @param Dictionary The placeholder dictionaries
1008 #
1009 # @retval str The string replaced with placeholder values
1010 #
1011 def Replace(self, Dictionary=None):
1012 return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList])
1013
1014 ## Progress indicator class
1015 #
1016 # This class makes use of thread to print progress on console.
1017 #
1018 class Progressor:
1019 # for avoiding deadloop
1020 _StopFlag = None
1021 _ProgressThread = None
1022 _CheckInterval = 0.25
1023
1024 ## Constructor
1025 #
1026 # @param OpenMessage The string printed before progress charaters
1027 # @param CloseMessage The string printed after progress charaters
1028 # @param ProgressChar The charater used to indicate the progress
1029 # @param Interval The interval in seconds between two progress charaters
1030 #
1031 def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0):
1032 self.PromptMessage = OpenMessage
1033 self.CodaMessage = CloseMessage
1034 self.ProgressChar = ProgressChar
1035 self.Interval = Interval
1036 if Progressor._StopFlag == None:
1037 Progressor._StopFlag = threading.Event()
1038
1039 ## Start to print progress charater
1040 #
1041 # @param OpenMessage The string printed before progress charaters
1042 #
1043 def Start(self, OpenMessage=None):
1044 if OpenMessage != None:
1045 self.PromptMessage = OpenMessage
1046 Progressor._StopFlag.clear()
1047 if Progressor._ProgressThread == None:
1048 Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)
1049 Progressor._ProgressThread.setDaemon(False)
1050 Progressor._ProgressThread.start()
1051
1052 ## Stop printing progress charater
1053 #
1054 # @param CloseMessage The string printed after progress charaters
1055 #
1056 def Stop(self, CloseMessage=None):
1057 OriginalCodaMessage = self.CodaMessage
1058 if CloseMessage != None:
1059 self.CodaMessage = CloseMessage
1060 self.Abort()
1061 self.CodaMessage = OriginalCodaMessage
1062
1063 ## Thread entry method
1064 def _ProgressThreadEntry(self):
1065 sys.stdout.write(self.PromptMessage + " ")
1066 sys.stdout.flush()
1067 TimeUp = 0.0
1068 while not Progressor._StopFlag.isSet():
1069 if TimeUp <= 0.0:
1070 sys.stdout.write(self.ProgressChar)
1071 sys.stdout.flush()
1072 TimeUp = self.Interval
1073 time.sleep(self._CheckInterval)
1074 TimeUp -= self._CheckInterval
1075 sys.stdout.write(" " + self.CodaMessage + "\n")
1076 sys.stdout.flush()
1077
1078 ## Abort the progress display
1079 @staticmethod
1080 def Abort():
1081 if Progressor._StopFlag != None:
1082 Progressor._StopFlag.set()
1083 if Progressor._ProgressThread != None:
1084 Progressor._ProgressThread.join()
1085 Progressor._ProgressThread = None
1086
1087 ## A dict which can access its keys and/or values orderly
1088 #
1089 # The class implements a new kind of dict which its keys or values can be
1090 # accessed in the order they are added into the dict. It guarantees the order
1091 # by making use of an internal list to keep a copy of keys.
1092 #
1093 class sdict(IterableUserDict):
1094 ## Constructor
1095 def __init__(self):
1096 IterableUserDict.__init__(self)
1097 self._key_list = []
1098
1099 ## [] operator
1100 def __setitem__(self, key, value):
1101 if key not in self._key_list:
1102 self._key_list.append(key)
1103 IterableUserDict.__setitem__(self, key, value)
1104
1105 ## del operator
1106 def __delitem__(self, key):
1107 self._key_list.remove(key)
1108 IterableUserDict.__delitem__(self, key)
1109
1110 ## used in "for k in dict" loop to ensure the correct order
1111 def __iter__(self):
1112 return self.iterkeys()
1113
1114 ## len() support
1115 def __len__(self):
1116 return len(self._key_list)
1117
1118 ## "in" test support
1119 def __contains__(self, key):
1120 return key in self._key_list
1121
1122 ## indexof support
1123 def index(self, key):
1124 return self._key_list.index(key)
1125
1126 ## insert support
1127 def insert(self, key, newkey, newvalue, order):
1128 index = self._key_list.index(key)
1129 if order == 'BEFORE':
1130 self._key_list.insert(index, newkey)
1131 IterableUserDict.__setitem__(self, newkey, newvalue)
1132 elif order == 'AFTER':
1133 self._key_list.insert(index + 1, newkey)
1134 IterableUserDict.__setitem__(self, newkey, newvalue)
1135
1136 ## append support
1137 def append(self, sdict):
1138 for key in sdict:
1139 if key not in self._key_list:
1140 self._key_list.append(key)
1141 IterableUserDict.__setitem__(self, key, sdict[key])
1142
1143 def has_key(self, key):
1144 return key in self._key_list
1145
1146 ## Empty the dict
1147 def clear(self):
1148 self._key_list = []
1149 IterableUserDict.clear(self)
1150
1151 ## Return a copy of keys
1152 def keys(self):
1153 keys = []
1154 for key in self._key_list:
1155 keys.append(key)
1156 return keys
1157
1158 ## Return a copy of values
1159 def values(self):
1160 values = []
1161 for key in self._key_list:
1162 values.append(self[key])
1163 return values
1164
1165 ## Return a copy of (key, value) list
1166 def items(self):
1167 items = []
1168 for key in self._key_list:
1169 items.append((key, self[key]))
1170 return items
1171
1172 ## Iteration support
1173 def iteritems(self):
1174 return iter(self.items())
1175
1176 ## Keys interation support
1177 def iterkeys(self):
1178 return iter(self.keys())
1179
1180 ## Values interation support
1181 def itervalues(self):
1182 return iter(self.values())
1183
1184 ## Return value related to a key, and remove the (key, value) from the dict
1185 def pop(self, key, *dv):
1186 value = None
1187 if key in self._key_list:
1188 value = self[key]
1189 self.__delitem__(key)
1190 elif len(dv) != 0 :
1191 value = kv[0]
1192 return value
1193
1194 ## Return (key, value) pair, and remove the (key, value) from the dict
1195 def popitem(self):
1196 key = self._key_list[-1]
1197 value = self[key]
1198 self.__delitem__(key)
1199 return key, value
1200
1201 def update(self, dict=None, **kwargs):
1202 if dict != None:
1203 for k, v in dict.items():
1204 self[k] = v
1205 if len(kwargs):
1206 for k, v in kwargs.items():
1207 self[k] = v
1208
1209 ## Dictionary with restricted keys
1210 #
1211 class rdict(dict):
1212 ## Constructor
1213 def __init__(self, KeyList):
1214 for Key in KeyList:
1215 dict.__setitem__(self, Key, "")
1216
1217 ## []= operator
1218 def __setitem__(self, key, value):
1219 if key not in self:
1220 EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key,
1221 ExtraData=", ".join(dict.keys(self)))
1222 dict.__setitem__(self, key, value)
1223
1224 ## =[] operator
1225 def __getitem__(self, key):
1226 if key not in self:
1227 return ""
1228 return dict.__getitem__(self, key)
1229
1230 ## del operator
1231 def __delitem__(self, key):
1232 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")
1233
1234 ## Empty the dict
1235 def clear(self):
1236 for Key in self:
1237 self.__setitem__(Key, "")
1238
1239 ## Return value related to a key, and remove the (key, value) from the dict
1240 def pop(self, key, *dv):
1241 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")
1242
1243 ## Return (key, value) pair, and remove the (key, value) from the dict
1244 def popitem(self):
1245 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")
1246
1247 ## Dictionary using prioritized list as key
1248 #
1249 class tdict:
1250 _ListType = type([])
1251 _TupleType = type(())
1252 _Wildcard = 'COMMON'
1253 _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']
1254
1255 def __init__(self, _Single_=False, _Level_=2):
1256 self._Level_ = _Level_
1257 self.data = {}
1258 self._Single_ = _Single_
1259
1260 # =[] operator
1261 def __getitem__(self, key):
1262 KeyType = type(key)
1263 RestKeys = None
1264 if KeyType == self._ListType or KeyType == self._TupleType:
1265 FirstKey = key[0]
1266 if len(key) > 1:
1267 RestKeys = key[1:]
1268 elif self._Level_ > 1:
1269 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
1270 else:
1271 FirstKey = key
1272 if self._Level_ > 1:
1273 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
1274
1275 if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:
1276 FirstKey = self._Wildcard
1277
1278 if self._Single_:
1279 return self._GetSingleValue(FirstKey, RestKeys)
1280 else:
1281 return self._GetAllValues(FirstKey, RestKeys)
1282
1283 def _GetSingleValue(self, FirstKey, RestKeys):
1284 Value = None
1285 #print "%s-%s" % (FirstKey, self._Level_) ,
1286 if self._Level_ > 1:
1287 if FirstKey == self._Wildcard:
1288 if FirstKey in self.data:
1289 Value = self.data[FirstKey][RestKeys]
1290 if Value == None:
1291 for Key in self.data:
1292 Value = self.data[Key][RestKeys]
1293 if Value != None: break
1294 else:
1295 if FirstKey in self.data:
1296 Value = self.data[FirstKey][RestKeys]
1297 if Value == None and self._Wildcard in self.data:
1298 #print "Value=None"
1299 Value = self.data[self._Wildcard][RestKeys]
1300 else:
1301 if FirstKey == self._Wildcard:
1302 if FirstKey in self.data:
1303 Value = self.data[FirstKey]
1304 if Value == None:
1305 for Key in self.data:
1306 Value = self.data[Key]
1307 if Value != None: break
1308 else:
1309 if FirstKey in self.data:
1310 Value = self.data[FirstKey]
1311 elif self._Wildcard in self.data:
1312 Value = self.data[self._Wildcard]
1313 return Value
1314
1315 def _GetAllValues(self, FirstKey, RestKeys):
1316 Value = []
1317 if self._Level_ > 1:
1318 if FirstKey == self._Wildcard:
1319 for Key in self.data:
1320 Value += self.data[Key][RestKeys]
1321 else:
1322 if FirstKey in self.data:
1323 Value += self.data[FirstKey][RestKeys]
1324 if self._Wildcard in self.data:
1325 Value += self.data[self._Wildcard][RestKeys]
1326 else:
1327 if FirstKey == self._Wildcard:
1328 for Key in self.data:
1329 Value.append(self.data[Key])
1330 else:
1331 if FirstKey in self.data:
1332 Value.append(self.data[FirstKey])
1333 if self._Wildcard in self.data:
1334 Value.append(self.data[self._Wildcard])
1335 return Value
1336
1337 ## []= operator
1338 def __setitem__(self, key, value):
1339 KeyType = type(key)
1340 RestKeys = None
1341 if KeyType == self._ListType or KeyType == self._TupleType:
1342 FirstKey = key[0]
1343 if len(key) > 1:
1344 RestKeys = key[1:]
1345 else:
1346 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
1347 else:
1348 FirstKey = key
1349 if self._Level_ > 1:
1350 RestKeys = [self._Wildcard for i in range(0, self._Level_ - 1)]
1351
1352 if FirstKey in self._ValidWildcardList:
1353 FirstKey = self._Wildcard
1354
1355 if FirstKey not in self.data and self._Level_ > 0:
1356 self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)
1357
1358 if self._Level_ > 1:
1359 self.data[FirstKey][RestKeys] = value
1360 else:
1361 self.data[FirstKey] = value
1362
1363 def SetGreedyMode(self):
1364 self._Single_ = False
1365 if self._Level_ > 1:
1366 for Key in self.data:
1367 self.data[Key].SetGreedyMode()
1368
1369 def SetSingleMode(self):
1370 self._Single_ = True
1371 if self._Level_ > 1:
1372 for Key in self.data:
1373 self.data[Key].SetSingleMode()
1374
1375 def GetKeys(self, KeyIndex=0):
1376 assert KeyIndex >= 0
1377 if KeyIndex == 0:
1378 return set(self.data.keys())
1379 else:
1380 keys = set()
1381 for Key in self.data:
1382 keys |= self.data[Key].GetKeys(KeyIndex - 1)
1383 return keys
1384
1385 ## Boolean chain list
1386 #
1387 class Blist(UserList):
1388 def __init__(self, initlist=None):
1389 UserList.__init__(self, initlist)
1390 def __setitem__(self, i, item):
1391 if item not in [True, False]:
1392 if item == 0:
1393 item = False
1394 else:
1395 item = True
1396 self.data[i] = item
1397 def _GetResult(self):
1398 Value = True
1399 for item in self.data:
1400 Value &= item
1401 return Value
1402 Result = property(_GetResult)
1403
1404 def ParseConsoleLog(Filename):
1405 Opr = open(os.path.normpath(Filename), 'r')
1406 Opw = open(os.path.normpath(Filename + '.New'), 'w+')
1407 for Line in Opr.readlines():
1408 if Line.find('.efi') > -1:
1409 Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip()
1410 Opw.write('%s\n' % Line)
1411
1412 Opr.close()
1413 Opw.close()
1414
1415 ## AnalyzeDscPcd
1416 #
1417 # Analyze DSC PCD value, since there is no data type info in DSC
1418 # This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
1419 # 1. Feature flag: TokenSpace.PcdCName|PcdValue
1420 # 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
1421 # 3. Dynamic default:
1422 # TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
1423 # TokenSpace.PcdCName|PcdValue
1424 # 4. Dynamic VPD:
1425 # TokenSpace.PcdCName|VpdOffset[|VpdValue]
1426 # TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
1427 # 5. Dynamic HII:
1428 # TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
1429 # PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
1430 # there might have "|" operator, also in string value.
1431 #
1432 # @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
1433 # @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
1434 # @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
1435 # @retval:
1436 # ValueList: A List contain fields described above
1437 # IsValid: True if conforming EBNF, otherwise False
1438 # Index: The index where PcdValue is in ValueList
1439 #
1440 def AnalyzeDscPcd(Setting, PcdType, DataType=''):
1441 Setting = Setting.strip()
1442 # There might be escaped quote in a string: \", \\\"
1443 Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')
1444 # There might be '|' in string and in ( ... | ... ), replace it with '-'
1445 NewStr = ''
1446 InStr = False
1447 Pair = 0
1448 for ch in Data:
1449 if ch == '"':
1450 InStr = not InStr
1451 elif ch == '(' and not InStr:
1452 Pair += 1
1453 elif ch == ')' and not InStr:
1454 Pair -= 1
1455
1456 if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT:
1457 NewStr += '-'
1458 else:
1459 NewStr += ch
1460 FieldList = []
1461 StartPos = 0
1462 while True:
1463 Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)
1464 if Pos < 0:
1465 FieldList.append(Setting[StartPos:].strip())
1466 break
1467 FieldList.append(Setting[StartPos:Pos].strip())
1468 StartPos = Pos + 1
1469
1470 IsValid = True
1471 if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):
1472 Value = FieldList[0]
1473 Size = ''
1474 if len(FieldList) > 1:
1475 Type = FieldList[1]
1476 # Fix the PCD type when no DataType input
1477 if Type == 'VOID*':
1478 DataType = 'VOID*'
1479 else:
1480 Size = FieldList[1]
1481 if len(FieldList) > 2:
1482 Size = FieldList[2]
1483 if DataType == 'VOID*':
1484 IsValid = (len(FieldList) <= 3)
1485 else:
1486 IsValid = (len(FieldList) <= 1)
1487 return [Value, '', Size], IsValid, 0
1488 elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1489 Value = FieldList[0]
1490 Size = Type = ''
1491 if len(FieldList) > 1:
1492 Type = FieldList[1]
1493 else:
1494 Type = DataType
1495 if len(FieldList) > 2:
1496 Size = FieldList[2]
1497 else:
1498 if Type == 'VOID*':
1499 if Value.startswith("L"):
1500 Size = str((len(Value)- 3 + 1) * 2)
1501 elif Value.startswith("{"):
1502 Size = str(len(Value.split(",")))
1503 else:
1504 Size = str(len(Value) -2 + 1 )
1505 if DataType == 'VOID*':
1506 IsValid = (len(FieldList) <= 3)
1507 else:
1508 IsValid = (len(FieldList) <= 1)
1509 return [Value, Type, Size], IsValid, 0
1510 elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):
1511 VpdOffset = FieldList[0]
1512 Value = Size = ''
1513 if not DataType == 'VOID*':
1514 if len(FieldList) > 1:
1515 Value = FieldList[1]
1516 else:
1517 if len(FieldList) > 1:
1518 Size = FieldList[1]
1519 if len(FieldList) > 2:
1520 Value = FieldList[2]
1521 if DataType == 'VOID*':
1522 IsValid = (len(FieldList) <= 3)
1523 else:
1524 IsValid = (len(FieldList) <= 2)
1525 return [VpdOffset, Size, Value], IsValid, 2
1526 elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):
1527 HiiString = FieldList[0]
1528 Guid = Offset = Value = Attribute = ''
1529 if len(FieldList) > 1:
1530 Guid = FieldList[1]
1531 if len(FieldList) > 2:
1532 Offset = FieldList[2]
1533 if len(FieldList) > 3:
1534 Value = FieldList[3]
1535 if len(FieldList) > 4:
1536 Attribute = FieldList[4]
1537 IsValid = (3 <= len(FieldList) <= 5)
1538 return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3
1539 return [], False, 0
1540
1541 ## AnalyzePcdData
1542 #
1543 # Analyze the pcd Value, Datum type and TokenNumber.
1544 # Used to avoid split issue while the value string contain "|" character
1545 #
1546 # @param[in] Setting: A String contain value/datum type/token number information;
1547 #
1548 # @retval ValueList: A List contain value, datum type and toke number.
1549 #
1550 def AnalyzePcdData(Setting):
1551 ValueList = ['', '', '']
1552
1553 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1554 PtrValue = ValueRe.findall(Setting)
1555
1556 ValueUpdateFlag = False
1557
1558 if len(PtrValue) >= 1:
1559 Setting = re.sub(ValueRe, '', Setting)
1560 ValueUpdateFlag = True
1561
1562 TokenList = Setting.split(TAB_VALUE_SPLIT)
1563 ValueList[0:len(TokenList)] = TokenList
1564
1565 if ValueUpdateFlag:
1566 ValueList[0] = PtrValue[0]
1567
1568 return ValueList
1569
1570 ## AnalyzeHiiPcdData
1571 #
1572 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1573 # Used to avoid split issue while the value string contain "|" character
1574 #
1575 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1576 #
1577 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1578 #
1579 def AnalyzeHiiPcdData(Setting):
1580 ValueList = ['', '', '', '']
1581
1582 TokenList = GetSplitValueList(Setting)
1583 ValueList[0:len(TokenList)] = TokenList
1584
1585 return ValueList
1586
1587 ## AnalyzeVpdPcdData
1588 #
1589 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1590 # Used to avoid split issue while the value string contain "|" character
1591 #
1592 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1593 #
1594 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1595 #
1596 def AnalyzeVpdPcdData(Setting):
1597 ValueList = ['', '', '']
1598
1599 ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')
1600 PtrValue = ValueRe.findall(Setting)
1601
1602 ValueUpdateFlag = False
1603
1604 if len(PtrValue) >= 1:
1605 Setting = re.sub(ValueRe, '', Setting)
1606 ValueUpdateFlag = True
1607
1608 TokenList = Setting.split(TAB_VALUE_SPLIT)
1609 ValueList[0:len(TokenList)] = TokenList
1610
1611 if ValueUpdateFlag:
1612 ValueList[2] = PtrValue[0]
1613
1614 return ValueList
1615
1616 ## check format of PCD value against its the datum type
1617 #
1618 # For PCD value setting
1619 #
1620 def CheckPcdDatum(Type, Value):
1621 if Type == "VOID*":
1622 ValueRe = re.compile(r'\s*L?\".*\"\s*$')
1623 if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))
1624 or (Value.startswith('{') and Value.endswith('}'))
1625 ):
1626 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1627 ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type)
1628 elif ValueRe.match(Value):
1629 # Check the chars in UnicodeString or CString is printable
1630 if Value.startswith("L"):
1631 Value = Value[2:-1]
1632 else:
1633 Value = Value[1:-1]
1634 Printset = set(string.printable)
1635 Printset.remove(TAB_PRINTCHAR_VT)
1636 Printset.add(TAB_PRINTCHAR_BS)
1637 Printset.add(TAB_PRINTCHAR_NUL)
1638 if not set(Value).issubset(Printset):
1639 PrintList = list(Printset)
1640 PrintList.sort()
1641 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList)
1642 elif Type == 'BOOLEAN':
1643 if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1644 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1645 ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type)
1646 elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]:
1647 try:
1648 Value = long(Value, 0)
1649 except:
1650 return False, "Invalid value [%s] of type [%s];"\
1651 " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)
1652 else:
1653 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type)
1654
1655 return True, ""
1656
1657 ## Split command line option string to list
1658 #
1659 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1660 # in non-windows platform to launch command
1661 #
1662 def SplitOption(OptionString):
1663 OptionList = []
1664 LastChar = " "
1665 OptionStart = 0
1666 QuotationMark = ""
1667 for Index in range(0, len(OptionString)):
1668 CurrentChar = OptionString[Index]
1669 if CurrentChar in ['"', "'"]:
1670 if QuotationMark == CurrentChar:
1671 QuotationMark = ""
1672 elif QuotationMark == "":
1673 QuotationMark = CurrentChar
1674 continue
1675 elif QuotationMark:
1676 continue
1677
1678 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
1679 if Index > OptionStart:
1680 OptionList.append(OptionString[OptionStart:Index - 1])
1681 OptionStart = Index
1682 LastChar = CurrentChar
1683 OptionList.append(OptionString[OptionStart:])
1684 return OptionList
1685
1686 def CommonPath(PathList):
1687 P1 = min(PathList).split(os.path.sep)
1688 P2 = max(PathList).split(os.path.sep)
1689 for Index in xrange(min(len(P1), len(P2))):
1690 if P1[Index] != P2[Index]:
1691 return os.path.sep.join(P1[:Index])
1692 return os.path.sep.join(P1)
1693
1694 #
1695 # Convert string to C format array
1696 #
1697 def ConvertStringToByteArray(Value):
1698 Value = Value.strip()
1699 if not Value:
1700 return None
1701 if Value[0] == '{':
1702 if not Value.endswith('}'):
1703 return None
1704 Value = Value.replace(' ', '').replace('{', '').replace('}', '')
1705 ValFields = Value.split(',')
1706 try:
1707 for Index in range(len(ValFields)):
1708 ValFields[Index] = str(int(ValFields[Index], 0))
1709 except ValueError:
1710 return None
1711 Value = '{' + ','.join(ValFields) + '}'
1712 return Value
1713
1714 Unicode = False
1715 if Value.startswith('L"'):
1716 if not Value.endswith('"'):
1717 return None
1718 Value = Value[1:]
1719 Unicode = True
1720 elif not Value.startswith('"') or not Value.endswith('"'):
1721 return None
1722
1723 Value = eval(Value) # translate escape character
1724 NewValue = '{'
1725 for Index in range(0,len(Value)):
1726 if Unicode:
1727 NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','
1728 else:
1729 NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','
1730 Value = NewValue + '0}'
1731 return Value
1732
1733 class PathClass(object):
1734 def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
1735 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):
1736 self.Arch = Arch
1737 self.File = str(File)
1738 if os.path.isabs(self.File):
1739 self.Root = ''
1740 self.AlterRoot = ''
1741 else:
1742 self.Root = str(Root)
1743 self.AlterRoot = str(AlterRoot)
1744
1745 # Remove any '.' and '..' in path
1746 if self.Root:
1747 self.Root = mws.getWs(self.Root, self.File)
1748 self.Path = os.path.normpath(os.path.join(self.Root, self.File))
1749 self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
1750 # eliminate the side-effect of 'C:'
1751 if self.Root[-1] == ':':
1752 self.Root += os.path.sep
1753 # file path should not start with path separator
1754 if self.Root[-1] == os.path.sep:
1755 self.File = self.Path[len(self.Root):]
1756 else:
1757 self.File = self.Path[len(self.Root) + 1:]
1758 else:
1759 self.Path = os.path.normpath(self.File)
1760
1761 self.SubDir, self.Name = os.path.split(self.File)
1762 self.BaseName, self.Ext = os.path.splitext(self.Name)
1763
1764 if self.Root:
1765 if self.SubDir:
1766 self.Dir = os.path.join(self.Root, self.SubDir)
1767 else:
1768 self.Dir = self.Root
1769 else:
1770 self.Dir = self.SubDir
1771
1772 if IsBinary:
1773 self.Type = Type
1774 else:
1775 self.Type = self.Ext.lower()
1776
1777 self.IsBinary = IsBinary
1778 self.Target = Target
1779 self.TagName = TagName
1780 self.ToolCode = ToolCode
1781 self.ToolChainFamily = ToolChainFamily
1782
1783 self._Key = None
1784
1785 ## Convert the object of this class to a string
1786 #
1787 # Convert member Path of the class to a string
1788 #
1789 # @retval string Formatted String
1790 #
1791 def __str__(self):
1792 return self.Path
1793
1794 ## Override __eq__ function
1795 #
1796 # Check whether PathClass are the same
1797 #
1798 # @retval False The two PathClass are different
1799 # @retval True The two PathClass are the same
1800 #
1801 def __eq__(self, Other):
1802 if type(Other) == type(self):
1803 return self.Path == Other.Path
1804 else:
1805 return self.Path == str(Other)
1806
1807 ## Override __cmp__ function
1808 #
1809 # Customize the comparsion operation of two PathClass
1810 #
1811 # @retval 0 The two PathClass are different
1812 # @retval -1 The first PathClass is less than the second PathClass
1813 # @retval 1 The first PathClass is Bigger than the second PathClass
1814 def __cmp__(self, Other):
1815 if type(Other) == type(self):
1816 OtherKey = Other.Path
1817 else:
1818 OtherKey = str(Other)
1819
1820 SelfKey = self.Path
1821 if SelfKey == OtherKey:
1822 return 0
1823 elif SelfKey > OtherKey:
1824 return 1
1825 else:
1826 return -1
1827
1828 ## Override __hash__ function
1829 #
1830 # Use Path as key in hash table
1831 #
1832 # @retval string Key for hash table
1833 #
1834 def __hash__(self):
1835 return hash(self.Path)
1836
1837 def _GetFileKey(self):
1838 if self._Key == None:
1839 self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1840 return self._Key
1841
1842 def _GetTimeStamp(self):
1843 return os.stat(self.Path)[8]
1844
1845 def Validate(self, Type='', CaseSensitive=True):
1846 if GlobalData.gCaseInsensitive:
1847 CaseSensitive = False
1848 if Type and Type.lower() != self.Type:
1849 return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)
1850
1851 RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
1852 if not RealRoot and not RealFile:
1853 RealFile = self.File
1854 if self.AlterRoot:
1855 RealFile = os.path.join(self.AlterRoot, self.File)
1856 elif self.Root:
1857 RealFile = os.path.join(self.Root, self.File)
1858 if len (mws.getPkgPath()) == 0:
1859 return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
1860 else:
1861 return FILE_NOT_FOUND, "%s is not found in packages path:\n\t%s" % (self.File, '\n\t'.join(mws.getPkgPath()))
1862
1863 ErrorCode = 0
1864 ErrorInfo = ''
1865 if RealRoot != self.Root or RealFile != self.File:
1866 if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):
1867 ErrorCode = FILE_CASE_MISMATCH
1868 ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"
1869
1870 self.SubDir, self.Name = os.path.split(RealFile)
1871 self.BaseName, self.Ext = os.path.splitext(self.Name)
1872 if self.SubDir:
1873 self.Dir = os.path.join(RealRoot, self.SubDir)
1874 else:
1875 self.Dir = RealRoot
1876 self.File = RealFile
1877 self.Root = RealRoot
1878 self.Path = os.path.join(RealRoot, RealFile)
1879 return ErrorCode, ErrorInfo
1880
1881 Key = property(_GetFileKey)
1882 TimeStamp = property(_GetTimeStamp)
1883
1884 ## Parse PE image to get the required PE informaion.
1885 #
1886 class PeImageClass():
1887 ## Constructor
1888 #
1889 # @param File FilePath of PeImage
1890 #
1891 def __init__(self, PeFile):
1892 self.FileName = PeFile
1893 self.IsValid = False
1894 self.Size = 0
1895 self.EntryPoint = 0
1896 self.SectionAlignment = 0
1897 self.SectionHeaderList = []
1898 self.ErrorInfo = ''
1899 try:
1900 PeObject = open(PeFile, 'rb')
1901 except:
1902 self.ErrorInfo = self.FileName + ' can not be found\n'
1903 return
1904 # Read DOS header
1905 ByteArray = array.array('B')
1906 ByteArray.fromfile(PeObject, 0x3E)
1907 ByteList = ByteArray.tolist()
1908 # DOS signature should be 'MZ'
1909 if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':
1910 self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'
1911 return
1912
1913 # Read 4 byte PE Signature
1914 PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])
1915 PeObject.seek(PeOffset)
1916 ByteArray = array.array('B')
1917 ByteArray.fromfile(PeObject, 4)
1918 # PE signature should be 'PE\0\0'
1919 if ByteArray.tostring() != 'PE\0\0':
1920 self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'
1921 return
1922
1923 # Read PE file header
1924 ByteArray = array.array('B')
1925 ByteArray.fromfile(PeObject, 0x14)
1926 ByteList = ByteArray.tolist()
1927 SecNumber = self._ByteListToInt(ByteList[0x2:0x4])
1928 if SecNumber == 0:
1929 self.ErrorInfo = self.FileName + ' has no section header'
1930 return
1931
1932 # Read PE optional header
1933 OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])
1934 ByteArray = array.array('B')
1935 ByteArray.fromfile(PeObject, OptionalHeaderSize)
1936 ByteList = ByteArray.tolist()
1937 self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14])
1938 self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])
1939 self.Size = self._ByteListToInt(ByteList[0x38:0x3C])
1940
1941 # Read each Section Header
1942 for Index in range(SecNumber):
1943 ByteArray = array.array('B')
1944 ByteArray.fromfile(PeObject, 0x28)
1945 ByteList = ByteArray.tolist()
1946 SecName = self._ByteListToStr(ByteList[0:8])
1947 SecVirtualSize = self._ByteListToInt(ByteList[8:12])
1948 SecRawAddress = self._ByteListToInt(ByteList[20:24])
1949 SecVirtualAddress = self._ByteListToInt(ByteList[12:16])
1950 self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))
1951 self.IsValid = True
1952 PeObject.close()
1953
1954 def _ByteListToStr(self, ByteList):
1955 String = ''
1956 for index in range(len(ByteList)):
1957 if ByteList[index] == 0:
1958 break
1959 String += chr(ByteList[index])
1960 return String
1961
1962 def _ByteListToInt(self, ByteList):
1963 Value = 0
1964 for index in range(len(ByteList) - 1, -1, -1):
1965 Value = (Value << 8) | int(ByteList[index])
1966 return Value
1967
1968
1969 class SkuClass():
1970
1971 DEFAULT = 0
1972 SINGLE = 1
1973 MULTIPLE =2
1974
1975 def __init__(self,SkuIdentifier='', SkuIds={}):
1976
1977 self.AvailableSkuIds = sdict()
1978 self.SkuIdSet = []
1979 self.SkuIdNumberSet = []
1980 if SkuIdentifier == '' or SkuIdentifier is None:
1981 self.SkuIdSet = ['DEFAULT']
1982 self.SkuIdNumberSet = ['0U']
1983 elif SkuIdentifier == 'ALL':
1984 self.SkuIdSet = SkuIds.keys()
1985 self.SkuIdNumberSet = [num.strip() + 'U' for num in SkuIds.values()]
1986 else:
1987 r = SkuIdentifier.split('|')
1988 self.SkuIdSet=[r[k].strip() for k in range(len(r))]
1989 k = None
1990 try:
1991 self.SkuIdNumberSet = [SkuIds[k].strip() + 'U' for k in self.SkuIdSet]
1992 except Exception:
1993 EdkLogger.error("build", PARAMETER_INVALID,
1994 ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
1995 % (k, " ".join(SkuIds.keys())))
1996 if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':
1997 self.SkuIdSet.remove('DEFAULT')
1998 self.SkuIdNumberSet.remove('0U')
1999 for each in self.SkuIdSet:
2000 if each in SkuIds:
2001 self.AvailableSkuIds[each] = SkuIds[each]
2002 else:
2003 EdkLogger.error("build", PARAMETER_INVALID,
2004 ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
2005 % (each, " ".join(SkuIds.keys())))
2006
2007 def __SkuUsageType(self):
2008
2009 if len(self.SkuIdSet) == 1:
2010 if self.SkuIdSet[0] == 'DEFAULT':
2011 return SkuClass.DEFAULT
2012 else:
2013 return SkuClass.SINGLE
2014 else:
2015 return SkuClass.MULTIPLE
2016
2017 def __GetAvailableSkuIds(self):
2018 return self.AvailableSkuIds
2019
2020 def __GetSystemSkuID(self):
2021 if self.__SkuUsageType() == SkuClass.SINGLE:
2022 return self.SkuIdSet[0]
2023 else:
2024 return 'DEFAULT'
2025 def __GetAvailableSkuIdNumber(self):
2026 return self.SkuIdNumberSet
2027 SystemSkuId = property(__GetSystemSkuID)
2028 AvailableSkuIdSet = property(__GetAvailableSkuIds)
2029 SkuUsageType = property(__SkuUsageType)
2030 AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber)
2031
2032 #
2033 # Pack a registry format GUID
2034 #
2035 def PackRegistryFormatGuid(Guid):
2036 Guid = Guid.split('-')
2037 return pack('=LHHBBBBBBBB',
2038 int(Guid[0], 16),
2039 int(Guid[1], 16),
2040 int(Guid[2], 16),
2041 int(Guid[3][-4:-2], 16),
2042 int(Guid[3][-2:], 16),
2043 int(Guid[4][-12:-10], 16),
2044 int(Guid[4][-10:-8], 16),
2045 int(Guid[4][-8:-6], 16),
2046 int(Guid[4][-6:-4], 16),
2047 int(Guid[4][-4:-2], 16),
2048 int(Guid[4][-2:], 16)
2049 )
2050
2051 ##
2052 #
2053 # This acts like the main() function for the script, unless it is 'import'ed into another
2054 # script.
2055 #
2056 if __name__ == '__main__':
2057 pass
2058