BaseTools: refactor to remove functions
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
CommitLineData
52302d4d
LG
1## @file\r
2# Generate AutoGen.h, AutoGen.c and *.depex files\r
3#\r
e74cea4c 4# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
3f34e36d
LD
5# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
6#\r
40d841f6 7# This program and the accompanying materials\r
52302d4d
LG
8# are licensed and made available under the terms and conditions of the BSD License\r
9# which accompanies this distribution. The full text of the license may be found at\r
10# http://opensource.org/licenses/bsd-license.php\r
11#\r
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14#\r
15\r
16## Import Modules\r
17#\r
1be2ed90 18import Common.LongFilePathOs as os\r
52302d4d
LG
19import re\r
20import os.path as path\r
21import copy\r
867d1cd4 22import uuid\r
52302d4d
LG
23\r
24import GenC\r
25import GenMake\r
26import GenDepex\r
27from StringIO import StringIO\r
28\r
29from StrGather import *\r
30from BuildEngine import BuildRule\r
31\r
1be2ed90 32from Common.LongFilePathSupport import CopyLongFilePath\r
52302d4d
LG
33from Common.BuildToolError import *\r
34from Common.DataType import *\r
35from Common.Misc import *\r
5a57246e 36from Common.StringUtils import *\r
52302d4d
LG
37import Common.GlobalData as GlobalData\r
38from GenFds.FdfParser import *\r
39from CommonDataClass.CommonClass import SkuInfoClass\r
40from Workspace.BuildClassObject import *\r
e8a47801 41from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile\r
e56468c0 42import Common.VpdInfoFile as VpdInfoFile\r
e8a47801
LG
43from GenPcdDb import CreatePcdDatabaseCode\r
44from Workspace.MetaFileCommentParser import UsageList\r
c14b5861 45from Workspace.WorkspaceCommon import GetModuleLibInstances\r
05cc51ad 46from Common.MultipleWorkspace import MultipleWorkspace as mws\r
97fa0ee9 47import InfSectionParser\r
c17956e0 48import datetime\r
36d083ef 49import hashlib\r
8518bf0b 50from GenVar import VariableMgr,var_info\r
9006a2c6 51from collections import OrderedDict\r
a993dc03 52from collections import defaultdict\r
97fa0ee9 53\r
e8a47801 54## Regular expression for splitting Dependency Expression string into tokens\r
52302d4d
LG
55gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
56\r
c8802c3d
CJ
57## Regular expression for match: PCD(xxxx.yyy)\r
58gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")\r
59\r
60#\r
61# Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
62# is the former use /I , the Latter used -I to specify include directories\r
63#\r
64gBuildOptIncludePatternMsft = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
65gBuildOptIncludePatternOther = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
66\r
97fa0ee9
YL
67#\r
68# Match name = variable\r
69#\r
70gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")\r
71#\r
72# The format of guid in efivarstore statement likes following and must be correct:\r
73# guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}\r
74#\r
75gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")\r
76\r
52302d4d
LG
77## Mapping Makefile type\r
78gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}\r
79\r
80\r
81## Build rule configuration file\r
51de5c30 82gDefaultBuildRuleFile = 'build_rule.txt'\r
52302d4d 83\r
86601b78 84## Tools definition configuration file\r
51de5c30 85gDefaultToolsDefFile = 'tools_def.txt'\r
86601b78 86\r
64b2609f
LG
87## Build rule default version\r
88AutoGenReqBuildRuleVerNum = "0.1"\r
89\r
52302d4d
LG
90## default file name for AutoGen\r
91gAutoGenCodeFileName = "AutoGen.c"\r
92gAutoGenHeaderFileName = "AutoGen.h"\r
93gAutoGenStringFileName = "%(module_name)sStrDefs.h"\r
94gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"\r
95gAutoGenDepexFileName = "%(module_name)s.depex"\r
333ba578
YZ
96gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"\r
97gAutoGenIdfFileName = "%(module_name)sIdf.hpk"\r
97fa0ee9
YL
98gInfSpecVersion = "0x00010017"\r
99\r
da92f276
LG
100#\r
101# Template string to generic AsBuilt INF\r
102#\r
e8a47801 103gAsBuiltInfHeaderString = TemplateString("""${header_comments}\r
da92f276 104\r
97fa0ee9
YL
105# DO NOT EDIT\r
106# FILE auto-generated\r
107\r
da92f276 108[Defines]\r
97fa0ee9 109 INF_VERSION = ${module_inf_version}\r
da92f276
LG
110 BASE_NAME = ${module_name}\r
111 FILE_GUID = ${module_guid}\r
97fa0ee9
YL
112 MODULE_TYPE = ${module_module_type}${BEGIN}\r
113 VERSION_STRING = ${module_version_string}${END}${BEGIN}\r
e8a47801 114 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}\r
da92f276 115 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}\r
97fa0ee9
YL
116 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}\r
117 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}\r
118 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}\r
119 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}\r
120 DESTRUCTOR = ${module_destructor}${END}${BEGIN}\r
121 SHADOW = ${module_shadow}${END}${BEGIN}\r
122 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}\r
123 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}\r
124 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}\r
125 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}\r
126 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}\r
127 SPEC = ${module_spec}${END}${BEGIN}\r
128 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}\r
129 MODULE_UNI_FILE = ${module_uni_file}${END}\r
130\r
131[Packages.${module_arch}]${BEGIN}\r
da92f276
LG
132 ${package_item}${END}\r
133\r
134[Binaries.${module_arch}]${BEGIN}\r
135 ${binary_item}${END}\r
136\r
e8a47801
LG
137[PatchPcd.${module_arch}]${BEGIN}\r
138 ${patchablepcd_item}\r
139${END}\r
97fa0ee9 140\r
e8a47801
LG
141[Protocols.${module_arch}]${BEGIN}\r
142 ${protocol_item}\r
143${END}\r
97fa0ee9 144\r
e8a47801
LG
145[Ppis.${module_arch}]${BEGIN}\r
146 ${ppi_item}\r
147${END}\r
97fa0ee9 148\r
e8a47801
LG
149[Guids.${module_arch}]${BEGIN}\r
150 ${guid_item}\r
151${END}\r
97fa0ee9 152\r
e8a47801
LG
153[PcdEx.${module_arch}]${BEGIN}\r
154 ${pcd_item}\r
155${END}\r
da92f276 156\r
97fa0ee9
YL
157[LibraryClasses.${module_arch}]\r
158## @LIB_INSTANCES${BEGIN}\r
159# ${libraryclasses_item}${END}\r
160\r
161${depexsection_item}\r
162\r
dfa41b4a
YZ
163${userextension_tianocore_item}\r
164\r
97fa0ee9
YL
165${tail_comments}\r
166\r
167[BuildOptions.${module_arch}]\r
da92f276
LG
168## @AsBuilt${BEGIN}\r
169## ${flags_item}${END}\r
170""")\r
171\r
52302d4d
LG
172## Base class for AutoGen\r
173#\r
174# This class just implements the cache mechanism of AutoGen objects.\r
175#\r
176class AutoGen(object):\r
b24e99f7
CJ
177 # database to maintain the objects in each child class\r
178 __ObjectCache = {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object\r
52302d4d
LG
179\r
180 ## Factory method\r
181 #\r
182 # @param Class class object of real AutoGen class\r
183 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)\r
184 # @param Workspace Workspace directory or WorkspaceAutoGen object\r
185 # @param MetaFile The path of meta file\r
186 # @param Target Build target\r
187 # @param Toolchain Tool chain name\r
188 # @param Arch Target arch\r
189 # @param *args The specific class related parameters\r
190 # @param **kwargs The specific class related dict parameters\r
191 #\r
b24e99f7 192 def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
52302d4d 193 # check if the object has been created\r
b24e99f7
CJ
194 Key = (Target, Toolchain, Arch, MetaFile)\r
195 try:\r
196 # if it exists, just return it directly\r
197 return cls.__ObjectCache[Key]\r
198 except:\r
199 # it didnt exist. create it, cache it, then return it\r
200 cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls)\r
201 return cls.__ObjectCache[Key]\r
202\r
203 def __init__ (self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
204 super(AutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
52302d4d
LG
205\r
206 ## hash() operator\r
207 #\r
208 # The file path of platform file will be used to represent hash value of this object\r
209 #\r
210 # @retval int Hash value of the file path of platform file\r
211 #\r
212 def __hash__(self):\r
213 return hash(self.MetaFile)\r
214\r
215 ## str() operator\r
216 #\r
217 # The file path of platform file will be used to represent this object\r
218 #\r
219 # @retval string String of platform file path\r
220 #\r
221 def __str__(self):\r
222 return str(self.MetaFile)\r
223\r
224 ## "==" operator\r
225 def __eq__(self, Other):\r
226 return Other and self.MetaFile == Other\r
227\r
228## Workspace AutoGen class\r
229#\r
230# This class is used mainly to control the whole platform build for different\r
231# architecture. This class will generate top level makefile.\r
232#\r
233class WorkspaceAutoGen(AutoGen):\r
b24e99f7
CJ
234 # call super().__init__ then call the worker function with different parameter count\r
235 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
236 try:\r
237 self._Init\r
238 except:\r
239 super(WorkspaceAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
240 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
241 self._Init = True\r
242 \r
243 ## Initialize WorkspaceAutoGen\r
52302d4d
LG
244 #\r
245 # @param WorkspaceDir Root directory of workspace\r
246 # @param ActivePlatform Meta-file of active platform\r
247 # @param Target Build target\r
248 # @param Toolchain Tool chain name\r
249 # @param ArchList List of architecture of current build\r
250 # @param MetaFileDb Database containing meta-files\r
251 # @param BuildConfig Configuration of build\r
252 # @param ToolDefinition Tool chain definitions\r
253 # @param FlashDefinitionFile File of flash definition\r
254 # @param Fds FD list to be generated\r
255 # @param Fvs FV list to be generated\r
4234283c 256 # @param Caps Capsule list to be generated\r
52302d4d
LG
257 # @param SkuId SKU id from command line\r
258 #\r
b24e99f7 259 def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,\r
47fea6af 260 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,\r
9508d0fa 261 Progress=None, BuildModule=None):\r
0d2711a6
LG
262 self.BuildDatabase = MetaFileDb\r
263 self.MetaFile = ActivePlatform\r
52302d4d 264 self.WorkspaceDir = WorkspaceDir\r
6b1f2cf4 265 self.Platform = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]\r
d0acc87a 266 GlobalData.gActivePlatform = self.Platform\r
52302d4d
LG
267 self.BuildTarget = Target\r
268 self.ToolChain = Toolchain\r
269 self.ArchList = ArchList\r
270 self.SkuId = SkuId\r
f3decdc3 271 self.UniFlag = UniFlag\r
52302d4d 272\r
52302d4d
LG
273 self.TargetTxt = BuildConfig\r
274 self.ToolDef = ToolDefinition\r
275 self.FdfFile = FlashDefinitionFile\r
066c7154
CJ
276 self.FdTargetList = Fds if Fds else []\r
277 self.FvTargetList = Fvs if Fvs else []\r
278 self.CapTargetList = Caps if Caps else []\r
52302d4d 279 self.AutoGenObjectList = []\r
36d083ef
YZ
280 self._BuildDir = None\r
281 self._FvDir = None\r
282 self._MakeFileDir = None\r
283 self._BuildCommand = None\r
726c501c 284 self._GuidDict = {}\r
52302d4d
LG
285\r
286 # there's many relative directory operations, so ...\r
287 os.chdir(self.WorkspaceDir)\r
288\r
0d2711a6
LG
289 #\r
290 # Merge Arch\r
291 #\r
292 if not self.ArchList:\r
293 ArchList = set(self.Platform.SupArchList)\r
294 else:\r
295 ArchList = set(self.ArchList) & set(self.Platform.SupArchList)\r
296 if not ArchList:\r
297 EdkLogger.error("build", PARAMETER_INVALID,\r
298 ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))\r
299 elif self.ArchList and len(ArchList) != len(self.ArchList):\r
300 SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))\r
301 EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"\r
302 % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))\r
303 self.ArchList = tuple(ArchList)\r
304\r
305 # Validate build target\r
306 if self.BuildTarget not in self.Platform.BuildTargets:\r
47fea6af 307 EdkLogger.error("build", PARAMETER_INVALID,\r
0d2711a6
LG
308 ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"\r
309 % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))\r
310\r
12d37ace 311 \r
52302d4d 312 # parse FDF file to get PCDs in it, if any\r
0d2711a6
LG
313 if not self.FdfFile:\r
314 self.FdfFile = self.Platform.FlashDefinition\r
47fea6af 315\r
9508d0fa
LG
316 EdkLogger.info("")\r
317 if self.ArchList:\r
318 EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))\r
319 EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))\r
47fea6af
YZ
320 EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))\r
321\r
9508d0fa
LG
322 EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))\r
323 if BuildModule:\r
324 EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))\r
47fea6af 325\r
9508d0fa
LG
326 if self.FdfFile:\r
327 EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))\r
0d2711a6 328\r
9508d0fa 329 EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)\r
47fea6af 330\r
e74cea4c
YZ
331 if Progress:\r
332 Progress.Start("\nProcessing meta-data")\r
47fea6af 333\r
0d2711a6 334 if self.FdfFile:\r
df692f02
LG
335 #\r
336 # Mark now build in AutoGen Phase\r
337 #\r
47fea6af 338 GlobalData.gAutoGenPhase = True\r
52302d4d
LG
339 Fdf = FdfParser(self.FdfFile.Path)\r
340 Fdf.ParseFile()\r
a0a2cd1e 341 GlobalData.gFdfParser = Fdf\r
0d2711a6 342 GlobalData.gAutoGenPhase = False\r
52302d4d 343 PcdSet = Fdf.Profile.PcdDict\r
cb04330e
YZ
344 if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:\r
345 FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]\r
346 for FdRegion in FdDict.RegionList:\r
347 if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):\r
348 if int(FdRegion.Offset) % 8 != 0:\r
349 EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))\r
52302d4d
LG
350 ModuleList = Fdf.Profile.InfList\r
351 self.FdfProfile = Fdf.Profile\r
0d2711a6
LG
352 for fvname in self.FvTargetList:\r
353 if fvname.upper() not in self.FdfProfile.FvDict:\r
354 EdkLogger.error("build", OPTION_VALUE_INVALID,\r
355 "No such an FV in FDF file: %s" % fvname)\r
2502b735 356\r
622b1758
YZ
357 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,\r
358 # but the path (self.MetaFile.Path) is the real path\r
2502b735
YZ
359 for key in self.FdfProfile.InfDict:\r
360 if key == 'ArchTBD':\r
992fbe35 361 MetaFile_cache = defaultdict(set)\r
2502b735 362 for Arch in self.ArchList:\r
1530ceda 363 Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
1530ceda
CJ
364 for Pkey in Current_Platform_cache.Modules:\r
365 MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)\r
2502b735
YZ
366 for Inf in self.FdfProfile.InfDict[key]:\r
367 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
368 for Arch in self.ArchList:\r
622b1758 369 if ModuleFile in MetaFile_cache[Arch]:\r
2502b735
YZ
370 break\r
371 else:\r
372 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
373 if not ModuleData.IsBinaryModule:\r
374 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
375\r
376 else:\r
377 for Arch in self.ArchList:\r
378 if Arch == key:\r
379 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
b74b419a
CJ
380 MetaFileList = set()\r
381 for Pkey in Platform.Modules:\r
382 MetaFileList.add(Platform.Modules[Pkey].MetaFile)\r
2502b735
YZ
383 for Inf in self.FdfProfile.InfDict[key]:\r
384 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
622b1758 385 if ModuleFile in MetaFileList:\r
2502b735
YZ
386 continue\r
387 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
388 if not ModuleData.IsBinaryModule:\r
389 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
390\r
52302d4d
LG
391 else:\r
392 PcdSet = {}\r
393 ModuleList = []\r
394 self.FdfProfile = None\r
0d2711a6
LG
395 if self.FdTargetList:\r
396 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))\r
397 self.FdTargetList = []\r
398 if self.FvTargetList:\r
399 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))\r
400 self.FvTargetList = []\r
401 if self.CapTargetList:\r
402 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))\r
403 self.CapTargetList = []\r
47fea6af 404\r
52302d4d
LG
405 # apply SKU and inject PCDs from Flash Definition file\r
406 for Arch in self.ArchList:\r
0d2711a6 407 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
f9fa014e
YZ
408 PlatformPcds = Platform.Pcds\r
409 self._GuidDict = Platform._GuidDict\r
6b1f2cf4
CJ
410 SourcePcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set(),TAB_PCDS_DYNAMIC:set(),TAB_PCDS_FIXED_AT_BUILD:set()}\r
411 BinaryPcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set()}\r
2a29017e
YZ
412 SourcePcdDict_Keys = SourcePcdDict.keys()\r
413 BinaryPcdDict_Keys = BinaryPcdDict.keys()\r
414\r
415 # generate the SourcePcdDict and BinaryPcdDict\r
6f49996c 416 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
2a29017e
YZ
417 for BuildData in PGen.BuildDatabase._CACHE_.values():\r
418 if BuildData.Arch != Arch:\r
419 continue\r
420 if BuildData.MetaFile.Ext == '.inf':\r
421 for key in BuildData.Pcds:\r
422 if BuildData.Pcds[key].Pending:\r
423 if key in Platform.Pcds:\r
424 PcdInPlatform = Platform.Pcds[key]\r
c93356ad 425 if PcdInPlatform.Type:\r
2a29017e 426 BuildData.Pcds[key].Type = PcdInPlatform.Type\r
74f59e92 427 BuildData.Pcds[key].Pending = False\r
2a29017e
YZ
428\r
429 if BuildData.MetaFile in Platform.Modules:\r
430 PlatformModule = Platform.Modules[str(BuildData.MetaFile)]\r
431 if key in PlatformModule.Pcds:\r
432 PcdInPlatform = PlatformModule.Pcds[key]\r
c93356ad 433 if PcdInPlatform.Type:\r
2a29017e 434 BuildData.Pcds[key].Type = PcdInPlatform.Type\r
74f59e92 435 BuildData.Pcds[key].Pending = False\r
5a444dfd
YF
436 else:\r
437 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending\r
438 if BuildData.Pcds[key].Pending:\r
439 MGen = ModuleAutoGen(self, BuildData.MetaFile, Target, Toolchain, Arch, self.MetaFile)\r
440 if MGen and MGen.IsLibrary:\r
441 if MGen in PGen.LibraryAutoGenList:\r
442 ReferenceModules = MGen._ReferenceModules\r
443 for ReferenceModule in ReferenceModules:\r
444 if ReferenceModule.MetaFile in Platform.Modules:\r
445 RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]\r
446 if key in RefPlatformModule.Pcds:\r
447 PcdInReferenceModule = RefPlatformModule.Pcds[key]\r
448 if PcdInReferenceModule.Type:\r
449 BuildData.Pcds[key].Type = PcdInReferenceModule.Type\r
450 BuildData.Pcds[key].Pending = False\r
451 break\r
2a29017e 452\r
6b1f2cf4 453 if TAB_PCDS_DYNAMIC_EX in BuildData.Pcds[key].Type:\r
2a29017e 454 if BuildData.IsBinaryModule:\r
6b1f2cf4 455 BinaryPcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 456 else:\r
6b1f2cf4 457 SourcePcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 458\r
6b1f2cf4 459 elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData.Pcds[key].Type:\r
2a29017e
YZ
460 if BuildData.MetaFile.Ext == '.inf':\r
461 if BuildData.IsBinaryModule:\r
6b1f2cf4 462 BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 463 else:\r
6b1f2cf4 464 SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 465\r
6b1f2cf4
CJ
466 elif TAB_PCDS_DYNAMIC in BuildData.Pcds[key].Type:\r
467 SourcePcdDict[TAB_PCDS_DYNAMIC].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
468 elif TAB_PCDS_FIXED_AT_BUILD in BuildData.Pcds[key].Type:\r
469 SourcePcdDict[TAB_PCDS_FIXED_AT_BUILD].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e
YZ
470 else:\r
471 pass\r
97cdb33b
YZ
472 #\r
473 # A PCD can only use one type for all source modules\r
474 #\r
475 for i in SourcePcdDict_Keys:\r
476 for j in SourcePcdDict_Keys:\r
477 if i != j:\r
ff5635e9
CJ
478 Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])\r
479 if len(Intersections) > 0:\r
97cdb33b
YZ
480 EdkLogger.error(\r
481 'build',\r
482 FORMAT_INVALID,\r
483 "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),\r
8252e6bf 484 ExtraData="%s" % '\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)\r
97cdb33b 485 )\r
2a29017e
YZ
486\r
487 #\r
488 # intersection the BinaryPCD for Mixed PCD\r
489 #\r
490 for i in BinaryPcdDict_Keys:\r
491 for j in BinaryPcdDict_Keys:\r
492 if i != j:\r
ff5635e9
CJ
493 Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])\r
494 for item in Intersections:\r
2a29017e
YZ
495 NewPcd1 = (item[0] + '_' + i, item[1])\r
496 NewPcd2 = (item[0] + '_' + j, item[1])\r
497 if item not in GlobalData.MixedPcd:\r
498 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
499 else:\r
500 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
501 GlobalData.MixedPcd[item].append(NewPcd1)\r
502 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
503 GlobalData.MixedPcd[item].append(NewPcd2)\r
2a29017e
YZ
504\r
505 #\r
506 # intersection the SourcePCD and BinaryPCD for Mixed PCD\r
507 #\r
508 for i in SourcePcdDict_Keys:\r
509 for j in BinaryPcdDict_Keys:\r
510 if i != j:\r
ff5635e9
CJ
511 Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])\r
512 for item in Intersections:\r
2a29017e
YZ
513 NewPcd1 = (item[0] + '_' + i, item[1])\r
514 NewPcd2 = (item[0] + '_' + j, item[1])\r
515 if item not in GlobalData.MixedPcd:\r
516 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
517 else:\r
518 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
519 GlobalData.MixedPcd[item].append(NewPcd1)\r
520 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
521 GlobalData.MixedPcd[item].append(NewPcd2)\r
2a29017e
YZ
522\r
523 for BuildData in PGen.BuildDatabase._CACHE_.values():\r
524 if BuildData.Arch != Arch:\r
525 continue\r
526 for key in BuildData.Pcds:\r
527 for SinglePcd in GlobalData.MixedPcd:\r
528 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
529 for item in GlobalData.MixedPcd[SinglePcd]:\r
530 Pcd_Type = item[0].split('_')[-1]\r
eece4292
CJ
531 if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \\r
532 (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):\r
2a29017e
YZ
533 Value = BuildData.Pcds[key]\r
534 Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type\r
535 if len(key) == 2:\r
536 newkey = (Value.TokenCName, key[1])\r
537 elif len(key) == 3:\r
538 newkey = (Value.TokenCName, key[1], key[2])\r
539 del BuildData.Pcds[key]\r
540 BuildData.Pcds[newkey] = Value\r
541 break\r
2a29017e 542 break\r
2a29017e
YZ
543\r
544 # handle the mixed pcd in FDF file\r
545 for key in PcdSet:\r
546 if key in GlobalData.MixedPcd:\r
547 Value = PcdSet[key]\r
548 del PcdSet[key]\r
549 for item in GlobalData.MixedPcd[key]:\r
550 PcdSet[item] = Value\r
551\r
97fa0ee9 552 #Collect package set information from INF of FDF\r
a0a2cd1e
FB
553 PkgSet = set()\r
554 for Inf in ModuleList:\r
555 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
556 if ModuleFile in Platform.Modules:\r
557 continue\r
558 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
559 PkgSet.update(ModuleData.Packages)\r
560 Pkgs = list(PkgSet) + list(PGen.PackageList)\r
6b26dd71 561 DecPcds = set()\r
6f49996c 562 DecPcdsKey = set()\r
64b2609f 563 for Pkg in Pkgs:\r
25918452 564 for Pcd in Pkg.Pcds:\r
6b26dd71 565 DecPcds.add((Pcd[0], Pcd[1]))\r
4afd3d04 566 DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
64b2609f 567\r
52302d4d
LG
568 Platform.SkuName = self.SkuId\r
569 for Name, Guid in PcdSet:\r
64b2609f
LG
570 if (Name, Guid) not in DecPcds:\r
571 EdkLogger.error(\r
572 'build',\r
573 PARSER_ERROR,\r
574 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
575 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
576 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
577 )\r
4afd3d04
LG
578 else:\r
579 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
580 if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
581 or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
582 or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
583 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])\r
584 continue\r
585 elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
586 EdkLogger.error(\r
587 'build',\r
588 PARSER_ERROR,\r
589 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
590 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
591 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
592 )\r
52302d4d
LG
593\r
594 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
595 #\r
596 # Explicitly collect platform's dynamic PCDs\r
597 #\r
598 Pa.CollectPlatformDynamicPcds()\r
2bc3256c 599 Pa.CollectFixedAtBuildPcds()\r
52302d4d 600 self.AutoGenObjectList.append(Pa)\r
47fea6af 601\r
36d083ef
YZ
602 #\r
603 # Generate Package level hash value\r
604 #\r
605 GlobalData.gPackageHash[Arch] = {}\r
606 if GlobalData.gUseHashCache:\r
607 for Pkg in Pkgs:\r
608 self._GenPkgLevelHash(Pkg)\r
609\r
6780eef1
LG
610 #\r
611 # Check PCDs token value conflict in each DEC file.\r
612 #\r
613 self._CheckAllPcdsTokenValueConflict()\r
47fea6af 614\r
4234283c
LG
615 #\r
616 # Check PCD type and definition between DSC and DEC\r
617 #\r
618 self._CheckPcdDefineAndType()\r
97fa0ee9
YL
619\r
620# if self.FdfFile:\r
621# self._CheckDuplicateInFV(Fdf)\r
622\r
c17956e0 623 #\r
2d499388 624 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.\r
c17956e0
DL
625 #\r
626 content = 'gCommandLineDefines: '\r
627 content += str(GlobalData.gCommandLineDefines)\r
628 content += os.linesep\r
629 content += 'BuildOptionPcd: '\r
630 content += str(GlobalData.BuildOptionPcd)\r
2d499388
YZ
631 content += os.linesep\r
632 content += 'Active Platform: '\r
633 content += str(self.Platform)\r
634 content += os.linesep\r
635 if self.FdfFile:\r
636 content += 'Flash Image Definition: '\r
637 content += str(self.FdfFile)\r
36d083ef 638 content += os.linesep\r
c17956e0
DL
639 SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)\r
640\r
99adfe9f
YZ
641 #\r
642 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.\r
643 #\r
644 PcdTokenNumber = 'PcdTokenNumber: '\r
645 if Pa.PcdTokenNumber:\r
646 if Pa.DynamicPcdList:\r
647 for Pcd in Pa.DynamicPcdList:\r
648 PcdTokenNumber += os.linesep\r
649 PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
650 PcdTokenNumber += ' : '\r
651 PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])\r
652 SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)\r
653\r
c17956e0
DL
654 #\r
655 # Get set of workspace metafiles\r
656 #\r
657 AllWorkSpaceMetaFiles = self._GetMetaFiles(Target, Toolchain, Arch)\r
658\r
659 #\r
660 # Retrieve latest modified time of all metafiles\r
661 #\r
662 SrcTimeStamp = 0\r
663 for f in AllWorkSpaceMetaFiles:\r
664 if os.stat(f)[8] > SrcTimeStamp:\r
665 SrcTimeStamp = os.stat(f)[8]\r
666 self._SrcTimeStamp = SrcTimeStamp\r
667\r
36d083ef
YZ
668 if GlobalData.gUseHashCache:\r
669 m = hashlib.md5()\r
670 for files in AllWorkSpaceMetaFiles:\r
671 if files.endswith('.dec'):\r
672 continue\r
673 f = open(files, 'r')\r
674 Content = f.read()\r
675 f.close()\r
676 m.update(Content)\r
677 SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), True)\r
678 GlobalData.gPlatformHash = m.hexdigest()\r
679\r
c17956e0
DL
680 #\r
681 # Write metafile list to build directory\r
682 #\r
683 AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')\r
684 if os.path.exists (AutoGenFilePath):\r
685 os.remove(AutoGenFilePath)\r
686 if not os.path.exists(self.BuildDir):\r
687 os.makedirs(self.BuildDir)\r
688 with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:\r
689 for f in AllWorkSpaceMetaFiles:\r
690 print >> file, f\r
52302d4d
LG
691 return True\r
692\r
36d083ef 693 def _GenPkgLevelHash(self, Pkg):\r
3f34e36d
LD
694 if Pkg.PackageName in GlobalData.gPackageHash[Pkg.Arch]:\r
695 return\r
696\r
36d083ef
YZ
697 PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)\r
698 CreateDirectory(PkgDir)\r
699 HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')\r
700 m = hashlib.md5()\r
701 # Get .dec file's hash value\r
702 f = open(Pkg.MetaFile.Path, 'r')\r
703 Content = f.read()\r
704 f.close()\r
705 m.update(Content)\r
706 # Get include files hash value\r
707 if Pkg.Includes:\r
3f34e36d 708 for inc in sorted(Pkg.Includes, key=lambda x: str(x)):\r
36d083ef 709 for Root, Dirs, Files in os.walk(str(inc)):\r
3f34e36d 710 for File in sorted(Files):\r
36d083ef
YZ
711 File_Path = os.path.join(Root, File)\r
712 f = open(File_Path, 'r')\r
713 Content = f.read()\r
714 f.close()\r
715 m.update(Content)\r
716 SaveFileOnChange(HashFile, m.hexdigest(), True)\r
3f34e36d 717 GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()\r
763e8edf 718\r
c17956e0
DL
719 def _GetMetaFiles(self, Target, Toolchain, Arch):\r
720 AllWorkSpaceMetaFiles = set()\r
721 #\r
722 # add fdf\r
723 #\r
724 if self.FdfFile:\r
725 AllWorkSpaceMetaFiles.add (self.FdfFile.Path)\r
726 if self.FdfFile:\r
727 FdfFiles = GlobalData.gFdfParser.GetAllIncludedFile()\r
728 for f in FdfFiles:\r
729 AllWorkSpaceMetaFiles.add (f.FileName)\r
730 #\r
731 # add dsc\r
732 #\r
733 AllWorkSpaceMetaFiles.add(self.MetaFile.Path)\r
734\r
735 #\r
86601b78
DL
736 # add build_rule.txt & tools_def.txt\r
737 #\r
51de5c30
YZ
738 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))\r
739 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))\r
86601b78 740\r
c17956e0
DL
741 # add BuildOption metafile\r
742 #\r
743 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))\r
744\r
99adfe9f
YZ
745 # add PcdToken Number file for Dynamic/DynamicEx Pcd\r
746 #\r
747 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))\r
748\r
c17956e0
DL
749 for Arch in self.ArchList:\r
750 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
751 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
752\r
753 #\r
754 # add dec\r
755 #\r
756 for Package in PGen.PackageList:\r
757 AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)\r
758\r
759 #\r
760 # add included dsc\r
761 #\r
762 for filePath in Platform._RawData.IncludedFiles:\r
763 AllWorkSpaceMetaFiles.add(filePath.Path)\r
764\r
765 return AllWorkSpaceMetaFiles\r
766\r
79b74a03
LG
767 ## _CheckDuplicateInFV() method\r
768 #\r
769 # Check whether there is duplicate modules/files exist in FV section. \r
770 # The check base on the file GUID;\r
771 #\r
772 def _CheckDuplicateInFV(self, Fdf):\r
773 for Fv in Fdf.Profile.FvDict:\r
774 _GuidDict = {}\r
775 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:\r
4231a819 776 if FfsFile.InfFileName and FfsFile.NameGuid is None:\r
79b74a03
LG
777 #\r
778 # Get INF file GUID\r
779 #\r
47fea6af 780 InfFoundFlag = False\r
79b74a03 781 for Pa in self.AutoGenObjectList:\r
64b2609f
LG
782 if InfFoundFlag:\r
783 break\r
79b74a03
LG
784 for Module in Pa.ModuleAutoGenList:\r
785 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):\r
786 InfFoundFlag = True\r
9eb87141 787 if Module.Guid.upper() not in _GuidDict:\r
79b74a03 788 _GuidDict[Module.Guid.upper()] = FfsFile\r
64b2609f 789 break\r
79b74a03 790 else:\r
47fea6af 791 EdkLogger.error("build",\r
79b74a03 792 FORMAT_INVALID,\r
47fea6af 793 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
794 FfsFile.CurrentLineContent,\r
795 _GuidDict[Module.Guid.upper()].CurrentLineNum,\r
796 _GuidDict[Module.Guid.upper()].CurrentLineContent,\r
797 Module.Guid.upper()),\r
798 ExtraData=self.FdfFile)\r
799 #\r
800 # Some INF files not have entity in DSC file. \r
801 #\r
802 if not InfFoundFlag:\r
803 if FfsFile.InfFileName.find('$') == -1:\r
804 InfPath = NormPath(FfsFile.InfFileName)\r
805 if not os.path.exists(InfPath):\r
806 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))\r
47fea6af 807\r
79b74a03
LG
808 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)\r
809 #\r
810 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use \r
811 # BuildObject from one of AutoGenObjectList is enough.\r
812 #\r
6b1f2cf4 813 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, TAB_ARCH_COMMON, self.BuildTarget, self.ToolChain]\r
9eb87141 814 if InfObj.Guid.upper() not in _GuidDict:\r
79b74a03
LG
815 _GuidDict[InfObj.Guid.upper()] = FfsFile\r
816 else:\r
47fea6af 817 EdkLogger.error("build",\r
79b74a03 818 FORMAT_INVALID,\r
47fea6af 819 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
820 FfsFile.CurrentLineContent,\r
821 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,\r
822 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,\r
823 InfObj.Guid.upper()),\r
824 ExtraData=self.FdfFile)\r
825 InfFoundFlag = False\r
47fea6af 826\r
4231a819 827 if FfsFile.NameGuid is not None:\r
79b74a03
LG
828 #\r
829 # If the NameGuid reference a PCD name. \r
830 # The style must match: PCD(xxxx.yyy)\r
831 #\r
c8802c3d 832 if gPCDAsGuidPattern.match(FfsFile.NameGuid):\r
79b74a03
LG
833 #\r
834 # Replace the PCD value.\r
835 #\r
836 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")\r
837 PcdFoundFlag = False\r
838 for Pa in self.AutoGenObjectList:\r
839 if not PcdFoundFlag:\r
840 for PcdItem in Pa.AllPcdList:\r
841 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:\r
842 #\r
843 # First convert from CFormatGuid to GUID string\r
844 #\r
845 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)\r
47fea6af 846\r
79b74a03
LG
847 if not _PcdGuidString:\r
848 #\r
849 # Then try Byte array.\r
850 #\r
851 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)\r
47fea6af 852\r
79b74a03
LG
853 if not _PcdGuidString:\r
854 #\r
855 # Not Byte array or CFormat GUID, raise error.\r
856 #\r
857 EdkLogger.error("build",\r
858 FORMAT_INVALID,\r
47fea6af 859 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),\r
79b74a03 860 ExtraData=self.FdfFile)\r
47fea6af 861\r
9eb87141 862 if _PcdGuidString.upper() not in _GuidDict:\r
79b74a03
LG
863 _GuidDict[_PcdGuidString.upper()] = FfsFile\r
864 PcdFoundFlag = True\r
865 break\r
866 else:\r
47fea6af 867 EdkLogger.error("build",\r
79b74a03 868 FORMAT_INVALID,\r
47fea6af 869 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
870 FfsFile.CurrentLineContent,\r
871 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,\r
872 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,\r
873 FfsFile.NameGuid.upper()),\r
47fea6af
YZ
874 ExtraData=self.FdfFile)\r
875\r
9eb87141 876 if FfsFile.NameGuid.upper() not in _GuidDict:\r
79b74a03
LG
877 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile\r
878 else:\r
879 #\r
880 # Two raw file GUID conflict.\r
881 #\r
47fea6af 882 EdkLogger.error("build",\r
79b74a03 883 FORMAT_INVALID,\r
47fea6af 884 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
885 FfsFile.CurrentLineContent,\r
886 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,\r
887 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,\r
888 FfsFile.NameGuid.upper()),\r
889 ExtraData=self.FdfFile)\r
47fea6af 890\r
79b74a03 891\r
4234283c
LG
892 def _CheckPcdDefineAndType(self):\r
893 PcdTypeList = [\r
6b1f2cf4 894 TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG,\r
be409b67
CJ
895 TAB_PCDS_DYNAMIC, #TAB_PCDS_DYNAMIC_HII, TAB_PCDS_DYNAMIC_VPD,\r
896 TAB_PCDS_DYNAMIC_EX, # TAB_PCDS_DYNAMIC_EX_HII, TAB_PCDS_DYNAMIC_EX_VPD\r
4234283c
LG
897 ]\r
898\r
899 # This dict store PCDs which are not used by any modules with specified arches\r
9006a2c6 900 UnusedPcd = OrderedDict()\r
4234283c
LG
901 for Pa in self.AutoGenObjectList:\r
902 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid\r
903 for Pcd in Pa.Platform.Pcds:\r
904 PcdType = Pa.Platform.Pcds[Pcd].Type\r
47fea6af 905\r
4234283c
LG
906 # If no PCD type, this PCD comes from FDF \r
907 if not PcdType:\r
908 continue\r
47fea6af 909\r
4234283c 910 # Try to remove Hii and Vpd suffix\r
6b1f2cf4
CJ
911 if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):\r
912 PcdType = TAB_PCDS_DYNAMIC_EX\r
913 elif PcdType.startswith(TAB_PCDS_DYNAMIC):\r
914 PcdType = TAB_PCDS_DYNAMIC\r
47fea6af 915\r
4234283c
LG
916 for Package in Pa.PackageList:\r
917 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType\r
918 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:\r
919 break\r
920 for Type in PcdTypeList:\r
921 if (Pcd[0], Pcd[1], Type) in Package.Pcds:\r
922 EdkLogger.error(\r
923 'build',\r
924 FORMAT_INVALID,\r
925 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \\r
926 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),\r
927 ExtraData=None\r
928 )\r
929 return\r
930 else:\r
931 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)\r
932\r
933 for Pcd in UnusedPcd:\r
934 EdkLogger.warn(\r
935 'build',\r
936 "The PCD was not specified by any INF module in the platform for the given architecture.\n"\r
937 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"\r
938 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),\r
939 ExtraData=None\r
940 )\r
941\r
52302d4d
LG
942 def __repr__(self):\r
943 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
944\r
945 ## Return the directory to store FV files\r
946 def _GetFvDir(self):\r
4231a819 947 if self._FvDir is None:\r
91fa33ee 948 self._FvDir = path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
52302d4d
LG
949 return self._FvDir\r
950\r
951 ## Return the directory to store all intermediate and final files built\r
952 def _GetBuildDir(self):\r
4231a819 953 if self._BuildDir is None:\r
36d083ef 954 return self.AutoGenObjectList[0].BuildDir\r
52302d4d
LG
955\r
956 ## Return the build output directory platform specifies\r
957 def _GetOutputDir(self):\r
958 return self.Platform.OutputDirectory\r
959\r
960 ## Return platform name\r
961 def _GetName(self):\r
962 return self.Platform.PlatformName\r
963\r
964 ## Return meta-file GUID\r
965 def _GetGuid(self):\r
966 return self.Platform.Guid\r
967\r
968 ## Return platform version\r
969 def _GetVersion(self):\r
970 return self.Platform.Version\r
971\r
972 ## Return paths of tools\r
973 def _GetToolDefinition(self):\r
974 return self.AutoGenObjectList[0].ToolDefinition\r
975\r
976 ## Return directory of platform makefile\r
977 #\r
978 # @retval string Makefile directory\r
979 #\r
980 def _GetMakeFileDir(self):\r
4231a819 981 if self._MakeFileDir is None:\r
52302d4d
LG
982 self._MakeFileDir = self.BuildDir\r
983 return self._MakeFileDir\r
984\r
985 ## Return build command string\r
986 #\r
987 # @retval string Build command string\r
988 #\r
989 def _GetBuildCommand(self):\r
4231a819 990 if self._BuildCommand is None:\r
52302d4d
LG
991 # BuildCommand should be all the same. So just get one from platform AutoGen\r
992 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand\r
993 return self._BuildCommand\r
47fea6af 994\r
6780eef1
LG
995 ## Check the PCDs token value conflict in each DEC file.\r
996 #\r
997 # Will cause build break and raise error message while two PCDs conflict.\r
998 # \r
999 # @return None\r
1000 #\r
1001 def _CheckAllPcdsTokenValueConflict(self):\r
b36d134f
LG
1002 for Pa in self.AutoGenObjectList:\r
1003 for Package in Pa.PackageList:\r
6780eef1 1004 PcdList = Package.Pcds.values()\r
f827cd07 1005 PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0))) \r
6780eef1
LG
1006 Count = 0\r
1007 while (Count < len(PcdList) - 1) :\r
1008 Item = PcdList[Count]\r
1009 ItemNext = PcdList[Count + 1]\r
1010 #\r
1011 # Make sure in the same token space the TokenValue should be unique\r
1012 #\r
f827cd07 1013 if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):\r
6780eef1
LG
1014 SameTokenValuePcdList = []\r
1015 SameTokenValuePcdList.append(Item)\r
1016 SameTokenValuePcdList.append(ItemNext)\r
1017 RemainPcdListLength = len(PcdList) - Count - 2\r
1018 for ValueSameCount in range(RemainPcdListLength):\r
f827cd07 1019 if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):\r
6780eef1
LG
1020 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
1021 else:\r
1022 break;\r
1023 #\r
1024 # Sort same token value PCD list with TokenGuid and TokenCName\r
1025 #\r
47fea6af
YZ
1026 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
1027 SameTokenValuePcdListCount = 0\r
6780eef1 1028 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
2a29017e 1029 Flag = False\r
47fea6af
YZ
1030 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]\r
1031 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]\r
1032\r
6780eef1 1033 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):\r
2a29017e
YZ
1034 for PcdItem in GlobalData.MixedPcd:\r
1035 if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \\r
1036 (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
1037 Flag = True\r
1038 if not Flag:\r
1039 EdkLogger.error(\r
1040 'build',\r
1041 FORMAT_INVALID,\r
1042 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\\r
1043 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),\r
1044 ExtraData=None\r
1045 )\r
6780eef1
LG
1046 SameTokenValuePcdListCount += 1\r
1047 Count += SameTokenValuePcdListCount\r
1048 Count += 1\r
47fea6af 1049\r
6780eef1 1050 PcdList = Package.Pcds.values()\r
47fea6af 1051 PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
6780eef1
LG
1052 Count = 0\r
1053 while (Count < len(PcdList) - 1) :\r
1054 Item = PcdList[Count]\r
47fea6af 1055 ItemNext = PcdList[Count + 1]\r
6780eef1
LG
1056 #\r
1057 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
1058 #\r
f827cd07 1059 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):\r
6780eef1
LG
1060 EdkLogger.error(\r
1061 'build',\r
1062 FORMAT_INVALID,\r
1063 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\\r
1064 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),\r
1065 ExtraData=None\r
1066 )\r
1067 Count += 1\r
97fa0ee9 1068 ## Generate fds command\r
03af2753
HC
1069 def _GenFdsCommand(self):\r
1070 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
52302d4d 1071\r
e56468c0 1072 ## Create makefile for the platform and modules in it\r
52302d4d
LG
1073 #\r
1074 # @param CreateDepsMakeFile Flag indicating if the makefile for\r
1075 # modules will be created as well\r
1076 #\r
1077 def CreateMakeFile(self, CreateDepsMakeFile=False):\r
52302d4d
LG
1078 if CreateDepsMakeFile:\r
1079 for Pa in self.AutoGenObjectList:\r
1080 Pa.CreateMakeFile(CreateDepsMakeFile)\r
1081\r
1082 ## Create autogen code for platform and modules\r
1083 #\r
1084 # Since there's no autogen code for platform, this method will do nothing\r
1085 # if CreateModuleCodeFile is set to False.\r
1086 #\r
1087 # @param CreateDepsCodeFile Flag indicating if creating module's\r
1088 # autogen code file or not\r
1089 #\r
1090 def CreateCodeFile(self, CreateDepsCodeFile=False):\r
1091 if not CreateDepsCodeFile:\r
1092 return\r
1093 for Pa in self.AutoGenObjectList:\r
1094 Pa.CreateCodeFile(CreateDepsCodeFile)\r
1095\r
7c1fd323
LG
1096 ## Create AsBuilt INF file the platform\r
1097 #\r
1098 def CreateAsBuiltInf(self):\r
1099 return\r
1100\r
52302d4d
LG
1101 Name = property(_GetName)\r
1102 Guid = property(_GetGuid)\r
1103 Version = property(_GetVersion)\r
1104 OutputDir = property(_GetOutputDir)\r
1105\r
1106 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
1107\r
1108 BuildDir = property(_GetBuildDir)\r
1109 FvDir = property(_GetFvDir)\r
1110 MakeFileDir = property(_GetMakeFileDir)\r
1111 BuildCommand = property(_GetBuildCommand)\r
03af2753 1112 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
1113\r
1114## AutoGen class for platform\r
1115#\r
1116# PlatformAutoGen class will process the original information in platform\r
1117# file in order to generate makefile for platform.\r
1118#\r
1119class PlatformAutoGen(AutoGen):\r
b24e99f7
CJ
1120 # call super().__init__ then call the worker function with different parameter count\r
1121 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
1122 try:\r
1123 self._Init\r
1124 except:\r
1125 super(PlatformAutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
1126 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
1127 self._Init = True\r
52302d4d
LG
1128 #\r
1129 # Used to store all PCDs for both PEI and DXE phase, in order to generate \r
1130 # correct PCD database\r
1131 # \r
1132 _DynaPcdList_ = []\r
1133 _NonDynaPcdList_ = []\r
61ee1dff 1134 _PlatformPcds = {}\r
6780eef1
LG
1135 \r
1136 #\r
1137 # The priority list while override build option \r
1138 #\r
1139 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
1140 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
1141 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
1142 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE \r
1143 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
1144 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
1145 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
1146 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
1147 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
1148 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
1149 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE\r
1150 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE\r
1151 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
1152 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
1153 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE\r
1154 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)\r
47fea6af 1155\r
b24e99f7 1156 ## Initialize PlatformAutoGen\r
52302d4d 1157 #\r
52302d4d
LG
1158 #\r
1159 # @param Workspace WorkspaceAutoGen object\r
1160 # @param PlatformFile Platform file (DSC file)\r
1161 # @param Target Build target (DEBUG, RELEASE)\r
1162 # @param Toolchain Name of tool chain\r
1163 # @param Arch arch of the platform supports\r
1164 #\r
b24e99f7 1165 def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
52302d4d
LG
1166 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
1167 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
1168\r
1169 self.MetaFile = PlatformFile\r
1170 self.Workspace = Workspace\r
1171 self.WorkspaceDir = Workspace.WorkspaceDir\r
1172 self.ToolChain = Toolchain\r
1173 self.BuildTarget = Target\r
1174 self.Arch = Arch\r
1175 self.SourceDir = PlatformFile.SubDir\r
1176 self.SourceOverrideDir = None\r
1177 self.FdTargetList = self.Workspace.FdTargetList\r
1178 self.FvTargetList = self.Workspace.FvTargetList\r
1179 self.AllPcdList = []\r
a0a2cd1e
FB
1180 # get the original module/package/platform objects\r
1181 self.BuildDatabase = Workspace.BuildDatabase\r
8518bf0b 1182 self.DscBuildDataObj = Workspace.Platform\r
35f613d9 1183 self._GuidDict = Workspace._GuidDict\r
52302d4d
LG
1184\r
1185 # flag indicating if the makefile/C-code file has been created or not\r
1186 self.IsMakeFileCreated = False\r
1187 self.IsCodeFileCreated = False\r
1188\r
1189 self._Platform = None\r
1190 self._Name = None\r
1191 self._Guid = None\r
1192 self._Version = None\r
1193\r
1194 self._BuildRule = None\r
1195 self._SourceDir = None\r
1196 self._BuildDir = None\r
1197 self._OutputDir = None\r
1198 self._FvDir = None\r
1199 self._MakeFileDir = None\r
1200 self._FdfFile = None\r
1201\r
1202 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
1203 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
1204 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 1205 self._NonDynamicPcdDict = {}\r
52302d4d
LG
1206\r
1207 self._ToolDefinitions = None\r
1208 self._ToolDefFile = None # toolcode : tool path\r
1209 self._ToolChainFamily = None\r
1210 self._BuildRuleFamily = None\r
1211 self._BuildOption = None # toolcode : option\r
1212 self._EdkBuildOption = None # edktoolcode : option\r
1213 self._EdkIIBuildOption = None # edkiitoolcode : option\r
1214 self._PackageList = None\r
1215 self._ModuleAutoGenList = None\r
1216 self._LibraryAutoGenList = None\r
1217 self._BuildCommand = None\r
a0a2cd1e
FB
1218 self._AsBuildInfList = []\r
1219 self._AsBuildModuleList = []\r
47854fd5
LG
1220\r
1221 self.VariableInfo = None\r
1222\r
4231a819 1223 if GlobalData.gFdfParser is not None:\r
a0a2cd1e
FB
1224 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
1225 for Inf in self._AsBuildInfList:\r
1226 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
1227 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1228 if not M.IsSupportedArch:\r
1229 continue\r
1230 self._AsBuildModuleList.append(InfClass)\r
03af2753
HC
1231 # get library/modules for build\r
1232 self.LibraryBuildDirectoryList = []\r
1233 self.ModuleBuildDirectoryList = []\r
47854fd5 1234\r
52302d4d
LG
1235 return True\r
1236\r
1237 def __repr__(self):\r
1238 return "%s [%s]" % (self.MetaFile, self.Arch)\r
1239\r
1240 ## Create autogen code for platform and modules\r
1241 #\r
1242 # Since there's no autogen code for platform, this method will do nothing\r
1243 # if CreateModuleCodeFile is set to False.\r
1244 #\r
1245 # @param CreateModuleCodeFile Flag indicating if creating module's\r
1246 # autogen code file or not\r
1247 #\r
1248 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
1249 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
1250 if self.IsCodeFileCreated or not CreateModuleCodeFile:\r
1251 return\r
1252\r
1253 for Ma in self.ModuleAutoGenList:\r
1254 Ma.CreateCodeFile(True)\r
1255\r
1256 # don't do this twice\r
1257 self.IsCodeFileCreated = True\r
1258\r
03af2753
HC
1259 ## Generate Fds Command\r
1260 def _GenFdsCommand(self):\r
1261 return self.Workspace.GenFdsCommand\r
481252bb 1262\r
52302d4d
LG
1263 ## Create makefile for the platform and mdoules in it\r
1264 #\r
1265 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
1266 # modules will be created as well\r
1267 #\r
37de70b7 1268 def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
52302d4d
LG
1269 if CreateModuleMakeFile:\r
1270 for ModuleFile in self.Platform.Modules:\r
1271 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,\r
1272 self.ToolChain, self.Arch, self.MetaFile)\r
37de70b7
YZ
1273 if (ModuleFile.File, self.Arch) in FfsCommand:\r
1274 Ma.CreateMakeFile(True, FfsCommand[ModuleFile.File, self.Arch])\r
1275 else:\r
1276 Ma.CreateMakeFile(True)\r
97fa0ee9 1277 #Ma.CreateAsBuiltInf()\r
52302d4d
LG
1278\r
1279 # no need to create makefile for the platform more than once\r
1280 if self.IsMakeFileCreated:\r
1281 return\r
1282\r
03af2753 1283 # create library/module build dirs for platform\r
52302d4d 1284 Makefile = GenMake.PlatformMakefile(self)\r
03af2753
HC
1285 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
1286 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
1287\r
52302d4d
LG
1288 self.IsMakeFileCreated = True\r
1289\r
2bc3256c
LG
1290 ## Deal with Shared FixedAtBuild Pcds\r
1291 #\r
1292 def CollectFixedAtBuildPcds(self):\r
1293 for LibAuto in self.LibraryAutoGenList:\r
1294 FixedAtBuildPcds = {} \r
1295 ShareFixedAtBuildPcdsSameValue = {} \r
1296 for Module in LibAuto._ReferenceModules: \r
8b0e6782 1297 for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:\r
2bc3256c
LG
1298 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName)) \r
1299 if key not in FixedAtBuildPcds:\r
1300 ShareFixedAtBuildPcdsSameValue[key] = True\r
1301 FixedAtBuildPcds[key] = Pcd.DefaultValue\r
1302 else:\r
1303 if FixedAtBuildPcds[key] != Pcd.DefaultValue:\r
1304 ShareFixedAtBuildPcdsSameValue[key] = False \r
1305 for Pcd in LibAuto.FixedAtBuildPcds:\r
1306 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))\r
1307 if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
1308 continue\r
1309 else:\r
1310 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]\r
6b1f2cf4 1311 if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
2bc3256c
LG
1312 continue\r
1313 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]: \r
eca980c0 1314 LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]\r
2bc3256c 1315\r
34952f49 1316 def CollectVariables(self, DynamicPcdSet):\r
47854fd5
LG
1317\r
1318 VpdRegionSize = 0\r
1319 VpdRegionBase = 0\r
1320 if self.Workspace.FdfFile:\r
1321 FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]\r
1322 for FdRegion in FdDict.RegionList:\r
1323 for item in FdRegion.RegionDataList:\r
1324 if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:\r
1325 VpdRegionSize = FdRegion.Size\r
1326 VpdRegionBase = FdRegion.Offset\r
1327 break\r
1328\r
1329\r
8518bf0b 1330 VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(),self.DscBuildDataObj._GetSkuIds())\r
47854fd5
LG
1331 VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
1332 VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
34952f49
LG
1333 Index = 0\r
1334 for Pcd in DynamicPcdSet:\r
8518bf0b
LG
1335 pcdname = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))\r
1336 for SkuName in Pcd.SkuInfoList:\r
1337 Sku = Pcd.SkuInfoList[SkuName]\r
1338 SkuId = Sku.SkuId\r
4231a819 1339 if SkuId is None or SkuId == '':\r
8518bf0b
LG
1340 continue\r
1341 if len(Sku.VariableName) > 0:\r
1342 VariableGuidStructure = Sku.VariableGuidValue\r
1343 VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
a3623244 1344 for StorageName in Sku.DefaultStoreDict:\r
e6bf3cfd 1345 VariableInfo.append_variable(var_info(Index,pcdname,StorageName,SkuName, StringToArray(Sku.VariableName),VariableGuid, Sku.VariableOffset, Sku.VariableAttribute , Sku.HiiDefaultValue,Sku.DefaultStoreDict[StorageName],Pcd.DatumType))\r
34952f49
LG
1346 Index += 1\r
1347 return VariableInfo\r
47854fd5
LG
1348\r
1349 def UpdateNVStoreMaxSize(self,OrgVpdFile):\r
0b6c5954 1350 if self.VariableInfo:\r
91fa33ee 1351 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
0b6c5954
LG
1352 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
1353\r
1354 if PcdNvStoreDfBuffer:\r
1355 if os.path.exists(VpdMapFilePath):\r
1356 OrgVpdFile.Read(VpdMapFilePath)\r
1357 PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
8ac16789 1358 NvStoreOffset = PcdItems.values()[0].strip() if PcdItems else '0'\r
0b6c5954
LG
1359 else:\r
1360 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
1361\r
1362 NvStoreOffset = int(NvStoreOffset,16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)\r
55c84777 1363 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
0b6c5954
LG
1364 maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))\r
1365 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)\r
1366\r
1367 if var_data and default_skuobj:\r
1368 default_skuobj.DefaultValue = var_data\r
1369 PcdNvStoreDfBuffer[0].DefaultValue = var_data\r
1370 PcdNvStoreDfBuffer[0].SkuInfoList.clear()\r
55c84777 1371 PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj\r
0b6c5954 1372 PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))\r
47854fd5
LG
1373\r
1374 return OrgVpdFile\r
1375\r
52302d4d
LG
1376 ## Collect dynamic PCDs\r
1377 #\r
1378 # Gather dynamic PCDs list from each module and their settings from platform\r
1379 # This interface should be invoked explicitly when platform action is created.\r
1380 #\r
1381 def CollectPlatformDynamicPcds(self):\r
763e8edf 1382\r
2a29017e
YZ
1383 for key in self.Platform.Pcds:\r
1384 for SinglePcd in GlobalData.MixedPcd:\r
1385 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
1386 for item in GlobalData.MixedPcd[SinglePcd]:\r
1387 Pcd_Type = item[0].split('_')[-1]\r
eece4292
CJ
1388 if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \\r
1389 (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):\r
2a29017e
YZ
1390 Value = self.Platform.Pcds[key]\r
1391 Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type\r
1392 if len(key) == 2:\r
1393 newkey = (Value.TokenCName, key[1])\r
1394 elif len(key) == 3:\r
1395 newkey = (Value.TokenCName, key[1], key[2])\r
1396 del self.Platform.Pcds[key]\r
1397 self.Platform.Pcds[newkey] = Value\r
1398 break\r
1399 else:\r
1400 pass\r
1401 break\r
1402 else:\r
1403 pass\r
1404\r
52302d4d
LG
1405 # for gathering error information\r
1406 NoDatumTypePcdList = set()\r
a0a2cd1e
FB
1407 FdfModuleList = []\r
1408 for InfName in self._AsBuildInfList:\r
05cc51ad 1409 InfName = mws.join(self.WorkspaceDir, InfName)\r
a0a2cd1e 1410 FdfModuleList.append(os.path.normpath(InfName))\r
52302d4d
LG
1411 for F in self.Platform.Modules.keys():\r
1412 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
1413 #GuidValue.update(M.Guids)\r
1414 \r
1415 self.Platform.Modules[F].M = M\r
47fea6af
YZ
1416\r
1417 for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
52302d4d 1418 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
c93356ad 1419 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
52302d4d
LG
1420 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))\r
1421\r
97fa0ee9 1422 # Check the PCD from Binary INF or Source INF\r
a0a2cd1e
FB
1423 if M.IsBinaryModule == True:\r
1424 PcdFromModule.IsFromBinaryInf = True\r
97fa0ee9
YL
1425\r
1426 # Check the PCD from DSC or not \r
9eb87141
CJ
1427 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds\r
1428\r
eece4292 1429 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
a0a2cd1e
FB
1430 if F.Path not in FdfModuleList:\r
1431 # If one of the Source built modules listed in the DSC is not listed \r
1432 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic \r
1433 # access method (it is only listed in the DEC file that declares the \r
1434 # PCD as PcdsDynamic), then build tool will report warning message\r
1435 # notify the PI that they are attempting to build a module that must \r
1436 # be included in a flash image in order to be functional. These Dynamic \r
1437 # PCD will not be added into the Database unless it is used by other \r
1438 # modules that are included in the FDF file.\r
eece4292 1439 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \\r
a0a2cd1e
FB
1440 PcdFromModule.IsFromBinaryInf == False:\r
1441 # Print warning message to let the developer make a determine.\r
a0a2cd1e
FB
1442 continue\r
1443 # If one of the Source built modules listed in the DSC is not listed in \r
1444 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx \r
1445 # access method (it is only listed in the DEC file that declares the \r
1446 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the \r
1447 # PCD to the Platform's PCD Database.\r
eece4292 1448 if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
a0a2cd1e 1449 continue\r
52302d4d
LG
1450 #\r
1451 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
1452 # it should be stored in Pcd PEI database, If a dynamic only\r
1453 # used by DXE module, it should be stored in DXE PCD database.\r
1454 # The default Phase is DXE\r
1455 #\r
88c6c1b6 1456 if M.ModuleType in SUP_MODULE_SET_PEI:\r
52302d4d
LG
1457 PcdFromModule.Phase = "PEI"\r
1458 if PcdFromModule not in self._DynaPcdList_:\r
1459 self._DynaPcdList_.append(PcdFromModule)\r
1460 elif PcdFromModule.Phase == 'PEI':\r
1461 # overwrite any the same PCD existing, if Phase is PEI\r
1462 Index = self._DynaPcdList_.index(PcdFromModule)\r
1463 self._DynaPcdList_[Index] = PcdFromModule\r
1464 elif PcdFromModule not in self._NonDynaPcdList_:\r
1465 self._NonDynaPcdList_.append(PcdFromModule)\r
a0a2cd1e
FB
1466 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
1467 Index = self._NonDynaPcdList_.index(PcdFromModule)\r
1468 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
1469 #The PCD from Binary INF will override the same one from source INF\r
1470 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
1471 PcdFromModule.Pending = False\r
1472 self._NonDynaPcdList_.append (PcdFromModule)\r
1563349a 1473 DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}\r
a0a2cd1e
FB
1474 # add the PCD from modules that listed in FDF but not in DSC to Database \r
1475 for InfName in FdfModuleList:\r
1563349a 1476 if InfName not in DscModuleSet:\r
a0a2cd1e
FB
1477 InfClass = PathClass(InfName)\r
1478 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1479 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source) \r
1480 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here. \r
1481 # For binary module, if in current arch, we need to list the PCDs into database. \r
1482 if not M.IsSupportedArch:\r
1483 continue\r
1484 # Override the module PCD setting by platform setting\r
1485 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
1486 for PcdFromModule in ModulePcdList:\r
1487 PcdFromModule.IsFromBinaryInf = True\r
1488 PcdFromModule.IsFromDsc = False\r
1489 # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
eece4292 1490 if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
a0a2cd1e
FB
1491 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1492 File=self.MetaFile,\r
1493 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
1494 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
1495 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
c93356ad 1496 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
a0a2cd1e 1497 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
88c6c1b6 1498 if M.ModuleType in SUP_MODULE_SET_PEI:\r
a0a2cd1e 1499 PcdFromModule.Phase = "PEI"\r
eece4292 1500 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
a0a2cd1e
FB
1501 self._DynaPcdList_.append(PcdFromModule)\r
1502 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1503 self._NonDynaPcdList_.append(PcdFromModule)\r
eece4292 1504 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
97fa0ee9
YL
1505 # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
1506 # It is to solve the case that a dynamic PCD used by a PEM module/PEI \r
1507 # module & DXE module at a same time.\r
1508 # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
1509 # INF file as DynamicEx. \r
a0a2cd1e
FB
1510 Index = self._DynaPcdList_.index(PcdFromModule)\r
1511 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
1512 self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
1513 for PcdFromModule in self._NonDynaPcdList_:\r
1514 # If a PCD is not listed in the DSC file, but binary INF files used by \r
1515 # this platform all (that use this PCD) list the PCD in a [PatchPcds] \r
1516 # section, AND all source INF files used by this platform the build \r
1517 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds] \r
1518 # section, then the tools must NOT add the PCD to the Platform's PCD\r
1519 # Database; the build must assign the access method for this PCD as \r
1520 # PcdsPatchableInModule.\r
1521 if PcdFromModule not in self._DynaPcdList_:\r
1522 continue\r
1523 Index = self._DynaPcdList_.index(PcdFromModule)\r
1524 if PcdFromModule.IsFromDsc == False and \\r
1525 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
1526 PcdFromModule.IsFromBinaryInf == True and \\r
1527 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
1528 Index = self._DynaPcdList_.index(PcdFromModule)\r
1529 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
52302d4d
LG
1530\r
1531 # print out error information and break the build, if error found\r
1532 if len(NoDatumTypePcdList) > 0:\r
1533 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
1534 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1535 File=self.MetaFile,\r
1536 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
1537 % NoDatumTypePcdListString)\r
1538 self._NonDynamicPcdList = self._NonDynaPcdList_\r
1539 self._DynamicPcdList = self._DynaPcdList_\r
52302d4d
LG
1540 #\r
1541 # Sort dynamic PCD list to:\r
1542 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should \r
1543 # try to be put header of dynamicd List\r
1544 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
1545 #\r
1546 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
1547 #\r
0b6c5954
LG
1548 UnicodePcdArray = set()\r
1549 HiiPcdArray = set()\r
1550 OtherPcdArray = set()\r
6780eef1 1551 VpdPcdDict = {}\r
e56468c0 1552 VpdFile = VpdInfoFile.VpdInfoFile()\r
61ee1dff
YZ
1553 NeedProcessVpdMapFile = False\r
1554\r
9eb87141
CJ
1555 for pcd in self.Platform.Pcds:\r
1556 if pcd not in self._PlatformPcds:\r
61ee1dff
YZ
1557 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]\r
1558\r
ae7b6df8
LG
1559 for item in self._PlatformPcds:\r
1560 if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
656d2539 1561 self._PlatformPcds[item].DatumType = TAB_VOID\r
ae7b6df8 1562\r
e56468c0 1563 if (self.Workspace.ArchList[-1] == self.Arch): \r
1564 for Pcd in self._DynamicPcdList:\r
e56468c0 1565 # just pick the a value to determine whether is unicode string type\r
9eb87141 1566 Sku = Pcd.SkuInfoList.values()[0]\r
e56468c0 1567 Sku.VpdOffset = Sku.VpdOffset.strip()\r
47fea6af 1568\r
ae7b6df8 1569 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
656d2539 1570 Pcd.DatumType = TAB_VOID\r
ae7b6df8 1571\r
e56468c0 1572 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
e56468c0 1573 # if found HII type PCD then insert to right of UnicodeIndex\r
e56468c0 1574 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
47fea6af
YZ
1575 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
1576\r
34952f49
LG
1577 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer\r
1578 PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))\r
1579 if PcdNvStoreDfBuffer:\r
47854fd5 1580 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
47854fd5 1581 vardump = self.VariableInfo.dump()\r
626bece4 1582 if vardump:\r
2b8a6c44 1583 PcdNvStoreDfBuffer.DefaultValue = vardump\r
626bece4
LG
1584 for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
1585 PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
1586 PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
34952f49 1587\r
61ee1dff 1588 PlatformPcds = self._PlatformPcds.keys()\r
47fea6af 1589 PlatformPcds.sort()\r
6780eef1
LG
1590 #\r
1591 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
1592 #\r
626bece4 1593 VpdSkuMap = {}\r
6780eef1 1594 for PcdKey in PlatformPcds:\r
61ee1dff 1595 Pcd = self._PlatformPcds[PcdKey]\r
e8a47801
LG
1596 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
1597 PcdKey in VpdPcdDict:\r
1598 Pcd = VpdPcdDict[PcdKey]\r
626bece4 1599 SkuValueMap = {}\r
55c84777 1600 DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
8ac16789
LG
1601 if DefaultSku:\r
1602 PcdValue = DefaultSku.DefaultValue\r
1603 if PcdValue not in SkuValueMap:\r
1604 SkuValueMap[PcdValue] = []\r
55c84777 1605 VpdFile.Add(Pcd, TAB_DEFAULT,DefaultSku.VpdOffset)\r
8ac16789
LG
1606 SkuValueMap[PcdValue].append(DefaultSku)\r
1607\r
e8a47801
LG
1608 for (SkuName,Sku) in Pcd.SkuInfoList.items():\r
1609 Sku.VpdOffset = Sku.VpdOffset.strip()\r
5a13737a
YZ
1610 PcdValue = Sku.DefaultValue\r
1611 if PcdValue == "":\r
1612 PcdValue = Pcd.DefaultValue\r
1613 if Sku.VpdOffset != '*':\r
1614 if PcdValue.startswith("{"):\r
1615 Alignment = 8\r
1616 elif PcdValue.startswith("L"):\r
1617 Alignment = 2\r
1618 else:\r
1619 Alignment = 1\r
ca85291f
YZ
1620 try:\r
1621 VpdOffset = int(Sku.VpdOffset)\r
1622 except:\r
1623 try:\r
1624 VpdOffset = int(Sku.VpdOffset, 16)\r
1625 except:\r
1626 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1627 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1628 if PcdValue.startswith("{"):\r
1629 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
1630 else:\r
1631 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))\r
626bece4
LG
1632 if PcdValue not in SkuValueMap:\r
1633 SkuValueMap[PcdValue] = []\r
8ac16789 1634 VpdFile.Add(Pcd, SkuName,Sku.VpdOffset)\r
626bece4 1635 SkuValueMap[PcdValue].append(Sku)\r
e8a47801
LG
1636 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
1637 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1638 NeedProcessVpdMapFile = True\r
4231a819 1639 if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
e8a47801
LG
1640 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
1641 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
47fea6af 1642\r
626bece4 1643 VpdSkuMap[PcdKey] = SkuValueMap\r
e56468c0 1644 #\r
1645 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
1646 # An example is PCD for signature usage.\r
6780eef1
LG
1647 # \r
1648 for DscPcd in PlatformPcds:\r
61ee1dff 1649 DscPcdEntry = self._PlatformPcds[DscPcd]\r
e56468c0 1650 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
4231a819 1651 if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):\r
e56468c0 1652 FoundFlag = False\r
9eb87141 1653 for VpdPcd in VpdFile._VpdArray:\r
e56468c0 1654 # This PCD has been referenced by module\r
1655 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1656 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
1657 FoundFlag = True\r
47fea6af 1658\r
e56468c0 1659 # Not found, it should be signature\r
1660 if not FoundFlag :\r
1661 # just pick the a value to determine whether is unicode string type\r
626bece4 1662 SkuValueMap = {}\r
e827d21d 1663 SkuObjList = DscPcdEntry.SkuInfoList.items()\r
55c84777 1664 DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)\r
8ac16789 1665 if DefaultSku:\r
55c84777 1666 defaultindex = SkuObjList.index((TAB_DEFAULT,DefaultSku))\r
e827d21d
B
1667 SkuObjList[0],SkuObjList[defaultindex] = SkuObjList[defaultindex],SkuObjList[0]\r
1668 for (SkuName,Sku) in SkuObjList:\r
e8a47801
LG
1669 Sku.VpdOffset = Sku.VpdOffset.strip() \r
1670 \r
1671 # Need to iterate DEC pcd information to get the value & datumtype\r
1672 for eachDec in self.PackageList:\r
1673 for DecPcd in eachDec.Pcds:\r
1674 DecPcdEntry = eachDec.Pcds[DecPcd]\r
1675 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1676 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
1677 # Print warning message to let the developer make a determine.\r
1678 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
1679 File=self.MetaFile, \\r
1680 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
1681 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path)) \r
1682 \r
1683 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
1684 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
1685 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
1686 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
1687 # Only fix the value while no value provided in DSC file.\r
128d435f 1688 if not Sku.DefaultValue:\r
e8a47801
LG
1689 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue\r
1690 \r
1691 if DscPcdEntry not in self._DynamicPcdList:\r
1692 self._DynamicPcdList.append(DscPcdEntry)\r
e8a47801
LG
1693 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1694 PcdValue = Sku.DefaultValue\r
5a13737a
YZ
1695 if PcdValue == "":\r
1696 PcdValue = DscPcdEntry.DefaultValue\r
1697 if Sku.VpdOffset != '*':\r
1698 if PcdValue.startswith("{"):\r
1699 Alignment = 8\r
1700 elif PcdValue.startswith("L"):\r
1701 Alignment = 2\r
1702 else:\r
1703 Alignment = 1\r
ca85291f
YZ
1704 try:\r
1705 VpdOffset = int(Sku.VpdOffset)\r
1706 except:\r
1707 try:\r
1708 VpdOffset = int(Sku.VpdOffset, 16)\r
1709 except:\r
1710 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
1711 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1712 if PcdValue.startswith("{"):\r
1713 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
1714 else:\r
1715 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))\r
626bece4
LG
1716 if PcdValue not in SkuValueMap:\r
1717 SkuValueMap[PcdValue] = []\r
8ac16789 1718 VpdFile.Add(DscPcdEntry, SkuName,Sku.VpdOffset)\r
626bece4 1719 SkuValueMap[PcdValue].append(Sku)\r
e8a47801
LG
1720 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1721 NeedProcessVpdMapFile = True \r
656d2539 1722 if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
0b6c5954 1723 UnicodePcdArray.add(DscPcdEntry)\r
e8a47801 1724 elif len(Sku.VariableName) > 0:\r
0b6c5954 1725 HiiPcdArray.add(DscPcdEntry)\r
e8a47801 1726 else:\r
0b6c5954
LG
1727 OtherPcdArray.add(DscPcdEntry)\r
1728\r
e8a47801 1729 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
626bece4 1730 VpdSkuMap[DscPcd] = SkuValueMap\r
4231a819 1731 if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
e56468c0 1732 VpdFile.GetCount() != 0:\r
1733 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, \r
1734 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
47fea6af 1735\r
e56468c0 1736 if VpdFile.GetCount() != 0:\r
47854fd5
LG
1737\r
1738 self.FixVpdOffset(VpdFile)\r
1739\r
1740 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
47fea6af 1741\r
e56468c0 1742 # Process VPD map file generated by third party BPDG tool\r
1743 if NeedProcessVpdMapFile:\r
91fa33ee 1744 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
e56468c0 1745 if os.path.exists(VpdMapFilePath):\r
1746 VpdFile.Read(VpdMapFilePath)\r
47fea6af 1747\r
e56468c0 1748 # Fixup "*" offset\r
626bece4
LG
1749 for pcd in VpdSkuMap:\r
1750 vpdinfo = VpdFile.GetVpdInfo(pcd)\r
1751 if vpdinfo is None:\r
e56468c0 1752 # just pick the a value to determine whether is unicode string type\r
626bece4
LG
1753 continue\r
1754 for pcdvalue in VpdSkuMap[pcd]:\r
1755 for sku in VpdSkuMap[pcd][pcdvalue]:\r
1756 for item in vpdinfo:\r
1757 if item[2] == pcdvalue:\r
1758 sku.VpdOffset = item[1]\r
e56468c0 1759 else:\r
1760 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
47fea6af 1761\r
626bece4
LG
1762 # Delete the DynamicPcdList At the last time enter into this function\r
1763 for Pcd in self._DynamicPcdList:\r
1764 # just pick the a value to determine whether is unicode string type\r
9eb87141 1765 Sku = Pcd.SkuInfoList.values()[0]\r
626bece4
LG
1766 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1767\r
1768 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
656d2539 1769 Pcd.DatumType = TAB_VOID\r
626bece4
LG
1770\r
1771 PcdValue = Sku.DefaultValue\r
656d2539 1772 if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
626bece4 1773 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
0b6c5954 1774 UnicodePcdArray.add(Pcd)\r
626bece4
LG
1775 elif len(Sku.VariableName) > 0:\r
1776 # if found HII type PCD then insert to right of UnicodeIndex\r
0b6c5954 1777 HiiPcdArray.add(Pcd)\r
626bece4 1778 else:\r
0b6c5954 1779 OtherPcdArray.add(Pcd)\r
47fea6af 1780 del self._DynamicPcdList[:]\r
0b6c5954
LG
1781 self._DynamicPcdList.extend(list(UnicodePcdArray))\r
1782 self._DynamicPcdList.extend(list(HiiPcdArray))\r
1783 self._DynamicPcdList.extend(list(OtherPcdArray))\r
2b8a6c44
LG
1784 allskuset = [(SkuName,Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName,Sku) in pcd.SkuInfoList.items()]\r
1785 for pcd in self._DynamicPcdList:\r
1786 if len(pcd.SkuInfoList) == 1:\r
1787 for (SkuName,SkuId) in allskuset:\r
1788 if type(SkuId) in (str,unicode) and eval(SkuId) == 0 or SkuId == 0:\r
1789 continue\r
55c84777 1790 pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])\r
65eff519 1791 pcd.SkuInfoList[SkuName].SkuId = SkuId\r
a0a2cd1e 1792 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList\r
47854fd5
LG
1793\r
1794 def FixVpdOffset(self,VpdFile ):\r
91fa33ee 1795 FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
47854fd5
LG
1796 if not os.path.exists(FvPath):\r
1797 try:\r
1798 os.makedirs(FvPath)\r
1799 except:\r
1800 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
1801\r
1802 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
1803\r
1804 if VpdFile.Write(VpdFilePath):\r
1805 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
1806 BPDGToolName = None\r
1807 for ToolDef in self.ToolDefinition.values():\r
91fa33ee 1808 if ToolDef.has_key(TAB_GUID) and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:\r
47854fd5
LG
1809 if not ToolDef.has_key("PATH"):\r
1810 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
1811 BPDGToolName = ToolDef["PATH"]\r
1812 break\r
1813 # Call third party GUID BPDG tool.\r
4231a819 1814 if BPDGToolName is not None:\r
47854fd5
LG
1815 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
1816 else:\r
1817 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
1818\r
52302d4d
LG
1819 ## Return the platform build data object\r
1820 def _GetPlatform(self):\r
4231a819 1821 if self._Platform is None:\r
0d2711a6 1822 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
1823 return self._Platform\r
1824\r
1825 ## Return platform name\r
1826 def _GetName(self):\r
1827 return self.Platform.PlatformName\r
1828\r
1829 ## Return the meta file GUID\r
1830 def _GetGuid(self):\r
1831 return self.Platform.Guid\r
1832\r
1833 ## Return the platform version\r
1834 def _GetVersion(self):\r
1835 return self.Platform.Version\r
1836\r
1837 ## Return the FDF file name\r
1838 def _GetFdfFile(self):\r
4231a819 1839 if self._FdfFile is None:\r
52302d4d 1840 if self.Workspace.FdfFile != "":\r
05cc51ad 1841 self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
52302d4d
LG
1842 else:\r
1843 self._FdfFile = ''\r
1844 return self._FdfFile\r
1845\r
1846 ## Return the build output directory platform specifies\r
1847 def _GetOutputDir(self):\r
1848 return self.Platform.OutputDirectory\r
1849\r
1850 ## Return the directory to store all intermediate and final files built\r
1851 def _GetBuildDir(self):\r
4231a819 1852 if self._BuildDir is None:\r
52302d4d
LG
1853 if os.path.isabs(self.OutputDir):\r
1854 self._BuildDir = path.join(\r
1855 path.abspath(self.OutputDir),\r
1856 self.BuildTarget + "_" + self.ToolChain,\r
1857 )\r
1858 else:\r
1859 self._BuildDir = path.join(\r
1860 self.WorkspaceDir,\r
1861 self.OutputDir,\r
1862 self.BuildTarget + "_" + self.ToolChain,\r
1863 )\r
97058144 1864 GlobalData.gBuildDirectory = self._BuildDir\r
52302d4d
LG
1865 return self._BuildDir\r
1866\r
1867 ## Return directory of platform makefile\r
1868 #\r
1869 # @retval string Makefile directory\r
1870 #\r
1871 def _GetMakeFileDir(self):\r
4231a819 1872 if self._MakeFileDir is None:\r
52302d4d
LG
1873 self._MakeFileDir = path.join(self.BuildDir, self.Arch)\r
1874 return self._MakeFileDir\r
1875\r
1876 ## Return build command string\r
1877 #\r
1878 # @retval string Build command string\r
1879 #\r
1880 def _GetBuildCommand(self):\r
4231a819 1881 if self._BuildCommand is None:\r
52302d4d
LG
1882 self._BuildCommand = []\r
1883 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
1884 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
1885 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
1886 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
1887 if NewOption != '':\r
6780eef1 1888 self._BuildCommand += SplitOption(NewOption)\r
02a908fc
YZ
1889 if "MAKE" in self.EdkIIBuildOption:\r
1890 if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
1891 Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
1892 if Flags.startswith('='):\r
1893 self._BuildCommand = [self._BuildCommand[0]] + [Flags[1:]]\r
1894 else:\r
1895 self._BuildCommand += [Flags]\r
52302d4d
LG
1896 return self._BuildCommand\r
1897\r
1898 ## Get tool chain definition\r
1899 #\r
1900 # Get each tool defition for given tool chain from tools_def.txt and platform\r
1901 #\r
1902 def _GetToolDefinition(self):\r
4231a819 1903 if self._ToolDefinitions is None:\r
52302d4d
LG
1904 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
1905 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
1906 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
1907 ExtraData="[%s]" % self.MetaFile)\r
1908 self._ToolDefinitions = {}\r
1909 DllPathList = set()\r
1910 for Def in ToolDefinition:\r
1911 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
1912 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
1913 continue\r
1914\r
1915 Value = ToolDefinition[Def]\r
1916 # don't record the DLL\r
1917 if Attr == "DLL":\r
1918 DllPathList.add(Value)\r
1919 continue\r
1920\r
1921 if Tool not in self._ToolDefinitions:\r
1922 self._ToolDefinitions[Tool] = {}\r
1923 self._ToolDefinitions[Tool][Attr] = Value\r
1924\r
1925 ToolsDef = ''\r
52302d4d
LG
1926 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:\r
1927 if "FLAGS" not in self._ToolDefinitions["MAKE"]:\r
1928 self._ToolDefinitions["MAKE"]["FLAGS"] = ""\r
1929 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"\r
1930 MakeFlags = ''\r
1931 for Tool in self._ToolDefinitions:\r
1932 for Attr in self._ToolDefinitions[Tool]:\r
1933 Value = self._ToolDefinitions[Tool][Attr]\r
1934 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:\r
1935 # check if override is indicated\r
1936 if self.BuildOption[Tool][Attr].startswith('='):\r
1937 Value = self.BuildOption[Tool][Attr][1:]\r
1938 else:\r
95816356
YZ
1939 if Attr != 'PATH':\r
1940 Value += " " + self.BuildOption[Tool][Attr]\r
1941 else:\r
1942 Value = self.BuildOption[Tool][Attr]\r
52302d4d
LG
1943\r
1944 if Attr == "PATH":\r
1945 # Don't put MAKE definition in the file\r
d98cce8e 1946 if Tool != "MAKE":\r
52302d4d
LG
1947 ToolsDef += "%s = %s\n" % (Tool, Value)\r
1948 elif Attr != "DLL":\r
1949 # Don't put MAKE definition in the file\r
1950 if Tool == "MAKE":\r
1951 if Attr == "FLAGS":\r
1952 MakeFlags = Value\r
1953 else:\r
1954 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
1955 ToolsDef += "\n"\r
1956\r
1957 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)\r
1958 for DllPath in DllPathList:\r
1959 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
1960 os.environ["MAKE_FLAGS"] = MakeFlags\r
1961\r
1962 return self._ToolDefinitions\r
1963\r
1964 ## Return the paths of tools\r
1965 def _GetToolDefFile(self):\r
4231a819 1966 if self._ToolDefFile is None:\r
52302d4d
LG
1967 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
1968 return self._ToolDefFile\r
1969\r
1970 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
1971 def _GetToolChainFamily(self):\r
4231a819 1972 if self._ToolChainFamily is None:\r
52302d4d
LG
1973 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1974 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
1975 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
1976 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
1977 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1978 % self.ToolChain)\r
1979 self._ToolChainFamily = "MSFT"\r
1980 else:\r
1981 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
1982 return self._ToolChainFamily\r
1983\r
1984 def _GetBuildRuleFamily(self):\r
4231a819 1985 if self._BuildRuleFamily is None:\r
52302d4d
LG
1986 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1987 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
1988 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
1989 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
1990 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1991 % self.ToolChain)\r
1992 self._BuildRuleFamily = "MSFT"\r
1993 else:\r
1994 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
1995 return self._BuildRuleFamily\r
1996\r
1997 ## Return the build options specific for all modules in this platform\r
1998 def _GetBuildOptions(self):\r
4231a819 1999 if self._BuildOption is None:\r
52302d4d
LG
2000 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)\r
2001 return self._BuildOption\r
2002\r
2003 ## Return the build options specific for EDK modules in this platform\r
2004 def _GetEdkBuildOptions(self):\r
4231a819 2005 if self._EdkBuildOption is None:\r
52302d4d
LG
2006 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
2007 return self._EdkBuildOption\r
2008\r
2009 ## Return the build options specific for EDKII modules in this platform\r
2010 def _GetEdkIIBuildOptions(self):\r
4231a819 2011 if self._EdkIIBuildOption is None:\r
52302d4d
LG
2012 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
2013 return self._EdkIIBuildOption\r
2014\r
97fa0ee9 2015 ## Parse build_rule.txt in Conf Directory.\r
52302d4d
LG
2016 #\r
2017 # @retval BuildRule object\r
2018 #\r
2019 def _GetBuildRule(self):\r
4231a819 2020 if self._BuildRule is None:\r
52302d4d
LG
2021 BuildRuleFile = None\r
2022 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
2023 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
c93356ad 2024 if not BuildRuleFile:\r
97fa0ee9 2025 BuildRuleFile = gDefaultBuildRuleFile\r
52302d4d 2026 self._BuildRule = BuildRule(BuildRuleFile)\r
64b2609f
LG
2027 if self._BuildRule._FileVersion == "":\r
2028 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum\r
2029 else:\r
2030 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :\r
2031 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
47fea6af 2032 EdkLogger.error("build", AUTOGEN_ERROR,\r
64b2609f
LG
2033 ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\\r
2034 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))\r
47fea6af 2035\r
52302d4d
LG
2036 return self._BuildRule\r
2037\r
2038 ## Summarize the packages used by modules in this platform\r
2039 def _GetPackageList(self):\r
4231a819 2040 if self._PackageList is None:\r
52302d4d
LG
2041 self._PackageList = set()\r
2042 for La in self.LibraryAutoGenList:\r
2043 self._PackageList.update(La.DependentPackageList)\r
2044 for Ma in self.ModuleAutoGenList:\r
2045 self._PackageList.update(Ma.DependentPackageList)\r
a0a2cd1e
FB
2046 #Collect package set information from INF of FDF\r
2047 PkgSet = set()\r
2048 for ModuleFile in self._AsBuildModuleList:\r
2049 if ModuleFile in self.Platform.Modules:\r
2050 continue\r
2051 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
2052 PkgSet.update(ModuleData.Packages)\r
2053 self._PackageList = list(self._PackageList) + list (PkgSet)\r
52302d4d
LG
2054 return self._PackageList\r
2055\r
2bc3256c
LG
2056 def _GetNonDynamicPcdDict(self):\r
2057 if self._NonDynamicPcdDict:\r
2058 return self._NonDynamicPcdDict\r
2059 for Pcd in self.NonDynamicPcdList:\r
2060 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd\r
2061 return self._NonDynamicPcdDict\r
2062\r
52302d4d
LG
2063 ## Get list of non-dynamic PCDs\r
2064 def _GetNonDynamicPcdList(self):\r
4231a819 2065 if self._NonDynamicPcdList is None:\r
e56468c0 2066 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
2067 return self._NonDynamicPcdList\r
2068\r
2069 ## Get list of dynamic PCDs\r
2070 def _GetDynamicPcdList(self):\r
4231a819 2071 if self._DynamicPcdList is None:\r
e56468c0 2072 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
2073 return self._DynamicPcdList\r
2074\r
2075 ## Generate Token Number for all PCD\r
2076 def _GetPcdTokenNumbers(self):\r
4231a819 2077 if self._PcdTokenNumber is None:\r
9006a2c6 2078 self._PcdTokenNumber = OrderedDict()\r
52302d4d 2079 TokenNumber = 1\r
d0acc87a
LG
2080 #\r
2081 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area. \r
2082 # Such as:\r
2083 # \r
2084 # Dynamic PCD:\r
2085 # TokenNumber 0 ~ 10\r
2086 # DynamicEx PCD:\r
2087 # TokeNumber 11 ~ 20\r
2088 #\r
52302d4d
LG
2089 for Pcd in self.DynamicPcdList:\r
2090 if Pcd.Phase == "PEI":\r
eece4292 2091 if Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
d0acc87a
LG
2092 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2093 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2094 TokenNumber += 1\r
47fea6af 2095\r
d0acc87a
LG
2096 for Pcd in self.DynamicPcdList:\r
2097 if Pcd.Phase == "PEI":\r
eece4292 2098 if Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
d0acc87a
LG
2099 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2100 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2101 TokenNumber += 1\r
47fea6af 2102\r
52302d4d
LG
2103 for Pcd in self.DynamicPcdList:\r
2104 if Pcd.Phase == "DXE":\r
eece4292 2105 if Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
d0acc87a
LG
2106 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2107 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2108 TokenNumber += 1\r
47fea6af 2109\r
d0acc87a
LG
2110 for Pcd in self.DynamicPcdList:\r
2111 if Pcd.Phase == "DXE":\r
eece4292 2112 if Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
d0acc87a
LG
2113 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2114 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2115 TokenNumber += 1\r
47fea6af 2116\r
52302d4d
LG
2117 for Pcd in self.NonDynamicPcdList:\r
2118 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2119 TokenNumber += 1\r
2120 return self._PcdTokenNumber\r
2121\r
2122 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform\r
2123 def _GetAutoGenObjectList(self):\r
2124 self._ModuleAutoGenList = []\r
2125 self._LibraryAutoGenList = []\r
2126 for ModuleFile in self.Platform.Modules:\r
2127 Ma = ModuleAutoGen(\r
2128 self.Workspace,\r
2129 ModuleFile,\r
2130 self.BuildTarget,\r
2131 self.ToolChain,\r
2132 self.Arch,\r
2133 self.MetaFile\r
2134 )\r
2135 if Ma not in self._ModuleAutoGenList:\r
2136 self._ModuleAutoGenList.append(Ma)\r
2137 for La in Ma.LibraryAutoGenList:\r
2138 if La not in self._LibraryAutoGenList:\r
2139 self._LibraryAutoGenList.append(La)\r
2bc3256c
LG
2140 if Ma not in La._ReferenceModules:\r
2141 La._ReferenceModules.append(Ma)\r
52302d4d
LG
2142\r
2143 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
2144 def _GetModuleAutoGenList(self):\r
4231a819 2145 if self._ModuleAutoGenList is None:\r
52302d4d
LG
2146 self._GetAutoGenObjectList()\r
2147 return self._ModuleAutoGenList\r
2148\r
2149 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
2150 def _GetLibraryAutoGenList(self):\r
4231a819 2151 if self._LibraryAutoGenList is None:\r
52302d4d
LG
2152 self._GetAutoGenObjectList()\r
2153 return self._LibraryAutoGenList\r
2154\r
2155 ## Test if a module is supported by the platform\r
2156 #\r
2157 # An error will be raised directly if the module or its arch is not supported\r
2158 # by the platform or current configuration\r
2159 #\r
2160 def ValidModule(self, Module):\r
a0a2cd1e
FB
2161 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
2162 or Module in self._AsBuildModuleList\r
52302d4d
LG
2163\r
2164 ## Resolve the library classes in a module to library instances\r
2165 #\r
2166 # This method will not only resolve library classes but also sort the library\r
2167 # instances according to the dependency-ship.\r
2168 #\r
2169 # @param Module The module from which the library classes will be resolved\r
2170 #\r
2171 # @retval library_list List of library instances sorted\r
2172 #\r
2173 def ApplyLibraryInstance(self, Module):\r
25193a33
YZ
2174 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly\r
2175 if str(Module) not in self.Platform.Modules:\r
2176 return []\r
2177\r
c14b5861
JC
2178 return GetModuleLibInstances(Module,\r
2179 self.Platform,\r
2180 self.BuildDatabase,\r
2181 self.Arch,\r
2182 self.BuildTarget,\r
2183 self.ToolChain,\r
2184 self.MetaFile,\r
2185 EdkLogger)\r
52302d4d
LG
2186\r
2187 ## Override PCD setting (type, value, ...)\r
2188 #\r
2189 # @param ToPcd The PCD to be overrided\r
2190 # @param FromPcd The PCD overrideing from\r
2191 #\r
a253d217 2192 def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
52302d4d
LG
2193 #\r
2194 # in case there's PCDs coming from FDF file, which have no type given.\r
2195 # at this point, ToPcd.Type has the type found from dependent\r
2196 # package\r
2197 #\r
2a29017e
YZ
2198 TokenCName = ToPcd.TokenCName\r
2199 for PcdItem in GlobalData.MixedPcd:\r
2200 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
2201 TokenCName = PcdItem[0]\r
2202 break\r
4231a819 2203 if FromPcd is not None:\r
c93356ad 2204 if ToPcd.Pending and FromPcd.Type:\r
52302d4d 2205 ToPcd.Type = FromPcd.Type\r
c93356ad 2206 elif (ToPcd.Type) and (FromPcd.Type)\\r
e56468c0 2207 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):\r
6b1f2cf4 2208 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r
47fea6af 2209 ToPcd.Type = FromPcd.Type\r
c93356ad 2210 elif ToPcd.Type and FromPcd.Type \\r
52302d4d 2211 and ToPcd.Type != FromPcd.Type:\r
a253d217
YF
2212 if Library:\r
2213 Module = str(Module) + " 's library file (" + str(Library) + ")"\r
52302d4d 2214 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
a253d217 2215 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r
2a29017e 2216 % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
a253d217 2217 ToPcd.Type, Module, FromPcd.Type, Msg),\r
52302d4d
LG
2218 File=self.MetaFile)\r
2219\r
6be94743 2220 if FromPcd.MaxDatumSize:\r
52302d4d 2221 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
c33081c9 2222 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r
6be94743 2223 if FromPcd.DefaultValue:\r
52302d4d 2224 ToPcd.DefaultValue = FromPcd.DefaultValue\r
6be94743 2225 if FromPcd.TokenValue:\r
52302d4d 2226 ToPcd.TokenValue = FromPcd.TokenValue\r
6be94743 2227 if FromPcd.DatumType:\r
52302d4d 2228 ToPcd.DatumType = FromPcd.DatumType\r
6be94743 2229 if FromPcd.SkuInfoList:\r
52302d4d 2230 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
726c501c 2231 # Add Flexible PCD format parse\r
726c501c 2232 if ToPcd.DefaultValue:\r
726c501c 2233 try:\r
35f613d9 2234 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)\r
726c501c
YZ
2235 except BadExpression, Value:\r
2236 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
2237 File=self.MetaFile)\r
52302d4d
LG
2238\r
2239 # check the validation of datum\r
2240 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
2241 if not IsValid:\r
2242 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
2a29017e 2243 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
82a6a960
BF
2244 ToPcd.validateranges = FromPcd.validateranges\r
2245 ToPcd.validlists = FromPcd.validlists\r
2246 ToPcd.expressions = FromPcd.expressions\r
52302d4d 2247\r
c93356ad 2248 if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
52302d4d 2249 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
2a29017e 2250 % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
52302d4d 2251 Value = ToPcd.DefaultValue\r
c93356ad 2252 if not Value:\r
e8a47801 2253 ToPcd.MaxDatumSize = '1'\r
52302d4d 2254 elif Value[0] == 'L':\r
e8a47801 2255 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
52302d4d
LG
2256 elif Value[0] == '{':\r
2257 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
2258 else:\r
e8a47801 2259 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
52302d4d
LG
2260\r
2261 # apply default SKU for dynamic PCDS if specified one is not available\r
eece4292 2262 if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r
c93356ad 2263 and not ToPcd.SkuInfoList:\r
52302d4d
LG
2264 if self.Platform.SkuName in self.Platform.SkuIds:\r
2265 SkuName = self.Platform.SkuName\r
2266 else:\r
55c84777 2267 SkuName = TAB_DEFAULT\r
52302d4d 2268 ToPcd.SkuInfoList = {\r
8518bf0b 2269 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
52302d4d
LG
2270 }\r
2271\r
2272 ## Apply PCD setting defined platform to a module\r
2273 #\r
2274 # @param Module The module from which the PCD setting will be overrided\r
2275 #\r
2276 # @retval PCD_list The list PCDs with settings from platform\r
2277 #\r
a253d217 2278 def ApplyPcdSetting(self, Module, Pcds, Library=""):\r
52302d4d 2279 # for each PCD in module\r
47fea6af
YZ
2280 for Name, Guid in Pcds:\r
2281 PcdInModule = Pcds[Name, Guid]\r
52302d4d 2282 # find out the PCD setting in platform\r
47fea6af
YZ
2283 if (Name, Guid) in self.Platform.Pcds:\r
2284 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
52302d4d
LG
2285 else:\r
2286 PcdInPlatform = None\r
2287 # then override the settings if any\r
a253d217 2288 self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r
52302d4d
LG
2289 # resolve the VariableGuid value\r
2290 for SkuId in PcdInModule.SkuInfoList:\r
2291 Sku = PcdInModule.SkuInfoList[SkuId]\r
2292 if Sku.VariableGuid == '': continue\r
c28d2e10 2293 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
4231a819 2294 if Sku.VariableGuidValue is None:\r
8252e6bf 2295 PackageList = "\n\t".join(str(P) for P in self.PackageList)\r
52302d4d
LG
2296 EdkLogger.error(\r
2297 'build',\r
2298 RESOURCE_NOT_AVAILABLE,\r
2299 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
2300 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
2301 % (Guid, Name, str(Module)),\r
2302 File=self.MetaFile\r
2303 )\r
2304\r
2305 # override PCD settings with module specific setting\r
2306 if Module in self.Platform.Modules:\r
2307 PlatformModule = self.Platform.Modules[str(Module)]\r
2308 for Key in PlatformModule.Pcds:\r
aa9aa47e 2309 Flag = False\r
52302d4d 2310 if Key in Pcds:\r
aa9aa47e
YZ
2311 ToPcd = Pcds[Key]\r
2312 Flag = True\r
2313 elif Key in GlobalData.MixedPcd:\r
2314 for PcdItem in GlobalData.MixedPcd[Key]:\r
2315 if PcdItem in Pcds:\r
2316 ToPcd = Pcds[PcdItem]\r
2317 Flag = True\r
2318 break\r
2319 if Flag:\r
a253d217 2320 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r
cdbf45ad
YZ
2321 # use PCD value to calculate the MaxDatumSize when it is not specified\r
2322 for Name, Guid in Pcds:\r
2323 Pcd = Pcds[Name, Guid]\r
c93356ad 2324 if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r
c33081c9 2325 Pcd.MaxSizeUserSet = None\r
cdbf45ad 2326 Value = Pcd.DefaultValue\r
c93356ad 2327 if not Value:\r
cdbf45ad
YZ
2328 Pcd.MaxDatumSize = '1'\r
2329 elif Value[0] == 'L':\r
2330 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
2331 elif Value[0] == '{':\r
2332 Pcd.MaxDatumSize = str(len(Value.split(',')))\r
2333 else:\r
2334 Pcd.MaxDatumSize = str(len(Value) - 1)\r
52302d4d
LG
2335 return Pcds.values()\r
2336\r
2337 ## Resolve library names to library modules\r
2338 #\r
b36d134f 2339 # (for Edk.x modules)\r
52302d4d
LG
2340 #\r
2341 # @param Module The module from which the library names will be resolved\r
2342 #\r
2343 # @retval library_list The list of library modules\r
2344 #\r
2345 def ResolveLibraryReference(self, Module):\r
2346 EdkLogger.verbose("")\r
2347 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
2348 LibraryConsumerList = [Module]\r
2349\r
b36d134f 2350 # "CompilerStub" is a must for Edk modules\r
52302d4d
LG
2351 if Module.Libraries:\r
2352 Module.Libraries.append("CompilerStub")\r
2353 LibraryList = []\r
2354 while len(LibraryConsumerList) > 0:\r
2355 M = LibraryConsumerList.pop()\r
2356 for LibraryName in M.Libraries:\r
2357 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']\r
4231a819 2358 if Library is None:\r
9eb87141 2359 for Key in self.Platform.LibraryClasses.data:\r
52302d4d
LG
2360 if LibraryName.upper() == Key.upper():\r
2361 Library = self.Platform.LibraryClasses[Key, ':dummy:']\r
2362 break\r
4231a819 2363 if Library is None:\r
52302d4d
LG
2364 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),\r
2365 ExtraData="\t%s [%s]" % (str(Module), self.Arch))\r
2366 continue\r
2367\r
2368 if Library not in LibraryList:\r
2369 LibraryList.append(Library)\r
2370 LibraryConsumerList.append(Library)\r
2371 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
2372 return LibraryList\r
2373\r
6780eef1
LG
2374 ## Calculate the priority value of the build option\r
2375 #\r
2376 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2377 #\r
2378 # @retval Value Priority value based on the priority list.\r
2379 #\r
2380 def CalculatePriorityValue(self, Key):\r
47fea6af
YZ
2381 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
2382 PriorityValue = 0x11111\r
6780eef1
LG
2383 if Target == "*":\r
2384 PriorityValue &= 0x01111\r
2385 if ToolChain == "*":\r
2386 PriorityValue &= 0x10111\r
2387 if Arch == "*":\r
2388 PriorityValue &= 0x11011\r
2389 if CommandType == "*":\r
2390 PriorityValue &= 0x11101\r
2391 if Attr == "*":\r
2392 PriorityValue &= 0x11110\r
47fea6af
YZ
2393\r
2394 return self.PrioList["0x%0.5x" % PriorityValue]\r
2395\r
6780eef1 2396\r
52302d4d
LG
2397 ## Expand * in build option key\r
2398 #\r
2399 # @param Options Options to be expanded\r
2400 #\r
2401 # @retval options Options expanded\r
6780eef1 2402 # \r
52302d4d
LG
2403 def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
2404 BuildOptions = {}\r
2405 FamilyMatch = False\r
2406 FamilyIsNull = True\r
47fea6af 2407\r
6780eef1
LG
2408 OverrideList = {}\r
2409 #\r
2410 # Construct a list contain the build options which need override.\r
2411 #\r
2412 for Key in Options:\r
2413 #\r
2414 # Key[0] -- tool family\r
2415 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2416 #\r
1ba5124e 2417 if (Key[0] == self.BuildRuleFamily and\r
4231a819 2418 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
6780eef1
LG
2419 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
2420 if Target == self.BuildTarget or Target == "*":\r
2421 if ToolChain == self.ToolChain or ToolChain == "*":\r
2422 if Arch == self.Arch or Arch == "*":\r
2423 if Options[Key].startswith("="):\r
4231a819 2424 if OverrideList.get(Key[1]) is not None:\r
6780eef1
LG
2425 OverrideList.pop(Key[1])\r
2426 OverrideList[Key[1]] = Options[Key]\r
2427 \r
2428 #\r
2429 # Use the highest priority value. \r
2430 #\r
2431 if (len(OverrideList) >= 2):\r
47fea6af 2432 KeyList = OverrideList.keys()\r
6780eef1 2433 for Index in range(len(KeyList)):\r
47fea6af 2434 NowKey = KeyList[Index]\r
6780eef1
LG
2435 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
2436 for Index1 in range(len(KeyList) - Index - 1):\r
2437 NextKey = KeyList[Index1 + Index + 1]\r
2438 #\r
2439 # Compare two Key, if one is included by another, choose the higher priority one\r
2440 # \r
2441 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
2442 if Target1 == Target2 or Target1 == "*" or Target2 == "*":\r
2443 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":\r
2444 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":\r
2445 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":\r
2446 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":\r
2447 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
4231a819 2448 if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
6780eef1
LG
2449 Options.pop((self.BuildRuleFamily, NextKey))\r
2450 else:\r
4231a819 2451 if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
6780eef1
LG
2452 Options.pop((self.BuildRuleFamily, NowKey))\r
2453 \r
52302d4d 2454 for Key in Options:\r
4231a819 2455 if ModuleStyle is not None and len (Key) > 2:\r
52302d4d
LG
2456 # Check Module style is EDK or EDKII.\r
2457 # Only append build option for the matched style module.\r
2458 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2459 continue\r
2460 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2461 continue\r
2462 Family = Key[0]\r
2463 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2464 # if tool chain family doesn't match, skip it\r
2465 if Tool in self.ToolDefinition and Family != "":\r
2466 FamilyIsNull = False\r
2467 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
2468 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
2469 continue\r
2470 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2471 continue\r
2472 FamilyMatch = True\r
2473 # expand any wildcard\r
2474 if Target == "*" or Target == self.BuildTarget:\r
2475 if Tag == "*" or Tag == self.ToolChain:\r
2476 if Arch == "*" or Arch == self.Arch:\r
2477 if Tool not in BuildOptions:\r
2478 BuildOptions[Tool] = {}\r
5015bee2 2479 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2480 BuildOptions[Tool][Attr] = Options[Key]\r
2481 else:\r
95816356
YZ
2482 # append options for the same tool except PATH\r
2483 if Attr != 'PATH':\r
2484 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2485 else:\r
2486 BuildOptions[Tool][Attr] = Options[Key]\r
52302d4d
LG
2487 # Build Option Family has been checked, which need't to be checked again for family.\r
2488 if FamilyMatch or FamilyIsNull:\r
2489 return BuildOptions\r
1ba5124e 2490\r
52302d4d 2491 for Key in Options:\r
4231a819 2492 if ModuleStyle is not None and len (Key) > 2:\r
52302d4d
LG
2493 # Check Module style is EDK or EDKII.\r
2494 # Only append build option for the matched style module.\r
2495 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2496 continue\r
2497 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2498 continue\r
2499 Family = Key[0]\r
2500 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2501 # if tool chain family doesn't match, skip it\r
47fea6af 2502 if Tool not in self.ToolDefinition or Family == "":\r
52302d4d
LG
2503 continue\r
2504 # option has been added before\r
2505 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2506 continue\r
2507\r
2508 # expand any wildcard\r
2509 if Target == "*" or Target == self.BuildTarget:\r
2510 if Tag == "*" or Tag == self.ToolChain:\r
2511 if Arch == "*" or Arch == self.Arch:\r
2512 if Tool not in BuildOptions:\r
2513 BuildOptions[Tool] = {}\r
5015bee2 2514 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2515 BuildOptions[Tool][Attr] = Options[Key]\r
2516 else:\r
95816356
YZ
2517 # append options for the same tool except PATH\r
2518 if Attr != 'PATH':\r
2519 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2520 else:\r
2521 BuildOptions[Tool][Attr] = Options[Key]\r
52302d4d
LG
2522 return BuildOptions\r
2523\r
2524 ## Append build options in platform to a module\r
2525 #\r
2526 # @param Module The module to which the build options will be appened\r
2527 #\r
2528 # @retval options The options appended with build options in platform\r
2529 #\r
2530 def ApplyBuildOption(self, Module):\r
2531 # Get the different options for the different style module\r
2532 if Module.AutoGenVersion < 0x00010005:\r
2533 PlatformOptions = self.EdkBuildOption\r
35f69db9 2534 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)\r
52302d4d
LG
2535 else:\r
2536 PlatformOptions = self.EdkIIBuildOption\r
35f69db9
YL
2537 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
2538 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
52302d4d
LG
2539 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
2540 if Module in self.Platform.Modules:\r
2541 PlatformModule = self.Platform.Modules[str(Module)]\r
2542 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
2543 else:\r
2544 PlatformModuleOptions = {}\r
2545\r
fe4bf2f9 2546 BuildRuleOrder = None\r
35f69db9 2547 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
fe4bf2f9
YL
2548 for Tool in Options:\r
2549 for Attr in Options[Tool]:\r
2550 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2551 BuildRuleOrder = Options[Tool][Attr]\r
2552\r
35f69db9
YL
2553 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +\r
2554 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +\r
2555 self.ToolDefinition.keys())\r
339fe8dd 2556 BuildOptions = defaultdict(lambda: defaultdict(str))\r
52302d4d 2557 for Tool in AllTools:\r
35f69db9 2558 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
52302d4d
LG
2559 if Tool not in Options:\r
2560 continue\r
2561 for Attr in Options[Tool]:\r
fe4bf2f9
YL
2562 #\r
2563 # Do not generate it in Makefile\r
2564 #\r
2565 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2566 continue\r
339fe8dd 2567 Value = Options[Tool][Attr]\r
52302d4d
LG
2568 # check if override is indicated\r
2569 if Value.startswith('='):\r
339fe8dd 2570 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])\r
5015bee2 2571 else:\r
95816356 2572 if Attr != 'PATH':\r
339fe8dd 2573 BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)\r
95816356 2574 else:\r
339fe8dd
CJ
2575 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
2576\r
4231a819 2577 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag is not None:\r
f3decdc3
LG
2578 #\r
2579 # Override UNI flag only for EDK module.\r
2580 #\r
f3decdc3 2581 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
fe4bf2f9 2582 return BuildOptions, BuildRuleOrder\r
52302d4d
LG
2583\r
2584 Platform = property(_GetPlatform)\r
2585 Name = property(_GetName)\r
2586 Guid = property(_GetGuid)\r
2587 Version = property(_GetVersion)\r
2588\r
2589 OutputDir = property(_GetOutputDir)\r
2590 BuildDir = property(_GetBuildDir)\r
2591 MakeFileDir = property(_GetMakeFileDir)\r
2592 FdfFile = property(_GetFdfFile)\r
2593\r
2594 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
2595 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2596 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 2597 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)\r
52302d4d
LG
2598 PackageList = property(_GetPackageList)\r
2599\r
2600 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
2601 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path\r
2602 ToolChainFamily = property(_GetToolChainFamily)\r
2603 BuildRuleFamily = property(_GetBuildRuleFamily)\r
2604 BuildOption = property(_GetBuildOptions) # toolcode : option\r
2605 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option\r
2606 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option\r
2607\r
2608 BuildCommand = property(_GetBuildCommand)\r
2609 BuildRule = property(_GetBuildRule)\r
2610 ModuleAutoGenList = property(_GetModuleAutoGenList)\r
2611 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
0923aa1c 2612 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
2613\r
2614## ModuleAutoGen class\r
2615#\r
2616# This class encapsules the AutoGen behaviors for the build tools. In addition to\r
2617# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according\r
2618# to the [depex] section in module's inf file.\r
2619#\r
2620class ModuleAutoGen(AutoGen):\r
b24e99f7
CJ
2621 # call super().__init__ then call the worker function with different parameter count\r
2622 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
2623 try:\r
2624 self._Init\r
2625 except:\r
2626 super(ModuleAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
2627 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)\r
2628 self._Init = True\r
2629\r
c17956e0
DL
2630 ## Cache the timestamps of metafiles of every module in a class variable\r
2631 #\r
2632 TimeDict = {}\r
2633\r
b24e99f7
CJ
2634 def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
2635 obj = super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
2636 # check if this module is employed by active platform\r
2637 if not PlatformAutoGen(Workspace, args[0], Target, Toolchain, Arch).ValidModule(MetaFile):\r
2638 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
2639 % (MetaFile, Arch))\r
2640 return None\r
2641 return obj\r
2642 \r
2643 ## Initialize ModuleAutoGen\r
52302d4d
LG
2644 #\r
2645 # @param Workspace EdkIIWorkspaceBuild object\r
2646 # @param ModuleFile The path of module file\r
2647 # @param Target Build target (DEBUG, RELEASE)\r
2648 # @param Toolchain Name of tool chain\r
2649 # @param Arch The arch the module supports\r
2650 # @param PlatformFile Platform meta-file\r
2651 #\r
b24e99f7 2652 def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):\r
52302d4d
LG
2653 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))\r
2654 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)\r
2655\r
2656 self.Workspace = Workspace\r
2657 self.WorkspaceDir = Workspace.WorkspaceDir\r
f9fa014e 2658 self._GuidDict = Workspace._GuidDict\r
52302d4d
LG
2659 self.MetaFile = ModuleFile\r
2660 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
52302d4d
LG
2661\r
2662 self.SourceDir = self.MetaFile.SubDir\r
05cc51ad 2663 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
97fa0ee9 2664\r
52302d4d
LG
2665 self.SourceOverrideDir = None\r
2666 # use overrided path defined in DSC file\r
2667 if self.MetaFile.Key in GlobalData.gOverrideDir:\r
2668 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]\r
2669\r
2670 self.ToolChain = Toolchain\r
2671 self.BuildTarget = Target\r
2672 self.Arch = Arch\r
2673 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
2674 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
2675\r
2676 self.IsMakeFileCreated = False\r
2677 self.IsCodeFileCreated = False\r
da92f276
LG
2678 self.IsAsBuiltInfCreated = False\r
2679 self.DepexGenerated = False\r
52302d4d
LG
2680\r
2681 self.BuildDatabase = self.Workspace.BuildDatabase\r
fe4bf2f9 2682 self.BuildRuleOrder = None\r
1b8eca8b 2683 self.BuildTime = 0\r
52302d4d
LG
2684\r
2685 self._Module = None\r
2686 self._Name = None\r
2687 self._Guid = None\r
2688 self._Version = None\r
2689 self._ModuleType = None\r
2690 self._ComponentType = None\r
2691 self._PcdIsDriver = None\r
2692 self._AutoGenVersion = None\r
2693 self._LibraryFlag = None\r
2694 self._CustomMakefile = None\r
2695 self._Macro = None\r
2696\r
2697 self._BuildDir = None\r
2698 self._OutputDir = None\r
37de70b7 2699 self._FfsOutputDir = None\r
52302d4d
LG
2700 self._DebugDir = None\r
2701 self._MakeFileDir = None\r
2702\r
2703 self._IncludePathList = None\r
725cdb8f 2704 self._IncludePathLength = 0\r
52302d4d
LG
2705 self._AutoGenFileList = None\r
2706 self._UnicodeFileList = None\r
5b97eb4c 2707 self._VfrFileList = None\r
333ba578 2708 self._IdfFileList = None\r
52302d4d
LG
2709 self._SourceFileList = None\r
2710 self._ObjectFileList = None\r