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