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