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