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