]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/Common/Misc.py
License header updated to match correct format.
[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
529 if OverrideDir:\r
530 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(OverrideDir, File))]\r
531 if NewFile:\r
532 if OverrideDir[-1] == os.path.sep:\r
533 return NewFile[len(OverrideDir):], NewFile[0:len(OverrideDir)]\r
534 else:\r
535 return NewFile[len(OverrideDir)+1:], NewFile[0:len(OverrideDir)]\r
536 if GlobalData.gAllFiles:\r
537 NewFile = GlobalData.gAllFiles[os.path.normpath(os.path.join(Dir, File))]\r
538 else:\r
539 NewFile = os.path.normpath(os.path.join(Dir, File))\r
540 if NewFile:\r
541 if Dir:\r
542 if Dir[-1] == os.path.sep:\r
543 return NewFile[len(Dir):], NewFile[0:len(Dir)]\r
544 else:\r
545 return NewFile[len(Dir)+1:], NewFile[0:len(Dir)]\r
546 else:\r
547 return NewFile, ''\r
548\r
549 return None, None\r
550\r
551## Check if gvien file exists or not\r
552#\r
553#\r
554def ValidFile2(AllFiles, File, Ext=None, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):\r
555 NewFile = File\r
556 if Ext != None:\r
557 Dummy, FileExt = os.path.splitext(File)\r
558 if FileExt.lower() != Ext.lower():\r
559 return False, File\r
560\r
561 # Replace the Edk macros\r
562 if OverrideDir != '' and OverrideDir != None:\r
563 if OverrideDir.find('$(EFI_SOURCE)') > -1:\r
564 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)\r
565 if OverrideDir.find('$(EDK_SOURCE)') > -1:\r
566 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)\r
567\r
568 # Replace the default dir to current dir\r
569 if Dir == '.':\r
570 Dir = os.getcwd()\r
571 Dir = Dir[len(Workspace)+1:]\r
572\r
573 # First check if File has Edk definition itself\r
574 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:\r
575 NewFile = File.replace('$(EFI_SOURCE)', EfiSource)\r
576 NewFile = NewFile.replace('$(EDK_SOURCE)', EdkSource)\r
577 NewFile = AllFiles[os.path.normpath(NewFile)]\r
578 if NewFile != None:\r
579 return True, NewFile\r
580\r
581 # Second check the path with override value\r
582 if OverrideDir != '' and OverrideDir != None:\r
583 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]\r
584 if NewFile != None:\r
585 return True, NewFile\r
586\r
587 # Last check the path with normal definitions\r
588 File = os.path.join(Dir, File)\r
589 NewFile = AllFiles[os.path.normpath(File)]\r
590 if NewFile != None:\r
591 return True, NewFile\r
592\r
593 return False, File\r
594\r
595## Check if gvien file exists or not\r
596#\r
597#\r
598def ValidFile3(AllFiles, File, Workspace='', EfiSource='', EdkSource='', Dir='.', OverrideDir=''):\r
599 # Replace the Edk macros\r
600 if OverrideDir != '' and OverrideDir != None:\r
601 if OverrideDir.find('$(EFI_SOURCE)') > -1:\r
602 OverrideDir = OverrideDir.replace('$(EFI_SOURCE)', EfiSource)\r
603 if OverrideDir.find('$(EDK_SOURCE)') > -1:\r
604 OverrideDir = OverrideDir.replace('$(EDK_SOURCE)', EdkSource)\r
605\r
606 # Replace the default dir to current dir\r
607 # Dir is current module dir related to workspace\r
608 if Dir == '.':\r
609 Dir = os.getcwd()\r
610 Dir = Dir[len(Workspace)+1:]\r
611\r
612 NewFile = File\r
613 RelaPath = AllFiles[os.path.normpath(Dir)]\r
614 NewRelaPath = RelaPath\r
615\r
616 while(True):\r
617 # First check if File has Edk definition itself\r
618 if File.find('$(EFI_SOURCE)') > -1 or File.find('$(EDK_SOURCE)') > -1:\r
619 File = File.replace('$(EFI_SOURCE)', EfiSource)\r
620 File = File.replace('$(EDK_SOURCE)', EdkSource)\r
621 NewFile = AllFiles[os.path.normpath(File)]\r
622 if NewFile != None:\r
623 NewRelaPath = os.path.dirname(NewFile)\r
624 File = os.path.basename(NewFile)\r
625 #NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]\r
626 break\r
627\r
628 # Second check the path with override value\r
629 if OverrideDir != '' and OverrideDir != None:\r
630 NewFile = AllFiles[os.path.normpath(os.path.join(OverrideDir, File))]\r
631 if NewFile != None:\r
632 #NewRelaPath = os.path.dirname(NewFile)\r
633 NewRelaPath = NewFile[:len(NewFile) - len(File.replace("..\\", '').replace("../", '')) - 1]\r
634 break\r
635\r
636 # Last check the path with normal definitions\r
637 NewFile = AllFiles[os.path.normpath(os.path.join(Dir, File))]\r
638 if NewFile != None:\r
639 break\r
640\r
641 # No file found\r
642 break\r
643\r
644 return NewRelaPath, RelaPath, File\r
645\r
646\r
647def GetRelPath(Path1, Path2):\r
648 FileName = os.path.basename(Path2)\r
649 L1 = os.path.normpath(Path1).split(os.path.normpath('/'))\r
650 L2 = os.path.normpath(Path2).split(os.path.normpath('/'))\r
651 for Index in range(0, len(L1)):\r
652 if L1[Index] != L2[Index]:\r
653 FileName = '../' * (len(L1) - Index)\r
654 for Index2 in range(Index, len(L2)):\r
655 FileName = os.path.join(FileName, L2[Index2])\r
656 break\r
657 return os.path.normpath(FileName)\r
658\r
659\r
660## Get GUID value from given packages\r
661#\r
662# @param CName The CName of the GUID\r
663# @param PackageList List of packages looking-up in\r
664#\r
665# @retval GuidValue if the CName is found in any given package\r
666# @retval None if the CName is not found in all given packages\r
667#\r
668def GuidValue(CName, PackageList):\r
669 for P in PackageList:\r
670 if CName in P.Guids:\r
671 return P.Guids[CName]\r
672 return None\r
673\r
674## Get Protocol value from given packages\r
675#\r
676# @param CName The CName of the GUID\r
677# @param PackageList List of packages looking-up in\r
678#\r
679# @retval GuidValue if the CName is found in any given package\r
680# @retval None if the CName is not found in all given packages\r
681#\r
682def ProtocolValue(CName, PackageList):\r
683 for P in PackageList:\r
684 if CName in P.Protocols:\r
685 return P.Protocols[CName]\r
686 return None\r
687\r
688## Get PPI value from given packages\r
689#\r
690# @param CName The CName of the GUID\r
691# @param PackageList List of packages looking-up in\r
692#\r
693# @retval GuidValue if the CName is found in any given package\r
694# @retval None if the CName is not found in all given packages\r
695#\r
696def PpiValue(CName, PackageList):\r
697 for P in PackageList:\r
698 if CName in P.Ppis:\r
699 return P.Ppis[CName]\r
700 return None\r
701\r
702## A string template class\r
703#\r
704# This class implements a template for string replacement. A string template\r
705# looks like following\r
706#\r
707# ${BEGIN} other_string ${placeholder_name} other_string ${END}\r
708#\r
709# The string between ${BEGIN} and ${END} will be repeated as many times as the\r
710# length of "placeholder_name", which is a list passed through a dict. The\r
711# "placeholder_name" is the key name of the dict. The ${BEGIN} and ${END} can\r
712# be not used and, in this case, the "placeholder_name" must not a list and it\r
713# will just be replaced once.\r
714#\r
715class TemplateString(object):\r
716 _REPEAT_START_FLAG = "BEGIN"\r
717 _REPEAT_END_FLAG = "END"\r
718\r
719 class Section(object):\r
720 _LIST_TYPES = [type([]), type(set()), type((0,))]\r
721\r
722 def __init__(self, TemplateSection, PlaceHolderList):\r
723 self._Template = TemplateSection\r
724 self._PlaceHolderList = []\r
725\r
726 # Split the section into sub-sections according to the position of placeholders\r
727 if PlaceHolderList:\r
728 self._SubSectionList = []\r
729 SubSectionStart = 0\r
730 #\r
731 # The placeholders passed in must be in the format of\r
732 #\r
733 # PlaceHolderName, PlaceHolderStartPoint, PlaceHolderEndPoint\r
734 #\r
735 for PlaceHolder,Start,End in PlaceHolderList:\r
736 self._SubSectionList.append(TemplateSection[SubSectionStart:Start])\r
737 self._SubSectionList.append(TemplateSection[Start:End])\r
738 self._PlaceHolderList.append(PlaceHolder)\r
739 SubSectionStart = End\r
740 if SubSectionStart < len(TemplateSection):\r
741 self._SubSectionList.append(TemplateSection[SubSectionStart:])\r
742 else:\r
743 self._SubSectionList = [TemplateSection]\r
744\r
745 def __str__(self):\r
746 return self._Template + " : " + str(self._PlaceHolderList)\r
747\r
748 def Instantiate(self, PlaceHolderValues):\r
749 RepeatTime = -1\r
750 RepeatPlaceHolders = {}\r
751 NonRepeatPlaceHolders = {}\r
752\r
753 for PlaceHolder in self._PlaceHolderList:\r
754 if PlaceHolder not in PlaceHolderValues:\r
755 continue\r
756 Value = PlaceHolderValues[PlaceHolder]\r
757 if type(Value) in self._LIST_TYPES:\r
758 if RepeatTime < 0:\r
759 RepeatTime = len(Value)\r
760 elif RepeatTime != len(Value):\r
761 EdkLogger.error(\r
762 "TemplateString",\r
763 PARAMETER_INVALID,\r
764 "${%s} has different repeat time from others!" % PlaceHolder,\r
765 ExtraData=str(self._Template)\r
766 )\r
767 RepeatPlaceHolders["${%s}" % PlaceHolder] = Value\r
768 else:\r
769 NonRepeatPlaceHolders["${%s}" % PlaceHolder] = Value\r
770\r
771 if NonRepeatPlaceHolders:\r
772 StringList = []\r
773 for S in self._SubSectionList:\r
774 if S not in NonRepeatPlaceHolders:\r
775 StringList.append(S)\r
776 else:\r
777 StringList.append(str(NonRepeatPlaceHolders[S]))\r
778 else:\r
779 StringList = self._SubSectionList\r
780\r
781 if RepeatPlaceHolders:\r
782 TempStringList = []\r
783 for Index in range(RepeatTime):\r
784 for S in StringList:\r
785 if S not in RepeatPlaceHolders:\r
786 TempStringList.append(S)\r
787 else:\r
788 TempStringList.append(str(RepeatPlaceHolders[S][Index]))\r
789 StringList = TempStringList\r
790\r
791 return "".join(StringList)\r
792\r
793 ## Constructor\r
794 def __init__(self, Template=None):\r
795 self.String = ''\r
796 self.IsBinary = False\r
797 self._Template = Template\r
798 self._TemplateSectionList = self._Parse(Template)\r
799\r
800 ## str() operator\r
801 #\r
802 # @retval string The string replaced\r
803 #\r
804 def __str__(self):\r
805 return self.String\r
806\r
807 ## Split the template string into fragments per the ${BEGIN} and ${END} flags\r
808 #\r
809 # @retval list A list of TemplateString.Section objects\r
810 #\r
811 def _Parse(self, Template):\r
812 SectionStart = 0\r
813 SearchFrom = 0\r
814 MatchEnd = 0\r
815 PlaceHolderList = []\r
816 TemplateSectionList = []\r
817 while Template:\r
818 MatchObj = gPlaceholderPattern.search(Template, SearchFrom)\r
819 if not MatchObj:\r
820 if MatchEnd <= len(Template):\r
821 TemplateSection = TemplateString.Section(Template[SectionStart:], PlaceHolderList)\r
822 TemplateSectionList.append(TemplateSection)\r
823 break\r
824\r
825 MatchString = MatchObj.group(1)\r
826 MatchStart = MatchObj.start()\r
827 MatchEnd = MatchObj.end()\r
828\r
829 if MatchString == self._REPEAT_START_FLAG:\r
830 if MatchStart > SectionStart:\r
831 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)\r
832 TemplateSectionList.append(TemplateSection)\r
833 SectionStart = MatchEnd\r
834 PlaceHolderList = []\r
835 elif MatchString == self._REPEAT_END_FLAG:\r
836 TemplateSection = TemplateString.Section(Template[SectionStart:MatchStart], PlaceHolderList)\r
837 TemplateSectionList.append(TemplateSection)\r
838 SectionStart = MatchEnd\r
839 PlaceHolderList = []\r
840 else:\r
841 PlaceHolderList.append((MatchString, MatchStart - SectionStart, MatchEnd - SectionStart))\r
842 SearchFrom = MatchEnd\r
843 return TemplateSectionList\r
844\r
845 ## Replace the string template with dictionary of placeholders and append it to previous one\r
846 #\r
847 # @param AppendString The string template to append\r
848 # @param Dictionary The placeholder dictionaries\r
849 #\r
850 def Append(self, AppendString, Dictionary=None):\r
851 if Dictionary:\r
852 SectionList = self._Parse(AppendString)\r
853 self.String += "".join([S.Instantiate(Dictionary) for S in SectionList])\r
854 else:\r
855 self.String += AppendString\r
856\r
857 ## Replace the string template with dictionary of placeholders\r
858 #\r
859 # @param Dictionary The placeholder dictionaries\r
860 #\r
861 # @retval str The string replaced with placeholder values\r
862 #\r
863 def Replace(self, Dictionary=None):\r
864 return "".join([S.Instantiate(Dictionary) for S in self._TemplateSectionList])\r
865\r
866## Progress indicator class\r
867#\r
868# This class makes use of thread to print progress on console.\r
869#\r
870class Progressor:\r
871 # for avoiding deadloop\r
872 _StopFlag = None\r
873 _ProgressThread = None\r
874 _CheckInterval = 0.25\r
875\r
876 ## Constructor\r
877 #\r
878 # @param OpenMessage The string printed before progress charaters\r
879 # @param CloseMessage The string printed after progress charaters\r
880 # @param ProgressChar The charater used to indicate the progress\r
881 # @param Interval The interval in seconds between two progress charaters\r
882 #\r
883 def __init__(self, OpenMessage="", CloseMessage="", ProgressChar='.', Interval=1.0):\r
884 self.PromptMessage = OpenMessage\r
885 self.CodaMessage = CloseMessage\r
886 self.ProgressChar = ProgressChar\r
887 self.Interval = Interval\r
888 if Progressor._StopFlag == None:\r
889 Progressor._StopFlag = threading.Event()\r
890\r
891 ## Start to print progress charater\r
892 #\r
893 # @param OpenMessage The string printed before progress charaters\r
894 #\r
895 def Start(self, OpenMessage=None):\r
896 if OpenMessage != None:\r
897 self.PromptMessage = OpenMessage\r
898 Progressor._StopFlag.clear()\r
899 if Progressor._ProgressThread == None:\r
900 Progressor._ProgressThread = threading.Thread(target=self._ProgressThreadEntry)\r
901 Progressor._ProgressThread.setDaemon(False)\r
902 Progressor._ProgressThread.start()\r
903\r
904 ## Stop printing progress charater\r
905 #\r
906 # @param CloseMessage The string printed after progress charaters\r
907 #\r
908 def Stop(self, CloseMessage=None):\r
909 OriginalCodaMessage = self.CodaMessage\r
910 if CloseMessage != None:\r
911 self.CodaMessage = CloseMessage\r
912 self.Abort()\r
913 self.CodaMessage = OriginalCodaMessage\r
914\r
915 ## Thread entry method\r
916 def _ProgressThreadEntry(self):\r
917 sys.stdout.write(self.PromptMessage + " ")\r
918 sys.stdout.flush()\r
919 TimeUp = 0.0\r
920 while not Progressor._StopFlag.isSet():\r
921 if TimeUp <= 0.0:\r
922 sys.stdout.write(self.ProgressChar)\r
923 sys.stdout.flush()\r
924 TimeUp = self.Interval\r
925 time.sleep(self._CheckInterval)\r
926 TimeUp -= self._CheckInterval\r
927 sys.stdout.write(" " + self.CodaMessage + "\n")\r
928 sys.stdout.flush()\r
929\r
930 ## Abort the progress display\r
931 @staticmethod\r
932 def Abort():\r
933 if Progressor._StopFlag != None:\r
934 Progressor._StopFlag.set()\r
935 if Progressor._ProgressThread != None:\r
936 Progressor._ProgressThread.join()\r
937 Progressor._ProgressThread = None\r
938\r
939## A dict which can access its keys and/or values orderly\r
940#\r
941# The class implements a new kind of dict which its keys or values can be\r
942# accessed in the order they are added into the dict. It guarantees the order\r
943# by making use of an internal list to keep a copy of keys.\r
944#\r
945class sdict(IterableUserDict):\r
946 ## Constructor\r
947 def __init__(self):\r
948 IterableUserDict.__init__(self)\r
949 self._key_list = []\r
950\r
951 ## [] operator\r
952 def __setitem__(self, key, value):\r
953 if key not in self._key_list:\r
954 self._key_list.append(key)\r
955 IterableUserDict.__setitem__(self, key, value)\r
956\r
957 ## del operator\r
958 def __delitem__(self, key):\r
959 self._key_list.remove(key)\r
960 IterableUserDict.__delitem__(self, key)\r
961\r
962 ## used in "for k in dict" loop to ensure the correct order\r
963 def __iter__(self):\r
964 return self.iterkeys()\r
965\r
966 ## len() support\r
967 def __len__(self):\r
968 return len(self._key_list)\r
969\r
970 ## "in" test support\r
971 def __contains__(self, key):\r
972 return key in self._key_list\r
973\r
974 ## indexof support\r
975 def index(self, key):\r
976 return self._key_list.index(key)\r
977\r
978 ## insert support\r
979 def insert(self, key, newkey, newvalue, order):\r
980 index = self._key_list.index(key)\r
981 if order == 'BEFORE':\r
982 self._key_list.insert(index, newkey)\r
983 IterableUserDict.__setitem__(self, newkey, newvalue)\r
984 elif order == 'AFTER':\r
985 self._key_list.insert(index + 1, newkey)\r
986 IterableUserDict.__setitem__(self, newkey, newvalue)\r
987\r
988 ## append support\r
989 def append(self, sdict):\r
990 for key in sdict:\r
991 if key not in self._key_list:\r
992 self._key_list.append(key)\r
993 IterableUserDict.__setitem__(self, key, sdict[key])\r
994\r
995 def has_key(self, key):\r
996 return key in self._key_list\r
997\r
998 ## Empty the dict\r
999 def clear(self):\r
1000 self._key_list = []\r
1001 IterableUserDict.clear(self)\r
1002\r
1003 ## Return a copy of keys\r
1004 def keys(self):\r
1005 keys = []\r
1006 for key in self._key_list:\r
1007 keys.append(key)\r
1008 return keys\r
1009\r
1010 ## Return a copy of values\r
1011 def values(self):\r
1012 values = []\r
1013 for key in self._key_list:\r
1014 values.append(self[key])\r
1015 return values\r
1016\r
1017 ## Return a copy of (key, value) list\r
1018 def items(self):\r
1019 items = []\r
1020 for key in self._key_list:\r
1021 items.append((key, self[key]))\r
1022 return items\r
1023\r
1024 ## Iteration support\r
1025 def iteritems(self):\r
1026 return iter(self.items())\r
1027\r
1028 ## Keys interation support\r
1029 def iterkeys(self):\r
1030 return iter(self.keys())\r
1031\r
1032 ## Values interation support\r
1033 def itervalues(self):\r
1034 return iter(self.values())\r
1035\r
1036 ## Return value related to a key, and remove the (key, value) from the dict\r
1037 def pop(self, key, *dv):\r
1038 value = None\r
1039 if key in self._key_list:\r
1040 value = self[key]\r
1041 self.__delitem__(key)\r
1042 elif len(dv) != 0 :\r
1043 value = kv[0]\r
1044 return value\r
1045\r
1046 ## Return (key, value) pair, and remove the (key, value) from the dict\r
1047 def popitem(self):\r
1048 key = self._key_list[-1]\r
1049 value = self[key]\r
1050 self.__delitem__(key)\r
1051 return key, value\r
1052\r
1053 def update(self, dict=None, **kwargs):\r
1054 if dict != None:\r
1055 for k, v in dict.items():\r
1056 self[k] = v\r
1057 if len(kwargs):\r
1058 for k, v in kwargs.items():\r
1059 self[k] = v\r
1060\r
1061## Dictionary with restricted keys\r
1062#\r
1063class rdict(dict):\r
1064 ## Constructor\r
1065 def __init__(self, KeyList):\r
1066 for Key in KeyList:\r
1067 dict.__setitem__(self, Key, "")\r
1068\r
1069 ## []= operator\r
1070 def __setitem__(self, key, value):\r
1071 if key not in self:\r
1072 EdkLogger.error("RestrictedDict", ATTRIBUTE_SET_FAILURE, "Key [%s] is not allowed" % key,\r
1073 ExtraData=", ".join(dict.keys(self)))\r
1074 dict.__setitem__(self, key, value)\r
1075\r
1076 ## =[] operator\r
1077 def __getitem__(self, key):\r
1078 if key not in self:\r
1079 return ""\r
1080 return dict.__getitem__(self, key)\r
1081\r
1082 ## del operator\r
1083 def __delitem__(self, key):\r
1084 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="del")\r
1085\r
1086 ## Empty the dict\r
1087 def clear(self):\r
1088 for Key in self:\r
1089 self.__setitem__(Key, "")\r
1090\r
1091 ## Return value related to a key, and remove the (key, value) from the dict\r
1092 def pop(self, key, *dv):\r
1093 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="pop")\r
1094\r
1095 ## Return (key, value) pair, and remove the (key, value) from the dict\r
1096 def popitem(self):\r
1097 EdkLogger.error("RestrictedDict", ATTRIBUTE_ACCESS_DENIED, ExtraData="popitem")\r
1098\r
1099## Dictionary using prioritized list as key\r
1100#\r
1101class tdict:\r
1102 _ListType = type([])\r
1103 _TupleType = type(())\r
1104 _Wildcard = 'COMMON'\r
1105 _ValidWildcardList = ['COMMON', 'DEFAULT', 'ALL', '*', 'PLATFORM']\r
1106\r
1107 def __init__(self, _Single_=False, _Level_=2):\r
1108 self._Level_ = _Level_\r
1109 self.data = {}\r
1110 self._Single_ = _Single_\r
1111\r
1112 # =[] operator\r
1113 def __getitem__(self, key):\r
1114 KeyType = type(key)\r
1115 RestKeys = None\r
1116 if KeyType == self._ListType or KeyType == self._TupleType:\r
1117 FirstKey = key[0]\r
1118 if len(key) > 1:\r
1119 RestKeys = key[1:]\r
1120 elif self._Level_ > 1:\r
1121 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
1122 else:\r
1123 FirstKey = key\r
1124 if self._Level_ > 1:\r
1125 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
1126\r
1127 if FirstKey == None or str(FirstKey).upper() in self._ValidWildcardList:\r
1128 FirstKey = self._Wildcard\r
1129\r
1130 if self._Single_:\r
1131 return self._GetSingleValue(FirstKey, RestKeys)\r
1132 else:\r
1133 return self._GetAllValues(FirstKey, RestKeys)\r
1134\r
1135 def _GetSingleValue(self, FirstKey, RestKeys):\r
1136 Value = None\r
1137 #print "%s-%s" % (FirstKey, self._Level_) ,\r
1138 if self._Level_ > 1:\r
1139 if FirstKey == self._Wildcard:\r
1140 if FirstKey in self.data:\r
1141 Value = self.data[FirstKey][RestKeys]\r
1142 if Value == None:\r
1143 for Key in self.data:\r
1144 Value = self.data[Key][RestKeys]\r
1145 if Value != None: break\r
1146 else:\r
1147 if FirstKey in self.data:\r
1148 Value = self.data[FirstKey][RestKeys]\r
1149 if Value == None and self._Wildcard in self.data:\r
1150 #print "Value=None"\r
1151 Value = self.data[self._Wildcard][RestKeys]\r
1152 else:\r
1153 if FirstKey == self._Wildcard:\r
1154 if FirstKey in self.data:\r
1155 Value = self.data[FirstKey]\r
1156 if Value == None:\r
1157 for Key in self.data:\r
1158 Value = self.data[Key]\r
1159 if Value != None: break\r
1160 else:\r
1161 if FirstKey in self.data:\r
1162 Value = self.data[FirstKey]\r
1163 elif self._Wildcard in self.data:\r
1164 Value = self.data[self._Wildcard]\r
1165 return Value\r
1166\r
1167 def _GetAllValues(self, FirstKey, RestKeys):\r
1168 Value = []\r
1169 if self._Level_ > 1:\r
1170 if FirstKey == self._Wildcard:\r
1171 for Key in self.data:\r
1172 Value += self.data[Key][RestKeys]\r
1173 else:\r
1174 if FirstKey in self.data:\r
1175 Value += self.data[FirstKey][RestKeys]\r
1176 if self._Wildcard in self.data:\r
1177 Value += self.data[self._Wildcard][RestKeys]\r
1178 else:\r
1179 if FirstKey == self._Wildcard:\r
1180 for Key in self.data:\r
1181 Value.append(self.data[Key])\r
1182 else:\r
1183 if FirstKey in self.data:\r
1184 Value.append(self.data[FirstKey])\r
1185 if self._Wildcard in self.data:\r
1186 Value.append(self.data[self._Wildcard])\r
1187 return Value\r
1188\r
1189 ## []= operator\r
1190 def __setitem__(self, key, value):\r
1191 KeyType = type(key)\r
1192 RestKeys = None\r
1193 if KeyType == self._ListType or KeyType == self._TupleType:\r
1194 FirstKey = key[0]\r
1195 if len(key) > 1:\r
1196 RestKeys = key[1:]\r
1197 else:\r
1198 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
1199 else:\r
1200 FirstKey = key\r
1201 if self._Level_ > 1:\r
1202 RestKeys = [self._Wildcard for i in range(0, self._Level_-1)]\r
1203\r
1204 if FirstKey in self._ValidWildcardList:\r
1205 FirstKey = self._Wildcard\r
1206\r
1207 if FirstKey not in self.data and self._Level_ > 0:\r
1208 self.data[FirstKey] = tdict(self._Single_, self._Level_ - 1)\r
1209\r
1210 if self._Level_ > 1:\r
1211 self.data[FirstKey][RestKeys] = value\r
1212 else:\r
1213 self.data[FirstKey] = value\r
1214\r
1215 def SetGreedyMode(self):\r
1216 self._Single_ = False\r
1217 if self._Level_ > 1:\r
1218 for Key in self.data:\r
1219 self.data[Key].SetGreedyMode()\r
1220\r
1221 def SetSingleMode(self):\r
1222 self._Single_ = True\r
1223 if self._Level_ > 1:\r
1224 for Key in self.data:\r
1225 self.data[Key].SetSingleMode()\r
1226\r
1227 def GetKeys(self, KeyIndex=0):\r
1228 assert KeyIndex >= 0\r
1229 if KeyIndex == 0:\r
1230 return set(self.data.keys())\r
1231 else:\r
1232 keys = set()\r
1233 for Key in self.data:\r
1234 keys |= self.data[Key].GetKeys(KeyIndex - 1)\r
1235 return keys\r
1236\r
1237## Boolean chain list\r
1238#\r
1239class Blist(UserList):\r
1240 def __init__(self, initlist=None):\r
1241 UserList.__init__(self, initlist)\r
1242 def __setitem__(self, i, item):\r
1243 if item not in [True, False]:\r
1244 if item == 0:\r
1245 item = False\r
1246 else:\r
1247 item = True\r
1248 self.data[i] = item\r
1249 def _GetResult(self):\r
1250 Value = True\r
1251 for item in self.data:\r
1252 Value &= item\r
1253 return Value\r
1254 Result = property(_GetResult)\r
1255\r
1256def ParseConsoleLog(Filename):\r
1257 Opr = open(os.path.normpath(Filename), 'r')\r
1258 Opw = open(os.path.normpath(Filename + '.New'), 'w+')\r
1259 for Line in Opr.readlines():\r
1260 if Line.find('.efi') > -1:\r
1261 Line = Line[Line.rfind(' ') : Line.rfind('.efi')].strip()\r
1262 Opw.write('%s\n' % Line)\r
1263\r
1264 Opr.close()\r
1265 Opw.close()\r
1266\r
1267## AnalyzeDscPcd\r
1268#\r
1269# Analyze DSC PCD value, since there is no data type info in DSC\r
1270# This fuction is used to match functions (AnalyzePcdData, AnalyzeHiiPcdData, AnalyzeVpdPcdData) used for retrieving PCD value from database\r
1271# 1. Feature flag: TokenSpace.PcdCName|PcdValue\r
1272# 2. Fix and Patch:TokenSpace.PcdCName|PcdValue[|MaxSize]\r
1273# 3. Dynamic default:\r
1274# TokenSpace.PcdCName|PcdValue[|VOID*[|MaxSize]]\r
1275# TokenSpace.PcdCName|PcdValue\r
1276# 4. Dynamic VPD:\r
1277# TokenSpace.PcdCName|VpdOffset[|VpdValue]\r
1278# TokenSpace.PcdCName|VpdOffset[|MaxSize[|VpdValue]]\r
1279# 5. Dynamic HII:\r
1280# TokenSpace.PcdCName|HiiString|VaiableGuid|VariableOffset[|HiiValue]\r
1281# PCD value needs to be located in such kind of string, and the PCD value might be an expression in which\r
1282# there might have "|" operator, also in string value.\r
1283#\r
1284# @param Setting: String contain information described above with "TokenSpace.PcdCName|" stripped\r
1285# @param PcdType: PCD type: feature, fixed, dynamic default VPD HII\r
1286# @param DataType: The datum type of PCD: VOID*, UNIT, BOOL\r
1287# @retval:\r
1288# ValueList: A List contain fields described above\r
1289# IsValid: True if conforming EBNF, otherwise False\r
1290# Index: The index where PcdValue is in ValueList\r
1291#\r
1292def AnalyzeDscPcd(Setting, PcdType, DataType=''):\r
1293 Setting = Setting.strip()\r
1294 # There might be escaped quote in a string: \", \\\"\r
1295 Data = Setting.replace('\\\\', '//').replace('\\\"', '\\\'')\r
1296 # There might be '|' in string and in ( ... | ... ), replace it with '-'\r
1297 NewStr = ''\r
1298 InStr = False\r
1299 Pair = 0\r
1300 for ch in Data:\r
1301 if ch == '"':\r
1302 InStr = not InStr\r
1303 elif ch == '(' and not InStr:\r
1304 Pair += 1\r
1305 elif ch == ')' and not InStr:\r
1306 Pair -= 1\r
1307 \r
1308 if (Pair > 0 or InStr) and ch == TAB_VALUE_SPLIT:\r
1309 NewStr += '-'\r
1310 else:\r
1311 NewStr += ch\r
1312 FieldList = []\r
1313 StartPos = 0\r
1314 while True:\r
1315 Pos = NewStr.find(TAB_VALUE_SPLIT, StartPos)\r
1316 if Pos < 0:\r
1317 FieldList.append(Setting[StartPos:].strip())\r
1318 break\r
1319 FieldList.append(Setting[StartPos:Pos].strip())\r
1320 StartPos = Pos + 1\r
1321\r
1322 IsValid = True\r
1323 if PcdType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_FEATURE_FLAG):\r
1324 Value = FieldList[0]\r
1325 Size = ''\r
1326 if len(FieldList) > 1:\r
1327 Type = FieldList[1]\r
1328 # Fix the PCD type when no DataType input\r
1329 if Type == 'VOID*':\r
1330 DataType = 'VOID*'\r
1331 else:\r
1332 Size = FieldList[1]\r
1333 if len(FieldList) > 2:\r
1334 Size = FieldList[2]\r
1335 if DataType == 'VOID*':\r
1336 IsValid = (len(FieldList) <= 3)\r
1337 else:\r
1338 IsValid = (len(FieldList) <= 1)\r
1339 return [Value, '', Size], IsValid, 0\r
1340 elif PcdType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):\r
1341 Value = FieldList[0]\r
1342 Size = Type = ''\r
1343 if len(FieldList) > 1:\r
1344 Type = FieldList[1]\r
1345 else:\r
1346 Type = DataType\r
1347 if len(FieldList) > 2:\r
1348 Size = FieldList[2]\r
1349 else:\r
1350 if Type == 'VOID*':\r
1351 if Value.startswith("L"):\r
1352 Size = str((len(Value)- 3 + 1) * 2)\r
1353 elif Value.startswith("{"):\r
1354 Size = str(len(Value.split(",")))\r
1355 else:\r
1356 Size = str(len(Value) -2 + 1 )\r
1357 if DataType == 'VOID*':\r
1358 IsValid = (len(FieldList) <= 3)\r
1359 else:\r
1360 IsValid = (len(FieldList) <= 1)\r
1361 return [Value, Type, Size], IsValid, 0 \r
1362 elif PcdType in (MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_VPD):\r
1363 VpdOffset = FieldList[0]\r
1364 Value = Size = ''\r
1365 if not DataType == 'VOID*':\r
1366 if len(FieldList) > 1:\r
1367 Value = FieldList[1]\r
1368 else:\r
1369 if len(FieldList) > 1:\r
1370 Size = FieldList[1]\r
1371 if len(FieldList) > 2:\r
1372 Value = FieldList[2]\r
1373 if DataType == 'VOID*':\r
1374 IsValid = (len(FieldList) <= 3)\r
1375 else:\r
1376 IsValid = (len(FieldList) <= 2)\r
1377 return [VpdOffset, Size, Value], IsValid, 2\r
1378 elif PcdType in (MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII):\r
1379 HiiString = FieldList[0]\r
1380 Guid = Offset = Value = ''\r
1381 if len(FieldList) > 1:\r
1382 Guid = FieldList[1]\r
1383 if len(FieldList) > 2:\r
1384 Offset = FieldList[2]\r
1385 if len(FieldList) > 3:\r
1386 Value = FieldList[3]\r
1387 IsValid = (3 <= len(FieldList) <= 4)\r
1388 return [HiiString, Guid, Offset, Value], IsValid, 3\r
1389 return [], False, 0\r
1390\r
1391## AnalyzePcdData\r
1392#\r
1393# Analyze the pcd Value, Datum type and TokenNumber.\r
1394# Used to avoid split issue while the value string contain "|" character\r
1395#\r
1396# @param[in] Setting: A String contain value/datum type/token number information;\r
1397# \r
1398# @retval ValueList: A List contain value, datum type and toke number. \r
1399#\r
1400def AnalyzePcdData(Setting): \r
1401 ValueList = ['', '', ''] \r
1402 \r
1403 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')\r
1404 PtrValue = ValueRe.findall(Setting)\r
1405 \r
1406 ValueUpdateFlag = False\r
1407 \r
1408 if len(PtrValue) >= 1:\r
1409 Setting = re.sub(ValueRe, '', Setting)\r
1410 ValueUpdateFlag = True \r
1411\r
1412 TokenList = Setting.split(TAB_VALUE_SPLIT)\r
1413 ValueList[0:len(TokenList)] = TokenList\r
1414 \r
1415 if ValueUpdateFlag:\r
1416 ValueList[0] = PtrValue[0]\r
1417 \r
1418 return ValueList \r
1419 \r
1420## AnalyzeHiiPcdData\r
1421#\r
1422# Analyze the pcd Value, variable name, variable Guid and variable offset.\r
1423# Used to avoid split issue while the value string contain "|" character\r
1424#\r
1425# @param[in] Setting: A String contain VariableName, VariableGuid, VariableOffset, DefaultValue information;\r
1426# \r
1427# @retval ValueList: A List contaian VariableName, VariableGuid, VariableOffset, DefaultValue. \r
1428#\r
1429def AnalyzeHiiPcdData(Setting):\r
1430 ValueList = ['', '', '', '']\r
1431\r
1432 TokenList = GetSplitValueList(Setting)\r
1433 ValueList[0:len(TokenList)] = TokenList\r
1434\r
1435 return ValueList\r
1436\r
1437## AnalyzeVpdPcdData\r
1438#\r
1439# Analyze the vpd pcd VpdOffset, MaxDatumSize and InitialValue.\r
1440# Used to avoid split issue while the value string contain "|" character\r
1441#\r
1442# @param[in] Setting: A String contain VpdOffset/MaxDatumSize/InitialValue information;\r
1443# \r
1444# @retval ValueList: A List contain VpdOffset, MaxDatumSize and InitialValue. \r
1445#\r
1446def AnalyzeVpdPcdData(Setting): \r
1447 ValueList = ['', '', ''] \r
1448 \r
1449 ValueRe = re.compile(r'\s*L?\".*\|.*\"\s*$')\r
1450 PtrValue = ValueRe.findall(Setting)\r
1451 \r
1452 ValueUpdateFlag = False\r
1453 \r
1454 if len(PtrValue) >= 1:\r
1455 Setting = re.sub(ValueRe, '', Setting)\r
1456 ValueUpdateFlag = True \r
1457\r
1458 TokenList = Setting.split(TAB_VALUE_SPLIT)\r
1459 ValueList[0:len(TokenList)] = TokenList\r
1460 \r
1461 if ValueUpdateFlag:\r
1462 ValueList[2] = PtrValue[0]\r
1463 \r
1464 return ValueList \r
1465\r
1466## check format of PCD value against its the datum type\r
1467#\r
1468# For PCD value setting\r
1469#\r
1470def CheckPcdDatum(Type, Value):\r
1471 if Type == "VOID*":\r
1472 ValueRe = re.compile(r'\s*L?\".*\"\s*$')\r
1473 if not (((Value.startswith('L"') or Value.startswith('"')) and Value.endswith('"'))\r
1474 or (Value.startswith('{') and Value.endswith('}'))\r
1475 ):\r
1476 return False, "Invalid value [%s] of type [%s]; must be in the form of {...} for array"\\r
1477 ", or \"...\" for string, or L\"...\" for unicode string" % (Value, Type) \r
1478 elif ValueRe.match(Value):\r
1479 # Check the chars in UnicodeString or CString is printable\r
1480 if Value.startswith("L"):\r
1481 Value = Value[2:-1]\r
1482 else:\r
1483 Value = Value[1:-1]\r
1484 Printset = set(string.printable)\r
1485 Printset.remove(TAB_PRINTCHAR_VT)\r
1486 Printset.add(TAB_PRINTCHAR_BS)\r
1487 Printset.add(TAB_PRINTCHAR_NUL)\r
1488 if not set(Value).issubset(Printset):\r
1489 PrintList = list(Printset)\r
1490 PrintList.sort()\r
1491 return False, "Invalid PCD string value of type [%s]; must be printable chars %s." % (Type, PrintList)\r
1492 elif Type == 'BOOLEAN':\r
1493 if Value not in ['TRUE', 'True', 'true', '0x1', '0x01', '1', 'FALSE', 'False', 'false', '0x0', '0x00', '0']:\r
1494 return False, "Invalid value [%s] of type [%s]; must be one of TRUE, True, true, 0x1, 0x01, 1"\\r
1495 ", FALSE, False, false, 0x0, 0x00, 0" % (Value, Type)\r
1496 elif Type in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64]:\r
1497 try:\r
1498 Value = long(Value, 0)\r
1499 except:\r
1500 return False, "Invalid value [%s] of type [%s];"\\r
1501 " must be a hexadecimal, decimal or octal in C language format." % (Value, Type)\r
1502 else:\r
1503 return False, "Invalid type [%s]; must be one of VOID*, BOOLEAN, UINT8, UINT16, UINT32, UINT64." % (Type)\r
1504\r
1505 return True, ""\r
1506\r
1507## Split command line option string to list\r
1508#\r
1509# subprocess.Popen needs the args to be a sequence. Otherwise there's problem\r
1510# in non-windows platform to launch command\r
1511#\r
1512def SplitOption(OptionString):\r
1513 OptionList = []\r
1514 LastChar = " "\r
1515 OptionStart = 0\r
1516 QuotationMark = ""\r
1517 for Index in range(0, len(OptionString)):\r
1518 CurrentChar = OptionString[Index]\r
1519 if CurrentChar in ['"', "'"]:\r
1520 if QuotationMark == CurrentChar:\r
1521 QuotationMark = ""\r
1522 elif QuotationMark == "":\r
1523 QuotationMark = CurrentChar\r
1524 continue\r
1525 elif QuotationMark:\r
1526 continue\r
1527\r
1528 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:\r
1529 if Index > OptionStart:\r
1530 OptionList.append(OptionString[OptionStart:Index-1])\r
1531 OptionStart = Index\r
1532 LastChar = CurrentChar\r
1533 OptionList.append(OptionString[OptionStart:])\r
1534 return OptionList\r
1535\r
1536def CommonPath(PathList):\r
1537 P1 = min(PathList).split(os.path.sep)\r
1538 P2 = max(PathList).split(os.path.sep)\r
1539 for Index in xrange(min(len(P1), len(P2))):\r
1540 if P1[Index] != P2[Index]:\r
1541 return os.path.sep.join(P1[:Index])\r
1542 return os.path.sep.join(P1)\r
1543\r
97fa0ee9
YL
1544#\r
1545# Convert string to C format array\r
1546#\r
1547def ConvertStringToByteArray(Value):\r
1548 Value = Value.strip()\r
1549 if not Value:\r
1550 return None\r
1551 if Value[0] == '{':\r
1552 if not Value.endswith('}'):\r
1553 return None\r
1554 Value = Value.replace(' ', '').replace('{', '').replace('}', '')\r
1555 ValFields = Value.split(',')\r
1556 try:\r
1557 for Index in range(len(ValFields)):\r
1558 ValFields[Index] = str(int(ValFields[Index], 0))\r
1559 except ValueError:\r
1560 return None\r
1561 Value = '{' + ','.join(ValFields) + '}'\r
1562 return Value\r
1563\r
1564 Unicode = False\r
1565 if Value.startswith('L"'):\r
1566 if not Value.endswith('"'):\r
1567 return None\r
1568 Value = Value[1:]\r
1569 Unicode = True\r
1570 elif not Value.startswith('"') or not Value.endswith('"'):\r
1571 return None\r
1572\r
1573 Value = eval(Value) # translate escape character\r
1574 NewValue = '{'\r
1575 for Index in range(0,len(Value)):\r
1576 if Unicode:\r
1577 NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','\r
1578 else:\r
1579 NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','\r
1580 Value = NewValue + '0}'\r
1581 return Value\r
1582\r
f51461c8
LG
1583class PathClass(object):\r
1584 def __init__(self, File='', Root='', AlterRoot='', Type='', IsBinary=False,\r
1585 Arch='COMMON', ToolChainFamily='', Target='', TagName='', ToolCode=''):\r
1586 self.Arch = Arch\r
1587 self.File = str(File)\r
1588 if os.path.isabs(self.File):\r
1589 self.Root = ''\r
1590 self.AlterRoot = ''\r
1591 else:\r
1592 self.Root = str(Root)\r
1593 self.AlterRoot = str(AlterRoot)\r
1594\r
1595 # Remove any '.' and '..' in path\r
1596 if self.Root:\r
1597 self.Path = os.path.normpath(os.path.join(self.Root, self.File))\r
1598 self.Root = os.path.normpath(CommonPath([self.Root, self.Path]))\r
1599 # eliminate the side-effect of 'C:'\r
1600 if self.Root[-1] == ':':\r
1601 self.Root += os.path.sep\r
1602 # file path should not start with path separator\r
1603 if self.Root[-1] == os.path.sep:\r
1604 self.File = self.Path[len(self.Root):]\r
1605 else:\r
1606 self.File = self.Path[len(self.Root)+1:]\r
1607 else:\r
1608 self.Path = os.path.normpath(self.File)\r
1609\r
1610 self.SubDir, self.Name = os.path.split(self.File)\r
1611 self.BaseName, self.Ext = os.path.splitext(self.Name)\r
1612\r
1613 if self.Root:\r
1614 if self.SubDir:\r
1615 self.Dir = os.path.join(self.Root, self.SubDir)\r
1616 else:\r
1617 self.Dir = self.Root\r
1618 else:\r
1619 self.Dir = self.SubDir\r
1620\r
1621 if IsBinary:\r
1622 self.Type = Type\r
1623 else:\r
1624 self.Type = self.Ext.lower()\r
1625\r
1626 self.IsBinary = IsBinary\r
1627 self.Target = Target\r
1628 self.TagName = TagName\r
1629 self.ToolCode = ToolCode\r
1630 self.ToolChainFamily = ToolChainFamily\r
1631\r
1632 self._Key = None\r
1633\r
1634 ## Convert the object of this class to a string\r
1635 #\r
1636 # Convert member Path of the class to a string\r
1637 #\r
1638 # @retval string Formatted String\r
1639 #\r
1640 def __str__(self):\r
1641 return self.Path\r
1642\r
1643 ## Override __eq__ function\r
1644 #\r
1645 # Check whether PathClass are the same\r
1646 #\r
1647 # @retval False The two PathClass are different\r
1648 # @retval True The two PathClass are the same\r
1649 #\r
1650 def __eq__(self, Other):\r
1651 if type(Other) == type(self):\r
1652 return self.Path == Other.Path\r
1653 else:\r
1654 return self.Path == str(Other)\r
1655\r
1656 ## Override __cmp__ function\r
1657 #\r
1658 # Customize the comparsion operation of two PathClass\r
1659 #\r
1660 # @retval 0 The two PathClass are different\r
1661 # @retval -1 The first PathClass is less than the second PathClass\r
1662 # @retval 1 The first PathClass is Bigger than the second PathClass\r
1663 def __cmp__(self, Other):\r
1664 if type(Other) == type(self):\r
1665 OtherKey = Other.Path\r
1666 else:\r
1667 OtherKey = str(Other)\r
1668 \r
1669 SelfKey = self.Path\r
1670 if SelfKey == OtherKey:\r
1671 return 0\r
1672 elif SelfKey > OtherKey:\r
1673 return 1\r
1674 else:\r
1675 return -1\r
1676\r
1677 ## Override __hash__ function\r
1678 #\r
1679 # Use Path as key in hash table\r
1680 #\r
1681 # @retval string Key for hash table\r
1682 #\r
1683 def __hash__(self):\r
1684 return hash(self.Path)\r
1685\r
1686 def _GetFileKey(self):\r
1687 if self._Key == None:\r
1688 self._Key = self.Path.upper() # + self.ToolChainFamily + self.TagName + self.ToolCode + self.Target\r
1689 return self._Key\r
1690\r
1691 def _GetTimeStamp(self):\r
1692 return os.stat(self.Path)[8]\r
1693\r
1694 def Validate(self, Type='', CaseSensitive=True):\r
1695 if GlobalData.gCaseInsensitive:\r
1696 CaseSensitive = False\r
1697 if Type and Type.lower() != self.Type:\r
1698 return FILE_TYPE_MISMATCH, '%s (expect %s but got %s)' % (self.File, Type, self.Type)\r
1699\r
1700 RealFile, RealRoot = RealPath2(self.File, self.Root, self.AlterRoot)\r
1701 if not RealRoot and not RealFile:\r
1702 RealFile = self.File\r
1703 if self.AlterRoot:\r
1704 RealFile = os.path.join(self.AlterRoot, self.File)\r
1705 elif self.Root:\r
1706 RealFile = os.path.join(self.Root, self.File)\r
1707 return FILE_NOT_FOUND, os.path.join(self.AlterRoot, RealFile)\r
1708\r
1709 ErrorCode = 0\r
1710 ErrorInfo = ''\r
1711 if RealRoot != self.Root or RealFile != self.File:\r
1712 if CaseSensitive and (RealFile != self.File or (RealRoot != self.Root and RealRoot != self.AlterRoot)):\r
1713 ErrorCode = FILE_CASE_MISMATCH\r
1714 ErrorInfo = self.File + '\n\t' + RealFile + " [in file system]"\r
1715\r
1716 self.SubDir, self.Name = os.path.split(RealFile)\r
1717 self.BaseName, self.Ext = os.path.splitext(self.Name)\r
1718 if self.SubDir:\r
1719 self.Dir = os.path.join(RealRoot, self.SubDir)\r
1720 else:\r
1721 self.Dir = RealRoot\r
1722 self.File = RealFile\r
1723 self.Root = RealRoot\r
1724 self.Path = os.path.join(RealRoot, RealFile)\r
1725 return ErrorCode, ErrorInfo\r
1726\r
1727 Key = property(_GetFileKey)\r
1728 TimeStamp = property(_GetTimeStamp)\r
1729\r
1730## Parse PE image to get the required PE informaion.\r
1731#\r
1732class PeImageClass():\r
1733 ## Constructor\r
1734 #\r
1735 # @param File FilePath of PeImage\r
1736 #\r
1737 def __init__(self, PeFile):\r
1738 self.FileName = PeFile\r
1739 self.IsValid = False\r
1740 self.Size = 0\r
1741 self.EntryPoint = 0\r
1742 self.SectionAlignment = 0\r
1743 self.SectionHeaderList = []\r
1744 self.ErrorInfo = ''\r
1745 try:\r
1746 PeObject = open(PeFile, 'rb')\r
1747 except:\r
1748 self.ErrorInfo = self.FileName + ' can not be found\n'\r
1749 return\r
1750 # Read DOS header\r
1751 ByteArray = array.array('B')\r
1752 ByteArray.fromfile(PeObject, 0x3E)\r
1753 ByteList = ByteArray.tolist()\r
1754 # DOS signature should be 'MZ'\r
1755 if self._ByteListToStr (ByteList[0x0:0x2]) != 'MZ':\r
1756 self.ErrorInfo = self.FileName + ' has no valid DOS signature MZ'\r
1757 return\r
1758\r
1759 # Read 4 byte PE Signature\r
1760 PeOffset = self._ByteListToInt(ByteList[0x3C:0x3E])\r
1761 PeObject.seek(PeOffset)\r
1762 ByteArray = array.array('B')\r
1763 ByteArray.fromfile(PeObject, 4)\r
1764 # PE signature should be 'PE\0\0'\r
1765 if ByteArray.tostring() != 'PE\0\0':\r
1766 self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'\r
1767 return\r
1768\r
1769 # Read PE file header\r
1770 ByteArray = array.array('B')\r
1771 ByteArray.fromfile(PeObject, 0x14)\r
1772 ByteList = ByteArray.tolist()\r
1773 SecNumber = self._ByteListToInt(ByteList[0x2:0x4])\r
1774 if SecNumber == 0:\r
1775 self.ErrorInfo = self.FileName + ' has no section header'\r
1776 return\r
1777\r
1778 # Read PE optional header\r
1779 OptionalHeaderSize = self._ByteListToInt(ByteArray[0x10:0x12])\r
1780 ByteArray = array.array('B')\r
1781 ByteArray.fromfile(PeObject, OptionalHeaderSize)\r
1782 ByteList = ByteArray.tolist()\r
1783 self.EntryPoint = self._ByteListToInt(ByteList[0x10:0x14])\r
1784 self.SectionAlignment = self._ByteListToInt(ByteList[0x20:0x24])\r
1785 self.Size = self._ByteListToInt(ByteList[0x38:0x3C])\r
1786\r
1787 # Read each Section Header\r
1788 for Index in range(SecNumber):\r
1789 ByteArray = array.array('B')\r
1790 ByteArray.fromfile(PeObject, 0x28)\r
1791 ByteList = ByteArray.tolist()\r
1792 SecName = self._ByteListToStr(ByteList[0:8])\r
1793 SecVirtualSize = self._ByteListToInt(ByteList[8:12])\r
1794 SecRawAddress = self._ByteListToInt(ByteList[20:24])\r
1795 SecVirtualAddress = self._ByteListToInt(ByteList[12:16])\r
1796 self.SectionHeaderList.append((SecName, SecVirtualAddress, SecRawAddress, SecVirtualSize))\r
1797 self.IsValid = True\r
1798 PeObject.close()\r
1799\r
1800 def _ByteListToStr(self, ByteList):\r
1801 String = ''\r
1802 for index in range(len(ByteList)):\r
1803 if ByteList[index] == 0: \r
1804 break\r
1805 String += chr(ByteList[index])\r
1806 return String\r
1807\r
1808 def _ByteListToInt(self, ByteList):\r
1809 Value = 0\r
1810 for index in range(len(ByteList) - 1, -1, -1):\r
1811 Value = (Value << 8) | int(ByteList[index])\r
1812 return Value\r
1813\r
1814\r
1815class SkuClass():\r
1816 \r
1817 DEFAULT = 0\r
1818 SINGLE = 1\r
1819 MULTIPLE =2\r
1820 \r
1821 def __init__(self,SkuIdentifier='', SkuIds={}):\r
1822 \r
1823 self.AvailableSkuIds = sdict()\r
1824 self.SkuIdSet = []\r
1825 \r
1826 if SkuIdentifier == '' or SkuIdentifier is None:\r
1827 self.SkuIdSet = ['DEFAULT']\r
1828 elif SkuIdentifier == 'ALL':\r
1829 self.SkuIdSet = SkuIds.keys()\r
1830 else:\r
1831 r = SkuIdentifier.split('|') \r
1832 self.SkuIdSet=[r[k].strip() for k in range(len(r))] \r
1833 if len(self.SkuIdSet) == 2 and 'DEFAULT' in self.SkuIdSet and SkuIdentifier != 'ALL':\r
1834 self.SkuIdSet.remove('DEFAULT')\r
1835 \r
1836 for each in self.SkuIdSet:\r
1837 if each in SkuIds:\r
1838 self.AvailableSkuIds[each] = SkuIds[each]\r
1839 else:\r
1840 EdkLogger.error("build", PARAMETER_INVALID,\r
1841 ExtraData="SKU-ID [%s] is not supported by the platform. [Valid SKU-ID: %s]"\r
1842 % (each, " ".join(SkuIds.keys())))\r
1843 \r
1844 def __SkuUsageType(self): \r
1845 \r
1846 if len(self.SkuIdSet) == 1:\r
1847 if self.SkuIdSet[0] == 'DEFAULT':\r
1848 return SkuClass.DEFAULT\r
1849 else:\r
1850 return SkuClass.SINGLE\r
1851 else:\r
1852 return SkuClass.MULTIPLE\r
1853\r
1854 def __GetAvailableSkuIds(self):\r
1855 return self.AvailableSkuIds\r
1856 \r
1857 def __GetSystemSkuID(self):\r
1858 if self.__SkuUsageType() == SkuClass.SINGLE:\r
1859 return self.SkuIdSet[0]\r
1860 else:\r
1861 return 'DEFAULT'\r
1862 \r
1863 SystemSkuId = property(__GetSystemSkuID)\r
1864 AvailableSkuIdSet = property(__GetAvailableSkuIds)\r
1865 SkuUsageType = property(__SkuUsageType)\r
1866\r
1867##\r
1868#\r
1869# This acts like the main() function for the script, unless it is 'import'ed into another\r
1870# script.\r
1871#\r
1872if __name__ == '__main__':\r
1873 pass\r
1874\r