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