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