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