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