]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Common/Misc.py
BaseTools: Fix a bug for ExpandMacros to support mixed case ENV var
[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 def AnalyzePcdExpression(Setting):
1416 Setting = Setting.strip()
1417 # There might be escaped quote in a string: \", \\\"
1418 Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')
1419 # There might be '|' in string and in ( ... | ... ), replace it with '-'
1420 NewStr = ''
1421 InStr = False
1422 Pair = 0
1423 for ch in Data:
1424 if ch == '"':
1425 InStr = not InStr
1426 elif ch == '(' and not InStr:
1427 Pair += 1
1428 elif ch == ')' and not InStr:
1429 Pair -= 1
1430
1431 if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT:
1432 NewStr += '-'
1433 else:
1434 NewStr += ch
1435 FieldList = []
1436 StartPos = 0
1437 while True:
1438 Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)
1439 if Pos < 0:
1440 FieldList.append(Setting[StartPos:].strip())
1441 break
1442 FieldList.append(Setting[StartPos:Pos].strip())
1443 StartPos = Pos + 1
1444
1445 return FieldList
1446
1447 ## AnalyzeDscPcd
1448 #
1449 # Analyze DSC PCD value, since there is no data type info in DSC
1450 # This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database
1451 # 1. Feature flag: TokenSpace.PcdCName|PcdValue
1452 # 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]
1453 # 3. Dynamic default:
1454 # TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]
1455 # TokenSpace.PcdCName|PcdValue
1456 # 4. Dynamic VPD:
1457 # TokenSpace.PcdCName|VpdOffset[|VpdValue]
1458 # TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]
1459 # 5. Dynamic HII:
1460 # TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]
1461 # PCD value needs to be located in such kind of string, and the PCD value might be an expression in which
1462 # there might have "|" operator, also in string value.
1463 #
1464 # @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped
1465 # @param PcdType: PCD type: feature, fixed, dynamic default VPD HII
1466 # @param DataType: The datum type of PCD: VOID*, UNIT, BOOL
1467 # @retval:
1468 # ValueList: A List contain fields described above
1469 # IsValid: True if conforming EBNF, otherwise False
1470 # Index: The index where PcdValue is in ValueList
1471 #
1472 def AnalyzeDscPcd(Setting, PcdType, DataType=''):
1473 FieldList = AnalyzePcdExpression(Setting)
1474
1475 IsValid = True
1476 if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):
1477 Value = FieldList[0]
1478 Size = ''
1479 if len(FieldList) > 1:
1480 Type = FieldList[1]
1481 # Fix the PCD type when no DataType input
1482 if Type == 'VOID*':
1483 DataType = 'VOID*'
1484 else:
1485 Size = FieldList[1]
1486 if len(FieldList) > 2:
1487 Size = FieldList[2]
1488 if DataType == 'VOID*':
1489 IsValid = (len(FieldList) <= 3)
1490 else:
1491 IsValid = (len(FieldList) <= 1)
1492 return [Value, '', Size], IsValid, 0
1493 elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1494 Value = FieldList[0]
1495 Size = Type = ''
1496 if len(FieldList) > 1:
1497 Type = FieldList[1]
1498 else:
1499 Type = DataType
1500 if len(FieldList) > 2:
1501 Size = FieldList[2]
1502 else:
1503 if Type == 'VOID*':
1504 if Value.startswith("L"):
1505 Size = str((len(Value)- 3 + 1) * 2)
1506 elif Value.startswith("{"):
1507 Size = str(len(Value.split(",")))
1508 else:
1509 Size = str(len(Value) -2 + 1 )
1510 if DataType == 'VOID*':
1511 IsValid = (len(FieldList) <= 3)
1512 else:
1513 IsValid = (len(FieldList) <= 1)
1514 return [Value, Type, Size], IsValid, 0
1515 elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):
1516 VpdOffset = FieldList[0]
1517 Value = Size = ''
1518 if not DataType == 'VOID*':
1519 if len(FieldList) > 1:
1520 Value = FieldList[1]
1521 else:
1522 if len(FieldList) > 1:
1523 Size = FieldList[1]
1524 if len(FieldList) > 2:
1525 Value = FieldList[2]
1526 if DataType == 'VOID*':
1527 IsValid = (len(FieldList) <= 3)
1528 else:
1529 IsValid = (len(FieldList) <= 2)
1530 return [VpdOffset, Size, Value], IsValid, 2
1531 elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):
1532 HiiString = FieldList[0]
1533 Guid = Offset = Value = Attribute = ''
1534 if len(FieldList) > 1:
1535 Guid = FieldList[1]
1536 if len(FieldList) > 2:
1537 Offset = FieldList[2]
1538 if len(FieldList) > 3:
1539 Value = FieldList[3]
1540 if len(FieldList) > 4:
1541 Attribute = FieldList[4]
1542 IsValid = (3 <= len(FieldList) <= 5)
1543 return [HiiString, Guid, Offset, Value, Attribute], IsValid, 3
1544 return [], False, 0
1545
1546 ## AnalyzePcdData
1547 #
1548 # Analyze the pcd Value, Datum type and TokenNumber.
1549 # Used to avoid split issue while the value string contain "|" character
1550 #
1551 # @param[in] Setting: A String contain value/datum type/token number information;
1552 #
1553 # @retval ValueList: A List contain value, datum type and toke number.
1554 #
1555 def AnalyzePcdData(Setting):
1556 ValueList = ['', '', '']
1557
1558 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1559 PtrValue = ValueRe.findall(Setting)
1560
1561 ValueUpdateFlag = False
1562
1563 if len(PtrValue) >= 1:
1564 Setting = re.sub(ValueRe, '', Setting)
1565 ValueUpdateFlag = True
1566
1567 TokenList = Setting.split(TAB_VALUE_SPLIT)
1568 ValueList[0:len(TokenList)] = TokenList
1569
1570 if ValueUpdateFlag:
1571 ValueList[0] = PtrValue[0]
1572
1573 return ValueList
1574
1575 ## AnalyzeHiiPcdData
1576 #
1577 # Analyze the pcd Value, variable name, variable Guid and variable offset.
1578 # Used to avoid split issue while the value string contain "|" character
1579 #
1580 # @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;
1581 #
1582 # @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue.
1583 #
1584 def AnalyzeHiiPcdData(Setting):
1585 ValueList = ['', '', '', '']
1586
1587 TokenList = GetSplitValueList(Setting)
1588 ValueList[0:len(TokenList)] = TokenList
1589
1590 return ValueList
1591
1592 ## AnalyzeVpdPcdData
1593 #
1594 # Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.
1595 # Used to avoid split issue while the value string contain "|" character
1596 #
1597 # @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;
1598 #
1599 # @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue.
1600 #
1601 def AnalyzeVpdPcdData(Setting):
1602 ValueList = ['', '', '']
1603
1604 ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')
1605 PtrValue = ValueRe.findall(Setting)
1606
1607 ValueUpdateFlag = False
1608
1609 if len(PtrValue) >= 1:
1610 Setting = re.sub(ValueRe, '', Setting)
1611 ValueUpdateFlag = True
1612
1613 TokenList = Setting.split(TAB_VALUE_SPLIT)
1614 ValueList[0:len(TokenList)] = TokenList
1615
1616 if ValueUpdateFlag:
1617 ValueList[2] = PtrValue[0]
1618
1619 return ValueList
1620
1621 ## check format of PCD value against its the datum type
1622 #
1623 # For PCD value setting
1624 #
1625 def CheckPcdDatum(Type, Value):
1626 if Type == "VOID*":
1627 ValueRe = re.compile(r'\s*L?\".*\"\s*$')
1628 if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))
1629 or (Value.startswith('{') and Value.endswith('}'))
1630 ):
1631 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\
1632 ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type)
1633 elif ValueRe.match(Value):
1634 # Check the chars in UnicodeString or CString is printable
1635 if Value.startswith("L"):
1636 Value = Value[2:-1]
1637 else:
1638 Value = Value[1:-1]
1639 Printset = set(string.printable)
1640 Printset.remove(TAB_PRINTCHAR_VT)
1641 Printset.add(TAB_PRINTCHAR_BS)
1642 Printset.add(TAB_PRINTCHAR_NUL)
1643 if not set(Value).issubset(Printset):
1644 PrintList = list(Printset)
1645 PrintList.sort()
1646 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList)
1647 elif Type == 'BOOLEAN':
1648 if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:
1649 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\
1650 ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type)
1651 elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]:
1652 try:
1653 Value = long(Value, 0)
1654 except:
1655 return False, "Invalid value [%s] of type [%s];"\
1656 " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)
1657 else:
1658 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type)
1659
1660 return True, ""
1661
1662 ## Split command line option string to list
1663 #
1664 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem
1665 # in non-windows platform to launch command
1666 #
1667 def SplitOption(OptionString):
1668 OptionList = []
1669 LastChar = " "
1670 OptionStart = 0
1671 QuotationMark = ""
1672 for Index in range(0, len(OptionString)):
1673 CurrentChar = OptionString[Index]
1674 if CurrentChar in ['"', "'"]:
1675 if QuotationMark == CurrentChar:
1676 QuotationMark = ""
1677 elif QuotationMark == "":
1678 QuotationMark = CurrentChar
1679 continue
1680 elif QuotationMark:
1681 continue
1682
1683 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:
1684 if Index > OptionStart:
1685 OptionList.append(OptionString[OptionStart:Index - 1])
1686 OptionStart = Index
1687 LastChar = CurrentChar
1688 OptionList.append(OptionString[OptionStart:])
1689 return OptionList
1690
1691 def CommonPath(PathList):
1692 P1 = min(PathList).split(os.path.sep)
1693 P2 = max(PathList).split(os.path.sep)
1694 for Index in xrange(min(len(P1), len(P2))):
1695 if P1[Index] != P2[Index]:
1696 return os.path.sep.join(P1[:Index])
1697 return os.path.sep.join(P1)
1698
1699 #
1700 # Convert string to C format array
1701 #
1702 def ConvertStringToByteArray(Value):
1703 Value = Value.strip()
1704 if not Value:
1705 return None
1706 if Value[0] == '{':
1707 if not Value.endswith('}'):
1708 return None
1709 Value = Value.replace(' ', '').replace('{', '').replace('}', '')
1710 ValFields = Value.split(',')
1711 try:
1712 for Index in range(len(ValFields)):
1713 ValFields[Index] = str(int(ValFields[Index], 0))
1714 except ValueError:
1715 return None
1716 Value = '{' + ','.join(ValFields) + '}'
1717 return Value
1718
1719 Unicode = False
1720 if Value.startswith('L"'):
1721 if not Value.endswith('"'):
1722 return None
1723 Value = Value[1:]
1724 Unicode = True
1725 elif not Value.startswith('"') or not Value.endswith('"'):
1726 return None
1727
1728 Value = eval(Value) # translate escape character
1729 NewValue = '{'
1730 for Index in range(0,len(Value)):
1731 if Unicode:
1732 NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','
1733 else:
1734 NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','
1735 Value = NewValue + '0}'
1736 return Value
1737
1738 class PathClass(object):
1739 def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,
1740 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):
1741 self.Arch = Arch
1742 self.File = str(File)
1743 if os.path.isabs(self.File):
1744 self.Root = ''
1745 self.AlterRoot = ''
1746 else:
1747 self.Root = str(Root)
1748 self.AlterRoot = str(AlterRoot)
1749
1750 # Remove any '.' and '..' in path
1751 if self.Root:
1752 self.Root = mws.getWs(self.Root, self.File)
1753 self.Path = os.path.normpath(os.path.join(self.Root, self.File))
1754 self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))
1755 # eliminate the side-effect of 'C:'
1756 if self.Root[-1] == ':':
1757 self.Root += os.path.sep
1758 # file path should not start with path separator
1759 if self.Root[-1] == os.path.sep:
1760 self.File = self.Path[len(self.Root):]
1761 else:
1762 self.File = self.Path[len(self.Root) + 1:]
1763 else:
1764 self.Path = os.path.normpath(self.File)
1765
1766 self.SubDir, self.Name = os.path.split(self.File)
1767 self.BaseName, self.Ext = os.path.splitext(self.Name)
1768
1769 if self.Root:
1770 if self.SubDir:
1771 self.Dir = os.path.join(self.Root, self.SubDir)
1772 else:
1773 self.Dir = self.Root
1774 else:
1775 self.Dir = self.SubDir
1776
1777 if IsBinary:
1778 self.Type = Type
1779 else:
1780 self.Type = self.Ext.lower()
1781
1782 self.IsBinary = IsBinary
1783 self.Target = Target
1784 self.TagName = TagName
1785 self.ToolCode = ToolCode
1786 self.ToolChainFamily = ToolChainFamily
1787
1788 self._Key = None
1789
1790 ## Convert the object of this class to a string
1791 #
1792 # Convert member Path of the class to a string
1793 #
1794 # @retval string Formatted String
1795 #
1796 def __str__(self):
1797 return self.Path
1798
1799 ## Override __eq__ function
1800 #
1801 # Check whether PathClass are the same
1802 #
1803 # @retval False The two PathClass are different
1804 # @retval True The two PathClass are the same
1805 #
1806 def __eq__(self, Other):
1807 if type(Other) == type(self):
1808 return self.Path == Other.Path
1809 else:
1810 return self.Path == str(Other)
1811
1812 ## Override __cmp__ function
1813 #
1814 # Customize the comparsion operation of two PathClass
1815 #
1816 # @retval 0 The two PathClass are different
1817 # @retval -1 The first PathClass is less than the second PathClass
1818 # @retval 1 The first PathClass is Bigger than the second PathClass
1819 def __cmp__(self, Other):
1820 if type(Other) == type(self):
1821 OtherKey = Other.Path
1822 else:
1823 OtherKey = str(Other)
1824
1825 SelfKey = self.Path
1826 if SelfKey == OtherKey:
1827 return 0
1828 elif SelfKey > OtherKey:
1829 return 1
1830 else:
1831 return -1
1832
1833 ## Override __hash__ function
1834 #
1835 # Use Path as key in hash table
1836 #
1837 # @retval string Key for hash table
1838 #
1839 def __hash__(self):
1840 return hash(self.Path)
1841
1842 def _GetFileKey(self):
1843 if self._Key == None:
1844 self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target
1845 return self._Key
1846
1847 def _GetTimeStamp(self):
1848 return os.stat(self.Path)[8]
1849
1850 def Validate(self, Type='', CaseSensitive=True):
1851 if GlobalData.gCaseInsensitive:
1852 CaseSensitive = False
1853 if Type and Type.lower() != self.Type:
1854 return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)
1855
1856 RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)
1857 if not RealRoot and not RealFile:
1858 RealFile = self.File
1859 if self.AlterRoot:
1860 RealFile = os.path.join(self.AlterRoot, self.File)
1861 elif self.Root:
1862 RealFile = os.path.join(self.Root, self.File)
1863 if len (mws.getPkgPath()) == 0:
1864 return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)
1865 else:
1866 return FILE_NOT_FOUND, "%s is not found in packages path:\n\t%s" % (self.File, '\n\t'.join(mws.getPkgPath()))
1867
1868 ErrorCode = 0
1869 ErrorInfo = ''
1870 if RealRoot != self.Root or RealFile != self.File:
1871 if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):
1872 ErrorCode = FILE_CASE_MISMATCH
1873 ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"
1874
1875 self.SubDir, self.Name = os.path.split(RealFile)
1876 self.BaseName, self.Ext = os.path.splitext(self.Name)
1877 if self.SubDir:
1878 self.Dir = os.path.join(RealRoot, self.SubDir)
1879 else:
1880 self.Dir = RealRoot
1881 self.File = RealFile
1882 self.Root = RealRoot
1883 self.Path = os.path.join(RealRoot, RealFile)
1884 return ErrorCode, ErrorInfo
1885
1886 Key = property(_GetFileKey)
1887 TimeStamp = property(_GetTimeStamp)
1888
1889 ## Parse PE image to get the required PE informaion.
1890 #
1891 class PeImageClass():
1892 ## Constructor
1893 #
1894 # @param File FilePath of PeImage
1895 #
1896 def __init__(self, PeFile):
1897 self.FileName = PeFile
1898 self.IsValid = False
1899 self.Size = 0
1900 self.EntryPoint = 0
1901 self.SectionAlignment = 0
1902 self.SectionHeaderList = []
1903 self.ErrorInfo = ''
1904 try:
1905 PeObject = open(PeFile, 'rb')
1906 except:
1907 self.ErrorInfo = self.FileName + ' can not be found\n'
1908 return
1909 # Read DOS header
1910 ByteArray = array.array('B')
1911 ByteArray.fromfile(PeObject, 0x3E)
1912 ByteList = ByteArray.tolist()
1913 # DOS signature should be 'MZ'
1914 if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':
1915 self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'
1916 return
1917
1918 # Read 4 byte PE Signature
1919 PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])
1920 PeObject.seek(PeOffset)
1921 ByteArray = array.array('B')
1922 ByteArray.fromfile(PeObject, 4)
1923 # PE signature should be 'PE\0\0'
1924 if ByteArray.tostring() != 'PE\0\0':
1925 self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'
1926 return
1927
1928 # Read PE file header
1929 ByteArray = array.array('B')
1930 ByteArray.fromfile(PeObject, 0x14)
1931 ByteList = ByteArray.tolist()
1932 SecNumber = self._ByteListToInt(ByteList[0x2:0x4])
1933 if SecNumber == 0:
1934 self.ErrorInfo = self.FileName + ' has no section header'
1935 return
1936
1937 # Read PE optional header
1938 OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])
1939 ByteArray = array.array('B')
1940 ByteArray.fromfile(PeObject, OptionalHeaderSize)
1941 ByteList = ByteArray.tolist()
1942 self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14])
1943 self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])
1944 self.Size = self._ByteListToInt(ByteList[0x38:0x3C])
1945
1946 # Read each Section Header
1947 for Index in range(SecNumber):
1948 ByteArray = array.array('B')
1949 ByteArray.fromfile(PeObject, 0x28)
1950 ByteList = ByteArray.tolist()
1951 SecName = self._ByteListToStr(ByteList[0:8])
1952 SecVirtualSize = self._ByteListToInt(ByteList[8:12])
1953 SecRawAddress = self._ByteListToInt(ByteList[20:24])
1954 SecVirtualAddress = self._ByteListToInt(ByteList[12:16])
1955 self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))
1956 self.IsValid = True
1957 PeObject.close()
1958
1959 def _ByteListToStr(self, ByteList):
1960 String = ''
1961 for index in range(len(ByteList)):
1962 if ByteList[index] == 0:
1963 break
1964 String += chr(ByteList[index])
1965 return String
1966
1967 def _ByteListToInt(self, ByteList):
1968 Value = 0
1969 for index in range(len(ByteList) - 1, -1, -1):
1970 Value = (Value << 8) | int(ByteList[index])
1971 return Value
1972
1973
1974 class SkuClass():
1975
1976 DEFAULT = 0
1977 SINGLE = 1
1978 MULTIPLE =2
1979
1980 def __init__(self,SkuIdentifier='', SkuIds={}):
1981
1982 self.AvailableSkuIds = sdict()
1983 self.SkuIdSet = []
1984 self.SkuIdNumberSet = []
1985 if SkuIdentifier == '' or SkuIdentifier is None:
1986 self.SkuIdSet = ['DEFAULT']
1987 self.SkuIdNumberSet = ['0U']
1988 elif SkuIdentifier == 'ALL':
1989 self.SkuIdSet = SkuIds.keys()
1990 self.SkuIdNumberSet = [num.strip() + 'U' for num in SkuIds.values()]
1991 else:
1992 r = SkuIdentifier.split('|')
1993 self.SkuIdSet=[r[k].strip() for k in range(len(r))]
1994 k = None
1995 try:
1996 self.SkuIdNumberSet = [SkuIds[k].strip() + 'U' for k in self.SkuIdSet]
1997 except Exception:
1998 EdkLogger.error("build", PARAMETER_INVALID,
1999 ExtraData = "SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
2000 % (k, " ".join(SkuIds.keys())))
2001 if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':
2002 self.SkuIdSet.remove('DEFAULT')
2003 self.SkuIdNumberSet.remove('0U')
2004 for each in self.SkuIdSet:
2005 if each in SkuIds:
2006 self.AvailableSkuIds[each] = SkuIds[each]
2007 else:
2008 EdkLogger.error("build", PARAMETER_INVALID,
2009 ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"
2010 % (each, " ".join(SkuIds.keys())))
2011
2012 def __SkuUsageType(self):
2013
2014 if len(self.SkuIdSet) == 1:
2015 if self.SkuIdSet[0] == 'DEFAULT':
2016 return SkuClass.DEFAULT
2017 else:
2018 return SkuClass.SINGLE
2019 else:
2020 return SkuClass.MULTIPLE
2021
2022 def __GetAvailableSkuIds(self):
2023 return self.AvailableSkuIds
2024
2025 def __GetSystemSkuID(self):
2026 if self.__SkuUsageType() == SkuClass.SINGLE:
2027 return self.SkuIdSet[0]
2028 else:
2029 return 'DEFAULT'
2030 def __GetAvailableSkuIdNumber(self):
2031 return self.SkuIdNumberSet
2032 SystemSkuId = property(__GetSystemSkuID)
2033 AvailableSkuIdSet = property(__GetAvailableSkuIds)
2034 SkuUsageType = property(__SkuUsageType)
2035 AvailableSkuIdNumSet = property(__GetAvailableSkuIdNumber)
2036
2037 #
2038 # Pack a registry format GUID
2039 #
2040 def PackRegistryFormatGuid(Guid):
2041 Guid = Guid.split('-')
2042 return pack('=LHHBBBBBBBB',
2043 int(Guid[0], 16),
2044 int(Guid[1], 16),
2045 int(Guid[2], 16),
2046 int(Guid[3][-4:-2], 16),
2047 int(Guid[3][-2:], 16),
2048 int(Guid[4][-12:-10], 16),
2049 int(Guid[4][-10:-8], 16),
2050 int(Guid[4][-8:-6], 16),
2051 int(Guid[4][-6:-4], 16),
2052 int(Guid[4][-4:-2], 16),
2053 int(Guid[4][-2:], 16)
2054 )
2055
2056 ##
2057 #
2058 # This acts like the main() function for the script, unless it is 'import'ed into another
2059 # script.
2060 #
2061 if __name__ == '__main__':
2062 pass
2063