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