]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - BaseTools/Source/Python/Workspace/DscBuildData.py
BaseTools: Collect DynamicHii PCD values and assign it to VPD PCD Value
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / DscBuildData.py
... / ...
CommitLineData
1## @file\r
2# This file is used to create a database used by build tool\r
3#\r
4# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
5# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
6# This program and the accompanying materials\r
7# are licensed and made available under the terms and conditions of the BSD License\r
8# which accompanies this distribution. The full text of the license may be found at\r
9# http://opensource.org/licenses/bsd-license.php\r
10#\r
11# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13#\r
14\r
15## Platform build information from DSC file\r
16#\r
17# This class is used to retrieve information stored in database and convert them\r
18# into PlatformBuildClassObject form for easier use for AutoGen.\r
19#\r
20from Common.String import *\r
21from Common.DataType import *\r
22from Common.Misc import *\r
23from types import *\r
24\r
25from CommonDataClass.CommonClass import SkuInfoClass\r
26\r
27from MetaDataTable import *\r
28from MetaFileTable import *\r
29from MetaFileParser import *\r
30\r
31from WorkspaceCommon import GetDeclaredPcd\r
32from Common.Misc import AnalyzeDscPcd\r
33from Common.Misc import ProcessDuplicatedInf\r
34import re\r
35from Common.Parsing import IsValidWord\r
36from Common.VariableAttributes import VariableAttributes\r
37import Common.GlobalData as GlobalData\r
38import subprocess\r
39from Workspace.BuildClassObject import PlatformBuildClassObject, StructurePcd, PcdClassObject, ModuleBuildClassObject\r
40\r
41#\r
42# Treat CHAR16 as a synonym for UINT16. CHAR16 support is required for VFR C structs\r
43#\r
44PcdValueInitName = 'PcdValueInit'\r
45PcdSupportedBaseTypes = ['BOOLEAN', 'UINT8', 'UINT16', 'UINT32', 'UINT64', 'CHAR16']\r
46PcdSupportedBaseTypeWidth = {'BOOLEAN':8, 'UINT8':8, 'UINT16':16, 'UINT32':32, 'UINT64':64}\r
47PcdUnsupportedBaseTypes = ['INT8', 'INT16', 'INT32', 'INT64', 'CHAR8', 'UINTN', 'INTN', 'VOID']\r
48\r
49PcdMainCHeader = '''\r
50/**\r
51 DO NOT EDIT\r
52 FILE auto-generated\r
53**/\r
54\r
55#include <stdio.h>\r
56#include <stdlib.h>\r
57#include <string.h>\r
58#include <PcdValueCommon.h>\r
59'''\r
60\r
61PcdMainCEntry = '''\r
62int\r
63main (\r
64 int argc,\r
65 char *argv[]\r
66 )\r
67{\r
68 return PcdValueMain (argc, argv);\r
69}\r
70'''\r
71\r
72PcdMakefileHeader = '''\r
73#\r
74# DO NOT EDIT\r
75# This file is auto-generated by build utility\r
76#\r
77\r
78'''\r
79\r
80PcdMakefileEnd = '''\r
81!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common\r
82\r
83CFLAGS = $(CFLAGS) /wd4200 /wd4034 /wd4101\r
84\r
85LIBS = $(LIB_PATH)\Common.lib\r
86\r
87!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app\r
88'''\r
89\r
90PcdGccMakefile = '''\r
91ARCH ?= IA32\r
92MAKEROOT ?= $(EDK_TOOLS_PATH)/Source/C\r
93LIBS = -lCommon\r
94'''\r
95\r
96class DscBuildData(PlatformBuildClassObject):\r
97 # dict used to convert PCD type in database to string used by build tool\r
98 _PCD_TYPE_STRING_ = {\r
99 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",\r
100 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",\r
101 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",\r
102 MODEL_PCD_DYNAMIC : "Dynamic",\r
103 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",\r
104 MODEL_PCD_DYNAMIC_HII : "DynamicHii",\r
105 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",\r
106 MODEL_PCD_DYNAMIC_EX : "DynamicEx",\r
107 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",\r
108 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",\r
109 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",\r
110 }\r
111\r
112 # dict used to convert part of [Defines] to members of DscBuildData directly\r
113 _PROPERTY_ = {\r
114 #\r
115 # Required Fields\r
116 #\r
117 TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName",\r
118 TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid",\r
119 TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version",\r
120 TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification",\r
121 # TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory",\r
122 # TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList",\r
123 # TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets",\r
124 TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName",\r
125 # TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition",\r
126 TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber",\r
127 TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName",\r
128 TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress",\r
129 TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress",\r
130 # TAB_DSC_DEFINES_RFC_LANGUAGES : "_RFCLanguages",\r
131 # TAB_DSC_DEFINES_ISO_LANGUAGES : "_ISOLanguages",\r
132 }\r
133\r
134 # used to compose dummy library class name for those forced library instances\r
135 _NullLibraryNumber = 0\r
136\r
137 ## Constructor of DscBuildData\r
138 #\r
139 # Initialize object of DscBuildData\r
140 #\r
141 # @param FilePath The path of platform description file\r
142 # @param RawData The raw data of DSC file\r
143 # @param BuildDataBase Database used to retrieve module/package information\r
144 # @param Arch The target architecture\r
145 # @param Platform (not used for DscBuildData)\r
146 # @param Macros Macros used for replacement in DSC file\r
147 #\r
148 def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None):\r
149 self.MetaFile = FilePath\r
150 self._RawData = RawData\r
151 self._Bdb = BuildDataBase\r
152 self._Arch = Arch\r
153 self._Target = Target\r
154 self._Toolchain = Toolchain\r
155 self._Clear()\r
156 self._HandleOverridePath()\r
157 if os.getenv("WORKSPACE"):\r
158 self.OutputPath = os.path.join(os.getenv("WORKSPACE"), 'Build', PcdValueInitName)\r
159 else:\r
160 self.OutputPath = os.path.dirname(self.DscFile)\r
161\r
162 ## XXX[key] = value\r
163 def __setitem__(self, key, value):\r
164 self.__dict__[self._PROPERTY_[key]] = value\r
165\r
166 ## value = XXX[key]\r
167 def __getitem__(self, key):\r
168 return self.__dict__[self._PROPERTY_[key]]\r
169\r
170 ## "in" test support\r
171 def __contains__(self, key):\r
172 return key in self._PROPERTY_\r
173\r
174 ## Set all internal used members of DscBuildData to None\r
175 def _Clear(self):\r
176 self._Header = None\r
177 self._PlatformName = None\r
178 self._Guid = None\r
179 self._Version = None\r
180 self._DscSpecification = None\r
181 self._OutputDirectory = None\r
182 self._SupArchList = None\r
183 self._BuildTargets = None\r
184 self._SkuName = None\r
185 self._SkuIdentifier = None\r
186 self._AvilableSkuIds = None\r
187 self._PcdInfoFlag = None\r
188 self._VarCheckFlag = None\r
189 self._FlashDefinition = None\r
190 self._Prebuild = None\r
191 self._Postbuild = None\r
192 self._BuildNumber = None\r
193 self._MakefileName = None\r
194 self._BsBaseAddress = None\r
195 self._RtBaseAddress = None\r
196 self._SkuIds = None\r
197 self._Modules = None\r
198 self._LibraryInstances = None\r
199 self._LibraryClasses = None\r
200 self._Pcds = None\r
201 self._DecPcds = None\r
202 self._BuildOptions = None\r
203 self._ModuleTypeOptions = None\r
204 self._LoadFixAddress = None\r
205 self._RFCLanguages = None\r
206 self._ISOLanguages = None\r
207 self._VpdToolGuid = None\r
208 self.__Macros = None\r
209\r
210\r
211 ## handle Override Path of Module\r
212 def _HandleOverridePath(self):\r
213 RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]\r
214 Macros = self._Macros\r
215 Macros["EDK_SOURCE"] = GlobalData.gEcpSource\r
216 for Record in RecordList:\r
217 ModuleId = Record[5]\r
218 LineNo = Record[6]\r
219 ModuleFile = PathClass(NormPath(Record[0]), GlobalData.gWorkspace, Arch=self._Arch)\r
220 RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]\r
221 if RecordList != []:\r
222 SourceOverridePath = mws.join(GlobalData.gWorkspace, NormPath(RecordList[0][0]))\r
223\r
224 # Check if the source override path exists\r
225 if not os.path.isdir(SourceOverridePath):\r
226 EdkLogger.error('build', FILE_NOT_FOUND, Message='Source override path does not exist:', File=self.MetaFile, ExtraData=SourceOverridePath, Line=LineNo)\r
227\r
228 # Add to GlobalData Variables\r
229 GlobalData.gOverrideDir[ModuleFile.Key] = SourceOverridePath\r
230\r
231 ## Get current effective macros\r
232 def _GetMacros(self):\r
233 if self.__Macros == None:\r
234 self.__Macros = {}\r
235 self.__Macros.update(GlobalData.gPlatformDefines)\r
236 self.__Macros.update(GlobalData.gGlobalDefines)\r
237 self.__Macros.update(GlobalData.gCommandLineDefines)\r
238 return self.__Macros\r
239\r
240 ## Get architecture\r
241 def _GetArch(self):\r
242 return self._Arch\r
243\r
244 ## Set architecture\r
245 #\r
246 # Changing the default ARCH to another may affect all other information\r
247 # because all information in a platform may be ARCH-related. That's\r
248 # why we need to clear all internal used members, in order to cause all\r
249 # information to be re-retrieved.\r
250 #\r
251 # @param Value The value of ARCH\r
252 #\r
253 def _SetArch(self, Value):\r
254 if self._Arch == Value:\r
255 return\r
256 self._Arch = Value\r
257 self._Clear()\r
258\r
259 ## Retrieve all information in [Defines] section\r
260 #\r
261 # (Retriving all [Defines] information in one-shot is just to save time.)\r
262 #\r
263 def _GetHeaderInfo(self):\r
264 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]\r
265 for Record in RecordList:\r
266 Name = Record[1]\r
267 # items defined _PROPERTY_ don't need additional processing\r
268\r
269 # some special items in [Defines] section need special treatment\r
270 if Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:\r
271 self._OutputDirectory = NormPath(Record[2], self._Macros)\r
272 if ' ' in self._OutputDirectory:\r
273 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",\r
274 File=self.MetaFile, Line=Record[-1],\r
275 ExtraData=self._OutputDirectory)\r
276 elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:\r
277 self._FlashDefinition = PathClass(NormPath(Record[2], self._Macros), GlobalData.gWorkspace)\r
278 ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')\r
279 if ErrorCode != 0:\r
280 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],\r
281 ExtraData=ErrorInfo)\r
282 elif Name == TAB_DSC_PREBUILD:\r
283 PrebuildValue = Record[2]\r
284 if Record[2][0] == '"':\r
285 if Record[2][-1] != '"':\r
286 EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_PREBUILD,\r
287 File=self.MetaFile, Line=Record[-1])\r
288 PrebuildValue = Record[2][1:-1]\r
289 self._Prebuild = PrebuildValue\r
290 elif Name == TAB_DSC_POSTBUILD:\r
291 PostbuildValue = Record[2]\r
292 if Record[2][0] == '"':\r
293 if Record[2][-1] != '"':\r
294 EdkLogger.error('build', FORMAT_INVALID, 'Missing double quotes in the end of %s statement.' % TAB_DSC_POSTBUILD,\r
295 File=self.MetaFile, Line=Record[-1])\r
296 PostbuildValue = Record[2][1:-1]\r
297 self._Postbuild = PostbuildValue\r
298 elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:\r
299 self._SupArchList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)\r
300 elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:\r
301 self._BuildTargets = GetSplitValueList(Record[2])\r
302 elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:\r
303 if self._SkuName == None:\r
304 self._SkuName = Record[2]\r
305 self._SkuIdentifier = Record[2]\r
306 self._AvilableSkuIds = Record[2]\r
307 elif Name == TAB_DSC_DEFINES_PCD_INFO_GENERATION:\r
308 self._PcdInfoFlag = Record[2]\r
309 elif Name == TAB_DSC_DEFINES_PCD_VAR_CHECK_GENERATION:\r
310 self._VarCheckFlag = Record[2]\r
311 elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:\r
312 try:\r
313 self._LoadFixAddress = int (Record[2], 0)\r
314 except:\r
315 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (Record[2]))\r
316 elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES:\r
317 if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:\r
318 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for RFC_LANGUAGES must have double quotes around it, for example: RFC_LANGUAGES = "en-us;zh-hans"',\r
319 File=self.MetaFile, Line=Record[-1])\r
320 LanguageCodes = Record[2][1:-1]\r
321 if not LanguageCodes:\r
322 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement',\r
323 File=self.MetaFile, Line=Record[-1])\r
324 LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT)\r
325 # check whether there is empty entries in the list\r
326 if None in LanguageList:\r
327 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement',\r
328 File=self.MetaFile, Line=Record[-1])\r
329 self._RFCLanguages = LanguageList\r
330 elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES:\r
331 if not Record[2] or Record[2][0] != '"' or Record[2][-1] != '"' or len(Record[2]) == 1:\r
332 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"',\r
333 File=self.MetaFile, Line=Record[-1])\r
334 LanguageCodes = Record[2][1:-1]\r
335 if not LanguageCodes:\r
336 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement',\r
337 File=self.MetaFile, Line=Record[-1])\r
338 if len(LanguageCodes) % 3:\r
339 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES',\r
340 File=self.MetaFile, Line=Record[-1])\r
341 LanguageList = []\r
342 for i in range(0, len(LanguageCodes), 3):\r
343 LanguageList.append(LanguageCodes[i:i + 3])\r
344 self._ISOLanguages = LanguageList\r
345 elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:\r
346 #\r
347 # try to convert GUID to a real UUID value to see whether the GUID is format\r
348 # for VPD_TOOL_GUID is correct.\r
349 #\r
350 try:\r
351 uuid.UUID(Record[2])\r
352 except:\r
353 EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)\r
354 self._VpdToolGuid = Record[2]\r
355 elif Name in self:\r
356 self[Name] = Record[2]\r
357 # set _Header to non-None in order to avoid database re-querying\r
358 self._Header = 'DUMMY'\r
359\r
360 ## Retrieve platform name\r
361 def _GetPlatformName(self):\r
362 if self._PlatformName == None:\r
363 if self._Header == None:\r
364 self._GetHeaderInfo()\r
365 if self._PlatformName == None:\r
366 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)\r
367 return self._PlatformName\r
368\r
369 ## Retrieve file guid\r
370 def _GetFileGuid(self):\r
371 if self._Guid == None:\r
372 if self._Header == None:\r
373 self._GetHeaderInfo()\r
374 if self._Guid == None:\r
375 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_GUID", File=self.MetaFile)\r
376 return self._Guid\r
377\r
378 ## Retrieve platform version\r
379 def _GetVersion(self):\r
380 if self._Version == None:\r
381 if self._Header == None:\r
382 self._GetHeaderInfo()\r
383 if self._Version == None:\r
384 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_VERSION", File=self.MetaFile)\r
385 return self._Version\r
386\r
387 ## Retrieve platform description file version\r
388 def _GetDscSpec(self):\r
389 if self._DscSpecification == None:\r
390 if self._Header == None:\r
391 self._GetHeaderInfo()\r
392 if self._DscSpecification == None:\r
393 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No DSC_SPECIFICATION", File=self.MetaFile)\r
394 return self._DscSpecification\r
395\r
396 ## Retrieve OUTPUT_DIRECTORY\r
397 def _GetOutpuDir(self):\r
398 if self._OutputDirectory == None:\r
399 if self._Header == None:\r
400 self._GetHeaderInfo()\r
401 if self._OutputDirectory == None:\r
402 self._OutputDirectory = os.path.join("Build", self._PlatformName)\r
403 return self._OutputDirectory\r
404\r
405 ## Retrieve SUPPORTED_ARCHITECTURES\r
406 def _GetSupArch(self):\r
407 if self._SupArchList == None:\r
408 if self._Header == None:\r
409 self._GetHeaderInfo()\r
410 if self._SupArchList == None:\r
411 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No SUPPORTED_ARCHITECTURES", File=self.MetaFile)\r
412 return self._SupArchList\r
413\r
414 ## Retrieve BUILD_TARGETS\r
415 def _GetBuildTarget(self):\r
416 if self._BuildTargets == None:\r
417 if self._Header == None:\r
418 self._GetHeaderInfo()\r
419 if self._BuildTargets == None:\r
420 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BUILD_TARGETS", File=self.MetaFile)\r
421 return self._BuildTargets\r
422\r
423 def _GetPcdInfoFlag(self):\r
424 if self._PcdInfoFlag == None or self._PcdInfoFlag.upper() == 'FALSE':\r
425 return False\r
426 elif self._PcdInfoFlag.upper() == 'TRUE':\r
427 return True\r
428 else:\r
429 return False\r
430 def _GetVarCheckFlag(self):\r
431 if self._VarCheckFlag == None or self._VarCheckFlag.upper() == 'FALSE':\r
432 return False\r
433 elif self._VarCheckFlag.upper() == 'TRUE':\r
434 return True\r
435 else:\r
436 return False\r
437 def _GetAviableSkuIds(self):\r
438 if self._AvilableSkuIds:\r
439 return self._AvilableSkuIds\r
440 return self.SkuIdentifier\r
441 def _GetSkuIdentifier(self):\r
442 if self._SkuName:\r
443 return self._SkuName\r
444 if self._SkuIdentifier == None:\r
445 if self._Header == None:\r
446 self._GetHeaderInfo()\r
447 return self._SkuIdentifier\r
448 ## Retrieve SKUID_IDENTIFIER\r
449 def _GetSkuName(self):\r
450 if self._SkuName == None:\r
451 if self._Header == None:\r
452 self._GetHeaderInfo()\r
453 if (self._SkuName == None or self._SkuName not in self.SkuIds):\r
454 self._SkuName = 'DEFAULT'\r
455 return self._SkuName\r
456\r
457 ## Override SKUID_IDENTIFIER\r
458 def _SetSkuName(self, Value):\r
459 self._SkuName = Value\r
460 self._Pcds = None\r
461\r
462 def _GetFdfFile(self):\r
463 if self._FlashDefinition == None:\r
464 if self._Header == None:\r
465 self._GetHeaderInfo()\r
466 if self._FlashDefinition == None:\r
467 self._FlashDefinition = ''\r
468 return self._FlashDefinition\r
469\r
470 def _GetPrebuild(self):\r
471 if self._Prebuild == None:\r
472 if self._Header == None:\r
473 self._GetHeaderInfo()\r
474 if self._Prebuild == None:\r
475 self._Prebuild = ''\r
476 return self._Prebuild\r
477\r
478 def _GetPostbuild(self):\r
479 if self._Postbuild == None:\r
480 if self._Header == None:\r
481 self._GetHeaderInfo()\r
482 if self._Postbuild == None:\r
483 self._Postbuild = ''\r
484 return self._Postbuild\r
485\r
486 ## Retrieve FLASH_DEFINITION\r
487 def _GetBuildNumber(self):\r
488 if self._BuildNumber == None:\r
489 if self._Header == None:\r
490 self._GetHeaderInfo()\r
491 if self._BuildNumber == None:\r
492 self._BuildNumber = ''\r
493 return self._BuildNumber\r
494\r
495 ## Retrieve MAKEFILE_NAME\r
496 def _GetMakefileName(self):\r
497 if self._MakefileName == None:\r
498 if self._Header == None:\r
499 self._GetHeaderInfo()\r
500 if self._MakefileName == None:\r
501 self._MakefileName = ''\r
502 return self._MakefileName\r
503\r
504 ## Retrieve BsBaseAddress\r
505 def _GetBsBaseAddress(self):\r
506 if self._BsBaseAddress == None:\r
507 if self._Header == None:\r
508 self._GetHeaderInfo()\r
509 if self._BsBaseAddress == None:\r
510 self._BsBaseAddress = ''\r
511 return self._BsBaseAddress\r
512\r
513 ## Retrieve RtBaseAddress\r
514 def _GetRtBaseAddress(self):\r
515 if self._RtBaseAddress == None:\r
516 if self._Header == None:\r
517 self._GetHeaderInfo()\r
518 if self._RtBaseAddress == None:\r
519 self._RtBaseAddress = ''\r
520 return self._RtBaseAddress\r
521\r
522 ## Retrieve the top address for the load fix address\r
523 def _GetLoadFixAddress(self):\r
524 if self._LoadFixAddress == None:\r
525 if self._Header == None:\r
526 self._GetHeaderInfo()\r
527\r
528 if self._LoadFixAddress == None:\r
529 self._LoadFixAddress = self._Macros.get(TAB_FIX_LOAD_TOP_MEMORY_ADDRESS, '0')\r
530\r
531 try:\r
532 self._LoadFixAddress = int (self._LoadFixAddress, 0)\r
533 except:\r
534 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (self._LoadFixAddress))\r
535\r
536 #\r
537 # If command line defined, should override the value in DSC file.\r
538 #\r
539 if 'FIX_LOAD_TOP_MEMORY_ADDRESS' in GlobalData.gCommandLineDefines.keys():\r
540 try:\r
541 self._LoadFixAddress = int(GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS'], 0)\r
542 except:\r
543 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS %s is not valid dec or hex string" % (GlobalData.gCommandLineDefines['FIX_LOAD_TOP_MEMORY_ADDRESS']))\r
544\r
545 if self._LoadFixAddress < 0:\r
546 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid negative value 0x%x" % (self._LoadFixAddress))\r
547 if self._LoadFixAddress != 0xFFFFFFFFFFFFFFFF and self._LoadFixAddress % 0x1000 != 0:\r
548 EdkLogger.error("build", PARAMETER_INVALID, "FIX_LOAD_TOP_MEMORY_ADDRESS is set to the invalid unaligned 4K value 0x%x" % (self._LoadFixAddress))\r
549\r
550 return self._LoadFixAddress\r
551\r
552 ## Retrieve RFCLanguage filter\r
553 def _GetRFCLanguages(self):\r
554 if self._RFCLanguages == None:\r
555 if self._Header == None:\r
556 self._GetHeaderInfo()\r
557 if self._RFCLanguages == None:\r
558 self._RFCLanguages = []\r
559 return self._RFCLanguages\r
560\r
561 ## Retrieve ISOLanguage filter\r
562 def _GetISOLanguages(self):\r
563 if self._ISOLanguages == None:\r
564 if self._Header == None:\r
565 self._GetHeaderInfo()\r
566 if self._ISOLanguages == None:\r
567 self._ISOLanguages = []\r
568 return self._ISOLanguages\r
569 ## Retrieve the GUID string for VPD tool\r
570 def _GetVpdToolGuid(self):\r
571 if self._VpdToolGuid == None:\r
572 if self._Header == None:\r
573 self._GetHeaderInfo()\r
574 if self._VpdToolGuid == None:\r
575 self._VpdToolGuid = ''\r
576 return self._VpdToolGuid\r
577\r
578 ## Retrieve [SkuIds] section information\r
579 def _GetSkuIds(self):\r
580 if self._SkuIds == None:\r
581 self._SkuIds = sdict()\r
582 RecordList = self._RawData[MODEL_EFI_SKU_ID, self._Arch]\r
583 for Record in RecordList:\r
584 if Record[0] in [None, '']:\r
585 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',\r
586 File=self.MetaFile, Line=Record[-1])\r
587 if Record[1] in [None, '']:\r
588 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',\r
589 File=self.MetaFile, Line=Record[-1])\r
590 self._SkuIds[Record[1]] = Record[0]\r
591 if 'DEFAULT' not in self._SkuIds:\r
592 self._SkuIds['DEFAULT'] = '0'\r
593 if 'COMMON' not in self._SkuIds:\r
594 self._SkuIds['COMMON'] = '0'\r
595 return self._SkuIds\r
596\r
597 ## Retrieve [Components] section information\r
598 def _GetModules(self):\r
599 if self._Modules != None:\r
600 return self._Modules\r
601\r
602 self._Modules = sdict()\r
603 RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]\r
604 Macros = self._Macros\r
605 Macros["EDK_SOURCE"] = GlobalData.gEcpSource\r
606 for Record in RecordList:\r
607 DuplicatedFile = False\r
608\r
609 ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)\r
610 ModuleId = Record[5]\r
611 LineNo = Record[6]\r
612\r
613 # check the file validation\r
614 ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')\r
615 if ErrorCode != 0:\r
616 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,\r
617 ExtraData=ErrorInfo)\r
618 # Check duplication\r
619 # If arch is COMMON, no duplicate module is checked since all modules in all component sections are selected\r
620 if self._Arch != 'COMMON' and ModuleFile in self._Modules:\r
621 DuplicatedFile = True\r
622\r
623 Module = ModuleBuildClassObject()\r
624 Module.MetaFile = ModuleFile\r
625\r
626 # get module private library instance\r
627 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]\r
628 for Record in RecordList:\r
629 LibraryClass = Record[0]\r
630 LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)\r
631 LineNo = Record[-1]\r
632\r
633 # check the file validation\r
634 ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')\r
635 if ErrorCode != 0:\r
636 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,\r
637 ExtraData=ErrorInfo)\r
638\r
639 if LibraryClass == '' or LibraryClass == 'NULL':\r
640 self._NullLibraryNumber += 1\r
641 LibraryClass = 'NULL%d' % self._NullLibraryNumber\r
642 EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))\r
643 Module.LibraryClasses[LibraryClass] = LibraryPath\r
644 if LibraryPath not in self.LibraryInstances:\r
645 self.LibraryInstances.append(LibraryPath)\r
646\r
647 # get module private PCD setting\r
648 for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \\r
649 MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:\r
650 RecordList = self._RawData[Type, self._Arch, None, ModuleId]\r
651 for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:\r
652 TokenList = GetSplitValueList(Setting)\r
653 DefaultValue = TokenList[0]\r
654 if len(TokenList) > 1:\r
655 MaxDatumSize = TokenList[1]\r
656 else:\r
657 MaxDatumSize = ''\r
658 TypeString = self._PCD_TYPE_STRING_[Type]\r
659 Pcd = PcdClassObject(\r
660 PcdCName,\r
661 TokenSpaceGuid,\r
662 TypeString,\r
663 '',\r
664 DefaultValue,\r
665 '',\r
666 MaxDatumSize,\r
667 {},\r
668 False,\r
669 None\r
670 )\r
671 Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd\r
672\r
673 # get module private build options\r
674 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]\r
675 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:\r
676 if (ToolChainFamily, ToolChain) not in Module.BuildOptions:\r
677 Module.BuildOptions[ToolChainFamily, ToolChain] = Option\r
678 else:\r
679 OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]\r
680 Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option\r
681\r
682 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, None, ModuleId]\r
683 if DuplicatedFile and not RecordList:\r
684 EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)\r
685 if RecordList:\r
686 if len(RecordList) != 1:\r
687 EdkLogger.error('build', OPTION_UNKNOWN, 'Only FILE_GUID can be listed in <Defines> section.',\r
688 File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)\r
689 ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)\r
690 ModuleFile.Arch = self._Arch\r
691\r
692 self._Modules[ModuleFile] = Module\r
693 return self._Modules\r
694\r
695 ## Retrieve all possible library instances used in this platform\r
696 def _GetLibraryInstances(self):\r
697 if self._LibraryInstances == None:\r
698 self._GetLibraryClasses()\r
699 return self._LibraryInstances\r
700\r
701 ## Retrieve [LibraryClasses] information\r
702 def _GetLibraryClasses(self):\r
703 if self._LibraryClasses == None:\r
704 self._LibraryInstances = []\r
705 #\r
706 # tdict is a special dict kind of type, used for selecting correct\r
707 # library instance for given library class and module type\r
708 #\r
709 LibraryClassDict = tdict(True, 3)\r
710 # track all library class names\r
711 LibraryClassSet = set()\r
712 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, -1]\r
713 Macros = self._Macros\r
714 for Record in RecordList:\r
715 LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, LineNo = Record\r
716 if LibraryClass == '' or LibraryClass == 'NULL':\r
717 self._NullLibraryNumber += 1\r
718 LibraryClass = 'NULL%d' % self._NullLibraryNumber\r
719 EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))\r
720 LibraryClassSet.add(LibraryClass)\r
721 LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)\r
722 # check the file validation\r
723 ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')\r
724 if ErrorCode != 0:\r
725 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,\r
726 ExtraData=ErrorInfo)\r
727\r
728 if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST:\r
729 EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,\r
730 File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)\r
731 LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance\r
732 if LibraryInstance not in self._LibraryInstances:\r
733 self._LibraryInstances.append(LibraryInstance)\r
734\r
735 # resolve the specific library instance for each class and each module type\r
736 self._LibraryClasses = tdict(True)\r
737 for LibraryClass in LibraryClassSet:\r
738 # try all possible module types\r
739 for ModuleType in SUP_MODULE_LIST:\r
740 LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]\r
741 if LibraryInstance == None:\r
742 continue\r
743 self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance\r
744\r
745 # for Edk style library instances, which are listed in different section\r
746 Macros["EDK_SOURCE"] = GlobalData.gEcpSource\r
747 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]\r
748 for Record in RecordList:\r
749 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)\r
750 LineNo = Record[-1]\r
751 # check the file validation\r
752 ErrorCode, ErrorInfo = File.Validate('.inf')\r
753 if ErrorCode != 0:\r
754 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,\r
755 ExtraData=ErrorInfo)\r
756 if File not in self._LibraryInstances:\r
757 self._LibraryInstances.append(File)\r
758 #\r
759 # we need the module name as the library class name, so we have\r
760 # to parse it here. (self._Bdb[] will trigger a file parse if it\r
761 # hasn't been parsed)\r
762 #\r
763 Library = self._Bdb[File, self._Arch, self._Target, self._Toolchain]\r
764 self._LibraryClasses[Library.BaseName, ':dummy:'] = Library\r
765 return self._LibraryClasses\r
766\r
767 def _ValidatePcd(self, PcdCName, TokenSpaceGuid, Setting, PcdType, LineNo):\r
768 if self._DecPcds == None:\r
769 self._DecPcds = GetDeclaredPcd(self, self._Bdb, self._Arch, self._Target, self._Toolchain)\r
770 FdfInfList = []\r
771 if GlobalData.gFdfParser:\r
772 FdfInfList = GlobalData.gFdfParser.Profile.InfList\r
773\r
774 PkgSet = set()\r
775 for Inf in FdfInfList:\r
776 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch=self._Arch)\r
777 if ModuleFile in self._Modules:\r
778 continue\r
779 ModuleData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]\r
780 PkgSet.update(ModuleData.Packages)\r
781 DecPcds = {}\r
782 for Pkg in PkgSet:\r
783 for Pcd in Pkg.Pcds:\r
784 DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]\r
785 self._DecPcds.update(DecPcds)\r
786\r
787 if (PcdCName, TokenSpaceGuid) not in self._DecPcds and "." in TokenSpaceGuid and (TokenSpaceGuid.split(".")[1], TokenSpaceGuid.split(".")[0]) not in self._DecPcds:\r
788 EdkLogger.error('build', PARSER_ERROR,\r
789 "Pcd (%s.%s) defined in DSC is not declared in DEC files. Arch: ['%s']" % (TokenSpaceGuid, PcdCName, self._Arch),\r
790 File=self.MetaFile, Line=LineNo)\r
791 ValueList, IsValid, Index = AnalyzeDscPcd(Setting, PcdType, self._DecPcds[PcdCName, TokenSpaceGuid].DatumType)\r
792 if not IsValid and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
793 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self.MetaFile, Line=LineNo,\r
794 ExtraData="%s.%s|%s" % (TokenSpaceGuid, PcdCName, Setting))\r
795 if ValueList[Index] and PcdType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:\r
796 try:\r
797 ValueList[Index] = ValueExpression(ValueList[Index], GlobalData.gPlatformPcds)(True)\r
798 except WrnExpression, Value:\r
799 ValueList[Index] = Value.result\r
800 except EvaluationException, Excpt:\r
801 if hasattr(Excpt, 'Pcd'):\r
802 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
803 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"\r
804 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
805 " of the DSC file" % Excpt.Pcd,\r
806 File=self.MetaFile, Line=LineNo)\r
807 else:\r
808 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,\r
809 File=self.MetaFile, Line=LineNo)\r
810 else:\r
811 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),\r
812 File=self.MetaFile, Line=LineNo)\r
813 if ValueList[Index] == 'True':\r
814 ValueList[Index] = '1'\r
815 elif ValueList[Index] == 'False':\r
816 ValueList[Index] = '0'\r
817 if ValueList[Index]:\r
818 Valid, ErrStr = CheckPcdDatum(self._DecPcds[PcdCName, TokenSpaceGuid].DatumType, ValueList[Index])\r
819 if not Valid:\r
820 EdkLogger.error('build', FORMAT_INVALID, ErrStr, File=self.MetaFile, Line=LineNo,\r
821 ExtraData="%s.%s" % (TokenSpaceGuid, PcdCName))\r
822 return ValueList\r
823\r
824 ## Retrieve all PCD settings in platform\r
825 def _GetPcds(self):\r
826 if self._Pcds == None:\r
827 self._Pcds = sdict()\r
828 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))\r
829 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))\r
830 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))\r
831 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))\r
832 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))\r
833 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))\r
834 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))\r
835 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))\r
836 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))\r
837\r
838 self._Pcds = self.UpdateStructuredPcds(MODEL_PCD_TYPE_LIST, self._Pcds)\r
839 return self._Pcds\r
840\r
841 ## Retrieve [BuildOptions]\r
842 def _GetBuildOptions(self):\r
843 if self._BuildOptions == None:\r
844 self._BuildOptions = sdict()\r
845 #\r
846 # Retrieve build option for EDKII and EDK style module\r
847 #\r
848 for CodeBase in (EDKII_NAME, EDK_NAME):\r
849 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, CodeBase]\r
850 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:\r
851 CurKey = (ToolChainFamily, ToolChain, CodeBase)\r
852 #\r
853 # Only flags can be appended\r
854 #\r
855 if CurKey not in self._BuildOptions or not ToolChain.endswith('_FLAGS') or Option.startswith('='):\r
856 self._BuildOptions[CurKey] = Option\r
857 else:\r
858 self._BuildOptions[CurKey] += ' ' + Option\r
859 return self._BuildOptions\r
860\r
861 def GetBuildOptionsByModuleType(self, Edk, ModuleType):\r
862 if self._ModuleTypeOptions == None:\r
863 self._ModuleTypeOptions = sdict()\r
864 if (Edk, ModuleType) not in self._ModuleTypeOptions:\r
865 options = sdict()\r
866 self._ModuleTypeOptions[Edk, ModuleType] = options\r
867 DriverType = '%s.%s' % (Edk, ModuleType)\r
868 CommonDriverType = '%s.%s' % ('COMMON', ModuleType)\r
869 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, DriverType]\r
870 for ToolChainFamily, ToolChain, Option, Arch, Type, Dummy3, Dummy4 in RecordList:\r
871 if Type == DriverType or Type == CommonDriverType:\r
872 Key = (ToolChainFamily, ToolChain, Edk)\r
873 if Key not in options or not ToolChain.endswith('_FLAGS') or Option.startswith('='):\r
874 options[Key] = Option\r
875 else:\r
876 options[Key] += ' ' + Option\r
877 return self._ModuleTypeOptions[Edk, ModuleType]\r
878\r
879 def GetStructurePcdInfo(self, PcdSet):\r
880 structure_pcd_data = {}\r
881 for item in PcdSet:\r
882 if item[1] not in structure_pcd_data:\r
883 structure_pcd_data[item[1]] = []\r
884 structure_pcd_data[item[1]].append(item)\r
885\r
886 return structure_pcd_data\r
887\r
888 def UpdateStructuredPcds(self, TypeList, AllPcds):\r
889 Pcds = AllPcds\r
890 SkuObj = SkuClass(self.SkuIdentifier, self.SkuIds)\r
891\r
892 S_PcdSet = []\r
893 # Find out all possible PCD candidates for self._Arch\r
894 RecordList = []\r
895 for Type in TypeList:\r
896 RecordList.extend(self._RawData[Type, self._Arch])\r
897\r
898 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
899 SkuName = 'DEFAULT' if SkuName == 'COMMON' else SkuName\r
900 if SkuName in SkuObj.SkuIdSet and "." in TokenSpaceGuid:\r
901 S_PcdSet.append((PcdCName, TokenSpaceGuid, SkuName, Dummy4, AnalyzePcdExpression(Setting)[0]))\r
902\r
903 # handle pcd value override\r
904 StrPcdSet = self.GetStructurePcdInfo(S_PcdSet)\r
905 S_pcd_set = {}\r
906 for str_pcd in StrPcdSet:\r
907 str_pcd_obj = Pcds.get((str_pcd.split(".")[1], str_pcd.split(".")[0]), None)\r
908 str_pcd_dec = self._DecPcds.get((str_pcd.split(".")[1], str_pcd.split(".")[0]), None)\r
909 if str_pcd_dec:\r
910 str_pcd_obj_str = StructurePcd()\r
911 str_pcd_obj_str.copy(str_pcd_dec)\r
912 if str_pcd_obj:\r
913 str_pcd_obj_str.copy(str_pcd_obj)\r
914 if str_pcd_obj.DefaultValue:\r
915 str_pcd_obj_str.DefaultFromDSC = str_pcd_obj.DefaultValue\r
916 for str_pcd_data in StrPcdSet[str_pcd]:\r
917 if str_pcd_data[2] in SkuObj.SkuIdSet:\r
918 str_pcd_obj_str.AddOverrideValue(str_pcd_data[0], str(str_pcd_data[4]), 'DEFAULT' if str_pcd_data[2] == 'COMMON' else str_pcd_data[2],self.MetaFile.File,LineNo=str_pcd_data[3])\r
919 S_pcd_set[str_pcd.split(".")[1], str_pcd.split(".")[0]] = str_pcd_obj_str\r
920 # Add the Structure PCD that only defined in DEC, don't have override in DSC file\r
921 for Pcd in self._DecPcds:\r
922 if type (self._DecPcds[Pcd]) is StructurePcd:\r
923 if Pcd not in S_pcd_set:\r
924 str_pcd_obj_str = StructurePcd()\r
925 str_pcd_obj_str.copy(self._DecPcds[Pcd])\r
926 str_pcd_obj = Pcds.get(Pcd, None)\r
927 if str_pcd_obj:\r
928 str_pcd_obj_str.copy(str_pcd_obj)\r
929 if str_pcd_obj.DefaultValue:\r
930 str_pcd_obj_str.DefaultFromDSC = str_pcd_obj.DefaultValue\r
931 S_pcd_set[Pcd] = str_pcd_obj_str\r
932 if S_pcd_set:\r
933 GlobalData.gStructurePcd[self.Arch] = S_pcd_set\r
934 Str_Pcd_Values = self.GenerateByteArrayValue(S_pcd_set)\r
935 if Str_Pcd_Values:\r
936 for item in Str_Pcd_Values:\r
937 str_pcd_obj = S_pcd_set.get((item[2], item[1]))\r
938 if str_pcd_obj is None:\r
939 raise\r
940 if str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII],\r
941 self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]]:\r
942 if item[0] not in str_pcd_obj.SkuInfoList:\r
943 str_pcd_obj.SkuInfoList[item[0]] = SkuInfoClass(SkuIdName=item[0], SkuId=self.SkuIds[item[0]], HiiDefaultValue=item[3])\r
944 else:\r
945 str_pcd_obj.SkuInfoList[item[0]].HiiDefaultValue = item[3]\r
946 elif str_pcd_obj.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],\r
947 self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:\r
948 if item[0] in (SkuObj.SystemSkuId, 'DEFAULT', 'COMMON'):\r
949 str_pcd_obj.DefaultValue = item[3]\r
950 else:\r
951 if item[0] not in str_pcd_obj.SkuInfoList:\r
952 str_pcd_obj.SkuInfoList[item[0]] = SkuInfoClass(SkuIdName=item[0], SkuId=self.SkuIds[item[0]], DefaultValue=item[3])\r
953 else:\r
954 str_pcd_obj.SkuInfoList[item[0]].DefaultValue = item[3]\r
955\r
956 for str_pcd_obj in S_pcd_set.values():\r
957 str_pcd_obj.MaxDatumSize = self.GetStructurePcdMaxSize(str_pcd_obj)\r
958 Pcds[str_pcd_obj.TokenCName, str_pcd_obj.TokenSpaceGuidCName] = str_pcd_obj\r
959\r
960 return Pcds\r
961\r
962 ## Retrieve non-dynamic PCD settings\r
963 #\r
964 # @param Type PCD type\r
965 #\r
966 # @retval a dict object contains settings of given PCD type\r
967 #\r
968 def _GetPcd(self, Type):\r
969 Pcds = sdict()\r
970 #\r
971 # tdict is a special dict kind of type, used for selecting correct\r
972 # PCD settings for certain ARCH\r
973 #\r
974\r
975 SkuObj = SkuClass(self.SkuIdentifier, self.SkuIds)\r
976\r
977 PcdDict = tdict(True, 3)\r
978 PcdSet = set()\r
979 # Find out all possible PCD candidates for self._Arch\r
980 RecordList = self._RawData[Type, self._Arch]\r
981 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy()\r
982 AvailableSkuIdSet.update({'DEFAULT':0, 'COMMON':0})\r
983 PcdValueDict = sdict()\r
984 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
985 if SkuName not in AvailableSkuIdSet:\r
986 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The SKUID name %s is not supported by the platform." % SkuName)\r
987 if "." not in TokenSpaceGuid:\r
988 PcdSet.add((PcdCName, TokenSpaceGuid, SkuName, Dummy4))\r
989 PcdDict[Arch, PcdCName, TokenSpaceGuid, SkuName] = Setting\r
990 else:\r
991 TokenSpaceGuid, PcdCName = TokenSpaceGuid.split('.')\r
992 Flag = True\r
993 for PcdItem in RecordList:\r
994 if (TokenSpaceGuid, PcdCName) == (PcdItem[0], PcdItem[1]):\r
995 Flag = False\r
996 break\r
997 if Flag:\r
998 PcdSet.add((PcdCName, TokenSpaceGuid, SkuName, 0))\r
999 PcdDict[Arch, PcdCName, TokenSpaceGuid, SkuName] = ''\r
1000\r
1001 for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdSet:\r
1002 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid, SkuName]\r
1003 if Setting == None:\r
1004 continue\r
1005 PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)\r
1006 if (PcdCName, TokenSpaceGuid) in PcdValueDict:\r
1007 PcdValueDict[PcdCName, TokenSpaceGuid][SkuName] = (PcdValue, DatumType, MaxDatumSize)\r
1008 else:\r
1009 PcdValueDict[PcdCName, TokenSpaceGuid] = {SkuName:(PcdValue, DatumType, MaxDatumSize)}\r
1010\r
1011 PcdsKeys = PcdValueDict.keys()\r
1012 for PcdCName, TokenSpaceGuid in PcdsKeys:\r
1013\r
1014 PcdSetting = PcdValueDict[PcdCName, TokenSpaceGuid]\r
1015 PcdValue = None\r
1016 DatumType = None\r
1017 MaxDatumSize = None\r
1018 if 'COMMON' in PcdSetting:\r
1019 PcdValue, DatumType, MaxDatumSize = PcdSetting['COMMON']\r
1020 if 'DEFAULT' in PcdSetting:\r
1021 PcdValue, DatumType, MaxDatumSize = PcdSetting['DEFAULT']\r
1022 if SkuObj.SystemSkuId in PcdSetting:\r
1023 PcdValue, DatumType, MaxDatumSize = PcdSetting[SkuObj.SystemSkuId]\r
1024\r
1025 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
1026 PcdCName,\r
1027 TokenSpaceGuid,\r
1028 self._PCD_TYPE_STRING_[Type],\r
1029 DatumType,\r
1030 PcdValue,\r
1031 '',\r
1032 MaxDatumSize,\r
1033 {},\r
1034 False,\r
1035 None,\r
1036 IsDsc=True)\r
1037\r
1038\r
1039 return Pcds\r
1040\r
1041 def GetStructurePcdMaxSize(self, str_pcd):\r
1042 pcd_default_value = str_pcd.DefaultValue\r
1043 sku_values = [skuobj.HiiDefaultValue if str_pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_HII], self._PCD_TYPE_STRING_[MODEL_PCD_DYNAMIC_EX_HII]] else skuobj.DefaultValue for skuobj in str_pcd.SkuInfoList.values()]\r
1044 sku_values.append(pcd_default_value)\r
1045\r
1046 def get_length(value):\r
1047 Value = value.strip()\r
1048 if Value.startswith('GUID') and Value.endswith(')'):\r
1049 return 16\r
1050 if Value.startswith('L"') and Value.endswith('"'):\r
1051 return len(Value[2:-1])\r
1052 if Value[0] == '"' and Value[-1] == '"':\r
1053 return len(Value) - 2\r
1054 if Value[0] == '{' and Value[-1] == '}':\r
1055 return len(Value.split(","))\r
1056 if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:\r
1057 return len(list(Value[2:-1]))\r
1058 if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:\r
1059 return len(Value) - 2\r
1060 return len(Value)\r
1061\r
1062 return str(max([pcd_size for pcd_size in [get_length(item) for item in sku_values]]))\r
1063\r
1064 def IsFieldValueAnArray (self, Value):\r
1065 Value = Value.strip()\r
1066 if Value.startswith('GUID') and Value.endswith(')'):\r
1067 return True\r
1068 if Value.startswith('L"') and Value.endswith('"') and len(list(Value[2:-1])) > 1:\r
1069 return True\r
1070 if Value[0] == '"' and Value[-1] == '"' and len(list(Value[1:-1])) > 1:\r
1071 return True\r
1072 if Value[0] == '{' and Value[-1] == '}':\r
1073 return True\r
1074 if Value.startswith("L'") and Value.endswith("'") and len(list(Value[2:-1])) > 1:\r
1075 print 'foo = ', list(Value[2:-1])\r
1076 return True\r
1077 if Value[0] == "'" and Value[-1] == "'" and len(list(Value[1:-1])) > 1:\r
1078 print 'bar = ', list(Value[1:-1])\r
1079 return True\r
1080 return False\r
1081\r
1082 def ExecuteCommand (self, Command):\r
1083 try:\r
1084 Process = subprocess.Popen(Command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)\r
1085 except:\r
1086 print 'ERROR: Can not execute command:', Command\r
1087 sys.exit(1)\r
1088 Result = Process.communicate()\r
1089 if Process.returncode <> 0:\r
1090 print 'ERROR: Can not collect output from command:', Command\r
1091 return Result[0], Result[1]\r
1092\r
1093 def IntToCString(self, Value, ValueSize):\r
1094 Result = '"'\r
1095 if not isinstance (Value, str):\r
1096 for Index in range(0, ValueSize):\r
1097 Result = Result + '\\x%02x' % (Value & 0xff)\r
1098 Value = Value >> 8\r
1099 Result = Result + '"'\r
1100 return Result\r
1101\r
1102 def GenerateInitializeFunc(self, SkuName, DefaultStoreName, Pcd, InitByteValue, CApp):\r
1103 OverrideValues = None\r
1104 if Pcd.SkuOverrideValues:\r
1105 OverrideValues = Pcd.SkuOverrideValues[SkuName]\r
1106 CApp = CApp + 'void\n'\r
1107 CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
1108 CApp = CApp + ' void\n'\r
1109 CApp = CApp + ' )\n'\r
1110 CApp = CApp + '{\n'\r
1111 CApp = CApp + ' UINT32 Size;\n'\r
1112 CApp = CApp + ' UINT32 FieldSize;\n'\r
1113 CApp = CApp + ' UINT8 *Value;\n'\r
1114 CApp = CApp + ' UINT32 OriginalSize;\n'\r
1115 CApp = CApp + ' VOID *OriginalPcd;\n'\r
1116 CApp = CApp + ' %s *Pcd;\n' % (Pcd.DatumType)\r
1117 CApp = CApp + '\n'\r
1118 InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, Pcd.DefaultValue)\r
1119\r
1120 #\r
1121 # Get current PCD value and size\r
1122 #\r
1123 CApp = CApp + ' OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
1124\r
1125 #\r
1126 # Determine the size of the PCD. For simple structures, sizeof(TYPE) provides\r
1127 # the correct value. For structures with a flexible array member, the flexible\r
1128 # array member is detected, and the size is based on the highest index used with\r
1129 # the flexible array member. The flexible array member must be the last field\r
1130 # in a structure. The size formula for this case is:\r
1131 # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)\r
1132 #\r
1133 CApp = CApp + ' Size = sizeof(%s);\n' % (Pcd.DatumType)\r
1134 for FieldList in [Pcd.DefaultValues, OverrideValues]:\r
1135 if not FieldList:\r
1136 continue\r
1137 for FieldName in FieldList:\r
1138 FieldName = "." + FieldName\r
1139 IsArray = self.IsFieldValueAnArray(FieldList[FieldName.strip(".")][0])\r
1140 if IsArray:\r
1141 Value, ValueSize = ParseFieldValue (FieldList[FieldName.strip(".")][0])\r
1142 CApp = CApp + ' __FLEXIBLE_SIZE(Size, %s, %s, %d / __ARRAY_ELEMENT_SIZE(%s, %s) + ((%d %% __ARRAY_ELEMENT_SIZE(%s, %s)) ? 1 : 0));\n' % (Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."), ValueSize, Pcd.DatumType, FieldName.strip("."))\r
1143 else:\r
1144 NewFieldName = ''\r
1145 while '[' in FieldName:\r
1146 NewFieldName = NewFieldName + FieldName.split('[', 1)[0] + '[0]'\r
1147 ArrayIndex = int(FieldName.split('[', 1)[1].split(']', 1)[0])\r
1148 FieldName = FieldName.split(']', 1)[1]\r
1149 FieldName = NewFieldName + FieldName\r
1150 while '[' in FieldName:\r
1151 FieldName = FieldName.rsplit('[', 1)[0]\r
1152 CApp = CApp + ' __FLEXIBLE_SIZE(Size, %s, %s, %d);\n' % (Pcd.DatumType, FieldName.strip("."), ArrayIndex + 1)\r
1153\r
1154 #\r
1155 # Allocate and zero buffer for the PCD\r
1156 # Must handle cases where current value is smaller, larger, or same size\r
1157 # Always keep that larger one as the current size\r
1158 #\r
1159 CApp = CApp + ' Size = (OriginalSize > Size ? OriginalSize : Size);\n'\r
1160 CApp = CApp + ' Pcd = (%s *)malloc (Size);\n' % (Pcd.DatumType)\r
1161 CApp = CApp + ' memset (Pcd, 0, Size);\n'\r
1162\r
1163 #\r
1164 # Copy current PCD value into allocated buffer.\r
1165 #\r
1166 CApp = CApp + ' memcpy (Pcd, OriginalPcd, OriginalSize);\n'\r
1167 CApp = CApp + ' free (OriginalPcd);\n'\r
1168\r
1169 #\r
1170 # Assign field values in PCD\r
1171 #\r
1172 for FieldList in [Pcd.DefaultValues, Pcd.DefaultFromDSC, OverrideValues]:\r
1173 if not FieldList:\r
1174 continue\r
1175 if Pcd.DefaultFromDSC and FieldList == Pcd.DefaultFromDSC:\r
1176 IsArray = self.IsFieldValueAnArray(FieldList)\r
1177 Value, ValueSize = ParseFieldValue (FieldList)\r
1178 if isinstance(Value, str):\r
1179 CApp = CApp + ' Pcd = %s; // From DSC Default Value %s\n' % (Value, Pcd.DefaultFromDSC)\r
1180 elif IsArray:\r
1181 #\r
1182 # Use memcpy() to copy value into field\r
1183 #\r
1184 CApp = CApp + ' Value = %s; // From DSC Default Value %s\n' % (self.IntToCString(Value, ValueSize), Pcd.DefaultFromDSC)\r
1185 CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)\r
1186 continue\r
1187\r
1188 for FieldName in FieldList:\r
1189 IsArray = self.IsFieldValueAnArray(FieldList[FieldName][0])\r
1190 Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])\r
1191 if isinstance(Value, str):\r
1192 CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])\r
1193 elif IsArray:\r
1194 #\r
1195 # Use memcpy() to copy value into field\r
1196 #\r
1197 CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.DatumType, FieldName)\r
1198 CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (self.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])\r
1199 CApp = CApp + ' memcpy (&Pcd->%s[0], Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)\r
1200 else:\r
1201 if ValueSize > 4:\r
1202 CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])\r
1203 else:\r
1204 CApp = CApp + ' Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])\r
1205\r
1206 #\r
1207 # Set new PCD value and size\r
1208 #\r
1209 CApp = CApp + ' PcdSetPtr (%s, %s, %s, %s, Size, (UINT8 *)Pcd);\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
1210\r
1211 #\r
1212 # Free PCD\r
1213 #\r
1214 CApp = CApp + ' free (Pcd);\n'\r
1215 CApp = CApp + '}\n'\r
1216 CApp = CApp + '\n'\r
1217 return InitByteValue, CApp\r
1218\r
1219 def GenerateByteArrayValue (self, StructuredPcds):\r
1220 #\r
1221 # Generate/Compile/Run C application to determine if there are any flexible array members\r
1222 #\r
1223 if not StructuredPcds:\r
1224 return\r
1225\r
1226 InitByteValue = ""\r
1227 CApp = PcdMainCHeader\r
1228\r
1229 Includes = {}\r
1230 for PcdName in StructuredPcds:\r
1231 Pcd = StructuredPcds[PcdName]\r
1232 IncludeFile = Pcd.StructuredPcdIncludeFile\r
1233 if IncludeFile not in Includes:\r
1234 Includes[IncludeFile] = True\r
1235 CApp = CApp + '#include <%s>\n' % (IncludeFile)\r
1236 CApp = CApp + '\n'\r
1237\r
1238 for PcdName in StructuredPcds:\r
1239 Pcd = StructuredPcds[PcdName]\r
1240 if not Pcd.SkuOverrideValues:\r
1241 InitByteValue, CApp = self.GenerateInitializeFunc('DEFAULT', 'STANDARD', Pcd, InitByteValue, CApp)\r
1242 else:\r
1243 for SkuName in Pcd.SkuOverrideValues:\r
1244 for DefaultStoreName in Pcd.DefaultStoreName:\r
1245 Pcd = StructuredPcds[PcdName]\r
1246 InitByteValue, CApp = self.GenerateInitializeFunc(SkuName, DefaultStoreName, Pcd, InitByteValue, CApp)\r
1247\r
1248 CApp = CApp + 'VOID\n'\r
1249 CApp = CApp + 'PcdEntryPoint(\n'\r
1250 CApp = CApp + ' VOID\n'\r
1251 CApp = CApp + ' )\n'\r
1252 CApp = CApp + '{\n'\r
1253 for Pcd in StructuredPcds.values():\r
1254 if not Pcd.SkuOverrideValues:\r
1255 CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % ('DEFAULT', 'STANDARD', Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
1256 else:\r
1257 for SkuName in Pcd.SkuOverrideValues:\r
1258 for DefaultStoreName in Pcd.DefaultStoreName:\r
1259 CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (SkuName, DefaultStoreName, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)\r
1260 CApp = CApp + '}\n'\r
1261\r
1262 CApp = CApp + PcdMainCEntry + '\n'\r
1263\r
1264 if not os.path.exists(self.OutputPath):\r
1265 os.makedirs(self.OutputPath)\r
1266 CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)\r
1267 File = open (CAppBaseFileName + '.c', 'w')\r
1268 File.write(CApp)\r
1269 File.close()\r
1270\r
1271 MakeApp = PcdMakefileHeader\r
1272 if sys.platform == "win32":\r
1273 MakeApp = MakeApp + 'ARCH = IA32\nAPPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj\n' % (self.OutputPath, PcdValueInitName) + 'INC = '\r
1274 else:\r
1275 MakeApp = MakeApp + PcdGccMakefile\r
1276 MakeApp = MakeApp + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s/%s.o\n' % (self.OutputPath, PcdValueInitName) + \\r
1277 'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'BUILD_CFLAGS += -Wno-error\n' + 'INCLUDE +='\r
1278\r
1279 PlatformInc = {}\r
1280 for Cache in self._Bdb._CACHE_.values():\r
1281 if Cache.MetaFile.Ext.lower() != '.dec':\r
1282 continue\r
1283 if Cache.Includes:\r
1284 if str(Cache.MetaFile.Path) not in PlatformInc:\r
1285 PlatformInc[str(Cache.MetaFile.Path)] = Cache.Includes\r
1286\r
1287 PcdDependDEC = []\r
1288 for Pcd in StructuredPcds.values():\r
1289 for PackageDec in Pcd.PackageDecs:\r
1290 Package = os.path.normpath(mws.join(GlobalData.gWorkspace, PackageDec))\r
1291 if not os.path.exists(Package):\r
1292 EdkLogger.error('Build', RESOURCE_NOT_AVAILABLE, "The dependent Package %s of PCD %s.%s is not exist." % (PackageDec, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1293 if Package not in PcdDependDEC:\r
1294 PcdDependDEC.append(Package)\r
1295\r
1296 if PlatformInc and PcdDependDEC:\r
1297 for pkg in PcdDependDEC:\r
1298 if pkg in PlatformInc:\r
1299 for inc in PlatformInc[pkg]:\r
1300 MakeApp += '-I' + str(inc) + ' '\r
1301 MakeApp = MakeApp + '\n'\r
1302 if sys.platform == "win32":\r
1303 MakeApp = MakeApp + PcdMakefileEnd\r
1304 MakeFileName = os.path.join(self.OutputPath, 'Makefile')\r
1305 File = open (MakeFileName, 'w')\r
1306 File.write(MakeApp)\r
1307 File.close()\r
1308\r
1309 InputValueFile = os.path.join(self.OutputPath, 'Input.txt')\r
1310 OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')\r
1311 File = open (InputValueFile, 'w')\r
1312 File.write(InitByteValue)\r
1313 File.close()\r
1314\r
1315 if sys.platform == "win32":\r
1316 StdOut, StdErr = self.ExecuteCommand ('nmake clean & nmake -f %s' % (MakeFileName))\r
1317 else:\r
1318 StdOut, StdErr = self.ExecuteCommand ('make clean & make -f %s' % (MakeFileName))\r
1319 Messages = StdOut.split('\r')\r
1320 for Message in Messages:\r
1321 if " error " in Message:\r
1322 FileInfo = Message.strip().split('(')\r
1323 if len (FileInfo) > 0:\r
1324 FileName = FileInfo [0]\r
1325 FileLine = FileInfo [1].split (')')[0]\r
1326 else:\r
1327 FileInfo = Message.strip().split(':')\r
1328 FileName = FileInfo [0]\r
1329 FileLine = FileInfo [1]\r
1330\r
1331 File = open (FileName, 'r')\r
1332 FileData = File.readlines()\r
1333 File.close()\r
1334 error_line = FileData[int (FileLine) - 1]\r
1335 if r"//" in error_line:\r
1336 c_line,dsc_line = error_line.split(r"//")\r
1337 else:\r
1338 dsc_line = error_line\r
1339\r
1340 message_itmes = Message.split(":")\r
1341 for item in message_itmes:\r
1342 if "PcdValueInit.c" in item:\r
1343 message_itmes[message_itmes.index(item)] = dsc_line.strip()\r
1344\r
1345 EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, ":".join(message_itmes[1:]))\r
1346\r
1347 PcdValueInitExe = PcdValueInitName\r
1348 if not sys.platform == "win32":\r
1349 PcdValueInitExe = os.path.join(os.getenv("EDK_TOOLS_PATH"), 'Source', 'C', 'bin', PcdValueInitName)\r
1350\r
1351 StdOut, StdErr = self.ExecuteCommand (PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile))\r
1352 File = open (OutputValueFile, 'r')\r
1353 FileBuffer = File.readlines()\r
1354 File.close()\r
1355\r
1356 StructurePcdSet = []\r
1357 for Pcd in FileBuffer:\r
1358 PcdValue = Pcd.split ('|')\r
1359 PcdInfo = PcdValue[0].split ('.')\r
1360 StructurePcdSet.append((PcdInfo[0], PcdInfo[2], PcdInfo[3], PcdValue[2].strip()))\r
1361 return StructurePcdSet\r
1362\r
1363 ## Retrieve dynamic PCD settings\r
1364 #\r
1365 # @param Type PCD type\r
1366 #\r
1367 # @retval a dict object contains settings of given PCD type\r
1368 #\r
1369 def _GetDynamicPcd(self, Type):\r
1370\r
1371 SkuObj = SkuClass(self.SkuIdentifier, self.SkuIds)\r
1372\r
1373 Pcds = sdict()\r
1374 #\r
1375 # tdict is a special dict kind of type, used for selecting correct\r
1376 # PCD settings for certain ARCH and SKU\r
1377 #\r
1378 PcdDict = tdict(True, 4)\r
1379 PcdList = []\r
1380 # Find out all possible PCD candidates for self._Arch\r
1381 RecordList = self._RawData[Type, self._Arch]\r
1382 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy()\r
1383\r
1384 AvailableSkuIdSet.update({'DEFAULT':0, 'COMMON':0})\r
1385\r
1386 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
1387 if SkuName not in AvailableSkuIdSet:\r
1388 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The SKUID name %s is not supported by the platform." % SkuName)\r
1389 if "." not in TokenSpaceGuid:\r
1390 PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy4))\r
1391 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting\r
1392\r
1393 # Remove redundant PCD candidates, per the ARCH and SKU\r
1394 for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:\r
1395\r
1396 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]\r
1397 if Setting == None:\r
1398 continue\r
1399\r
1400 PcdValue, DatumType, MaxDatumSize = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)\r
1401 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], '', '', '', '', '', PcdValue)\r
1402 if (PcdCName, TokenSpaceGuid) in Pcds.keys():\r
1403 pcdObject = Pcds[PcdCName, TokenSpaceGuid]\r
1404 pcdObject.SkuInfoList[SkuName] = SkuInfo\r
1405 if MaxDatumSize.strip():\r
1406 CurrentMaxSize = int(MaxDatumSize.strip(), 0)\r
1407 else:\r
1408 CurrentMaxSize = 0\r
1409 if pcdObject.MaxDatumSize:\r
1410 PcdMaxSize = int(pcdObject.MaxDatumSize, 0)\r
1411 else:\r
1412 PcdMaxSize = 0\r
1413 if CurrentMaxSize > PcdMaxSize:\r
1414 pcdObject.MaxDatumSize = str(CurrentMaxSize)\r
1415 else:\r
1416 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
1417 PcdCName,\r
1418 TokenSpaceGuid,\r
1419 self._PCD_TYPE_STRING_[Type],\r
1420 DatumType,\r
1421 PcdValue,\r
1422 '',\r
1423 MaxDatumSize,\r
1424 {SkuName : SkuInfo},\r
1425 False,\r
1426 None,\r
1427 IsDsc=True)\r
1428\r
1429 for pcd in Pcds.values():\r
1430 pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]\r
1431 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():\r
1432 valuefromDec = pcdDecObject.DefaultValue\r
1433 SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', '', valuefromDec)\r
1434 pcd.SkuInfoList['DEFAULT'] = SkuInfo\r
1435 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():\r
1436 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']\r
1437 del(pcd.SkuInfoList['COMMON'])\r
1438 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():\r
1439 del(pcd.SkuInfoList['COMMON'])\r
1440 if SkuObj.SkuUsageType == SkuObj.SINGLE:\r
1441 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys():\r
1442 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT']\r
1443 del(pcd.SkuInfoList['DEFAULT'])\r
1444\r
1445 return Pcds\r
1446\r
1447 def CompareVarAttr(self, Attr1, Attr2):\r
1448 if not Attr1 or not Attr2: # for empty string\r
1449 return True\r
1450 Attr1s = [attr.strip() for attr in Attr1.split(",")]\r
1451 Attr1Set = set(Attr1s)\r
1452 Attr2s = [attr.strip() for attr in Attr2.split(",")]\r
1453 Attr2Set = set(Attr2s)\r
1454 if Attr2Set == Attr1Set:\r
1455 return True\r
1456 else:\r
1457 return False\r
1458 ## Retrieve dynamic HII PCD settings\r
1459 #\r
1460 # @param Type PCD type\r
1461 #\r
1462 # @retval a dict object contains settings of given PCD type\r
1463 #\r
1464 def _GetDynamicHiiPcd(self, Type):\r
1465\r
1466 SkuObj = SkuClass(self.SkuIdentifier, self.SkuIds)\r
1467 VariableAttrs = {}\r
1468\r
1469 Pcds = sdict()\r
1470 #\r
1471 # tdict is a special dict kind of type, used for selecting correct\r
1472 # PCD settings for certain ARCH and SKU\r
1473 #\r
1474 PcdDict = tdict(True, 4)\r
1475 PcdSet = set()\r
1476 RecordList = self._RawData[Type, self._Arch]\r
1477 # Find out all possible PCD candidates for self._Arch\r
1478 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy()\r
1479\r
1480 AvailableSkuIdSet.update({'DEFAULT':0, 'COMMON':0})\r
1481 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
1482 if SkuName not in AvailableSkuIdSet:\r
1483 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The SKUID name %s is not supported by the platform." % SkuName)\r
1484 if "." not in TokenSpaceGuid:\r
1485 PcdSet.add((PcdCName, TokenSpaceGuid, SkuName, Dummy4))\r
1486 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting\r
1487\r
1488\r
1489 # Remove redundant PCD candidates, per the ARCH and SKU\r
1490 for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdSet:\r
1491\r
1492 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]\r
1493 if Setting == None:\r
1494 continue\r
1495 VariableName, VariableGuid, VariableOffset, DefaultValue, VarAttribute = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)\r
1496\r
1497 rt, Msg = VariableAttributes.ValidateVarAttributes(VarAttribute)\r
1498 if not rt:\r
1499 EdkLogger.error("build", PCD_VARIABLE_ATTRIBUTES_ERROR, "Variable attributes settings for %s is incorrect.\n %s" % (".".join((TokenSpaceGuid, PcdCName)), Msg),\r
1500 ExtraData="[%s]" % VarAttribute)\r
1501 ExceedMax = False\r
1502 FormatCorrect = True\r
1503 if VariableOffset.isdigit():\r
1504 if int(VariableOffset, 10) > 0xFFFF:\r
1505 ExceedMax = True\r
1506 elif re.match(r'[\t\s]*0[xX][a-fA-F0-9]+$', VariableOffset):\r
1507 if int(VariableOffset, 16) > 0xFFFF:\r
1508 ExceedMax = True\r
1509 # For Offset written in "A.B"\r
1510 elif VariableOffset.find('.') > -1:\r
1511 VariableOffsetList = VariableOffset.split(".")\r
1512 if not (len(VariableOffsetList) == 2\r
1513 and IsValidWord(VariableOffsetList[0])\r
1514 and IsValidWord(VariableOffsetList[1])):\r
1515 FormatCorrect = False\r
1516 else:\r
1517 FormatCorrect = False\r
1518 if not FormatCorrect:\r
1519 EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid, PcdCName)))\r
1520\r
1521 if ExceedMax:\r
1522 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid, PcdCName)))\r
1523 if (VariableName, VariableGuid) not in VariableAttrs:\r
1524 VariableAttrs[(VariableName, VariableGuid)] = VarAttribute\r
1525 else:\r
1526 if not self.CompareVarAttr(VariableAttrs[(VariableName, VariableGuid)], VarAttribute):\r
1527 EdkLogger.error('Build', PCD_VARIABLE_ATTRIBUTES_CONFLICT_ERROR, "The variable %s.%s for DynamicHii PCDs has conflicting attributes [%s] and [%s] " % (VariableGuid, VariableName, VarAttribute, VariableAttrs[(VariableName, VariableGuid)]))\r
1528\r
1529 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue, VariableAttribute=VarAttribute)\r
1530 pcdDecObject = self._DecPcds[PcdCName, TokenSpaceGuid]\r
1531 if (PcdCName, TokenSpaceGuid) in Pcds.keys():\r
1532 pcdObject = Pcds[PcdCName, TokenSpaceGuid]\r
1533 pcdObject.SkuInfoList[SkuName] = SkuInfo\r
1534 else:\r
1535 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
1536 PcdCName,\r
1537 TokenSpaceGuid,\r
1538 self._PCD_TYPE_STRING_[Type],\r
1539 '',\r
1540 DefaultValue,\r
1541 '',\r
1542 '',\r
1543 {SkuName : SkuInfo},\r
1544 False,\r
1545 None,\r
1546 pcdDecObject.validateranges,\r
1547 pcdDecObject.validlists,\r
1548 pcdDecObject.expressions,\r
1549 IsDsc=True)\r
1550\r
1551\r
1552 for pcd in Pcds.values():\r
1553 SkuInfoObj = pcd.SkuInfoList.values()[0]\r
1554 pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]\r
1555 # Only fix the value while no value provided in DSC file.\r
1556 for sku in pcd.SkuInfoList.values():\r
1557 if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue == None):\r
1558 sku.HiiDefaultValue = pcdDecObject.DefaultValue\r
1559 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():\r
1560 valuefromDec = pcdDecObject.DefaultValue\r
1561 SkuInfo = SkuInfoClass('DEFAULT', '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec)\r
1562 pcd.SkuInfoList['DEFAULT'] = SkuInfo\r
1563 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():\r
1564 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']\r
1565 del(pcd.SkuInfoList['COMMON'])\r
1566 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():\r
1567 del(pcd.SkuInfoList['COMMON'])\r
1568\r
1569 if SkuObj.SkuUsageType == SkuObj.SINGLE:\r
1570 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys():\r
1571 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT']\r
1572 del(pcd.SkuInfoList['DEFAULT'])\r
1573\r
1574 if pcd.MaxDatumSize.strip():\r
1575 MaxSize = int(pcd.MaxDatumSize, 0)\r
1576 else:\r
1577 MaxSize = 0\r
1578 if pcdDecObject.DatumType == 'VOID*':\r
1579 for (skuname, skuobj) in pcd.SkuInfoList.items():\r
1580 datalen = 0\r
1581 if skuobj.HiiDefaultValue.startswith("L"):\r
1582 datalen = (len(skuobj.HiiDefaultValue) - 3 + 1) * 2\r
1583 elif skuobj.HiiDefaultValue.startswith("{"):\r
1584 datalen = len(skuobj.HiiDefaultValue.split(","))\r
1585 else:\r
1586 datalen = len(skuobj.HiiDefaultValue) - 2 + 1\r
1587 if datalen > MaxSize:\r
1588 MaxSize = datalen\r
1589 pcd.MaxDatumSize = str(MaxSize)\r
1590 return Pcds\r
1591\r
1592\r
1593 ## Retrieve dynamic VPD PCD settings\r
1594 #\r
1595 # @param Type PCD type\r
1596 #\r
1597 # @retval a dict object contains settings of given PCD type\r
1598 #\r
1599 def _GetDynamicVpdPcd(self, Type):\r
1600\r
1601 SkuObj = SkuClass(self.SkuIdentifier, self.SkuIds)\r
1602\r
1603 Pcds = sdict()\r
1604 #\r
1605 # tdict is a special dict kind of type, used for selecting correct\r
1606 # PCD settings for certain ARCH and SKU\r
1607 #\r
1608 PcdDict = tdict(True, 4)\r
1609 PcdList = []\r
1610\r
1611 # Find out all possible PCD candidates for self._Arch\r
1612 RecordList = self._RawData[Type, self._Arch]\r
1613 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy()\r
1614\r
1615 AvailableSkuIdSet.update({'DEFAULT':0, 'COMMON':0})\r
1616 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:\r
1617 if SkuName not in AvailableSkuIdSet:\r
1618 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The SKUID name %s is not supported by the platform." % SkuName)\r
1619 if "." not in TokenSpaceGuid:\r
1620 PcdList.append((PcdCName, TokenSpaceGuid, SkuName, Dummy4))\r
1621 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting\r
1622\r
1623 # Remove redundant PCD candidates, per the ARCH and SKU\r
1624 for PcdCName, TokenSpaceGuid, SkuName, Dummy4 in PcdList:\r
1625 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]\r
1626 if Setting == None:\r
1627 continue\r
1628 #\r
1629 # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue\r
1630 # For the Integer & Boolean type, the optional data can only be InitialValue.\r
1631 # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype\r
1632 # until the DEC parser has been called.\r
1633 #\r
1634 VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)\r
1635 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], '', '', '', '', VpdOffset, InitialValue)\r
1636 if (PcdCName, TokenSpaceGuid) in Pcds.keys():\r
1637 pcdObject = Pcds[PcdCName, TokenSpaceGuid]\r
1638 pcdObject.SkuInfoList[SkuName] = SkuInfo\r
1639 if MaxDatumSize.strip():\r
1640 CurrentMaxSize = int(MaxDatumSize.strip(), 0)\r
1641 else:\r
1642 CurrentMaxSize = 0\r
1643 if pcdObject.MaxDatumSize:\r
1644 PcdMaxSize = int(pcdObject.MaxDatumSize, 0)\r
1645 else:\r
1646 PcdMaxSize = 0\r
1647 if CurrentMaxSize > PcdMaxSize:\r
1648 pcdObject.MaxDatumSize = str(CurrentMaxSize)\r
1649 else:\r
1650 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(\r
1651 PcdCName,\r
1652 TokenSpaceGuid,\r
1653 self._PCD_TYPE_STRING_[Type],\r
1654 '',\r
1655 InitialValue,\r
1656 '',\r
1657 MaxDatumSize,\r
1658 {SkuName : SkuInfo},\r
1659 False,\r
1660 None,\r
1661 IsDsc=True)\r
1662 for pcd in Pcds.values():\r
1663 SkuInfoObj = pcd.SkuInfoList.values()[0]\r
1664 pcdDecObject = self._DecPcds[pcd.TokenCName, pcd.TokenSpaceGuidCName]\r
1665 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():\r
1666 valuefromDec = pcdDecObject.DefaultValue\r
1667 SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '', '', SkuInfoObj.VpdOffset, valuefromDec)\r
1668 pcd.SkuInfoList['DEFAULT'] = SkuInfo\r
1669 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():\r
1670 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']\r
1671 del(pcd.SkuInfoList['COMMON'])\r
1672 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():\r
1673 del(pcd.SkuInfoList['COMMON'])\r
1674 if SkuObj.SkuUsageType == SkuObj.SINGLE:\r
1675 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys():\r
1676 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT']\r
1677 del(pcd.SkuInfoList['DEFAULT'])\r
1678\r
1679 return Pcds\r
1680\r
1681 ## Add external modules\r
1682 #\r
1683 # The external modules are mostly those listed in FDF file, which don't\r
1684 # need "build".\r
1685 #\r
1686 # @param FilePath The path of module description file\r
1687 #\r
1688 def AddModule(self, FilePath):\r
1689 FilePath = NormPath(FilePath)\r
1690 if FilePath not in self.Modules:\r
1691 Module = ModuleBuildClassObject()\r
1692 Module.MetaFile = FilePath\r
1693 self.Modules.append(Module)\r
1694\r
1695 ## Add external PCDs\r
1696 #\r
1697 # The external PCDs are mostly those listed in FDF file to specify address\r
1698 # or offset information.\r
1699 #\r
1700 # @param Name Name of the PCD\r
1701 # @param Guid Token space guid of the PCD\r
1702 # @param Value Value of the PCD\r
1703 #\r
1704 def AddPcd(self, Name, Guid, Value):\r
1705 if (Name, Guid) not in self.Pcds:\r
1706 self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)\r
1707 self.Pcds[Name, Guid].DefaultValue = Value\r
1708\r
1709 _Macros = property(_GetMacros)\r
1710 Arch = property(_GetArch, _SetArch)\r
1711 Platform = property(_GetPlatformName)\r
1712 PlatformName = property(_GetPlatformName)\r
1713 Guid = property(_GetFileGuid)\r
1714 Version = property(_GetVersion)\r
1715 DscSpecification = property(_GetDscSpec)\r
1716 OutputDirectory = property(_GetOutpuDir)\r
1717 SupArchList = property(_GetSupArch)\r
1718 BuildTargets = property(_GetBuildTarget)\r
1719 SkuName = property(_GetSkuName, _SetSkuName)\r
1720 SkuIdentifier = property(_GetSkuIdentifier)\r
1721 AvilableSkuIds = property(_GetAviableSkuIds)\r
1722 PcdInfoFlag = property(_GetPcdInfoFlag)\r
1723 VarCheckFlag = property(_GetVarCheckFlag)\r
1724 FlashDefinition = property(_GetFdfFile)\r
1725 Prebuild = property(_GetPrebuild)\r
1726 Postbuild = property(_GetPostbuild)\r
1727 BuildNumber = property(_GetBuildNumber)\r
1728 MakefileName = property(_GetMakefileName)\r
1729 BsBaseAddress = property(_GetBsBaseAddress)\r
1730 RtBaseAddress = property(_GetRtBaseAddress)\r
1731 LoadFixAddress = property(_GetLoadFixAddress)\r
1732 RFCLanguages = property(_GetRFCLanguages)\r
1733 ISOLanguages = property(_GetISOLanguages)\r
1734 VpdToolGuid = property(_GetVpdToolGuid)\r
1735 SkuIds = property(_GetSkuIds)\r
1736 Modules = property(_GetModules)\r
1737 LibraryInstances = property(_GetLibraryInstances)\r
1738 LibraryClasses = property(_GetLibraryClasses)\r
1739 Pcds = property(_GetPcds)\r
1740 BuildOptions = property(_GetBuildOptions)\r