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