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