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