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