]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/AutoGen.py
BaseTools: small cleanup
[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
40d841f6 5# This program and the accompanying materials\r
52302d4d
LG
6# are licensed and made available under the terms and conditions of the BSD License\r
7# which accompanies this distribution. The full text of the license may be found at\r
8# http://opensource.org/licenses/bsd-license.php\r
9#\r
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12#\r
13\r
14## Import Modules\r
15#\r
1be2ed90 16import Common.LongFilePathOs as os\r
52302d4d
LG
17import re\r
18import os.path as path\r
19import copy\r
867d1cd4 20import uuid\r
52302d4d
LG
21\r
22import GenC\r
23import GenMake\r
24import GenDepex\r
25from StringIO import StringIO\r
26\r
27from StrGather import *\r
28from BuildEngine import BuildRule\r
29\r
1be2ed90 30from Common.LongFilePathSupport import CopyLongFilePath\r
52302d4d
LG
31from Common.BuildToolError import *\r
32from Common.DataType import *\r
33from Common.Misc import *\r
34from Common.String import *\r
35import Common.GlobalData as GlobalData\r
36from GenFds.FdfParser import *\r
37from CommonDataClass.CommonClass import SkuInfoClass\r
38from Workspace.BuildClassObject import *\r
e8a47801 39from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile\r
e56468c0 40import Common.VpdInfoFile as VpdInfoFile\r
e8a47801
LG
41from GenPcdDb import CreatePcdDatabaseCode\r
42from Workspace.MetaFileCommentParser import UsageList\r
05cc51ad 43from Common.MultipleWorkspace import MultipleWorkspace as mws\r
97fa0ee9 44import InfSectionParser\r
c17956e0 45import datetime\r
36d083ef 46import hashlib\r
8518bf0b 47from GenVar import VariableMgr,var_info\r
9006a2c6 48from collections import OrderedDict\r
97fa0ee9 49\r
e8a47801 50## Regular expression for splitting Dependency Expression string into tokens\r
52302d4d
LG
51gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
52\r
c8802c3d
CJ
53## Regular expression for match: PCD(xxxx.yyy)\r
54gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")\r
55\r
56#\r
57# Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
58# is the former use /I , the Latter used -I to specify include directories\r
59#\r
60gBuildOptIncludePatternMsft = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
61gBuildOptIncludePatternOther = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
62\r
97fa0ee9
YL
63#\r
64# Match name = variable\r
65#\r
66gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")\r
67#\r
68# The format of guid in efivarstore statement likes following and must be correct:\r
69# guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}\r
70#\r
71gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")\r
72\r
52302d4d
LG
73## Mapping Makefile type\r
74gMakeTypeMap = {"MSFT":"nmake", "GCC":"gmake"}\r
75\r
76\r
77## Build rule configuration file\r
51de5c30 78gDefaultBuildRuleFile = 'build_rule.txt'\r
52302d4d 79\r
86601b78 80## Tools definition configuration file\r
51de5c30 81gDefaultToolsDefFile = 'tools_def.txt'\r
86601b78 82\r
64b2609f
LG
83## Build rule default version\r
84AutoGenReqBuildRuleVerNum = "0.1"\r
85\r
52302d4d
LG
86## default file name for AutoGen\r
87gAutoGenCodeFileName = "AutoGen.c"\r
88gAutoGenHeaderFileName = "AutoGen.h"\r
89gAutoGenStringFileName = "%(module_name)sStrDefs.h"\r
90gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"\r
91gAutoGenDepexFileName = "%(module_name)s.depex"\r
333ba578
YZ
92gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"\r
93gAutoGenIdfFileName = "%(module_name)sIdf.hpk"\r
97fa0ee9
YL
94gInfSpecVersion = "0x00010017"\r
95\r
da92f276
LG
96#\r
97# Template string to generic AsBuilt INF\r
98#\r
e8a47801 99gAsBuiltInfHeaderString = TemplateString("""${header_comments}\r
da92f276 100\r
97fa0ee9
YL
101# DO NOT EDIT\r
102# FILE auto-generated\r
103\r
da92f276 104[Defines]\r
97fa0ee9 105 INF_VERSION = ${module_inf_version}\r
da92f276
LG
106 BASE_NAME = ${module_name}\r
107 FILE_GUID = ${module_guid}\r
97fa0ee9
YL
108 MODULE_TYPE = ${module_module_type}${BEGIN}\r
109 VERSION_STRING = ${module_version_string}${END}${BEGIN}\r
e8a47801 110 PCD_IS_DRIVER = ${pcd_is_driver_string}${END}${BEGIN}\r
da92f276 111 UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}\r
97fa0ee9
YL
112 PI_SPECIFICATION_VERSION = ${module_pi_specification_version}${END}${BEGIN}\r
113 ENTRY_POINT = ${module_entry_point}${END}${BEGIN}\r
114 UNLOAD_IMAGE = ${module_unload_image}${END}${BEGIN}\r
115 CONSTRUCTOR = ${module_constructor}${END}${BEGIN}\r
116 DESTRUCTOR = ${module_destructor}${END}${BEGIN}\r
117 SHADOW = ${module_shadow}${END}${BEGIN}\r
118 PCI_VENDOR_ID = ${module_pci_vendor_id}${END}${BEGIN}\r
119 PCI_DEVICE_ID = ${module_pci_device_id}${END}${BEGIN}\r
120 PCI_CLASS_CODE = ${module_pci_class_code}${END}${BEGIN}\r
121 PCI_REVISION = ${module_pci_revision}${END}${BEGIN}\r
122 BUILD_NUMBER = ${module_build_number}${END}${BEGIN}\r
123 SPEC = ${module_spec}${END}${BEGIN}\r
124 UEFI_HII_RESOURCE_SECTION = ${module_uefi_hii_resource_section}${END}${BEGIN}\r
125 MODULE_UNI_FILE = ${module_uni_file}${END}\r
126\r
127[Packages.${module_arch}]${BEGIN}\r
da92f276
LG
128 ${package_item}${END}\r
129\r
130[Binaries.${module_arch}]${BEGIN}\r
131 ${binary_item}${END}\r
132\r
e8a47801
LG
133[PatchPcd.${module_arch}]${BEGIN}\r
134 ${patchablepcd_item}\r
135${END}\r
97fa0ee9 136\r
e8a47801
LG
137[Protocols.${module_arch}]${BEGIN}\r
138 ${protocol_item}\r
139${END}\r
97fa0ee9 140\r
e8a47801
LG
141[Ppis.${module_arch}]${BEGIN}\r
142 ${ppi_item}\r
143${END}\r
97fa0ee9 144\r
e8a47801
LG
145[Guids.${module_arch}]${BEGIN}\r
146 ${guid_item}\r
147${END}\r
97fa0ee9 148\r
e8a47801
LG
149[PcdEx.${module_arch}]${BEGIN}\r
150 ${pcd_item}\r
151${END}\r
da92f276 152\r
97fa0ee9
YL
153[LibraryClasses.${module_arch}]\r
154## @LIB_INSTANCES${BEGIN}\r
155# ${libraryclasses_item}${END}\r
156\r
157${depexsection_item}\r
158\r
dfa41b4a
YZ
159${userextension_tianocore_item}\r
160\r
97fa0ee9
YL
161${tail_comments}\r
162\r
163[BuildOptions.${module_arch}]\r
da92f276
LG
164## @AsBuilt${BEGIN}\r
165## ${flags_item}${END}\r
166""")\r
167\r
52302d4d
LG
168## Base class for AutoGen\r
169#\r
170# This class just implements the cache mechanism of AutoGen objects.\r
171#\r
172class AutoGen(object):\r
b24e99f7
CJ
173 # database to maintain the objects in each child class\r
174 __ObjectCache = {} # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object\r
52302d4d
LG
175\r
176 ## Factory method\r
177 #\r
178 # @param Class class object of real AutoGen class\r
179 # (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)\r
180 # @param Workspace Workspace directory or WorkspaceAutoGen object\r
181 # @param MetaFile The path of meta file\r
182 # @param Target Build target\r
183 # @param Toolchain Tool chain name\r
184 # @param Arch Target arch\r
185 # @param *args The specific class related parameters\r
186 # @param **kwargs The specific class related dict parameters\r
187 #\r
b24e99f7 188 def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
52302d4d 189 # check if the object has been created\r
b24e99f7
CJ
190 Key = (Target, Toolchain, Arch, MetaFile)\r
191 try:\r
192 # if it exists, just return it directly\r
193 return cls.__ObjectCache[Key]\r
194 except:\r
195 # it didnt exist. create it, cache it, then return it\r
196 cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls)\r
197 return cls.__ObjectCache[Key]\r
198\r
199 def __init__ (self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
200 super(AutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
52302d4d
LG
201\r
202 ## hash() operator\r
203 #\r
204 # The file path of platform file will be used to represent hash value of this object\r
205 #\r
206 # @retval int Hash value of the file path of platform file\r
207 #\r
208 def __hash__(self):\r
209 return hash(self.MetaFile)\r
210\r
211 ## str() operator\r
212 #\r
213 # The file path of platform file will be used to represent this object\r
214 #\r
215 # @retval string String of platform file path\r
216 #\r
217 def __str__(self):\r
218 return str(self.MetaFile)\r
219\r
220 ## "==" operator\r
221 def __eq__(self, Other):\r
222 return Other and self.MetaFile == Other\r
223\r
224## Workspace AutoGen class\r
225#\r
226# This class is used mainly to control the whole platform build for different\r
227# architecture. This class will generate top level makefile.\r
228#\r
229class WorkspaceAutoGen(AutoGen):\r
b24e99f7
CJ
230 # call super().__init__ then call the worker function with different parameter count\r
231 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
232 try:\r
233 self._Init\r
234 except:\r
235 super(WorkspaceAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
236 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
237 self._Init = True\r
238 \r
239 ## Initialize WorkspaceAutoGen\r
52302d4d
LG
240 #\r
241 # @param WorkspaceDir Root directory of workspace\r
242 # @param ActivePlatform Meta-file of active platform\r
243 # @param Target Build target\r
244 # @param Toolchain Tool chain name\r
245 # @param ArchList List of architecture of current build\r
246 # @param MetaFileDb Database containing meta-files\r
247 # @param BuildConfig Configuration of build\r
248 # @param ToolDefinition Tool chain definitions\r
249 # @param FlashDefinitionFile File of flash definition\r
250 # @param Fds FD list to be generated\r
251 # @param Fvs FV list to be generated\r
4234283c 252 # @param Caps Capsule list to be generated\r
52302d4d
LG
253 # @param SkuId SKU id from command line\r
254 #\r
b24e99f7 255 def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,\r
47fea6af 256 BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,\r
9508d0fa 257 Progress=None, BuildModule=None):\r
4234283c
LG
258 if Fds is None:\r
259 Fds = []\r
260 if Fvs is None:\r
261 Fvs = []\r
262 if Caps is None:\r
263 Caps = []\r
0d2711a6
LG
264 self.BuildDatabase = MetaFileDb\r
265 self.MetaFile = ActivePlatform\r
52302d4d 266 self.WorkspaceDir = WorkspaceDir\r
0d2711a6 267 self.Platform = self.BuildDatabase[self.MetaFile, 'COMMON', Target, Toolchain]\r
d0acc87a 268 GlobalData.gActivePlatform = self.Platform\r
52302d4d
LG
269 self.BuildTarget = Target\r
270 self.ToolChain = Toolchain\r
271 self.ArchList = ArchList\r
272 self.SkuId = SkuId\r
f3decdc3 273 self.UniFlag = UniFlag\r
52302d4d 274\r
52302d4d
LG
275 self.TargetTxt = BuildConfig\r
276 self.ToolDef = ToolDefinition\r
277 self.FdfFile = FlashDefinitionFile\r
278 self.FdTargetList = Fds\r
279 self.FvTargetList = Fvs\r
4234283c 280 self.CapTargetList = Caps\r
52302d4d 281 self.AutoGenObjectList = []\r
36d083ef
YZ
282 self._BuildDir = None\r
283 self._FvDir = None\r
284 self._MakeFileDir = None\r
285 self._BuildCommand = None\r
726c501c 286 self._GuidDict = {}\r
52302d4d
LG
287\r
288 # there's many relative directory operations, so ...\r
289 os.chdir(self.WorkspaceDir)\r
290\r
0d2711a6
LG
291 #\r
292 # Merge Arch\r
293 #\r
294 if not self.ArchList:\r
295 ArchList = set(self.Platform.SupArchList)\r
296 else:\r
297 ArchList = set(self.ArchList) & set(self.Platform.SupArchList)\r
298 if not ArchList:\r
299 EdkLogger.error("build", PARAMETER_INVALID,\r
300 ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))\r
301 elif self.ArchList and len(ArchList) != len(self.ArchList):\r
302 SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))\r
303 EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"\r
304 % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))\r
305 self.ArchList = tuple(ArchList)\r
306\r
307 # Validate build target\r
308 if self.BuildTarget not in self.Platform.BuildTargets:\r
47fea6af 309 EdkLogger.error("build", PARAMETER_INVALID,\r
0d2711a6
LG
310 ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"\r
311 % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))\r
312\r
12d37ace 313 \r
52302d4d 314 # parse FDF file to get PCDs in it, if any\r
0d2711a6
LG
315 if not self.FdfFile:\r
316 self.FdfFile = self.Platform.FlashDefinition\r
47fea6af 317\r
9508d0fa
LG
318 EdkLogger.info("")\r
319 if self.ArchList:\r
320 EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))\r
321 EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))\r
47fea6af
YZ
322 EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))\r
323\r
9508d0fa
LG
324 EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))\r
325 if BuildModule:\r
326 EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))\r
47fea6af 327\r
9508d0fa
LG
328 if self.FdfFile:\r
329 EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))\r
0d2711a6 330\r
9508d0fa 331 EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)\r
47fea6af 332\r
e74cea4c
YZ
333 if Progress:\r
334 Progress.Start("\nProcessing meta-data")\r
47fea6af 335\r
0d2711a6 336 if self.FdfFile:\r
df692f02
LG
337 #\r
338 # Mark now build in AutoGen Phase\r
339 #\r
47fea6af 340 GlobalData.gAutoGenPhase = True\r
52302d4d
LG
341 Fdf = FdfParser(self.FdfFile.Path)\r
342 Fdf.ParseFile()\r
a0a2cd1e 343 GlobalData.gFdfParser = Fdf\r
0d2711a6 344 GlobalData.gAutoGenPhase = False\r
52302d4d 345 PcdSet = Fdf.Profile.PcdDict\r
cb04330e
YZ
346 if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:\r
347 FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]\r
348 for FdRegion in FdDict.RegionList:\r
349 if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):\r
350 if int(FdRegion.Offset) % 8 != 0:\r
351 EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))\r
52302d4d
LG
352 ModuleList = Fdf.Profile.InfList\r
353 self.FdfProfile = Fdf.Profile\r
0d2711a6
LG
354 for fvname in self.FvTargetList:\r
355 if fvname.upper() not in self.FdfProfile.FvDict:\r
356 EdkLogger.error("build", OPTION_VALUE_INVALID,\r
357 "No such an FV in FDF file: %s" % fvname)\r
2502b735 358\r
622b1758
YZ
359 # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,\r
360 # but the path (self.MetaFile.Path) is the real path\r
2502b735
YZ
361 for key in self.FdfProfile.InfDict:\r
362 if key == 'ArchTBD':\r
363 Platform_cache = {}\r
622b1758 364 MetaFile_cache = {}\r
2502b735
YZ
365 for Arch in self.ArchList:\r
366 Platform_cache[Arch] = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
622b1758
YZ
367 MetaFile_cache[Arch] = []\r
368 for Pkey in Platform_cache[Arch].Modules.keys():\r
369 MetaFile_cache[Arch].append(Platform_cache[Arch].Modules[Pkey].MetaFile)\r
2502b735
YZ
370 for Inf in self.FdfProfile.InfDict[key]:\r
371 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
372 for Arch in self.ArchList:\r
622b1758 373 if ModuleFile in MetaFile_cache[Arch]:\r
2502b735
YZ
374 break\r
375 else:\r
376 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
377 if not ModuleData.IsBinaryModule:\r
378 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
379\r
380 else:\r
381 for Arch in self.ArchList:\r
382 if Arch == key:\r
383 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
622b1758
YZ
384 MetaFileList = []\r
385 for Pkey in Platform.Modules.keys():\r
386 MetaFileList.append(Platform.Modules[Pkey].MetaFile)\r
2502b735
YZ
387 for Inf in self.FdfProfile.InfDict[key]:\r
388 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
622b1758 389 if ModuleFile in MetaFileList:\r
2502b735
YZ
390 continue\r
391 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
392 if not ModuleData.IsBinaryModule:\r
393 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
394\r
52302d4d
LG
395 else:\r
396 PcdSet = {}\r
397 ModuleList = []\r
398 self.FdfProfile = None\r
0d2711a6
LG
399 if self.FdTargetList:\r
400 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))\r
401 self.FdTargetList = []\r
402 if self.FvTargetList:\r
403 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))\r
404 self.FvTargetList = []\r
405 if self.CapTargetList:\r
406 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))\r
407 self.CapTargetList = []\r
47fea6af 408\r
52302d4d
LG
409 # apply SKU and inject PCDs from Flash Definition file\r
410 for Arch in self.ArchList:\r
0d2711a6 411 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
64b2609f 412\r
ff5635e9
CJ
413 SourcePcdDict = {'DynamicEx':set(), 'PatchableInModule':set(),'Dynamic':set(),'FixedAtBuild':set()}\r
414 BinaryPcdDict = {'DynamicEx':set(), 'PatchableInModule':set()}\r
2a29017e
YZ
415 SourcePcdDict_Keys = SourcePcdDict.keys()\r
416 BinaryPcdDict_Keys = BinaryPcdDict.keys()\r
417\r
418 # generate the SourcePcdDict and BinaryPcdDict\r
6f49996c 419 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
2a29017e
YZ
420 for BuildData in PGen.BuildDatabase._CACHE_.values():\r
421 if BuildData.Arch != Arch:\r
422 continue\r
423 if BuildData.MetaFile.Ext == '.inf':\r
424 for key in BuildData.Pcds:\r
425 if BuildData.Pcds[key].Pending:\r
426 if key in Platform.Pcds:\r
427 PcdInPlatform = Platform.Pcds[key]\r
428 if PcdInPlatform.Type not in [None, '']:\r
429 BuildData.Pcds[key].Type = PcdInPlatform.Type\r
430\r
431 if BuildData.MetaFile in Platform.Modules:\r
432 PlatformModule = Platform.Modules[str(BuildData.MetaFile)]\r
433 if key in PlatformModule.Pcds:\r
434 PcdInPlatform = PlatformModule.Pcds[key]\r
435 if PcdInPlatform.Type not in [None, '']:\r
436 BuildData.Pcds[key].Type = PcdInPlatform.Type\r
437\r
438 if 'DynamicEx' in BuildData.Pcds[key].Type:\r
439 if BuildData.IsBinaryModule:\r
ff5635e9 440 BinaryPcdDict['DynamicEx'].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 441 else:\r
ff5635e9 442 SourcePcdDict['DynamicEx'].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e
YZ
443\r
444 elif 'PatchableInModule' in BuildData.Pcds[key].Type:\r
445 if BuildData.MetaFile.Ext == '.inf':\r
446 if BuildData.IsBinaryModule:\r
ff5635e9 447 BinaryPcdDict['PatchableInModule'].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 448 else:\r
ff5635e9 449 SourcePcdDict['PatchableInModule'].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e
YZ
450\r
451 elif 'Dynamic' in BuildData.Pcds[key].Type:\r
ff5635e9 452 SourcePcdDict['Dynamic'].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e 453 elif 'FixedAtBuild' in BuildData.Pcds[key].Type:\r
ff5635e9 454 SourcePcdDict['FixedAtBuild'].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
2a29017e
YZ
455 else:\r
456 pass\r
97cdb33b
YZ
457 #\r
458 # A PCD can only use one type for all source modules\r
459 #\r
460 for i in SourcePcdDict_Keys:\r
461 for j in SourcePcdDict_Keys:\r
462 if i != j:\r
ff5635e9
CJ
463 Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])\r
464 if len(Intersections) > 0:\r
97cdb33b
YZ
465 EdkLogger.error(\r
466 'build',\r
467 FORMAT_INVALID,\r
468 "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
ff5635e9 469 ExtraData="%s" % '\n\t'.join([str(P[1]+'.'+P[0]) for P in Intersections])\r
97cdb33b 470 )\r
2a29017e
YZ
471\r
472 #\r
473 # intersection the BinaryPCD for Mixed PCD\r
474 #\r
475 for i in BinaryPcdDict_Keys:\r
476 for j in BinaryPcdDict_Keys:\r
477 if i != j:\r
ff5635e9
CJ
478 Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])\r
479 for item in Intersections:\r
2a29017e
YZ
480 NewPcd1 = (item[0] + '_' + i, item[1])\r
481 NewPcd2 = (item[0] + '_' + j, item[1])\r
482 if item not in GlobalData.MixedPcd:\r
483 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
484 else:\r
485 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
486 GlobalData.MixedPcd[item].append(NewPcd1)\r
487 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
488 GlobalData.MixedPcd[item].append(NewPcd2)\r
2a29017e
YZ
489\r
490 #\r
491 # intersection the SourcePCD and BinaryPCD for Mixed PCD\r
492 #\r
493 for i in SourcePcdDict_Keys:\r
494 for j in BinaryPcdDict_Keys:\r
495 if i != j:\r
ff5635e9
CJ
496 Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])\r
497 for item in Intersections:\r
2a29017e
YZ
498 NewPcd1 = (item[0] + '_' + i, item[1])\r
499 NewPcd2 = (item[0] + '_' + j, item[1])\r
500 if item not in GlobalData.MixedPcd:\r
501 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
502 else:\r
503 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
504 GlobalData.MixedPcd[item].append(NewPcd1)\r
505 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
506 GlobalData.MixedPcd[item].append(NewPcd2)\r
2a29017e
YZ
507\r
508 for BuildData in PGen.BuildDatabase._CACHE_.values():\r
509 if BuildData.Arch != Arch:\r
510 continue\r
511 for key in BuildData.Pcds:\r
512 for SinglePcd in GlobalData.MixedPcd:\r
513 if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
514 for item in GlobalData.MixedPcd[SinglePcd]:\r
515 Pcd_Type = item[0].split('_')[-1]\r
516 if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in GenC.gDynamicExPcd) or \\r
517 (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in GenC.gDynamicPcd):\r
518 Value = BuildData.Pcds[key]\r
519 Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type\r
520 if len(key) == 2:\r
521 newkey = (Value.TokenCName, key[1])\r
522 elif len(key) == 3:\r
523 newkey = (Value.TokenCName, key[1], key[2])\r
524 del BuildData.Pcds[key]\r
525 BuildData.Pcds[newkey] = Value\r
526 break\r
2a29017e 527 break\r
2a29017e
YZ
528\r
529 # handle the mixed pcd in FDF file\r
530 for key in PcdSet:\r
531 if key in GlobalData.MixedPcd:\r
532 Value = PcdSet[key]\r
533 del PcdSet[key]\r
534 for item in GlobalData.MixedPcd[key]:\r
535 PcdSet[item] = Value\r
536\r
97fa0ee9 537 #Collect package set information from INF of FDF\r
a0a2cd1e
FB
538 PkgSet = set()\r
539 for Inf in ModuleList:\r
540 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
541 if ModuleFile in Platform.Modules:\r
542 continue\r
543 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
544 PkgSet.update(ModuleData.Packages)\r
545 Pkgs = list(PkgSet) + list(PGen.PackageList)\r
6f49996c
FB
546 DecPcds = {}\r
547 DecPcdsKey = set()\r
64b2609f 548 for Pkg in Pkgs:\r
25918452
LG
549 for Pcd in Pkg.Pcds:\r
550 DecPcds[Pcd[0], Pcd[1]] = Pkg.Pcds[Pcd]\r
4afd3d04 551 DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
64b2609f 552\r
52302d4d
LG
553 Platform.SkuName = self.SkuId\r
554 for Name, Guid in PcdSet:\r
64b2609f
LG
555 if (Name, Guid) not in DecPcds:\r
556 EdkLogger.error(\r
557 'build',\r
558 PARSER_ERROR,\r
559 "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
560 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
561 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
562 )\r
4afd3d04
LG
563 else:\r
564 # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
565 if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
566 or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
567 or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
568 Platform.AddPcd(Name, Guid, PcdSet[Name, Guid])\r
569 continue\r
570 elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
571 EdkLogger.error(\r
572 'build',\r
573 PARSER_ERROR,\r
574 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
575 File = self.FdfProfile.PcdFileLineDict[Name, Guid][0],\r
576 Line = self.FdfProfile.PcdFileLineDict[Name, Guid][1]\r
577 )\r
52302d4d
LG
578\r
579 Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
580 #\r
581 # Explicitly collect platform's dynamic PCDs\r
582 #\r
583 Pa.CollectPlatformDynamicPcds()\r
2bc3256c 584 Pa.CollectFixedAtBuildPcds()\r
52302d4d 585 self.AutoGenObjectList.append(Pa)\r
47fea6af 586\r
36d083ef
YZ
587 #\r
588 # Generate Package level hash value\r
589 #\r
590 GlobalData.gPackageHash[Arch] = {}\r
591 if GlobalData.gUseHashCache:\r
592 for Pkg in Pkgs:\r
593 self._GenPkgLevelHash(Pkg)\r
594\r
6780eef1
LG
595 #\r
596 # Check PCDs token value conflict in each DEC file.\r
597 #\r
598 self._CheckAllPcdsTokenValueConflict()\r
47fea6af 599\r
4234283c
LG
600 #\r
601 # Check PCD type and definition between DSC and DEC\r
602 #\r
603 self._CheckPcdDefineAndType()\r
97fa0ee9
YL
604\r
605# if self.FdfFile:\r
606# self._CheckDuplicateInFV(Fdf)\r
607\r
c17956e0 608 #\r
2d499388 609 # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.\r
c17956e0
DL
610 #\r
611 content = 'gCommandLineDefines: '\r
612 content += str(GlobalData.gCommandLineDefines)\r
613 content += os.linesep\r
614 content += 'BuildOptionPcd: '\r
615 content += str(GlobalData.BuildOptionPcd)\r
2d499388
YZ
616 content += os.linesep\r
617 content += 'Active Platform: '\r
618 content += str(self.Platform)\r
619 content += os.linesep\r
620 if self.FdfFile:\r
621 content += 'Flash Image Definition: '\r
622 content += str(self.FdfFile)\r
36d083ef 623 content += os.linesep\r
c17956e0
DL
624 SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)\r
625\r
99adfe9f
YZ
626 #\r
627 # Create PcdToken Number file for Dynamic/DynamicEx Pcd.\r
628 #\r
629 PcdTokenNumber = 'PcdTokenNumber: '\r
630 if Pa.PcdTokenNumber:\r
631 if Pa.DynamicPcdList:\r
632 for Pcd in Pa.DynamicPcdList:\r
633 PcdTokenNumber += os.linesep\r
634 PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
635 PcdTokenNumber += ' : '\r
636 PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])\r
637 SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)\r
638\r
c17956e0
DL
639 #\r
640 # Get set of workspace metafiles\r
641 #\r
642 AllWorkSpaceMetaFiles = self._GetMetaFiles(Target, Toolchain, Arch)\r
643\r
644 #\r
645 # Retrieve latest modified time of all metafiles\r
646 #\r
647 SrcTimeStamp = 0\r
648 for f in AllWorkSpaceMetaFiles:\r
649 if os.stat(f)[8] > SrcTimeStamp:\r
650 SrcTimeStamp = os.stat(f)[8]\r
651 self._SrcTimeStamp = SrcTimeStamp\r
652\r
36d083ef
YZ
653 if GlobalData.gUseHashCache:\r
654 m = hashlib.md5()\r
655 for files in AllWorkSpaceMetaFiles:\r
656 if files.endswith('.dec'):\r
657 continue\r
658 f = open(files, 'r')\r
659 Content = f.read()\r
660 f.close()\r
661 m.update(Content)\r
662 SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), True)\r
663 GlobalData.gPlatformHash = m.hexdigest()\r
664\r
c17956e0
DL
665 #\r
666 # Write metafile list to build directory\r
667 #\r
668 AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')\r
669 if os.path.exists (AutoGenFilePath):\r
670 os.remove(AutoGenFilePath)\r
671 if not os.path.exists(self.BuildDir):\r
672 os.makedirs(self.BuildDir)\r
673 with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:\r
674 for f in AllWorkSpaceMetaFiles:\r
675 print >> file, f\r
52302d4d
LG
676 return True\r
677\r
36d083ef
YZ
678 def _GenPkgLevelHash(self, Pkg):\r
679 PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)\r
680 CreateDirectory(PkgDir)\r
681 HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')\r
682 m = hashlib.md5()\r
683 # Get .dec file's hash value\r
684 f = open(Pkg.MetaFile.Path, 'r')\r
685 Content = f.read()\r
686 f.close()\r
687 m.update(Content)\r
688 # Get include files hash value\r
689 if Pkg.Includes:\r
690 for inc in Pkg.Includes:\r
691 for Root, Dirs, Files in os.walk(str(inc)):\r
692 for File in Files:\r
693 File_Path = os.path.join(Root, File)\r
694 f = open(File_Path, 'r')\r
695 Content = f.read()\r
696 f.close()\r
697 m.update(Content)\r
698 SaveFileOnChange(HashFile, m.hexdigest(), True)\r
699 if Pkg.PackageName not in GlobalData.gPackageHash[Pkg.Arch]:\r
700 GlobalData.gPackageHash[Pkg.Arch][Pkg.PackageName] = m.hexdigest()\r
763e8edf 701\r
c17956e0
DL
702 def _GetMetaFiles(self, Target, Toolchain, Arch):\r
703 AllWorkSpaceMetaFiles = set()\r
704 #\r
705 # add fdf\r
706 #\r
707 if self.FdfFile:\r
708 AllWorkSpaceMetaFiles.add (self.FdfFile.Path)\r
709 if self.FdfFile:\r
710 FdfFiles = GlobalData.gFdfParser.GetAllIncludedFile()\r
711 for f in FdfFiles:\r
712 AllWorkSpaceMetaFiles.add (f.FileName)\r
713 #\r
714 # add dsc\r
715 #\r
716 AllWorkSpaceMetaFiles.add(self.MetaFile.Path)\r
717\r
718 #\r
86601b78
DL
719 # add build_rule.txt & tools_def.txt\r
720 #\r
51de5c30
YZ
721 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))\r
722 AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))\r
86601b78 723\r
c17956e0
DL
724 # add BuildOption metafile\r
725 #\r
726 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))\r
727\r
99adfe9f
YZ
728 # add PcdToken Number file for Dynamic/DynamicEx Pcd\r
729 #\r
730 AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))\r
731\r
c17956e0
DL
732 for Arch in self.ArchList:\r
733 Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
734 PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
735\r
736 #\r
737 # add dec\r
738 #\r
739 for Package in PGen.PackageList:\r
740 AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)\r
741\r
742 #\r
743 # add included dsc\r
744 #\r
745 for filePath in Platform._RawData.IncludedFiles:\r
746 AllWorkSpaceMetaFiles.add(filePath.Path)\r
747\r
748 return AllWorkSpaceMetaFiles\r
749\r
79b74a03
LG
750 ## _CheckDuplicateInFV() method\r
751 #\r
752 # Check whether there is duplicate modules/files exist in FV section. \r
753 # The check base on the file GUID;\r
754 #\r
755 def _CheckDuplicateInFV(self, Fdf):\r
756 for Fv in Fdf.Profile.FvDict:\r
757 _GuidDict = {}\r
758 for FfsFile in Fdf.Profile.FvDict[Fv].FfsList:\r
4231a819 759 if FfsFile.InfFileName and FfsFile.NameGuid is None:\r
79b74a03
LG
760 #\r
761 # Get INF file GUID\r
762 #\r
47fea6af 763 InfFoundFlag = False\r
79b74a03 764 for Pa in self.AutoGenObjectList:\r
64b2609f
LG
765 if InfFoundFlag:\r
766 break\r
79b74a03
LG
767 for Module in Pa.ModuleAutoGenList:\r
768 if path.normpath(Module.MetaFile.File) == path.normpath(FfsFile.InfFileName):\r
769 InfFoundFlag = True\r
770 if not Module.Guid.upper() in _GuidDict.keys():\r
771 _GuidDict[Module.Guid.upper()] = FfsFile\r
64b2609f 772 break\r
79b74a03 773 else:\r
47fea6af 774 EdkLogger.error("build",\r
79b74a03 775 FORMAT_INVALID,\r
47fea6af 776 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
777 FfsFile.CurrentLineContent,\r
778 _GuidDict[Module.Guid.upper()].CurrentLineNum,\r
779 _GuidDict[Module.Guid.upper()].CurrentLineContent,\r
780 Module.Guid.upper()),\r
781 ExtraData=self.FdfFile)\r
782 #\r
783 # Some INF files not have entity in DSC file. \r
784 #\r
785 if not InfFoundFlag:\r
786 if FfsFile.InfFileName.find('$') == -1:\r
787 InfPath = NormPath(FfsFile.InfFileName)\r
788 if not os.path.exists(InfPath):\r
789 EdkLogger.error('build', GENFDS_ERROR, "Non-existant Module %s !" % (FfsFile.InfFileName))\r
47fea6af 790\r
79b74a03
LG
791 PathClassObj = PathClass(FfsFile.InfFileName, self.WorkspaceDir)\r
792 #\r
793 # Here we just need to get FILE_GUID from INF file, use 'COMMON' as ARCH attribute. and use \r
794 # BuildObject from one of AutoGenObjectList is enough.\r
795 #\r
796 InfObj = self.AutoGenObjectList[0].BuildDatabase.WorkspaceDb.BuildObject[PathClassObj, 'COMMON', self.BuildTarget, self.ToolChain]\r
797 if not InfObj.Guid.upper() in _GuidDict.keys():\r
798 _GuidDict[InfObj.Guid.upper()] = FfsFile\r
799 else:\r
47fea6af 800 EdkLogger.error("build",\r
79b74a03 801 FORMAT_INVALID,\r
47fea6af 802 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
803 FfsFile.CurrentLineContent,\r
804 _GuidDict[InfObj.Guid.upper()].CurrentLineNum,\r
805 _GuidDict[InfObj.Guid.upper()].CurrentLineContent,\r
806 InfObj.Guid.upper()),\r
807 ExtraData=self.FdfFile)\r
808 InfFoundFlag = False\r
47fea6af 809\r
4231a819 810 if FfsFile.NameGuid is not None:\r
79b74a03
LG
811 #\r
812 # If the NameGuid reference a PCD name. \r
813 # The style must match: PCD(xxxx.yyy)\r
814 #\r
c8802c3d 815 if gPCDAsGuidPattern.match(FfsFile.NameGuid):\r
79b74a03
LG
816 #\r
817 # Replace the PCD value.\r
818 #\r
819 _PcdName = FfsFile.NameGuid.lstrip("PCD(").rstrip(")")\r
820 PcdFoundFlag = False\r
821 for Pa in self.AutoGenObjectList:\r
822 if not PcdFoundFlag:\r
823 for PcdItem in Pa.AllPcdList:\r
824 if (PcdItem.TokenSpaceGuidCName + "." + PcdItem.TokenCName) == _PcdName:\r
825 #\r
826 # First convert from CFormatGuid to GUID string\r
827 #\r
828 _PcdGuidString = GuidStructureStringToGuidString(PcdItem.DefaultValue)\r
47fea6af 829\r
79b74a03
LG
830 if not _PcdGuidString:\r
831 #\r
832 # Then try Byte array.\r
833 #\r
834 _PcdGuidString = GuidStructureByteArrayToGuidString(PcdItem.DefaultValue)\r
47fea6af 835\r
79b74a03
LG
836 if not _PcdGuidString:\r
837 #\r
838 # Not Byte array or CFormat GUID, raise error.\r
839 #\r
840 EdkLogger.error("build",\r
841 FORMAT_INVALID,\r
47fea6af 842 "The format of PCD value is incorrect. PCD: %s , Value: %s\n" % (_PcdName, PcdItem.DefaultValue),\r
79b74a03 843 ExtraData=self.FdfFile)\r
47fea6af
YZ
844\r
845 if not _PcdGuidString.upper() in _GuidDict.keys():\r
79b74a03
LG
846 _GuidDict[_PcdGuidString.upper()] = FfsFile\r
847 PcdFoundFlag = True\r
848 break\r
849 else:\r
47fea6af 850 EdkLogger.error("build",\r
79b74a03 851 FORMAT_INVALID,\r
47fea6af 852 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
853 FfsFile.CurrentLineContent,\r
854 _GuidDict[_PcdGuidString.upper()].CurrentLineNum,\r
855 _GuidDict[_PcdGuidString.upper()].CurrentLineContent,\r
856 FfsFile.NameGuid.upper()),\r
47fea6af
YZ
857 ExtraData=self.FdfFile)\r
858\r
79b74a03
LG
859 if not FfsFile.NameGuid.upper() in _GuidDict.keys():\r
860 _GuidDict[FfsFile.NameGuid.upper()] = FfsFile\r
861 else:\r
862 #\r
863 # Two raw file GUID conflict.\r
864 #\r
47fea6af 865 EdkLogger.error("build",\r
79b74a03 866 FORMAT_INVALID,\r
47fea6af 867 "Duplicate GUID found for these lines: Line %d: %s and Line %d: %s. GUID: %s" % (FfsFile.CurrentLineNum,\r
79b74a03
LG
868 FfsFile.CurrentLineContent,\r
869 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineNum,\r
870 _GuidDict[FfsFile.NameGuid.upper()].CurrentLineContent,\r
871 FfsFile.NameGuid.upper()),\r
872 ExtraData=self.FdfFile)\r
47fea6af 873\r
79b74a03 874\r
4234283c
LG
875 def _CheckPcdDefineAndType(self):\r
876 PcdTypeList = [\r
877 "FixedAtBuild", "PatchableInModule", "FeatureFlag",\r
878 "Dynamic", #"DynamicHii", "DynamicVpd",\r
879 "DynamicEx", # "DynamicExHii", "DynamicExVpd"\r
880 ]\r
881\r
882 # This dict store PCDs which are not used by any modules with specified arches\r
9006a2c6 883 UnusedPcd = OrderedDict()\r
4234283c
LG
884 for Pa in self.AutoGenObjectList:\r
885 # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid\r
886 for Pcd in Pa.Platform.Pcds:\r
887 PcdType = Pa.Platform.Pcds[Pcd].Type\r
47fea6af 888\r
4234283c
LG
889 # If no PCD type, this PCD comes from FDF \r
890 if not PcdType:\r
891 continue\r
47fea6af 892\r
4234283c
LG
893 # Try to remove Hii and Vpd suffix\r
894 if PcdType.startswith("DynamicEx"):\r
895 PcdType = "DynamicEx"\r
896 elif PcdType.startswith("Dynamic"):\r
897 PcdType = "Dynamic"\r
47fea6af 898\r
4234283c
LG
899 for Package in Pa.PackageList:\r
900 # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType\r
901 if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:\r
902 break\r
903 for Type in PcdTypeList:\r
904 if (Pcd[0], Pcd[1], Type) in Package.Pcds:\r
905 EdkLogger.error(\r
906 'build',\r
907 FORMAT_INVALID,\r
908 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \\r
909 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),\r
910 ExtraData=None\r
911 )\r
912 return\r
913 else:\r
914 UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)\r
915\r
916 for Pcd in UnusedPcd:\r
917 EdkLogger.warn(\r
918 'build',\r
919 "The PCD was not specified by any INF module in the platform for the given architecture.\n"\r
920 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"\r
921 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),\r
922 ExtraData=None\r
923 )\r
924\r
52302d4d
LG
925 def __repr__(self):\r
926 return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
927\r
928 ## Return the directory to store FV files\r
929 def _GetFvDir(self):\r
4231a819 930 if self._FvDir is None:\r
52302d4d
LG
931 self._FvDir = path.join(self.BuildDir, 'FV')\r
932 return self._FvDir\r
933\r
934 ## Return the directory to store all intermediate and final files built\r
935 def _GetBuildDir(self):\r
4231a819 936 if self._BuildDir is None:\r
36d083ef 937 return self.AutoGenObjectList[0].BuildDir\r
52302d4d
LG
938\r
939 ## Return the build output directory platform specifies\r
940 def _GetOutputDir(self):\r
941 return self.Platform.OutputDirectory\r
942\r
943 ## Return platform name\r
944 def _GetName(self):\r
945 return self.Platform.PlatformName\r
946\r
947 ## Return meta-file GUID\r
948 def _GetGuid(self):\r
949 return self.Platform.Guid\r
950\r
951 ## Return platform version\r
952 def _GetVersion(self):\r
953 return self.Platform.Version\r
954\r
955 ## Return paths of tools\r
956 def _GetToolDefinition(self):\r
957 return self.AutoGenObjectList[0].ToolDefinition\r
958\r
959 ## Return directory of platform makefile\r
960 #\r
961 # @retval string Makefile directory\r
962 #\r
963 def _GetMakeFileDir(self):\r
4231a819 964 if self._MakeFileDir is None:\r
52302d4d
LG
965 self._MakeFileDir = self.BuildDir\r
966 return self._MakeFileDir\r
967\r
968 ## Return build command string\r
969 #\r
970 # @retval string Build command string\r
971 #\r
972 def _GetBuildCommand(self):\r
4231a819 973 if self._BuildCommand is None:\r
52302d4d
LG
974 # BuildCommand should be all the same. So just get one from platform AutoGen\r
975 self._BuildCommand = self.AutoGenObjectList[0].BuildCommand\r
976 return self._BuildCommand\r
47fea6af 977\r
6780eef1
LG
978 ## Check the PCDs token value conflict in each DEC file.\r
979 #\r
980 # Will cause build break and raise error message while two PCDs conflict.\r
981 # \r
982 # @return None\r
983 #\r
984 def _CheckAllPcdsTokenValueConflict(self):\r
b36d134f
LG
985 for Pa in self.AutoGenObjectList:\r
986 for Package in Pa.PackageList:\r
6780eef1 987 PcdList = Package.Pcds.values()\r
f827cd07 988 PcdList.sort(lambda x, y: cmp(int(x.TokenValue, 0), int(y.TokenValue, 0))) \r
6780eef1
LG
989 Count = 0\r
990 while (Count < len(PcdList) - 1) :\r
991 Item = PcdList[Count]\r
992 ItemNext = PcdList[Count + 1]\r
993 #\r
994 # Make sure in the same token space the TokenValue should be unique\r
995 #\r
f827cd07 996 if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):\r
6780eef1
LG
997 SameTokenValuePcdList = []\r
998 SameTokenValuePcdList.append(Item)\r
999 SameTokenValuePcdList.append(ItemNext)\r
1000 RemainPcdListLength = len(PcdList) - Count - 2\r
1001 for ValueSameCount in range(RemainPcdListLength):\r
f827cd07 1002 if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):\r
6780eef1
LG
1003 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
1004 else:\r
1005 break;\r
1006 #\r
1007 # Sort same token value PCD list with TokenGuid and TokenCName\r
1008 #\r
47fea6af
YZ
1009 SameTokenValuePcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
1010 SameTokenValuePcdListCount = 0\r
6780eef1 1011 while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
2a29017e 1012 Flag = False\r
47fea6af
YZ
1013 TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]\r
1014 TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]\r
1015\r
6780eef1 1016 if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):\r
2a29017e
YZ
1017 for PcdItem in GlobalData.MixedPcd:\r
1018 if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \\r
1019 (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
1020 Flag = True\r
1021 if not Flag:\r
1022 EdkLogger.error(\r
1023 'build',\r
1024 FORMAT_INVALID,\r
1025 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\\r
1026 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),\r
1027 ExtraData=None\r
1028 )\r
6780eef1
LG
1029 SameTokenValuePcdListCount += 1\r
1030 Count += SameTokenValuePcdListCount\r
1031 Count += 1\r
47fea6af 1032\r
6780eef1 1033 PcdList = Package.Pcds.values()\r
47fea6af 1034 PcdList.sort(lambda x, y: cmp("%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName), "%s.%s" % (y.TokenSpaceGuidCName, y.TokenCName)))\r
6780eef1
LG
1035 Count = 0\r
1036 while (Count < len(PcdList) - 1) :\r
1037 Item = PcdList[Count]\r
47fea6af 1038 ItemNext = PcdList[Count + 1]\r
6780eef1
LG
1039 #\r
1040 # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
1041 #\r
f827cd07 1042 if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):\r
6780eef1
LG
1043 EdkLogger.error(\r
1044 'build',\r
1045 FORMAT_INVALID,\r
1046 "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\\r
1047 % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),\r
1048 ExtraData=None\r
1049 )\r
1050 Count += 1\r
97fa0ee9 1051 ## Generate fds command\r
03af2753
HC
1052 def _GenFdsCommand(self):\r
1053 return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
52302d4d 1054\r
e56468c0 1055 ## Create makefile for the platform and modules in it\r
52302d4d
LG
1056 #\r
1057 # @param CreateDepsMakeFile Flag indicating if the makefile for\r
1058 # modules will be created as well\r
1059 #\r
1060 def CreateMakeFile(self, CreateDepsMakeFile=False):\r
52302d4d
LG
1061 if CreateDepsMakeFile:\r
1062 for Pa in self.AutoGenObjectList:\r
1063 Pa.CreateMakeFile(CreateDepsMakeFile)\r
1064\r
1065 ## Create autogen code for platform and modules\r
1066 #\r
1067 # Since there's no autogen code for platform, this method will do nothing\r
1068 # if CreateModuleCodeFile is set to False.\r
1069 #\r
1070 # @param CreateDepsCodeFile Flag indicating if creating module's\r
1071 # autogen code file or not\r
1072 #\r
1073 def CreateCodeFile(self, CreateDepsCodeFile=False):\r
1074 if not CreateDepsCodeFile:\r
1075 return\r
1076 for Pa in self.AutoGenObjectList:\r
1077 Pa.CreateCodeFile(CreateDepsCodeFile)\r
1078\r
7c1fd323
LG
1079 ## Create AsBuilt INF file the platform\r
1080 #\r
1081 def CreateAsBuiltInf(self):\r
1082 return\r
1083\r
52302d4d
LG
1084 Name = property(_GetName)\r
1085 Guid = property(_GetGuid)\r
1086 Version = property(_GetVersion)\r
1087 OutputDir = property(_GetOutputDir)\r
1088\r
1089 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
1090\r
1091 BuildDir = property(_GetBuildDir)\r
1092 FvDir = property(_GetFvDir)\r
1093 MakeFileDir = property(_GetMakeFileDir)\r
1094 BuildCommand = property(_GetBuildCommand)\r
03af2753 1095 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
1096\r
1097## AutoGen class for platform\r
1098#\r
1099# PlatformAutoGen class will process the original information in platform\r
1100# file in order to generate makefile for platform.\r
1101#\r
1102class PlatformAutoGen(AutoGen):\r
b24e99f7
CJ
1103 # call super().__init__ then call the worker function with different parameter count\r
1104 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
1105 try:\r
1106 self._Init\r
1107 except:\r
1108 super(PlatformAutoGen, self).__init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
1109 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
1110 self._Init = True\r
52302d4d
LG
1111 #\r
1112 # Used to store all PCDs for both PEI and DXE phase, in order to generate \r
1113 # correct PCD database\r
1114 # \r
1115 _DynaPcdList_ = []\r
1116 _NonDynaPcdList_ = []\r
61ee1dff 1117 _PlatformPcds = {}\r
6780eef1
LG
1118 \r
1119 #\r
1120 # The priority list while override build option \r
1121 #\r
1122 PrioList = {"0x11111" : 16, # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
1123 "0x01111" : 15, # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
1124 "0x10111" : 14, # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
1125 "0x00111" : 13, # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE \r
1126 "0x11011" : 12, # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
1127 "0x01011" : 11, # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
1128 "0x10011" : 10, # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
1129 "0x00011" : 9, # ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
1130 "0x11101" : 8, # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
1131 "0x01101" : 7, # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
1132 "0x10101" : 6, # TARGET_*********_ARCH_***********_ATTRIBUTE\r
1133 "0x00101" : 5, # ******_*********_ARCH_***********_ATTRIBUTE\r
1134 "0x11001" : 4, # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
1135 "0x01001" : 3, # ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
1136 "0x10001" : 2, # TARGET_*********_****_***********_ATTRIBUTE\r
1137 "0x00001" : 1} # ******_*********_****_***********_ATTRIBUTE (Lowest)\r
47fea6af 1138\r
b24e99f7 1139 ## Initialize PlatformAutoGen\r
52302d4d 1140 #\r
52302d4d
LG
1141 #\r
1142 # @param Workspace WorkspaceAutoGen object\r
1143 # @param PlatformFile Platform file (DSC file)\r
1144 # @param Target Build target (DEBUG, RELEASE)\r
1145 # @param Toolchain Name of tool chain\r
1146 # @param Arch arch of the platform supports\r
1147 #\r
b24e99f7 1148 def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
52302d4d
LG
1149 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
1150 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
1151\r
1152 self.MetaFile = PlatformFile\r
1153 self.Workspace = Workspace\r
1154 self.WorkspaceDir = Workspace.WorkspaceDir\r
1155 self.ToolChain = Toolchain\r
1156 self.BuildTarget = Target\r
1157 self.Arch = Arch\r
1158 self.SourceDir = PlatformFile.SubDir\r
1159 self.SourceOverrideDir = None\r
1160 self.FdTargetList = self.Workspace.FdTargetList\r
1161 self.FvTargetList = self.Workspace.FvTargetList\r
1162 self.AllPcdList = []\r
a0a2cd1e
FB
1163 # get the original module/package/platform objects\r
1164 self.BuildDatabase = Workspace.BuildDatabase\r
8518bf0b 1165 self.DscBuildDataObj = Workspace.Platform\r
35f613d9 1166 self._GuidDict = Workspace._GuidDict\r
52302d4d
LG
1167\r
1168 # flag indicating if the makefile/C-code file has been created or not\r
1169 self.IsMakeFileCreated = False\r
1170 self.IsCodeFileCreated = False\r
1171\r
1172 self._Platform = None\r
1173 self._Name = None\r
1174 self._Guid = None\r
1175 self._Version = None\r
1176\r
1177 self._BuildRule = None\r
1178 self._SourceDir = None\r
1179 self._BuildDir = None\r
1180 self._OutputDir = None\r
1181 self._FvDir = None\r
1182 self._MakeFileDir = None\r
1183 self._FdfFile = None\r
1184\r
1185 self._PcdTokenNumber = None # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
1186 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
1187 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 1188 self._NonDynamicPcdDict = {}\r
52302d4d
LG
1189\r
1190 self._ToolDefinitions = None\r
1191 self._ToolDefFile = None # toolcode : tool path\r
1192 self._ToolChainFamily = None\r
1193 self._BuildRuleFamily = None\r
1194 self._BuildOption = None # toolcode : option\r
1195 self._EdkBuildOption = None # edktoolcode : option\r
1196 self._EdkIIBuildOption = None # edkiitoolcode : option\r
1197 self._PackageList = None\r
1198 self._ModuleAutoGenList = None\r
1199 self._LibraryAutoGenList = None\r
1200 self._BuildCommand = None\r
a0a2cd1e
FB
1201 self._AsBuildInfList = []\r
1202 self._AsBuildModuleList = []\r
47854fd5
LG
1203\r
1204 self.VariableInfo = None\r
1205\r
4231a819 1206 if GlobalData.gFdfParser is not None:\r
a0a2cd1e
FB
1207 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
1208 for Inf in self._AsBuildInfList:\r
1209 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
1210 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1211 if not M.IsSupportedArch:\r
1212 continue\r
1213 self._AsBuildModuleList.append(InfClass)\r
03af2753
HC
1214 # get library/modules for build\r
1215 self.LibraryBuildDirectoryList = []\r
1216 self.ModuleBuildDirectoryList = []\r
47854fd5 1217\r
52302d4d
LG
1218 return True\r
1219\r
1220 def __repr__(self):\r
1221 return "%s [%s]" % (self.MetaFile, self.Arch)\r
1222\r
1223 ## Create autogen code for platform and modules\r
1224 #\r
1225 # Since there's no autogen code for platform, this method will do nothing\r
1226 # if CreateModuleCodeFile is set to False.\r
1227 #\r
1228 # @param CreateModuleCodeFile Flag indicating if creating module's\r
1229 # autogen code file or not\r
1230 #\r
1231 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
1232 # only module has code to be greated, so do nothing if CreateModuleCodeFile is False\r
1233 if self.IsCodeFileCreated or not CreateModuleCodeFile:\r
1234 return\r
1235\r
1236 for Ma in self.ModuleAutoGenList:\r
1237 Ma.CreateCodeFile(True)\r
1238\r
1239 # don't do this twice\r
1240 self.IsCodeFileCreated = True\r
1241\r
03af2753
HC
1242 ## Generate Fds Command\r
1243 def _GenFdsCommand(self):\r
1244 return self.Workspace.GenFdsCommand\r
481252bb 1245\r
52302d4d
LG
1246 ## Create makefile for the platform and mdoules in it\r
1247 #\r
1248 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
1249 # modules will be created as well\r
1250 #\r
37de70b7 1251 def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
52302d4d
LG
1252 if CreateModuleMakeFile:\r
1253 for ModuleFile in self.Platform.Modules:\r
1254 Ma = ModuleAutoGen(self.Workspace, ModuleFile, self.BuildTarget,\r
1255 self.ToolChain, self.Arch, self.MetaFile)\r
37de70b7
YZ
1256 if (ModuleFile.File, self.Arch) in FfsCommand:\r
1257 Ma.CreateMakeFile(True, FfsCommand[ModuleFile.File, self.Arch])\r
1258 else:\r
1259 Ma.CreateMakeFile(True)\r
97fa0ee9 1260 #Ma.CreateAsBuiltInf()\r
52302d4d
LG
1261\r
1262 # no need to create makefile for the platform more than once\r
1263 if self.IsMakeFileCreated:\r
1264 return\r
1265\r
03af2753 1266 # create library/module build dirs for platform\r
52302d4d 1267 Makefile = GenMake.PlatformMakefile(self)\r
03af2753
HC
1268 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
1269 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
1270\r
52302d4d
LG
1271 self.IsMakeFileCreated = True\r
1272\r
2bc3256c
LG
1273 ## Deal with Shared FixedAtBuild Pcds\r
1274 #\r
1275 def CollectFixedAtBuildPcds(self):\r
1276 for LibAuto in self.LibraryAutoGenList:\r
1277 FixedAtBuildPcds = {} \r
1278 ShareFixedAtBuildPcdsSameValue = {} \r
1279 for Module in LibAuto._ReferenceModules: \r
1280 for Pcd in Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds:\r
1281 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName)) \r
1282 if key not in FixedAtBuildPcds:\r
1283 ShareFixedAtBuildPcdsSameValue[key] = True\r
1284 FixedAtBuildPcds[key] = Pcd.DefaultValue\r
1285 else:\r
1286 if FixedAtBuildPcds[key] != Pcd.DefaultValue:\r
1287 ShareFixedAtBuildPcdsSameValue[key] = False \r
1288 for Pcd in LibAuto.FixedAtBuildPcds:\r
1289 key = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))\r
1290 if (Pcd.TokenCName,Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
1291 continue\r
1292 else:\r
1293 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]\r
1294 if DscPcd.Type != "FixedAtBuild":\r
1295 continue\r
1296 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]: \r
1297 LibAuto.ConstPcd[key] = Pcd.DefaultValue\r
1298\r
34952f49 1299 def CollectVariables(self, DynamicPcdSet):\r
47854fd5
LG
1300\r
1301 VpdRegionSize = 0\r
1302 VpdRegionBase = 0\r
1303 if self.Workspace.FdfFile:\r
1304 FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]\r
1305 for FdRegion in FdDict.RegionList:\r
1306 for item in FdRegion.RegionDataList:\r
1307 if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:\r
1308 VpdRegionSize = FdRegion.Size\r
1309 VpdRegionBase = FdRegion.Offset\r
1310 break\r
1311\r
1312\r
8518bf0b 1313 VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(),self.DscBuildDataObj._GetSkuIds())\r
47854fd5
LG
1314 VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
1315 VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
34952f49
LG
1316 Index = 0\r
1317 for Pcd in DynamicPcdSet:\r
8518bf0b
LG
1318 pcdname = ".".join((Pcd.TokenSpaceGuidCName,Pcd.TokenCName))\r
1319 for SkuName in Pcd.SkuInfoList:\r
1320 Sku = Pcd.SkuInfoList[SkuName]\r
1321 SkuId = Sku.SkuId\r
4231a819 1322 if SkuId is None or SkuId == '':\r
8518bf0b
LG
1323 continue\r
1324 if len(Sku.VariableName) > 0:\r
1325 VariableGuidStructure = Sku.VariableGuidValue\r
1326 VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
a3623244 1327 for StorageName in Sku.DefaultStoreDict:\r
e6bf3cfd 1328 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
1329 Index += 1\r
1330 return VariableInfo\r
47854fd5
LG
1331\r
1332 def UpdateNVStoreMaxSize(self,OrgVpdFile):\r
0b6c5954
LG
1333 if self.VariableInfo:\r
1334 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)\r
1335 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
1336\r
1337 if PcdNvStoreDfBuffer:\r
1338 if os.path.exists(VpdMapFilePath):\r
1339 OrgVpdFile.Read(VpdMapFilePath)\r
1340 PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
8ac16789 1341 NvStoreOffset = PcdItems.values()[0].strip() if PcdItems else '0'\r
0b6c5954
LG
1342 else:\r
1343 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
1344\r
1345 NvStoreOffset = int(NvStoreOffset,16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)\r
1346 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get("DEFAULT")\r
1347 maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))\r
1348 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)\r
1349\r
1350 if var_data and default_skuobj:\r
1351 default_skuobj.DefaultValue = var_data\r
1352 PcdNvStoreDfBuffer[0].DefaultValue = var_data\r
1353 PcdNvStoreDfBuffer[0].SkuInfoList.clear()\r
1354 PcdNvStoreDfBuffer[0].SkuInfoList['DEFAULT'] = default_skuobj\r
1355 PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))\r
47854fd5
LG
1356\r
1357 return OrgVpdFile\r
1358\r
52302d4d
LG
1359 ## Collect dynamic PCDs\r
1360 #\r
1361 # Gather dynamic PCDs list from each module and their settings from platform\r
1362 # This interface should be invoked explicitly when platform action is created.\r
1363 #\r
1364 def CollectPlatformDynamicPcds(self):\r
763e8edf 1365\r
2a29017e
YZ
1366 for key in self.Platform.Pcds:\r
1367 for SinglePcd in GlobalData.MixedPcd:\r
1368 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
1369 for item in GlobalData.MixedPcd[SinglePcd]:\r
1370 Pcd_Type = item[0].split('_')[-1]\r
1371 if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in GenC.gDynamicExPcd) or \\r
1372 (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in GenC.gDynamicPcd):\r
1373 Value = self.Platform.Pcds[key]\r
1374 Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type\r
1375 if len(key) == 2:\r
1376 newkey = (Value.TokenCName, key[1])\r
1377 elif len(key) == 3:\r
1378 newkey = (Value.TokenCName, key[1], key[2])\r
1379 del self.Platform.Pcds[key]\r
1380 self.Platform.Pcds[newkey] = Value\r
1381 break\r
1382 else:\r
1383 pass\r
1384 break\r
1385 else:\r
1386 pass\r
1387\r
52302d4d
LG
1388 # for gathering error information\r
1389 NoDatumTypePcdList = set()\r
a0a2cd1e 1390 PcdNotInDb = []\r
52302d4d 1391 self._GuidValue = {}\r
a0a2cd1e
FB
1392 FdfModuleList = []\r
1393 for InfName in self._AsBuildInfList:\r
05cc51ad 1394 InfName = mws.join(self.WorkspaceDir, InfName)\r
a0a2cd1e 1395 FdfModuleList.append(os.path.normpath(InfName))\r
52302d4d
LG
1396 for F in self.Platform.Modules.keys():\r
1397 M = ModuleAutoGen(self.Workspace, F, self.BuildTarget, self.ToolChain, self.Arch, self.MetaFile)\r
1398 #GuidValue.update(M.Guids)\r
1399 \r
1400 self.Platform.Modules[F].M = M\r
47fea6af
YZ
1401\r
1402 for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
52302d4d 1403 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
e8a47801 1404 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:\r
52302d4d
LG
1405 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, F))\r
1406\r
97fa0ee9 1407 # Check the PCD from Binary INF or Source INF\r
a0a2cd1e
FB
1408 if M.IsBinaryModule == True:\r
1409 PcdFromModule.IsFromBinaryInf = True\r
97fa0ee9
YL
1410\r
1411 # Check the PCD from DSC or not \r
a0a2cd1e
FB
1412 if (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds.keys():\r
1413 PcdFromModule.IsFromDsc = True\r
1414 else:\r
1415 PcdFromModule.IsFromDsc = False\r
52302d4d 1416 if PcdFromModule.Type in GenC.gDynamicPcd or PcdFromModule.Type in GenC.gDynamicExPcd:\r
a0a2cd1e
FB
1417 if F.Path not in FdfModuleList:\r
1418 # If one of the Source built modules listed in the DSC is not listed \r
1419 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic \r
1420 # access method (it is only listed in the DEC file that declares the \r
1421 # PCD as PcdsDynamic), then build tool will report warning message\r
1422 # notify the PI that they are attempting to build a module that must \r
1423 # be included in a flash image in order to be functional. These Dynamic \r
1424 # PCD will not be added into the Database unless it is used by other \r
1425 # modules that are included in the FDF file.\r
1426 if PcdFromModule.Type in GenC.gDynamicPcd and \\r
1427 PcdFromModule.IsFromBinaryInf == False:\r
1428 # Print warning message to let the developer make a determine.\r
1429 if PcdFromModule not in PcdNotInDb:\r
a0a2cd1e
FB
1430 PcdNotInDb.append(PcdFromModule)\r
1431 continue\r
1432 # If one of the Source built modules listed in the DSC is not listed in \r
1433 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx \r
1434 # access method (it is only listed in the DEC file that declares the \r
1435 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the \r
1436 # PCD to the Platform's PCD Database.\r
1437 if PcdFromModule.Type in GenC.gDynamicExPcd:\r
1438 if PcdFromModule not in PcdNotInDb:\r
1439 PcdNotInDb.append(PcdFromModule)\r
1440 continue\r
52302d4d
LG
1441 #\r
1442 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
1443 # it should be stored in Pcd PEI database, If a dynamic only\r
1444 # used by DXE module, it should be stored in DXE PCD database.\r
1445 # The default Phase is DXE\r
1446 #\r
1447 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
1448 PcdFromModule.Phase = "PEI"\r
1449 if PcdFromModule not in self._DynaPcdList_:\r
1450 self._DynaPcdList_.append(PcdFromModule)\r
1451 elif PcdFromModule.Phase == 'PEI':\r
1452 # overwrite any the same PCD existing, if Phase is PEI\r
1453 Index = self._DynaPcdList_.index(PcdFromModule)\r
1454 self._DynaPcdList_[Index] = PcdFromModule\r
1455 elif PcdFromModule not in self._NonDynaPcdList_:\r
1456 self._NonDynaPcdList_.append(PcdFromModule)\r
a0a2cd1e
FB
1457 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
1458 Index = self._NonDynaPcdList_.index(PcdFromModule)\r
1459 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
1460 #The PCD from Binary INF will override the same one from source INF\r
1461 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
1462 PcdFromModule.Pending = False\r
1463 self._NonDynaPcdList_.append (PcdFromModule)\r
1464 # Parse the DynamicEx PCD from the AsBuild INF module list of FDF.\r
1465 DscModuleList = []\r
1466 for ModuleInf in self.Platform.Modules.keys():\r
1467 DscModuleList.append (os.path.normpath(ModuleInf.Path))\r
1468 # add the PCD from modules that listed in FDF but not in DSC to Database \r
1469 for InfName in FdfModuleList:\r
1470 if InfName not in DscModuleList:\r
1471 InfClass = PathClass(InfName)\r
1472 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1473 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source) \r
1474 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here. \r
1475 # For binary module, if in current arch, we need to list the PCDs into database. \r
1476 if not M.IsSupportedArch:\r
1477 continue\r
1478 # Override the module PCD setting by platform setting\r
1479 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
1480 for PcdFromModule in ModulePcdList:\r
1481 PcdFromModule.IsFromBinaryInf = True\r
1482 PcdFromModule.IsFromDsc = False\r
1483 # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
1484 if PcdFromModule.Type not in GenC.gDynamicExPcd and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1485 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1486 File=self.MetaFile,\r
1487 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
1488 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
1489 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
1490 if PcdFromModule.DatumType == "VOID*" and PcdFromModule.MaxDatumSize in [None, '']:\r
1491 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
1492 if M.ModuleType in ["PEIM", "PEI_CORE"]:\r
1493 PcdFromModule.Phase = "PEI"\r
1494 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in GenC.gDynamicExPcd:\r
1495 self._DynaPcdList_.append(PcdFromModule)\r
1496 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1497 self._NonDynaPcdList_.append(PcdFromModule)\r
1498 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in GenC.gDynamicExPcd:\r
97fa0ee9
YL
1499 # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
1500 # It is to solve the case that a dynamic PCD used by a PEM module/PEI \r
1501 # module & DXE module at a same time.\r
1502 # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
1503 # INF file as DynamicEx. \r
a0a2cd1e
FB
1504 Index = self._DynaPcdList_.index(PcdFromModule)\r
1505 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
1506 self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
1507 for PcdFromModule in self._NonDynaPcdList_:\r
1508 # If a PCD is not listed in the DSC file, but binary INF files used by \r
1509 # this platform all (that use this PCD) list the PCD in a [PatchPcds] \r
1510 # section, AND all source INF files used by this platform the build \r
1511 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds] \r
1512 # section, then the tools must NOT add the PCD to the Platform's PCD\r
1513 # Database; the build must assign the access method for this PCD as \r
1514 # PcdsPatchableInModule.\r
1515 if PcdFromModule not in self._DynaPcdList_:\r
1516 continue\r
1517 Index = self._DynaPcdList_.index(PcdFromModule)\r
1518 if PcdFromModule.IsFromDsc == False and \\r
1519 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
1520 PcdFromModule.IsFromBinaryInf == True and \\r
1521 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
1522 Index = self._DynaPcdList_.index(PcdFromModule)\r
1523 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
52302d4d
LG
1524\r
1525 # print out error information and break the build, if error found\r
1526 if len(NoDatumTypePcdList) > 0:\r
1527 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
1528 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1529 File=self.MetaFile,\r
1530 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
1531 % NoDatumTypePcdListString)\r
1532 self._NonDynamicPcdList = self._NonDynaPcdList_\r
1533 self._DynamicPcdList = self._DynaPcdList_\r
52302d4d
LG
1534 #\r
1535 # Sort dynamic PCD list to:\r
1536 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should \r
1537 # try to be put header of dynamicd List\r
1538 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
1539 #\r
1540 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
1541 #\r
0b6c5954
LG
1542 UnicodePcdArray = set()\r
1543 HiiPcdArray = set()\r
1544 OtherPcdArray = set()\r
6780eef1 1545 VpdPcdDict = {}\r
e56468c0 1546 VpdFile = VpdInfoFile.VpdInfoFile()\r
61ee1dff
YZ
1547 NeedProcessVpdMapFile = False\r
1548\r
1549 for pcd in self.Platform.Pcds.keys():\r
1550 if pcd not in self._PlatformPcds.keys():\r
1551 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]\r
1552\r
ae7b6df8
LG
1553 for item in self._PlatformPcds:\r
1554 if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
1555 self._PlatformPcds[item].DatumType = "VOID*"\r
1556\r
e56468c0 1557 if (self.Workspace.ArchList[-1] == self.Arch): \r
1558 for Pcd in self._DynamicPcdList:\r
e56468c0 1559 # just pick the a value to determine whether is unicode string type\r
47fea6af 1560 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
e56468c0 1561 Sku.VpdOffset = Sku.VpdOffset.strip()\r
47fea6af 1562\r
ae7b6df8
LG
1563 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
1564 Pcd.DatumType = "VOID*"\r
1565\r
e56468c0 1566 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
e56468c0 1567 # if found HII type PCD then insert to right of UnicodeIndex\r
e56468c0 1568 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
47fea6af
YZ
1569 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
1570\r
34952f49
LG
1571 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer\r
1572 PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer","gEfiMdeModulePkgTokenSpaceGuid"))\r
1573 if PcdNvStoreDfBuffer:\r
47854fd5 1574 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
47854fd5 1575 vardump = self.VariableInfo.dump()\r
626bece4 1576 if vardump:\r
2b8a6c44 1577 PcdNvStoreDfBuffer.DefaultValue = vardump\r
626bece4
LG
1578 for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
1579 PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
1580 PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
34952f49 1581\r
61ee1dff 1582 PlatformPcds = self._PlatformPcds.keys()\r
47fea6af 1583 PlatformPcds.sort()\r
6780eef1
LG
1584 #\r
1585 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
1586 #\r
626bece4 1587 VpdSkuMap = {}\r
6780eef1 1588 for PcdKey in PlatformPcds:\r
61ee1dff 1589 Pcd = self._PlatformPcds[PcdKey]\r
e8a47801
LG
1590 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
1591 PcdKey in VpdPcdDict:\r
1592 Pcd = VpdPcdDict[PcdKey]\r
626bece4 1593 SkuValueMap = {}\r
8ac16789
LG
1594 DefaultSku = Pcd.SkuInfoList.get('DEFAULT')\r
1595 if DefaultSku:\r
1596 PcdValue = DefaultSku.DefaultValue\r
1597 if PcdValue not in SkuValueMap:\r
1598 SkuValueMap[PcdValue] = []\r
1599 VpdFile.Add(Pcd, 'DEFAULT',DefaultSku.VpdOffset)\r
1600 SkuValueMap[PcdValue].append(DefaultSku)\r
1601\r
e8a47801
LG
1602 for (SkuName,Sku) in Pcd.SkuInfoList.items():\r
1603 Sku.VpdOffset = Sku.VpdOffset.strip()\r
5a13737a
YZ
1604 PcdValue = Sku.DefaultValue\r
1605 if PcdValue == "":\r
1606 PcdValue = Pcd.DefaultValue\r
1607 if Sku.VpdOffset != '*':\r
1608 if PcdValue.startswith("{"):\r
1609 Alignment = 8\r
1610 elif PcdValue.startswith("L"):\r
1611 Alignment = 2\r
1612 else:\r
1613 Alignment = 1\r
ca85291f
YZ
1614 try:\r
1615 VpdOffset = int(Sku.VpdOffset)\r
1616 except:\r
1617 try:\r
1618 VpdOffset = int(Sku.VpdOffset, 16)\r
1619 except:\r
1620 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1621 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1622 if PcdValue.startswith("{"):\r
1623 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
1624 else:\r
1625 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
1626 if PcdValue not in SkuValueMap:\r
1627 SkuValueMap[PcdValue] = []\r
8ac16789 1628 VpdFile.Add(Pcd, SkuName,Sku.VpdOffset)\r
626bece4 1629 SkuValueMap[PcdValue].append(Sku)\r
e8a47801
LG
1630 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
1631 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1632 NeedProcessVpdMapFile = True\r
4231a819 1633 if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
e8a47801
LG
1634 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
1635 "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 1636\r
626bece4 1637 VpdSkuMap[PcdKey] = SkuValueMap\r
e56468c0 1638 #\r
1639 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
1640 # An example is PCD for signature usage.\r
6780eef1
LG
1641 # \r
1642 for DscPcd in PlatformPcds:\r
61ee1dff 1643 DscPcdEntry = self._PlatformPcds[DscPcd]\r
e56468c0 1644 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
4231a819 1645 if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):\r
e56468c0 1646 FoundFlag = False\r
1647 for VpdPcd in VpdFile._VpdArray.keys():\r
1648 # This PCD has been referenced by module\r
1649 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1650 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
1651 FoundFlag = True\r
47fea6af 1652\r
e56468c0 1653 # Not found, it should be signature\r
1654 if not FoundFlag :\r
1655 # just pick the a value to determine whether is unicode string type\r
626bece4 1656 SkuValueMap = {}\r
e827d21d 1657 SkuObjList = DscPcdEntry.SkuInfoList.items()\r
8ac16789
LG
1658 DefaultSku = DscPcdEntry.SkuInfoList.get('DEFAULT')\r
1659 if DefaultSku:\r
e827d21d
B
1660 defaultindex = SkuObjList.index(('DEFAULT',DefaultSku))\r
1661 SkuObjList[0],SkuObjList[defaultindex] = SkuObjList[defaultindex],SkuObjList[0]\r
1662 for (SkuName,Sku) in SkuObjList:\r
e8a47801
LG
1663 Sku.VpdOffset = Sku.VpdOffset.strip() \r
1664 \r
1665 # Need to iterate DEC pcd information to get the value & datumtype\r
1666 for eachDec in self.PackageList:\r
1667 for DecPcd in eachDec.Pcds:\r
1668 DecPcdEntry = eachDec.Pcds[DecPcd]\r
1669 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1670 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
1671 # Print warning message to let the developer make a determine.\r
1672 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
1673 File=self.MetaFile, \\r
1674 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
1675 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path)) \r
1676 \r
1677 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
1678 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
1679 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
1680 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
1681 # Only fix the value while no value provided in DSC file.\r
1682 if (Sku.DefaultValue == "" or Sku.DefaultValue==None):\r
1683 DscPcdEntry.SkuInfoList[DscPcdEntry.SkuInfoList.keys()[0]].DefaultValue = DecPcdEntry.DefaultValue\r
1684 \r
1685 if DscPcdEntry not in self._DynamicPcdList:\r
1686 self._DynamicPcdList.append(DscPcdEntry)\r
e8a47801
LG
1687 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1688 PcdValue = Sku.DefaultValue\r
5a13737a
YZ
1689 if PcdValue == "":\r
1690 PcdValue = DscPcdEntry.DefaultValue\r
1691 if Sku.VpdOffset != '*':\r
1692 if PcdValue.startswith("{"):\r
1693 Alignment = 8\r
1694 elif PcdValue.startswith("L"):\r
1695 Alignment = 2\r
1696 else:\r
1697 Alignment = 1\r
ca85291f
YZ
1698 try:\r
1699 VpdOffset = int(Sku.VpdOffset)\r
1700 except:\r
1701 try:\r
1702 VpdOffset = int(Sku.VpdOffset, 16)\r
1703 except:\r
1704 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
1705 if VpdOffset % Alignment != 0:\r
815ada26
YZ
1706 if PcdValue.startswith("{"):\r
1707 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
1708 else:\r
1709 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
1710 if PcdValue not in SkuValueMap:\r
1711 SkuValueMap[PcdValue] = []\r
8ac16789 1712 VpdFile.Add(DscPcdEntry, SkuName,Sku.VpdOffset)\r
626bece4 1713 SkuValueMap[PcdValue].append(Sku)\r
e8a47801
LG
1714 if not NeedProcessVpdMapFile and Sku.VpdOffset == "*":\r
1715 NeedProcessVpdMapFile = True \r
1716 if DscPcdEntry.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
0b6c5954 1717 UnicodePcdArray.add(DscPcdEntry)\r
e8a47801 1718 elif len(Sku.VariableName) > 0:\r
0b6c5954 1719 HiiPcdArray.add(DscPcdEntry)\r
e8a47801 1720 else:\r
0b6c5954
LG
1721 OtherPcdArray.add(DscPcdEntry)\r
1722\r
e8a47801 1723 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
626bece4 1724 VpdSkuMap[DscPcd] = SkuValueMap\r
4231a819 1725 if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
e56468c0 1726 VpdFile.GetCount() != 0:\r
1727 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, \r
1728 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
47fea6af 1729\r
e56468c0 1730 if VpdFile.GetCount() != 0:\r
47854fd5
LG
1731\r
1732 self.FixVpdOffset(VpdFile)\r
1733\r
1734 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
47fea6af 1735\r
e56468c0 1736 # Process VPD map file generated by third party BPDG tool\r
1737 if NeedProcessVpdMapFile:\r
08dd311f 1738 VpdMapFilePath = os.path.join(self.BuildDir, "FV", "%s.map" % self.Platform.VpdToolGuid)\r
e56468c0 1739 if os.path.exists(VpdMapFilePath):\r
1740 VpdFile.Read(VpdMapFilePath)\r
47fea6af 1741\r
e56468c0 1742 # Fixup "*" offset\r
626bece4
LG
1743 for pcd in VpdSkuMap:\r
1744 vpdinfo = VpdFile.GetVpdInfo(pcd)\r
1745 if vpdinfo is None:\r
e56468c0 1746 # just pick the a value to determine whether is unicode string type\r
626bece4
LG
1747 continue\r
1748 for pcdvalue in VpdSkuMap[pcd]:\r
1749 for sku in VpdSkuMap[pcd][pcdvalue]:\r
1750 for item in vpdinfo:\r
1751 if item[2] == pcdvalue:\r
1752 sku.VpdOffset = item[1]\r
e56468c0 1753 else:\r
1754 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
47fea6af 1755\r
626bece4
LG
1756 # Delete the DynamicPcdList At the last time enter into this function\r
1757 for Pcd in self._DynamicPcdList:\r
1758 # just pick the a value to determine whether is unicode string type\r
1759 Sku = Pcd.SkuInfoList[Pcd.SkuInfoList.keys()[0]]\r
1760 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1761\r
1762 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
1763 Pcd.DatumType = "VOID*"\r
1764\r
1765 PcdValue = Sku.DefaultValue\r
1766 if Pcd.DatumType == 'VOID*' and PcdValue.startswith("L"):\r
1767 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
0b6c5954 1768 UnicodePcdArray.add(Pcd)\r
626bece4
LG
1769 elif len(Sku.VariableName) > 0:\r
1770 # if found HII type PCD then insert to right of UnicodeIndex\r
0b6c5954 1771 HiiPcdArray.add(Pcd)\r
626bece4 1772 else:\r
0b6c5954 1773 OtherPcdArray.add(Pcd)\r
47fea6af 1774 del self._DynamicPcdList[:]\r
0b6c5954
LG
1775 self._DynamicPcdList.extend(list(UnicodePcdArray))\r
1776 self._DynamicPcdList.extend(list(HiiPcdArray))\r
1777 self._DynamicPcdList.extend(list(OtherPcdArray))\r
2b8a6c44
LG
1778 allskuset = [(SkuName,Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName,Sku) in pcd.SkuInfoList.items()]\r
1779 for pcd in self._DynamicPcdList:\r
1780 if len(pcd.SkuInfoList) == 1:\r
1781 for (SkuName,SkuId) in allskuset:\r
1782 if type(SkuId) in (str,unicode) and eval(SkuId) == 0 or SkuId == 0:\r
1783 continue\r
65eff519
LG
1784 pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList['DEFAULT'])\r
1785 pcd.SkuInfoList[SkuName].SkuId = SkuId\r
a0a2cd1e 1786 self.AllPcdList = self._NonDynamicPcdList + self._DynamicPcdList\r
47854fd5
LG
1787\r
1788 def FixVpdOffset(self,VpdFile ):\r
1789 FvPath = os.path.join(self.BuildDir, "FV")\r
1790 if not os.path.exists(FvPath):\r
1791 try:\r
1792 os.makedirs(FvPath)\r
1793 except:\r
1794 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
1795\r
1796 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
1797\r
1798 if VpdFile.Write(VpdFilePath):\r
1799 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
1800 BPDGToolName = None\r
1801 for ToolDef in self.ToolDefinition.values():\r
1802 if ToolDef.has_key("GUID") and ToolDef["GUID"] == self.Platform.VpdToolGuid:\r
1803 if not ToolDef.has_key("PATH"):\r
1804 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
1805 BPDGToolName = ToolDef["PATH"]\r
1806 break\r
1807 # Call third party GUID BPDG tool.\r
4231a819 1808 if BPDGToolName is not None:\r
47854fd5
LG
1809 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
1810 else:\r
1811 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
1812\r
52302d4d
LG
1813 ## Return the platform build data object\r
1814 def _GetPlatform(self):\r
4231a819 1815 if self._Platform is None:\r
0d2711a6 1816 self._Platform = self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
1817 return self._Platform\r
1818\r
1819 ## Return platform name\r
1820 def _GetName(self):\r
1821 return self.Platform.PlatformName\r
1822\r
1823 ## Return the meta file GUID\r
1824 def _GetGuid(self):\r
1825 return self.Platform.Guid\r
1826\r
1827 ## Return the platform version\r
1828 def _GetVersion(self):\r
1829 return self.Platform.Version\r
1830\r
1831 ## Return the FDF file name\r
1832 def _GetFdfFile(self):\r
4231a819 1833 if self._FdfFile is None:\r
52302d4d 1834 if self.Workspace.FdfFile != "":\r
05cc51ad 1835 self._FdfFile= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
52302d4d
LG
1836 else:\r
1837 self._FdfFile = ''\r
1838 return self._FdfFile\r
1839\r
1840 ## Return the build output directory platform specifies\r
1841 def _GetOutputDir(self):\r
1842 return self.Platform.OutputDirectory\r
1843\r
1844 ## Return the directory to store all intermediate and final files built\r
1845 def _GetBuildDir(self):\r
4231a819 1846 if self._BuildDir is None:\r
52302d4d
LG
1847 if os.path.isabs(self.OutputDir):\r
1848 self._BuildDir = path.join(\r
1849 path.abspath(self.OutputDir),\r
1850 self.BuildTarget + "_" + self.ToolChain,\r
1851 )\r
1852 else:\r
1853 self._BuildDir = path.join(\r
1854 self.WorkspaceDir,\r
1855 self.OutputDir,\r
1856 self.BuildTarget + "_" + self.ToolChain,\r
1857 )\r
97058144 1858 GlobalData.gBuildDirectory = self._BuildDir\r
52302d4d
LG
1859 return self._BuildDir\r
1860\r
1861 ## Return directory of platform makefile\r
1862 #\r
1863 # @retval string Makefile directory\r
1864 #\r
1865 def _GetMakeFileDir(self):\r
4231a819 1866 if self._MakeFileDir is None:\r
52302d4d
LG
1867 self._MakeFileDir = path.join(self.BuildDir, self.Arch)\r
1868 return self._MakeFileDir\r
1869\r
1870 ## Return build command string\r
1871 #\r
1872 # @retval string Build command string\r
1873 #\r
1874 def _GetBuildCommand(self):\r
4231a819 1875 if self._BuildCommand is None:\r
52302d4d
LG
1876 self._BuildCommand = []\r
1877 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
1878 self._BuildCommand += SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
1879 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
1880 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
1881 if NewOption != '':\r
6780eef1 1882 self._BuildCommand += SplitOption(NewOption)\r
02a908fc
YZ
1883 if "MAKE" in self.EdkIIBuildOption:\r
1884 if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
1885 Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
1886 if Flags.startswith('='):\r
1887 self._BuildCommand = [self._BuildCommand[0]] + [Flags[1:]]\r
1888 else:\r
1889 self._BuildCommand += [Flags]\r
52302d4d
LG
1890 return self._BuildCommand\r
1891\r
1892 ## Get tool chain definition\r
1893 #\r
1894 # Get each tool defition for given tool chain from tools_def.txt and platform\r
1895 #\r
1896 def _GetToolDefinition(self):\r
4231a819 1897 if self._ToolDefinitions is None:\r
52302d4d
LG
1898 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
1899 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
1900 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
1901 ExtraData="[%s]" % self.MetaFile)\r
1902 self._ToolDefinitions = {}\r
1903 DllPathList = set()\r
1904 for Def in ToolDefinition:\r
1905 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
1906 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
1907 continue\r
1908\r
1909 Value = ToolDefinition[Def]\r
1910 # don't record the DLL\r
1911 if Attr == "DLL":\r
1912 DllPathList.add(Value)\r
1913 continue\r
1914\r
1915 if Tool not in self._ToolDefinitions:\r
1916 self._ToolDefinitions[Tool] = {}\r
1917 self._ToolDefinitions[Tool][Attr] = Value\r
1918\r
1919 ToolsDef = ''\r
1920 MakePath = ''\r
1921 if GlobalData.gOptions.SilentMode and "MAKE" in self._ToolDefinitions:\r
1922 if "FLAGS" not in self._ToolDefinitions["MAKE"]:\r
1923 self._ToolDefinitions["MAKE"]["FLAGS"] = ""\r
1924 self._ToolDefinitions["MAKE"]["FLAGS"] += " -s"\r
1925 MakeFlags = ''\r
1926 for Tool in self._ToolDefinitions:\r
1927 for Attr in self._ToolDefinitions[Tool]:\r
1928 Value = self._ToolDefinitions[Tool][Attr]\r
1929 if Tool in self.BuildOption and Attr in self.BuildOption[Tool]:\r
1930 # check if override is indicated\r
1931 if self.BuildOption[Tool][Attr].startswith('='):\r
1932 Value = self.BuildOption[Tool][Attr][1:]\r
1933 else:\r
95816356
YZ
1934 if Attr != 'PATH':\r
1935 Value += " " + self.BuildOption[Tool][Attr]\r
1936 else:\r
1937 Value = self.BuildOption[Tool][Attr]\r
52302d4d
LG
1938\r
1939 if Attr == "PATH":\r
1940 # Don't put MAKE definition in the file\r
1941 if Tool == "MAKE":\r
1942 MakePath = Value\r
1943 else:\r
1944 ToolsDef += "%s = %s\n" % (Tool, Value)\r
1945 elif Attr != "DLL":\r
1946 # Don't put MAKE definition in the file\r
1947 if Tool == "MAKE":\r
1948 if Attr == "FLAGS":\r
1949 MakeFlags = Value\r
1950 else:\r
1951 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
1952 ToolsDef += "\n"\r
1953\r
1954 SaveFileOnChange(self.ToolDefinitionFile, ToolsDef)\r
1955 for DllPath in DllPathList:\r
1956 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
1957 os.environ["MAKE_FLAGS"] = MakeFlags\r
1958\r
1959 return self._ToolDefinitions\r
1960\r
1961 ## Return the paths of tools\r
1962 def _GetToolDefFile(self):\r
4231a819 1963 if self._ToolDefFile is None:\r
52302d4d
LG
1964 self._ToolDefFile = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
1965 return self._ToolDefFile\r
1966\r
1967 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
1968 def _GetToolChainFamily(self):\r
4231a819 1969 if self._ToolChainFamily is None:\r
52302d4d
LG
1970 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1971 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
1972 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
1973 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
1974 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1975 % self.ToolChain)\r
1976 self._ToolChainFamily = "MSFT"\r
1977 else:\r
1978 self._ToolChainFamily = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
1979 return self._ToolChainFamily\r
1980\r
1981 def _GetBuildRuleFamily(self):\r
4231a819 1982 if self._BuildRuleFamily is None:\r
52302d4d
LG
1983 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1984 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
1985 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
1986 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
1987 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1988 % self.ToolChain)\r
1989 self._BuildRuleFamily = "MSFT"\r
1990 else:\r
1991 self._BuildRuleFamily = ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
1992 return self._BuildRuleFamily\r
1993\r
1994 ## Return the build options specific for all modules in this platform\r
1995 def _GetBuildOptions(self):\r
4231a819 1996 if self._BuildOption is None:\r
52302d4d
LG
1997 self._BuildOption = self._ExpandBuildOption(self.Platform.BuildOptions)\r
1998 return self._BuildOption\r
1999\r
2000 ## Return the build options specific for EDK modules in this platform\r
2001 def _GetEdkBuildOptions(self):\r
4231a819 2002 if self._EdkBuildOption is None:\r
52302d4d
LG
2003 self._EdkBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
2004 return self._EdkBuildOption\r
2005\r
2006 ## Return the build options specific for EDKII modules in this platform\r
2007 def _GetEdkIIBuildOptions(self):\r
4231a819 2008 if self._EdkIIBuildOption is None:\r
52302d4d
LG
2009 self._EdkIIBuildOption = self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
2010 return self._EdkIIBuildOption\r
2011\r
97fa0ee9 2012 ## Parse build_rule.txt in Conf Directory.\r
52302d4d
LG
2013 #\r
2014 # @retval BuildRule object\r
2015 #\r
2016 def _GetBuildRule(self):\r
4231a819 2017 if self._BuildRule is None:\r
52302d4d
LG
2018 BuildRuleFile = None\r
2019 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
2020 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
2021 if BuildRuleFile in [None, '']:\r
97fa0ee9 2022 BuildRuleFile = gDefaultBuildRuleFile\r
52302d4d 2023 self._BuildRule = BuildRule(BuildRuleFile)\r
64b2609f
LG
2024 if self._BuildRule._FileVersion == "":\r
2025 self._BuildRule._FileVersion = AutoGenReqBuildRuleVerNum\r
2026 else:\r
2027 if self._BuildRule._FileVersion < AutoGenReqBuildRuleVerNum :\r
2028 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
47fea6af 2029 EdkLogger.error("build", AUTOGEN_ERROR,\r
64b2609f
LG
2030 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
2031 % (self._BuildRule._FileVersion, AutoGenReqBuildRuleVerNum))\r
47fea6af 2032\r
52302d4d
LG
2033 return self._BuildRule\r
2034\r
2035 ## Summarize the packages used by modules in this platform\r
2036 def _GetPackageList(self):\r
4231a819 2037 if self._PackageList is None:\r
52302d4d
LG
2038 self._PackageList = set()\r
2039 for La in self.LibraryAutoGenList:\r
2040 self._PackageList.update(La.DependentPackageList)\r
2041 for Ma in self.ModuleAutoGenList:\r
2042 self._PackageList.update(Ma.DependentPackageList)\r
a0a2cd1e
FB
2043 #Collect package set information from INF of FDF\r
2044 PkgSet = set()\r
2045 for ModuleFile in self._AsBuildModuleList:\r
2046 if ModuleFile in self.Platform.Modules:\r
2047 continue\r
2048 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
2049 PkgSet.update(ModuleData.Packages)\r
2050 self._PackageList = list(self._PackageList) + list (PkgSet)\r
52302d4d
LG
2051 return self._PackageList\r
2052\r
2bc3256c
LG
2053 def _GetNonDynamicPcdDict(self):\r
2054 if self._NonDynamicPcdDict:\r
2055 return self._NonDynamicPcdDict\r
2056 for Pcd in self.NonDynamicPcdList:\r
2057 self._NonDynamicPcdDict[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)] = Pcd\r
2058 return self._NonDynamicPcdDict\r
2059\r
52302d4d
LG
2060 ## Get list of non-dynamic PCDs\r
2061 def _GetNonDynamicPcdList(self):\r
4231a819 2062 if self._NonDynamicPcdList is None:\r
e56468c0 2063 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
2064 return self._NonDynamicPcdList\r
2065\r
2066 ## Get list of dynamic PCDs\r
2067 def _GetDynamicPcdList(self):\r
4231a819 2068 if self._DynamicPcdList is None:\r
e56468c0 2069 self.CollectPlatformDynamicPcds()\r
52302d4d
LG
2070 return self._DynamicPcdList\r
2071\r
2072 ## Generate Token Number for all PCD\r
2073 def _GetPcdTokenNumbers(self):\r
4231a819 2074 if self._PcdTokenNumber is None:\r
9006a2c6 2075 self._PcdTokenNumber = OrderedDict()\r
52302d4d 2076 TokenNumber = 1\r
d0acc87a
LG
2077 #\r
2078 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area. \r
2079 # Such as:\r
2080 # \r
2081 # Dynamic PCD:\r
2082 # TokenNumber 0 ~ 10\r
2083 # DynamicEx PCD:\r
2084 # TokeNumber 11 ~ 20\r
2085 #\r
52302d4d
LG
2086 for Pcd in self.DynamicPcdList:\r
2087 if Pcd.Phase == "PEI":\r
d0acc87a
LG
2088 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:\r
2089 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2090 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2091 TokenNumber += 1\r
47fea6af 2092\r
d0acc87a
LG
2093 for Pcd in self.DynamicPcdList:\r
2094 if Pcd.Phase == "PEI":\r
2095 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:\r
2096 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2097 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2098 TokenNumber += 1\r
47fea6af 2099\r
52302d4d
LG
2100 for Pcd in self.DynamicPcdList:\r
2101 if Pcd.Phase == "DXE":\r
d0acc87a
LG
2102 if Pcd.Type in ["Dynamic", "DynamicDefault", "DynamicVpd", "DynamicHii"]:\r
2103 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2104 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2105 TokenNumber += 1\r
47fea6af 2106\r
d0acc87a
LG
2107 for Pcd in self.DynamicPcdList:\r
2108 if Pcd.Phase == "DXE":\r
2109 if Pcd.Type in ["DynamicEx", "DynamicExDefault", "DynamicExVpd", "DynamicExHii"]:\r
2110 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2111 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2112 TokenNumber += 1\r
47fea6af 2113\r
52302d4d
LG
2114 for Pcd in self.NonDynamicPcdList:\r
2115 self._PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2116 TokenNumber += 1\r
2117 return self._PcdTokenNumber\r
2118\r
2119 ## Summarize ModuleAutoGen objects of all modules/libraries to be built for this platform\r
2120 def _GetAutoGenObjectList(self):\r
2121 self._ModuleAutoGenList = []\r
2122 self._LibraryAutoGenList = []\r
2123 for ModuleFile in self.Platform.Modules:\r
2124 Ma = ModuleAutoGen(\r
2125 self.Workspace,\r
2126 ModuleFile,\r
2127 self.BuildTarget,\r
2128 self.ToolChain,\r
2129 self.Arch,\r
2130 self.MetaFile\r
2131 )\r
2132 if Ma not in self._ModuleAutoGenList:\r
2133 self._ModuleAutoGenList.append(Ma)\r
2134 for La in Ma.LibraryAutoGenList:\r
2135 if La not in self._LibraryAutoGenList:\r
2136 self._LibraryAutoGenList.append(La)\r
2bc3256c
LG
2137 if Ma not in La._ReferenceModules:\r
2138 La._ReferenceModules.append(Ma)\r
52302d4d
LG
2139\r
2140 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
2141 def _GetModuleAutoGenList(self):\r
4231a819 2142 if self._ModuleAutoGenList is None:\r
52302d4d
LG
2143 self._GetAutoGenObjectList()\r
2144 return self._ModuleAutoGenList\r
2145\r
2146 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
2147 def _GetLibraryAutoGenList(self):\r
4231a819 2148 if self._LibraryAutoGenList is None:\r
52302d4d
LG
2149 self._GetAutoGenObjectList()\r
2150 return self._LibraryAutoGenList\r
2151\r
2152 ## Test if a module is supported by the platform\r
2153 #\r
2154 # An error will be raised directly if the module or its arch is not supported\r
2155 # by the platform or current configuration\r
2156 #\r
2157 def ValidModule(self, Module):\r
a0a2cd1e
FB
2158 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
2159 or Module in self._AsBuildModuleList\r
52302d4d
LG
2160\r
2161 ## Resolve the library classes in a module to library instances\r
2162 #\r
2163 # This method will not only resolve library classes but also sort the library\r
2164 # instances according to the dependency-ship.\r
2165 #\r
2166 # @param Module The module from which the library classes will be resolved\r
2167 #\r
2168 # @retval library_list List of library instances sorted\r
2169 #\r
2170 def ApplyLibraryInstance(self, Module):\r
25193a33
YZ
2171 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly\r
2172 if str(Module) not in self.Platform.Modules:\r
2173 return []\r
2174\r
52302d4d
LG
2175 ModuleType = Module.ModuleType\r
2176\r
2177 # for overridding library instances with module specific setting\r
2178 PlatformModule = self.Platform.Modules[str(Module)]\r
2179\r
2180 # add forced library instances (specified under LibraryClasses sections)\r
da92f276
LG
2181 #\r
2182 # If a module has a MODULE_TYPE of USER_DEFINED,\r
2183 # do not link in NULL library class instances from the global [LibraryClasses.*] sections.\r
2184 #\r
2185 if Module.ModuleType != SUP_MODULE_USER_DEFINED:\r
2186 for LibraryClass in self.Platform.LibraryClasses.GetKeys():\r
2187 if LibraryClass.startswith("NULL") and self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]:\r
2188 Module.LibraryClasses[LibraryClass] = self.Platform.LibraryClasses[LibraryClass, Module.ModuleType]\r
52302d4d
LG
2189\r
2190 # add forced library instances (specified in module overrides)\r
2191 for LibraryClass in PlatformModule.LibraryClasses:\r
2192 if LibraryClass.startswith("NULL"):\r
2193 Module.LibraryClasses[LibraryClass] = PlatformModule.LibraryClasses[LibraryClass]\r
2194\r
b36d134f 2195 # EdkII module\r
52302d4d
LG
2196 LibraryConsumerList = [Module]\r
2197 Constructor = []\r
9006a2c6
CJ
2198 ConsumedByList = OrderedDict()\r
2199 LibraryInstance = OrderedDict()\r
52302d4d
LG
2200\r
2201 EdkLogger.verbose("")\r
2202 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
2203 while len(LibraryConsumerList) > 0:\r
2204 M = LibraryConsumerList.pop()\r
2205 for LibraryClassName in M.LibraryClasses:\r
2206 if LibraryClassName not in LibraryInstance:\r
2207 # override library instance for this module\r
2208 if LibraryClassName in PlatformModule.LibraryClasses:\r
2209 LibraryPath = PlatformModule.LibraryClasses[LibraryClassName]\r
2210 else:\r
2211 LibraryPath = self.Platform.LibraryClasses[LibraryClassName, ModuleType]\r
4231a819 2212 if LibraryPath is None or LibraryPath == "":\r
52302d4d 2213 LibraryPath = M.LibraryClasses[LibraryClassName]\r
4231a819 2214 if LibraryPath is None or LibraryPath == "":\r
52302d4d
LG
2215 EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,\r
2216 "Instance of library class [%s] is not found" % LibraryClassName,\r
2217 File=self.MetaFile,\r
2218 ExtraData="in [%s] [%s]\n\tconsumed by module [%s]" % (str(M), self.Arch, str(Module)))\r
2219\r
0d2711a6 2220 LibraryModule = self.BuildDatabase[LibraryPath, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
2221 # for those forced library instance (NULL library), add a fake library class\r
2222 if LibraryClassName.startswith("NULL"):\r
2223 LibraryModule.LibraryClass.append(LibraryClassObject(LibraryClassName, [ModuleType]))\r
4231a819 2224 elif LibraryModule.LibraryClass is None \\r
52302d4d
LG
2225 or len(LibraryModule.LibraryClass) == 0 \\r
2226 or (ModuleType != 'USER_DEFINED'\r
2227 and ModuleType not in LibraryModule.LibraryClass[0].SupModList):\r
2228 # only USER_DEFINED can link against any library instance despite of its SupModList\r
2229 EdkLogger.error("build", OPTION_MISSING,\r
2230 "Module type [%s] is not supported by library instance [%s]" \\r
2231 % (ModuleType, LibraryPath), File=self.MetaFile,\r
2232 ExtraData="consumed by [%s]" % str(Module))\r
2233\r
2234 LibraryInstance[LibraryClassName] = LibraryModule\r
2235 LibraryConsumerList.append(LibraryModule)\r
2236 EdkLogger.verbose("\t" + str(LibraryClassName) + " : " + str(LibraryModule))\r
2237 else:\r
2238 LibraryModule = LibraryInstance[LibraryClassName]\r
2239\r
4231a819 2240 if LibraryModule is None:\r
52302d4d
LG
2241 continue\r
2242\r
2243 if LibraryModule.ConstructorList != [] and LibraryModule not in Constructor:\r
2244 Constructor.append(LibraryModule)\r
2245\r
2246 if LibraryModule not in ConsumedByList:\r
2247 ConsumedByList[LibraryModule] = []\r
2248 # don't add current module itself to consumer list\r
2249 if M != Module:\r
2250 if M in ConsumedByList[LibraryModule]:\r
2251 continue\r
2252 ConsumedByList[LibraryModule].append(M)\r
2253 #\r
2254 # Initialize the sorted output list to the empty set\r
2255 #\r
2256 SortedLibraryList = []\r
2257 #\r
2258 # Q <- Set of all nodes with no incoming edges\r
2259 #\r
2260 LibraryList = [] #LibraryInstance.values()\r
2261 Q = []\r
2262 for LibraryClassName in LibraryInstance:\r
2263 M = LibraryInstance[LibraryClassName]\r
2264 LibraryList.append(M)\r
2265 if ConsumedByList[M] == []:\r
2266 Q.append(M)\r
2267\r
2268 #\r
2269 # start the DAG algorithm\r
2270 #\r
2271 while True:\r
2272 EdgeRemoved = True\r
2273 while Q == [] and EdgeRemoved:\r
2274 EdgeRemoved = False\r
2275 # for each node Item with a Constructor\r
2276 for Item in LibraryList:\r
2277 if Item not in Constructor:\r
2278 continue\r
2279 # for each Node without a constructor with an edge e from Item to Node\r
2280 for Node in ConsumedByList[Item]:\r
2281 if Node in Constructor:\r
2282 continue\r
2283 # remove edge e from the graph if Node has no constructor\r
2284 ConsumedByList[Item].remove(Node)\r
2285 EdgeRemoved = True\r
2286 if ConsumedByList[Item] == []:\r
2287 # insert Item into Q\r
2288 Q.insert(0, Item)\r
2289 break\r
2290 if Q != []:\r
2291 break\r
2292 # DAG is done if there's no more incoming edge for all nodes\r
2293 if Q == []:\r
2294 break\r
2295\r
2296 # remove node from Q\r
2297 Node = Q.pop()\r
2298 # output Node\r
2299 SortedLibraryList.append(Node)\r
2300\r
2301 # for each node Item with an edge e from Node to Item do\r
2302 for Item in LibraryList:\r
2303 if Node not in ConsumedByList[Item]:\r
2304 continue\r
2305 # remove edge e from the graph\r
2306 ConsumedByList[Item].remove(Node)\r
2307\r
2308 if ConsumedByList[Item] != []:\r
2309 continue\r
2310 # insert Item into Q, if Item has no other incoming edges\r
2311 Q.insert(0, Item)\r
2312\r
2313 #\r
2314 # if any remaining node Item in the graph has a constructor and an incoming edge, then the graph has a cycle\r
2315 #\r
2316 for Item in LibraryList:\r
2317 if ConsumedByList[Item] != [] and Item in Constructor and len(Constructor) > 1:\r
2318 ErrorMessage = "\tconsumed by " + "\n\tconsumed by ".join([str(L) for L in ConsumedByList[Item]])\r
2319 EdkLogger.error("build", BUILD_ERROR, 'Library [%s] with constructors has a cycle' % str(Item),\r
2320 ExtraData=ErrorMessage, File=self.MetaFile)\r
2321 if Item not in SortedLibraryList:\r
2322 SortedLibraryList.append(Item)\r
2323\r
2324 #\r
2325 # Build the list of constructor and destructir names\r
2326 # The DAG Topo sort produces the destructor order, so the list of constructors must generated in the reverse order\r
2327 #\r
2328 SortedLibraryList.reverse()\r
2329 return SortedLibraryList\r
2330\r
2331\r
2332 ## Override PCD setting (type, value, ...)\r
2333 #\r
2334 # @param ToPcd The PCD to be overrided\r
2335 # @param FromPcd The PCD overrideing from\r
2336 #\r
2337 def _OverridePcd(self, ToPcd, FromPcd, Module=""):\r
2338 #\r
2339 # in case there's PCDs coming from FDF file, which have no type given.\r
2340 # at this point, ToPcd.Type has the type found from dependent\r
2341 # package\r
2342 #\r
2a29017e
YZ
2343 TokenCName = ToPcd.TokenCName\r
2344 for PcdItem in GlobalData.MixedPcd:\r
2345 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
2346 TokenCName = PcdItem[0]\r
2347 break\r
4231a819 2348 if FromPcd is not None:\r
52302d4d
LG
2349 if ToPcd.Pending and FromPcd.Type not in [None, '']:\r
2350 ToPcd.Type = FromPcd.Type\r
e56468c0 2351 elif (ToPcd.Type not in [None, '']) and (FromPcd.Type not in [None, ''])\\r
2352 and (ToPcd.Type != FromPcd.Type) and (ToPcd.Type in FromPcd.Type):\r
2353 if ToPcd.Type.strip() == "DynamicEx":\r
47fea6af 2354 ToPcd.Type = FromPcd.Type\r
52302d4d
LG
2355 elif ToPcd.Type not in [None, ''] and FromPcd.Type not in [None, ''] \\r
2356 and ToPcd.Type != FromPcd.Type:\r
2357 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
2358 ExtraData="%s.%s is defined as [%s] in module %s, but as [%s] in platform."\\r
2a29017e 2359 % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
52302d4d
LG
2360 ToPcd.Type, Module, FromPcd.Type),\r
2361 File=self.MetaFile)\r
2362\r
2363 if FromPcd.MaxDatumSize not in [None, '']:\r
2364 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
2365 if FromPcd.DefaultValue not in [None, '']:\r
2366 ToPcd.DefaultValue = FromPcd.DefaultValue\r
2367 if FromPcd.TokenValue not in [None, '']:\r
2368 ToPcd.TokenValue = FromPcd.TokenValue\r
2369 if FromPcd.MaxDatumSize not in [None, '']:\r
2370 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
2371 if FromPcd.DatumType not in [None, '']:\r
2372 ToPcd.DatumType = FromPcd.DatumType\r
2373 if FromPcd.SkuInfoList not in [None, '', []]:\r
2374 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
726c501c 2375 # Add Flexible PCD format parse\r
726c501c 2376 if ToPcd.DefaultValue:\r
726c501c 2377 try:\r
35f613d9 2378 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self._GuidDict)(True)\r
726c501c
YZ
2379 except BadExpression, Value:\r
2380 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
2381 File=self.MetaFile)\r
52302d4d
LG
2382\r
2383 # check the validation of datum\r
2384 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
2385 if not IsValid:\r
2386 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
2a29017e 2387 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
82a6a960
BF
2388 ToPcd.validateranges = FromPcd.validateranges\r
2389 ToPcd.validlists = FromPcd.validlists\r
2390 ToPcd.expressions = FromPcd.expressions\r
52302d4d 2391\r
4231a819 2392 if FromPcd is not None and ToPcd.DatumType == "VOID*" and ToPcd.MaxDatumSize in ['', None]:\r
52302d4d 2393 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
2a29017e 2394 % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
52302d4d
LG
2395 Value = ToPcd.DefaultValue\r
2396 if Value in [None, '']:\r
e8a47801 2397 ToPcd.MaxDatumSize = '1'\r
52302d4d 2398 elif Value[0] == 'L':\r
e8a47801 2399 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
52302d4d
LG
2400 elif Value[0] == '{':\r
2401 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
2402 else:\r
e8a47801 2403 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
52302d4d
LG
2404\r
2405 # apply default SKU for dynamic PCDS if specified one is not available\r
2406 if (ToPcd.Type in PCD_DYNAMIC_TYPE_LIST or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_LIST) \\r
2407 and ToPcd.SkuInfoList in [None, {}, '']:\r
2408 if self.Platform.SkuName in self.Platform.SkuIds:\r
2409 SkuName = self.Platform.SkuName\r
2410 else:\r
2411 SkuName = 'DEFAULT'\r
2412 ToPcd.SkuInfoList = {\r
8518bf0b 2413 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
52302d4d
LG
2414 }\r
2415\r
2416 ## Apply PCD setting defined platform to a module\r
2417 #\r
2418 # @param Module The module from which the PCD setting will be overrided\r
2419 #\r
2420 # @retval PCD_list The list PCDs with settings from platform\r
2421 #\r
2422 def ApplyPcdSetting(self, Module, Pcds):\r
2423 # for each PCD in module\r
47fea6af
YZ
2424 for Name, Guid in Pcds:\r
2425 PcdInModule = Pcds[Name, Guid]\r
52302d4d 2426 # find out the PCD setting in platform\r
47fea6af
YZ
2427 if (Name, Guid) in self.Platform.Pcds:\r
2428 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
52302d4d
LG
2429 else:\r
2430 PcdInPlatform = None\r
2431 # then override the settings if any\r
2432 self._OverridePcd(PcdInModule, PcdInPlatform, Module)\r
2433 # resolve the VariableGuid value\r
2434 for SkuId in PcdInModule.SkuInfoList:\r
2435 Sku = PcdInModule.SkuInfoList[SkuId]\r
2436 if Sku.VariableGuid == '': continue\r
c28d2e10 2437 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
4231a819 2438 if Sku.VariableGuidValue is None:\r
52302d4d
LG
2439 PackageList = "\n\t".join([str(P) for P in self.PackageList])\r
2440 EdkLogger.error(\r
2441 'build',\r
2442 RESOURCE_NOT_AVAILABLE,\r
2443 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
2444 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
2445 % (Guid, Name, str(Module)),\r
2446 File=self.MetaFile\r
2447 )\r
2448\r
2449 # override PCD settings with module specific setting\r
2450 if Module in self.Platform.Modules:\r
2451 PlatformModule = self.Platform.Modules[str(Module)]\r
2452 for Key in PlatformModule.Pcds:\r
aa9aa47e 2453 Flag = False\r
52302d4d 2454 if Key in Pcds:\r
aa9aa47e
YZ
2455 ToPcd = Pcds[Key]\r
2456 Flag = True\r
2457 elif Key in GlobalData.MixedPcd:\r
2458 for PcdItem in GlobalData.MixedPcd[Key]:\r
2459 if PcdItem in Pcds:\r
2460 ToPcd = Pcds[PcdItem]\r
2461 Flag = True\r
2462 break\r
2463 if Flag:\r
2464 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module)\r
cdbf45ad
YZ
2465 # use PCD value to calculate the MaxDatumSize when it is not specified\r
2466 for Name, Guid in Pcds:\r
2467 Pcd = Pcds[Name, Guid]\r
2468 if Pcd.DatumType == "VOID*" and Pcd.MaxDatumSize in ['', None]:\r
2469 Value = Pcd.DefaultValue\r
2470 if Value in [None, '']:\r
2471 Pcd.MaxDatumSize = '1'\r
2472 elif Value[0] == 'L':\r
2473 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
2474 elif Value[0] == '{':\r
2475 Pcd.MaxDatumSize = str(len(Value.split(',')))\r
2476 else:\r
2477 Pcd.MaxDatumSize = str(len(Value) - 1)\r
52302d4d
LG
2478 return Pcds.values()\r
2479\r
2480 ## Resolve library names to library modules\r
2481 #\r
b36d134f 2482 # (for Edk.x modules)\r
52302d4d
LG
2483 #\r
2484 # @param Module The module from which the library names will be resolved\r
2485 #\r
2486 # @retval library_list The list of library modules\r
2487 #\r
2488 def ResolveLibraryReference(self, Module):\r
2489 EdkLogger.verbose("")\r
2490 EdkLogger.verbose("Library instances of module [%s] [%s]:" % (str(Module), self.Arch))\r
2491 LibraryConsumerList = [Module]\r
2492\r
b36d134f 2493 # "CompilerStub" is a must for Edk modules\r
52302d4d
LG
2494 if Module.Libraries:\r
2495 Module.Libraries.append("CompilerStub")\r
2496 LibraryList = []\r
2497 while len(LibraryConsumerList) > 0:\r
2498 M = LibraryConsumerList.pop()\r
2499 for LibraryName in M.Libraries:\r
2500 Library = self.Platform.LibraryClasses[LibraryName, ':dummy:']\r
4231a819 2501 if Library is None:\r
52302d4d
LG
2502 for Key in self.Platform.LibraryClasses.data.keys():\r
2503 if LibraryName.upper() == Key.upper():\r
2504 Library = self.Platform.LibraryClasses[Key, ':dummy:']\r
2505 break\r
4231a819 2506 if Library is None:\r
52302d4d
LG
2507 EdkLogger.warn("build", "Library [%s] is not found" % LibraryName, File=str(M),\r
2508 ExtraData="\t%s [%s]" % (str(Module), self.Arch))\r
2509 continue\r
2510\r
2511 if Library not in LibraryList:\r
2512 LibraryList.append(Library)\r
2513 LibraryConsumerList.append(Library)\r
2514 EdkLogger.verbose("\t" + LibraryName + " : " + str(Library) + ' ' + str(type(Library)))\r
2515 return LibraryList\r
2516\r
6780eef1
LG
2517 ## Calculate the priority value of the build option\r
2518 #\r
2519 # @param Key Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2520 #\r
2521 # @retval Value Priority value based on the priority list.\r
2522 #\r
2523 def CalculatePriorityValue(self, Key):\r
47fea6af
YZ
2524 Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
2525 PriorityValue = 0x11111\r
6780eef1
LG
2526 if Target == "*":\r
2527 PriorityValue &= 0x01111\r
2528 if ToolChain == "*":\r
2529 PriorityValue &= 0x10111\r
2530 if Arch == "*":\r
2531 PriorityValue &= 0x11011\r
2532 if CommandType == "*":\r
2533 PriorityValue &= 0x11101\r
2534 if Attr == "*":\r
2535 PriorityValue &= 0x11110\r
47fea6af
YZ
2536\r
2537 return self.PrioList["0x%0.5x" % PriorityValue]\r
2538\r
6780eef1 2539\r
52302d4d
LG
2540 ## Expand * in build option key\r
2541 #\r
2542 # @param Options Options to be expanded\r
2543 #\r
2544 # @retval options Options expanded\r
6780eef1 2545 # \r
52302d4d
LG
2546 def _ExpandBuildOption(self, Options, ModuleStyle=None):\r
2547 BuildOptions = {}\r
2548 FamilyMatch = False\r
2549 FamilyIsNull = True\r
47fea6af 2550\r
6780eef1
LG
2551 OverrideList = {}\r
2552 #\r
2553 # Construct a list contain the build options which need override.\r
2554 #\r
2555 for Key in Options:\r
2556 #\r
2557 # Key[0] -- tool family\r
2558 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2559 #\r
1ba5124e 2560 if (Key[0] == self.BuildRuleFamily and\r
4231a819 2561 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
6780eef1
LG
2562 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
2563 if Target == self.BuildTarget or Target == "*":\r
2564 if ToolChain == self.ToolChain or ToolChain == "*":\r
2565 if Arch == self.Arch or Arch == "*":\r
2566 if Options[Key].startswith("="):\r
4231a819 2567 if OverrideList.get(Key[1]) is not None:\r
6780eef1
LG
2568 OverrideList.pop(Key[1])\r
2569 OverrideList[Key[1]] = Options[Key]\r
2570 \r
2571 #\r
2572 # Use the highest priority value. \r
2573 #\r
2574 if (len(OverrideList) >= 2):\r
47fea6af 2575 KeyList = OverrideList.keys()\r
6780eef1 2576 for Index in range(len(KeyList)):\r
47fea6af 2577 NowKey = KeyList[Index]\r
6780eef1
LG
2578 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
2579 for Index1 in range(len(KeyList) - Index - 1):\r
2580 NextKey = KeyList[Index1 + Index + 1]\r
2581 #\r
2582 # Compare two Key, if one is included by another, choose the higher priority one\r
2583 # \r
2584 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
2585 if Target1 == Target2 or Target1 == "*" or Target2 == "*":\r
2586 if ToolChain1 == ToolChain2 or ToolChain1 == "*" or ToolChain2 == "*":\r
2587 if Arch1 == Arch2 or Arch1 == "*" or Arch2 == "*":\r
2588 if CommandType1 == CommandType2 or CommandType1 == "*" or CommandType2 == "*":\r
2589 if Attr1 == Attr2 or Attr1 == "*" or Attr2 == "*":\r
2590 if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
4231a819 2591 if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
6780eef1
LG
2592 Options.pop((self.BuildRuleFamily, NextKey))\r
2593 else:\r
4231a819 2594 if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
6780eef1
LG
2595 Options.pop((self.BuildRuleFamily, NowKey))\r
2596 \r
52302d4d 2597 for Key in Options:\r
4231a819 2598 if ModuleStyle is not None and len (Key) > 2:\r
52302d4d
LG
2599 # Check Module style is EDK or EDKII.\r
2600 # Only append build option for the matched style module.\r
2601 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2602 continue\r
2603 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2604 continue\r
2605 Family = Key[0]\r
2606 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2607 # if tool chain family doesn't match, skip it\r
2608 if Tool in self.ToolDefinition and Family != "":\r
2609 FamilyIsNull = False\r
2610 if self.ToolDefinition[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
2611 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
2612 continue\r
2613 elif Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2614 continue\r
2615 FamilyMatch = True\r
2616 # expand any wildcard\r
2617 if Target == "*" or Target == self.BuildTarget:\r
2618 if Tag == "*" or Tag == self.ToolChain:\r
2619 if Arch == "*" or Arch == self.Arch:\r
2620 if Tool not in BuildOptions:\r
2621 BuildOptions[Tool] = {}\r
5015bee2 2622 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2623 BuildOptions[Tool][Attr] = Options[Key]\r
2624 else:\r
95816356
YZ
2625 # append options for the same tool except PATH\r
2626 if Attr != 'PATH':\r
2627 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2628 else:\r
2629 BuildOptions[Tool][Attr] = Options[Key]\r
52302d4d
LG
2630 # Build Option Family has been checked, which need't to be checked again for family.\r
2631 if FamilyMatch or FamilyIsNull:\r
2632 return BuildOptions\r
1ba5124e 2633\r
52302d4d 2634 for Key in Options:\r
4231a819 2635 if ModuleStyle is not None and len (Key) > 2:\r
52302d4d
LG
2636 # Check Module style is EDK or EDKII.\r
2637 # Only append build option for the matched style module.\r
2638 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2639 continue\r
2640 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2641 continue\r
2642 Family = Key[0]\r
2643 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2644 # if tool chain family doesn't match, skip it\r
47fea6af 2645 if Tool not in self.ToolDefinition or Family == "":\r
52302d4d
LG
2646 continue\r
2647 # option has been added before\r
2648 if Family != self.ToolDefinition[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2649 continue\r
2650\r
2651 # expand any wildcard\r
2652 if Target == "*" or Target == self.BuildTarget:\r
2653 if Tag == "*" or Tag == self.ToolChain:\r
2654 if Arch == "*" or Arch == self.Arch:\r
2655 if Tool not in BuildOptions:\r
2656 BuildOptions[Tool] = {}\r
5015bee2 2657 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
52302d4d
LG
2658 BuildOptions[Tool][Attr] = Options[Key]\r
2659 else:\r
95816356
YZ
2660 # append options for the same tool except PATH\r
2661 if Attr != 'PATH':\r
2662 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2663 else:\r
2664 BuildOptions[Tool][Attr] = Options[Key]\r
52302d4d
LG
2665 return BuildOptions\r
2666\r
2667 ## Append build options in platform to a module\r
2668 #\r
2669 # @param Module The module to which the build options will be appened\r
2670 #\r
2671 # @retval options The options appended with build options in platform\r
2672 #\r
2673 def ApplyBuildOption(self, Module):\r
2674 # Get the different options for the different style module\r
2675 if Module.AutoGenVersion < 0x00010005:\r
2676 PlatformOptions = self.EdkBuildOption\r
35f69db9 2677 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDK_NAME, Module.ModuleType)\r
52302d4d
LG
2678 else:\r
2679 PlatformOptions = self.EdkIIBuildOption\r
35f69db9
YL
2680 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
2681 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
52302d4d
LG
2682 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
2683 if Module in self.Platform.Modules:\r
2684 PlatformModule = self.Platform.Modules[str(Module)]\r
2685 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
2686 else:\r
2687 PlatformModuleOptions = {}\r
2688\r
fe4bf2f9 2689 BuildRuleOrder = None\r
35f69db9 2690 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
fe4bf2f9
YL
2691 for Tool in Options:\r
2692 for Attr in Options[Tool]:\r
2693 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2694 BuildRuleOrder = Options[Tool][Attr]\r
2695\r
35f69db9
YL
2696 AllTools = set(ModuleOptions.keys() + PlatformOptions.keys() +\r
2697 PlatformModuleOptions.keys() + ModuleTypeOptions.keys() +\r
2698 self.ToolDefinition.keys())\r
52302d4d
LG
2699 BuildOptions = {}\r
2700 for Tool in AllTools:\r
2701 if Tool not in BuildOptions:\r
2702 BuildOptions[Tool] = {}\r
2703\r
35f69db9 2704 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
52302d4d
LG
2705 if Tool not in Options:\r
2706 continue\r
2707 for Attr in Options[Tool]:\r
2708 Value = Options[Tool][Attr]\r
fe4bf2f9
YL
2709 #\r
2710 # Do not generate it in Makefile\r
2711 #\r
2712 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2713 continue\r
52302d4d
LG
2714 if Attr not in BuildOptions[Tool]:\r
2715 BuildOptions[Tool][Attr] = ""\r
2716 # check if override is indicated\r
2717 if Value.startswith('='):\r
05cc51ad
LY
2718 ToolPath = Value[1:]\r
2719 ToolPath = mws.handleWsMacro(ToolPath)\r
2720 BuildOptions[Tool][Attr] = ToolPath\r
5015bee2 2721 else:\r
05cc51ad 2722 Value = mws.handleWsMacro(Value)\r
95816356
YZ
2723 if Attr != 'PATH':\r
2724 BuildOptions[Tool][Attr] += " " + Value\r
2725 else:\r
2726 BuildOptions[Tool][Attr] = Value\r
4231a819 2727 if Module.AutoGenVersion < 0x00010005 and self.Workspace.UniFlag is not None:\r
f3decdc3
LG
2728 #\r
2729 # Override UNI flag only for EDK module.\r
2730 #\r
2731 if 'BUILD' not in BuildOptions:\r
2732 BuildOptions['BUILD'] = {}\r
2733 BuildOptions['BUILD']['FLAGS'] = self.Workspace.UniFlag\r
fe4bf2f9 2734 return BuildOptions, BuildRuleOrder\r
52302d4d
LG
2735\r
2736 Platform = property(_GetPlatform)\r
2737 Name = property(_GetName)\r
2738 Guid = property(_GetGuid)\r
2739 Version = property(_GetVersion)\r
2740\r
2741 OutputDir = property(_GetOutputDir)\r
2742 BuildDir = property(_GetBuildDir)\r
2743 MakeFileDir = property(_GetMakeFileDir)\r
2744 FdfFile = property(_GetFdfFile)\r
2745\r
2746 PcdTokenNumber = property(_GetPcdTokenNumbers) # (TokenCName, TokenSpaceGuidCName) : GeneratedTokenNumber\r
2747 DynamicPcdList = property(_GetDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2748 NonDynamicPcdList = property(_GetNonDynamicPcdList) # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
2bc3256c 2749 NonDynamicPcdDict = property(_GetNonDynamicPcdDict)\r
52302d4d
LG
2750 PackageList = property(_GetPackageList)\r
2751\r
2752 ToolDefinition = property(_GetToolDefinition) # toolcode : tool path\r
2753 ToolDefinitionFile = property(_GetToolDefFile) # toolcode : lib path\r
2754 ToolChainFamily = property(_GetToolChainFamily)\r
2755 BuildRuleFamily = property(_GetBuildRuleFamily)\r
2756 BuildOption = property(_GetBuildOptions) # toolcode : option\r
2757 EdkBuildOption = property(_GetEdkBuildOptions) # edktoolcode : option\r
2758 EdkIIBuildOption = property(_GetEdkIIBuildOptions) # edkiitoolcode : option\r
2759\r
2760 BuildCommand = property(_GetBuildCommand)\r
2761 BuildRule = property(_GetBuildRule)\r
2762 ModuleAutoGenList = property(_GetModuleAutoGenList)\r
2763 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
0923aa1c 2764 GenFdsCommand = property(_GenFdsCommand)\r
52302d4d
LG
2765\r
2766## ModuleAutoGen class\r
2767#\r
2768# This class encapsules the AutoGen behaviors for the build tools. In addition to\r
2769# the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according\r
2770# to the [depex] section in module's inf file.\r
2771#\r
2772class ModuleAutoGen(AutoGen):\r
b24e99f7
CJ
2773 # call super().__init__ then call the worker function with different parameter count\r
2774 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
2775 try:\r
2776 self._Init\r
2777 except:\r
2778 super(ModuleAutoGen, self).__init__(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
2779 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)\r
2780 self._Init = True\r
2781\r
c17956e0
DL
2782 ## Cache the timestamps of metafiles of every module in a class variable\r
2783 #\r
2784 TimeDict = {}\r
2785\r
b24e99f7
CJ
2786 def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
2787 obj = super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
2788 # check if this module is employed by active platform\r
2789 if not PlatformAutoGen(Workspace, args[0], Target, Toolchain, Arch).ValidModule(MetaFile):\r
2790 EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
2791 % (MetaFile, Arch))\r
2792 return None\r
2793 return obj\r
2794 \r
2795 ## Initialize ModuleAutoGen\r
52302d4d
LG
2796 #\r
2797 # @param Workspace EdkIIWorkspaceBuild object\r
2798 # @param ModuleFile The path of module file\r
2799 # @param Target Build target (DEBUG, RELEASE)\r
2800 # @param Toolchain Name of tool chain\r
2801 # @param Arch The arch the module supports\r
2802 # @param PlatformFile Platform meta-file\r
2803 #\r
b24e99f7 2804 def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):\r
52302d4d
LG
2805 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))\r
2806 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)\r
2807\r
2808 self.Workspace = Workspace\r
2809 self.WorkspaceDir = Workspace.WorkspaceDir\r
2810\r
2811 self.MetaFile = ModuleFile\r
2812 self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
52302d4d
LG
2813\r
2814 self.SourceDir = self.MetaFile.SubDir\r
05cc51ad 2815 self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
97fa0ee9 2816\r
52302d4d
LG
2817 self.SourceOverrideDir = None\r
2818 # use overrided path defined in DSC file\r
2819 if self.MetaFile.Key in GlobalData.gOverrideDir:\r
2820 self.SourceOverrideDir = GlobalData.gOverrideDir[self.MetaFile.Key]\r
2821\r
2822 self.ToolChain = Toolchain\r
2823 self.BuildTarget = Target\r
2824 self.Arch = Arch\r
2825 self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
2826 self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
2827\r
2828 self.IsMakeFileCreated = False\r
2829 self.IsCodeFileCreated = False\r
da92f276
LG
2830 self.IsAsBuiltInfCreated = False\r
2831 self.DepexGenerated = False\r
52302d4d
LG
2832\r
2833 self.BuildDatabase = self.Workspace.BuildDatabase\r
fe4bf2f9 2834 self.BuildRuleOrder = None\r
1b8eca8b 2835 self.BuildTime = 0\r
52302d4d
LG
2836\r
2837 self._Module = None\r
2838 self._Name = None\r
2839 self._Guid = None\r
2840 self._Version = None\r
2841 self._ModuleType = None\r
2842 self._ComponentType = None\r
2843 self._PcdIsDriver = None\r
2844 self._AutoGenVersion = None\r
2845 self._LibraryFlag = None\r
2846 self._CustomMakefile = None\r
2847 self._Macro = None\r
2848\r
2849 self._BuildDir = None\r
2850 self._OutputDir = None\r
37de70b7 2851 self._FfsOutputDir = None\r
52302d4d
LG
2852 self._DebugDir = None\r
2853 self._MakeFileDir = None\r
2854\r
2855 self._IncludePathList = None\r
725cdb8f 2856 self._IncludePathLength = 0\r
52302d4d
LG
2857 self._AutoGenFileList = None\r
2858 self._UnicodeFileList = None\r
5b97eb4c 2859 self._VfrFileList = None\r
333ba578 2860 self._IdfFileList = None\r
52302d4d
LG
2861 self._SourceFileList = None\r
2862 self._ObjectFileList = None\r
2863 self._BinaryFileList = None\r
2864\r
2865 self._DependentPackageList = None\r
2866 self._DependentLibraryList = None\r
2867 self._LibraryAutoGenList = None\r
2868 self._DerivedPackageList = None\r
2869 self._ModulePcdList = None\r
2870 self._LibraryPcdList = None\r
9006a2c6 2871 self._PcdComments = OrderedDict()\r
52302d4d 2872 self._GuidList = None\r
e8a47801 2873 self._GuidsUsedByPcd = None\r
9006a2c6 2874 self._GuidComments = OrderedDict()\r
52302d4d 2875 self._ProtocolList = None\r
9006a2c6 2876 self._ProtocolComments = OrderedDict()\r
52302d4d 2877 self._PpiList = None\r
9006a2c6 2878 self._PpiComments = OrderedDict()\r
52302d4d
LG
2879 self._DepexList = None\r
2880 self._DepexExpressionList = None\r
2881 self._BuildOption = None\r
79b74a03 2882 self._BuildOptionIncPathList = None\r
52302d4d
LG
2883 self._BuildTargets = None\r
2884 self._IntroBuildTargetList = None\r
2885 self._FinalBuildTargetList = None\r
2886 self._FileTypes = None\r
2887 self._BuildRules = None\r
c17956e0
DL
2888\r
2889 self._TimeStampPath = None\r
2890\r
2891 self.AutoGenDepSet = set()\r
2892\r
2bc3256c
LG
2893 \r
2894 ## The Modules referenced to this Library\r
2895 # Only Library has this attribute\r
2896 self._ReferenceModules = [] \r
2897 \r
2898 ## Store the FixedAtBuild Pcds\r
2899 # \r
2900 self._FixedAtBuildPcds = []\r
2901 self.ConstPcd = {}\r
52302d4d
LG
2902 return True\r
2903\r
2904 def __repr__(self):\r
2905 return "%s [%s]" % (self.MetaFile, self.Arch)\r
2906\r
2bc3256c
LG
2907 # Get FixedAtBuild Pcds of this Module\r
2908 def _GetFixedAtBuildPcds(self):\r
2909 if self._FixedAtBuildPcds:\r
2910 return self._FixedAtBuildPcds\r
2911 for Pcd in self.ModulePcdList:\r
7256bd55 2912 if Pcd.Type != "FixedAtBuild":\r
2bc3256c
LG
2913 continue\r
2914 if Pcd not in self._FixedAtBuildPcds:\r
2915 self._FixedAtBuildPcds.append(Pcd)\r
2916 \r
2917 return self._FixedAtBuildPcds \r
2918\r
867d1cd4
YL
2919 def _GetUniqueBaseName(self):\r
2920 BaseName = self.Name\r
2921 for Module in self.PlatformInfo.ModuleAutoGenList:\r
2922 if Module.MetaFile == self.MetaFile:\r
2923 continue\r
2924 if Module.Name == self.Name:\r
867d1cd4
YL
2925 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):\r
2926 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
2927 ' %s\n %s' % (Module.MetaFile, self.MetaFile))\r
2928 BaseName = '%s_%s' % (self.Name, self.Guid)\r
2929 return BaseName\r
2930\r
52302d4d
LG
2931 # Macros could be used in build_rule.txt (also Makefile)\r
2932 def _GetMacros(self):\r
4231a819 2933 if self._Macro is None:\r
9006a2c6 2934 self._Macro = OrderedDict()\r
52302d4d
LG
2935 self._Macro["WORKSPACE" ] = self.WorkspaceDir\r
2936 self._Macro["MODULE_NAME" ] = self.Name\r
867d1cd4 2937 self._Macro["MODULE_NAME_GUID" ] = self._GetUniqueBaseName()\r
52302d4d
LG
2938 self._Macro["MODULE_GUID" ] = self.Guid\r
2939 self._Macro["MODULE_VERSION" ] = self.Version\r
2940 self._Macro["MODULE_TYPE" ] = self.ModuleType\r
2941 self._Macro["MODULE_FILE" ] = str(self.MetaFile)\r
2942 self._Macro["MODULE_FILE_BASE_NAME" ] = self.MetaFile.BaseName\r
2943 self._Macro["MODULE_RELATIVE_DIR" ] = self.SourceDir\r
2944 self._Macro["MODULE_DIR" ] = self.SourceDir\r
2945\r
2946 self._Macro["BASE_NAME" ] = self.Name\r
2947\r
2948 self._Macro["ARCH" ] = self.Arch\r
2949 self._Macro["TOOLCHAIN" ] = self.ToolChain\r
2950 self._Macro["TOOLCHAIN_TAG" ] = self.ToolChain\r
0d2711a6 2951 self._Macro["TOOL_CHAIN_TAG" ] = self.ToolChain\r
52302d4d
LG
2952 self._Macro["TARGET" ] = self.BuildTarget\r
2953\r
2954 self._Macro["BUILD_DIR" ] = self.PlatformInfo.BuildDir\r
2955 self._Macro["BIN_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2956 self._Macro["LIB_DIR" ] = os.path.join(self.PlatformInfo.BuildDir, self.Arch)\r
2957 self._Macro["MODULE_BUILD_DIR" ] = self.BuildDir\r
2958 self._Macro["OUTPUT_DIR" ] = self.OutputDir\r
2959 self._Macro["DEBUG_DIR" ] = self.DebugDir\r
df1e1b63
YZ
2960 self._Macro["DEST_DIR_OUTPUT" ] = self.OutputDir\r
2961 self._Macro["DEST_DIR_DEBUG" ] = self.DebugDir\r
3570e332
YZ
2962 self._Macro["PLATFORM_NAME" ] = self.PlatformInfo.Name\r
2963 self._Macro["PLATFORM_GUID" ] = self.PlatformInfo.Guid\r
2964 self._Macro["PLATFORM_VERSION" ] = self.PlatformInfo.Version\r
2965 self._Macro["PLATFORM_RELATIVE_DIR" ] = self.PlatformInfo.SourceDir\r
2966 self._Macro["PLATFORM_DIR" ] = mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)\r
2967 self._Macro["PLATFORM_OUTPUT_DIR" ] = self.PlatformInfo.OutputDir\r
37de70b7 2968 self._Macro["FFS_OUTPUT_DIR" ] = self.FfsOutputDir\r
52302d4d
LG
2969 return self._Macro\r
2970\r
2971 ## Return the module build data object\r
2972 def _GetModule(self):\r
4231a819 2973 if self._Module is None:\r
0d2711a6 2974 self._Module = self.Workspace.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
52302d4d
LG
2975 return self._Module\r
2976\r
2977 ## Return the module name\r
2978 def _GetBaseName(self):\r
2979 return self.Module.BaseName\r
2980\r
b36d134f
LG
2981 ## Return the module DxsFile if exist\r
2982 def _GetDxsFile(self):\r
2983 return self.Module.DxsFile\r
2984\r
52302d4d
LG
2985 ## Return the module SourceOverridePath\r
2986 def _GetSourceOverridePath(self):\r
2987 return self.Module.SourceOverridePath\r
2988\r
2989 ## Return the module meta-file GUID\r
2990 def _GetGuid(self):\r
97fa0ee9
YL
2991 #\r
2992 # To build same module more than once, the module path with FILE_GUID overridden has\r
2993 # the file name FILE_GUIDmodule.inf, but the relative path (self.MetaFile.File) is the realy path\r
2994 # in DSC. The overridden GUID can be retrieved from file name\r
2995 #\r
2996 if os.path.basename(self.MetaFile.File) != os.path.basename(self.MetaFile.Path):\r
2997 #\r
2998 # Length of GUID is 36\r
2999 #\r
3000 return os.path.basename(self.MetaFile.Path)[:36]\r
52302d4d
LG
3001 return self.Module.Guid\r
3002\r
3003 ## Return the module version\r
3004 def _GetVersion(self):\r
3005 return self.Module.Version\r
3006\r
3007 ## Return the module type\r
3008 def _GetModuleType(self):\r
3009 return self.Module.ModuleType\r
3010\r
b36d134f 3011 ## Return the component type (for Edk.x style of module)\r
52302d4d
LG
3012 def _GetComponentType(self):\r
3013 return self.Module.ComponentType\r
3014\r
3015 ## Return the build type\r
3016 def _GetBuildType(self):\r
3017 return self.Module.BuildType\r
3018\r
3019 ## Return the PCD_IS_DRIVER setting\r
3020 def _GetPcdIsDriver(self):\r
3021 return self.Module.PcdIsDriver\r
3022\r
3023 ## Return the autogen version, i.e. module meta-file version\r
3024 def _GetAutoGenVersion(self):\r
3025 return self.Module.AutoGenVersion\r
3026\r
3027 ## Check if the module is library or not\r
3028 def _IsLibrary(self):\r
4231a819
CJ
3029 if self._LibraryFlag is None:\r
3030 if self.Module.LibraryClass is not None and self.Module.LibraryClass != []:\r
52302d4d
LG
3031 self._LibraryFlag = True\r
3032 else:\r
3033 self._LibraryFlag = False\r
3034 return self._LibraryFlag\r
3035\r
e8a47801
LG
3036 ## Check if the module is binary module or not\r
3037 def _IsBinaryModule(self):\r
3038 return self.Module.IsBinaryModule\r
3039\r
52302d4d
LG
3040 ## Return the directory to store intermediate files of the module\r
3041 def _GetBuildDir(self):\r
4231a819 3042 if self._BuildDir is None:\r
52302d4d
LG
3043 self._BuildDir = path.join(\r
3044 self.PlatformInfo.BuildDir,\r
3045 self.Arch,\r
3046 self.SourceDir,\r
3047 self.MetaFile.BaseName\r
3048 )\r
3049 CreateDirectory(self._BuildDir)\r
3050 return self._BuildDir\r
3051\r
3052 ## Return the directory to store the intermediate object files of the mdoule\r
3053 def _GetOutputDir(self):\r
4231a819 3054 if self._OutputDir is None:\r
52302d4d
LG
3055 self._OutputDir = path.join(self.BuildDir, "OUTPUT")\r
3056 CreateDirectory(self._OutputDir)\r
3057 return self._OutputDir\r
3058\r
37de70b7
YZ
3059 ## Return the directory to store ffs file\r
3060 def _GetFfsOutputDir(self):\r
4231a819
CJ
3061 if self._FfsOutputDir is None:\r
3062 if GlobalData.gFdfParser is not None:\r
37de70b7
YZ
3063 self._FfsOutputDir = path.join(self.PlatformInfo.BuildDir, "FV", "Ffs", self.Guid + self.Name)\r
3064 else:\r
3065 self._FfsOutputDir = ''\r
3066 return self._FfsOutputDir\r
3067\r
52302d4d
LG
3068 ## Return the directory to store auto-gened source files of the mdoule\r
3069 def _GetDebugDir(self):\r
4231a819 3070 if self._DebugDir is None:\r
52302d4d
LG
3071 self._DebugDir = path.join(self.BuildDir, "DEBUG")\r
3072 CreateDirectory(self._DebugDir)\r
3073 return self._DebugDir\r
3074\r
3075 ## Return the path of custom file\r
3076 def _GetCustomMakefile(self):\r
4231a819 3077 if self._CustomMakefile is None:\r
52302d4d
LG
3078 self._CustomMakefile = {}\r
3079 for Type in self.Module.CustomMakefile:\r
3080 if Type in gMakeTypeMap:\r
3081 MakeType = gMakeTypeMap[Type]\r
3082 else:\r
3083 MakeType = 'nmake'\r
4231a819 3084 if self.SourceOverrideDir is not None:\r
52302d4d
LG
3085 File = os.path.join(self.SourceOverrideDir, self.Module.CustomMakefile[Type])\r
3086 if not os.path.exists(File):\r
3087 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
3088 else:\r
3089 File = os.path.join(self.SourceDir, self.Module.CustomMakefile[Type])\r
3090 self._CustomMakefile[MakeType] = File\r
3091 return self._CustomMakefile\r
3092\r
3093 ## Return the directory of the makefile\r
3094 #\r
3095 # @retval string The directory string of module's makefile\r
3096 #\r
3097 def _GetMakeFileDir(self):\r
3098 return self.BuildDir\r
3099\r
3100 ## Return build command string\r
3101 #\r
3102 # @retval string Build command string\r
3103 #\r
3104 def _GetBuildCommand(self):\r
3105 return self.PlatformInfo.BuildCommand\r
3106\r
3107 ## Get object list of all packages the module and its dependent libraries belong to\r
3108 #\r
3109 # @retval list The list of package object\r
3110 #\r
3111 def _GetDerivedPackageList(self):\r
3112 PackageList = []\r
3113 for M in [self.Module] + self.DependentLibraryList:\r
3114 for Package in M.Packages:\r
3115 if Package in PackageList:\r
3116 continue\r
3117 PackageList.append(Package)\r
3118 return PackageList\r
97fa0ee9
YL
3119 \r
3120 ## Get the depex string\r
3121 #\r
3122 # @return : a string contain all depex expresion.\r
3123 def _GetDepexExpresionString(self):\r
3124 DepexStr = ''\r
3125 DepexList = []\r
3126 ## DPX_SOURCE IN Define section.\r
3127 if self.Module.DxsFile:\r
3128 return DepexStr\r
3129 for M in [self.Module] + self.DependentLibraryList:\r
3130 Filename = M.MetaFile.Path\r
3131 InfObj = InfSectionParser.InfSectionParser(Filename)\r
3132 DepexExpresionList = InfObj.GetDepexExpresionList()\r
3133 for DepexExpresion in DepexExpresionList:\r
3134 for key in DepexExpresion.keys():\r
3135 Arch, ModuleType = key\r
518aebe2 3136 DepexExpr = [x for x in DepexExpresion[key] if not str(x).startswith('#')]\r
97fa0ee9
YL
3137 # the type of build module is USER_DEFINED.\r
3138 # All different DEPEX section tags would be copied into the As Built INF file\r
3139 # and there would be separate DEPEX section tags\r
3140 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
3141 if (Arch.upper() == self.Arch.upper()) and (ModuleType.upper() != TAB_ARCH_COMMON):\r
518aebe2 3142 DepexList.append({(Arch, ModuleType): DepexExpr})\r
97fa0ee9
YL
3143 else:\r
3144 if Arch.upper() == TAB_ARCH_COMMON or \\r
3145 (Arch.upper() == self.Arch.upper() and \\r
3146 ModuleType.upper() in [TAB_ARCH_COMMON, self.ModuleType.upper()]):\r
518aebe2 3147 DepexList.append({(Arch, ModuleType): DepexExpr})\r
97fa0ee9
YL
3148 \r
3149 #the type of build module is USER_DEFINED.\r
3150 if self.ModuleType.upper() == SUP_MODULE_USER_DEFINED:\r
3151 for Depex in DepexList:\r
3152 for key in Depex.keys():\r
3153 DepexStr += '[Depex.%s.%s]\n' % key\r
3154 DepexStr += '\n'.join(['# '+ val for val in Depex[key]])\r
3155 DepexStr += '\n\n'\r
3156 if not DepexStr:\r
3157 return '[Depex.%s]\n' % self.Arch\r
3158 return DepexStr\r
3159 \r
3160 #the type of build module not is USER_DEFINED.\r
3161 Count = 0\r
3162 for Depex in DepexList:\r
3163 Count += 1\r
3164 if DepexStr != '':\r
3165 DepexStr += ' AND '\r
3166 DepexStr += '('\r
3167 for D in Depex.values():\r
3168 DepexStr += ' '.join([val for val in D])\r
3169 Index = DepexStr.find('END')\r
3170 if Index > -1 and Index == len(DepexStr) - 3:\r
3171 DepexStr = DepexStr[:-3]\r
3172 DepexStr = DepexStr.strip()\r
3173 DepexStr += ')'\r
3174 if Count == 1:\r
3175 DepexStr = DepexStr.lstrip('(').rstrip(')').strip()\r
3176 if not DepexStr:\r
3177 return '[Depex.%s]\n' % self.Arch\r
3178 return '[Depex.%s]\n# ' % self.Arch + DepexStr\r
3179 \r
52302d4d
LG
3180 ## Merge dependency expression\r
3181 #\r
3182 # @retval list The token list of the dependency expression after parsed\r
3183 #\r
3184 def _GetDepexTokenList(self):\r
4231a819 3185 if self._DepexList is None:\r
52302d4d 3186 self._DepexList = {}\r
b36d134f 3187 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
3188 return self._DepexList\r
3189\r
3190 self._DepexList[self.ModuleType] = []\r
3191\r
3192 for ModuleType in self._DepexList:\r
3193 DepexList = self._DepexList[ModuleType]\r
3194 #\r
3195 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
3196 #\r
3197 for M in [self.Module] + self.DependentLibraryList:\r
3198 Inherited = False\r
3199 for D in M.Depex[self.Arch, ModuleType]:\r
3200 if DepexList != []:\r
3201 DepexList.append('AND')\r
3202 DepexList.append('(')\r
3203 DepexList.extend(D)\r
3204 if DepexList[-1] == 'END': # no need of a END at this time\r
3205 DepexList.pop()\r
3206 DepexList.append(')')\r
3207 Inherited = True\r
3208 if Inherited:\r
3209 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexList))\r
3210 if 'BEFORE' in DepexList or 'AFTER' in DepexList:\r
3211 break\r
3212 if len(DepexList) > 0:\r
3213 EdkLogger.verbose('')\r
3214 return self._DepexList\r
3215\r
3216 ## Merge dependency expression\r
3217 #\r
3218 # @retval list The token list of the dependency expression after parsed\r
3219 #\r
3220 def _GetDepexExpressionTokenList(self):\r
4231a819 3221 if self._DepexExpressionList is None:\r
52302d4d 3222 self._DepexExpressionList = {}\r
b36d134f 3223 if self.DxsFile or self.IsLibrary or TAB_DEPENDENCY_EXPRESSION_FILE in self.FileTypes:\r
52302d4d
LG
3224 return self._DepexExpressionList\r
3225\r
3226 self._DepexExpressionList[self.ModuleType] = ''\r
3227\r
3228 for ModuleType in self._DepexExpressionList:\r
3229 DepexExpressionList = self._DepexExpressionList[ModuleType]\r
3230 #\r
3231 # Append depex from dependent libraries, if not "BEFORE", "AFTER" expresion\r
3232 #\r
3233 for M in [self.Module] + self.DependentLibraryList:\r
3234 Inherited = False\r
3235 for D in M.DepexExpression[self.Arch, ModuleType]:\r
3236 if DepexExpressionList != '':\r
3237 DepexExpressionList += ' AND '\r
3238 DepexExpressionList += '('\r
3239 DepexExpressionList += D\r
3240 DepexExpressionList = DepexExpressionList.rstrip('END').strip()\r
3241 DepexExpressionList += ')'\r
3242 Inherited = True\r
3243 if Inherited:\r
3244 EdkLogger.verbose("DEPEX[%s] (+%s) = %s" % (self.Name, M.BaseName, DepexExpressionList))\r
3245 if 'BEFORE' in DepexExpressionList or 'AFTER' in DepexExpressionList:\r
3246 break\r
3247 if len(DepexExpressionList) > 0:\r
3248 EdkLogger.verbose('')\r
3249 self._DepexExpressionList[ModuleType] = DepexExpressionList\r
3250 return self._DepexExpressionList\r
3251\r
dfa41b4a
YZ
3252 # Get the tiano core user extension, it is contain dependent library.\r
3253 # @retval: a list contain tiano core userextension.\r
3254 #\r
3255 def _GetTianoCoreUserExtensionList(self):\r
3256 TianoCoreUserExtentionList = []\r
3257 for M in [self.Module] + self.DependentLibraryList:\r
3258 Filename = M.MetaFile.Path\r
3259 InfObj = InfSectionParser.InfSectionParser(Filename)\r
3260 TianoCoreUserExtenList = InfObj.GetUserExtensionTianoCore()\r
3261 for TianoCoreUserExtent in TianoCoreUserExtenList:\r
3262 for Section in TianoCoreUserExtent.keys():\r
3263 ItemList = Section.split(TAB_SPLIT)\r
3264 Arch = self.Arch\r
3265 if len(ItemList) == 4:\r
3266 Arch = ItemList[3]\r
3267 if Arch.upper() == TAB_ARCH_COMMON or Arch.upper() == self.Arch.upper():\r
3268 TianoCoreList = []\r
3269 TianoCoreList.extend([TAB_SECTION_START + Section + TAB_SECTION_END])\r
3270 TianoCoreList.extend(TianoCoreUserExtent[Section][:])\r
3271 TianoCoreList.append('\n')\r
3272 TianoCoreUserExtentionList.append(TianoCoreList)\r
3273\r
3274 return TianoCoreUserExtentionList\r
3275\r
52302d4d
LG
3276 ## Return the list of specification version required for the module\r
3277 #\r
3278 # @retval list The list of specification defined in module file\r
3279 #\r
3280 def _GetSpecification(self):\r
3281 return self.Module.Specification\r
3282\r
3283 ## Tool option for the module build\r
3284 #\r
3285 # @param PlatformInfo The object of PlatformBuildInfo\r
3286 # @retval dict The dict containing valid options\r
3287 #\r
3288 def _GetModuleBuildOption(self):\r
4231a819 3289 if self._BuildOption is None:\r
fe4bf2f9
YL
3290 self._BuildOption, self.BuildRuleOrder = self.PlatformInfo.ApplyBuildOption(self.Module)\r
3291 if self.BuildRuleOrder:\r
3292 self.BuildRuleOrder = ['.%s' % Ext for Ext in self.BuildRuleOrder.split()]\r
52302d4d
LG
3293 return self._BuildOption\r
3294\r
79b74a03
LG
3295 ## Get include path list from tool option for the module build\r
3296 #\r
3297 # @retval list The include path list\r
3298 #\r
3299 def _GetBuildOptionIncPathList(self):\r
4231a819 3300 if self._BuildOptionIncPathList is None:\r
79b74a03 3301 #\r
d40b2ee6 3302 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
79b74a03
LG
3303 # is the former use /I , the Latter used -I to specify include directories\r
3304 #\r
3305 if self.PlatformInfo.ToolChainFamily in ('MSFT'):\r
c8802c3d 3306 BuildOptIncludeRegEx = gBuildOptIncludePatternMsft\r
d40b2ee6 3307 elif self.PlatformInfo.ToolChainFamily in ('INTEL', 'GCC', 'RVCT'):\r
c8802c3d 3308 BuildOptIncludeRegEx = gBuildOptIncludePatternOther\r
d40b2ee6
LG
3309 else:\r
3310 #\r
3311 # New ToolChainFamily, don't known whether there is option to specify include directories\r
3312 #\r
3313 self._BuildOptionIncPathList = []\r
3314 return self._BuildOptionIncPathList\r
79b74a03
LG
3315 \r
3316 BuildOptionIncPathList = []\r
3317 for Tool in ('CC', 'PP', 'VFRPP', 'ASLPP', 'ASLCC', 'APP', 'ASM'):\r
3318 Attr = 'FLAGS'\r
3319 try:\r
3320 FlagOption = self.BuildOption[Tool][Attr]\r
3321 except KeyError:\r
3322 FlagOption = ''\r
3323 \r
d40b2ee6 3324 if self.PlatformInfo.ToolChainFamily != 'RVCT':\r
c8802c3d 3325 IncPathList = [NormPath(Path, self.Macros) for Path in BuildOptIncludeRegEx.findall(FlagOption)]\r
d40b2ee6
LG
3326 else:\r
3327 #\r
3328 # RVCT may specify a list of directory seperated by commas\r
3329 #\r
3330 IncPathList = []\r
c8802c3d 3331 for Path in BuildOptIncludeRegEx.findall(FlagOption):\r
d40b2ee6
LG
3332 PathList = GetSplitList(Path, TAB_COMMA_SPLIT)\r
3333 IncPathList += [NormPath(PathEntry, self.Macros) for PathEntry in PathList]\r
3334\r
79b74a03
LG
3335 #\r
3336 # EDK II modules must not reference header files outside of the packages they depend on or \r
3337 # within the module's directory tree. Report error if violation.\r
3338 #\r
3339 if self.AutoGenVersion >= 0x00010005 and len(IncPathList) > 0:\r
3340 for Path in IncPathList:\r
3341 if (Path not in self.IncludePathList) and (CommonPath([Path, self.MetaFile.Dir]) != self.MetaFile.Dir):\r
47fea6af
YZ
3342 ErrMsg = "The include directory for the EDK II module in this line is invalid %s specified in %s FLAGS '%s'" % (Path, Tool, FlagOption)\r
3343 EdkLogger.error("build",\r
79b74a03 3344 PARAMETER_INVALID,\r
47fea6af
YZ
3345 ExtraData=ErrMsg,\r
3346 File=str(self.MetaFile))\r
79b74a03
LG
3347\r
3348 \r
3349 BuildOptionIncPathList += IncPathList\r
3350 \r
3351 self._BuildOptionIncPathList = BuildOptionIncPathList\r
3352 \r
3353 return self._BuildOptionIncPathList\r
3354 \r
52302d4d
LG
3355 ## Return a list of files which can be built from source\r
3356 #\r
3357 # What kind of files can be built is determined by build rules in\r
97fa0ee9 3358 # $(CONF_DIRECTORY)/build_rule.txt and toolchain family.\r
52302d4d
LG
3359 #\r
3360 def _GetSourceFileList(self):\r
4231a819 3361 if self._SourceFileList is None:\r
52302d4d
LG
3362 self._SourceFileList = []\r
3363 for F in self.Module.Sources:\r
3364 # match tool chain\r
08dd311f 3365 if F.TagName not in ("", "*", self.ToolChain):\r
52302d4d
LG
3366 EdkLogger.debug(EdkLogger.DEBUG_9, "The toolchain [%s] for processing file [%s] is found, "\r
3367 "but [%s] is needed" % (F.TagName, str(F), self.ToolChain))\r
3368 continue\r
e2597799
YZ
3369 # match tool chain family or build rule family\r
3370 if F.ToolChainFamily not in ("", "*", self.ToolChainFamily, self.BuildRuleFamily):\r
52302d4d
LG
3371 EdkLogger.debug(\r
3372 EdkLogger.DEBUG_0,\r
3373 "The file [%s] must be built by tools of [%s], " \\r
e2597799
YZ
3374 "but current toolchain family is [%s], buildrule family is [%s]" \\r
3375 % (str(F), F.ToolChainFamily, self.ToolChainFamily, self.BuildRuleFamily))\r
52302d4d
LG
3376 continue\r
3377\r
3378 # add the file path into search path list for file including\r
3379 if F.Dir not in self.IncludePathList and self.AutoGenVersion >= 0x00010005:\r
3380 self.IncludePathList.insert(0, F.Dir)\r
3381 self._SourceFileList.append(F)\r
4cb7bade
YZ
3382\r
3383 self._MatchBuildRuleOrder(self._SourceFileList)\r
3384\r
3385 for F in self._SourceFileList:\r
52302d4d
LG
3386 self._ApplyBuildRule(F, TAB_UNKNOWN_FILE)\r
3387 return self._SourceFileList\r
3388\r
4cb7bade
YZ
3389 def _MatchBuildRuleOrder(self, FileList):\r
3390 Order_Dict = {}\r
3391 self._GetModuleBuildOption()\r
3392 for SingleFile in FileList:\r
3393 if self.BuildRuleOrder and SingleFile.Ext in self.BuildRuleOrder and SingleFile.Ext in self.BuildRules:\r
3394 key = SingleFile.Path.split(SingleFile.Ext)[0]\r
3395 if key in Order_Dict:\r
3396 Order_Dict[key].append(SingleFile.Ext)\r
3397 else:\r
3398 Order_Dict[key] = [SingleFile.Ext]\r
3399\r
3400 RemoveList = []\r
3401 for F in Order_Dict:\r
3402 if len(Order_Dict[F]) > 1:\r
3403 Order_Dict[F].sort(key=lambda i: self.BuildRuleOrder.index(i))\r
3404 for Ext in Order_Dict[F][1:]:\r
3405 RemoveList.append(F + Ext)\r
3406 \r
3407 for item in RemoveList:\r
3408 FileList.remove(item)\r
3409\r
3410 return FileList\r
3411\r
52302d4d
LG
3412 ## Return the list of unicode files\r
3413 def _GetUnicodeFileList(self):\r
4231a819 3414 if self._UnicodeFileList is None:\r
52302d4d
LG
3415 if TAB_UNICODE_FILE in self.FileTypes:\r
3416 self._UnicodeFileList = self.FileTypes[TAB_UNICODE_FILE]\r
3417 else:\r
3418 self._UnicodeFileList = []\r
3419 return self._UnicodeFileList\r
3420\r
5b97eb4c
YZ
3421 ## Return the list of vfr files\r
3422 def _GetVfrFileList(self):\r
4231a819 3423 if self._VfrFileList is None:\r
5b97eb4c
YZ
3424 if TAB_VFR_FILE in self.FileTypes:\r
3425 self._VfrFileList = self.FileTypes[TAB_VFR_FILE]\r
3426 else:\r
3427 self._VfrFileList = []\r
3428 return self._VfrFileList\r
3429\r
333ba578
YZ
3430 ## Return the list of Image Definition files\r
3431 def _GetIdfFileList(self):\r
4231a819 3432 if self._IdfFileList is None:\r
333ba578
YZ
3433 if TAB_IMAGE_FILE in self.FileTypes:\r
3434 self._IdfFileList = self.FileTypes[TAB_IMAGE_FILE]\r
3435 else:\r
3436 self._IdfFileList = []\r
3437 return self._IdfFileList\r
3438\r
52302d4d
LG
3439 ## Return a list of files which can be built from binary\r
3440 #\r
3441 # "Build" binary files are just to copy them to build directory.\r
3442 #\r
3443 # @retval list The list of files which can be built later\r
3444 #\r
3445 def _GetBinaryFiles(self):\r
4231a819 3446 if self._BinaryFileList is None:\r
52302d4d
LG
3447 self._BinaryFileList = []\r
3448 for F in self.Module.Binaries:\r
3449 if F.Target not in ['COMMON', '*'] and F.Target != self.BuildTarget:\r
3450 continue\r
3451 self._BinaryFileList.append(F)\r
3452 self._ApplyBuildRule(F, F.Type)\r
3453 return self._BinaryFileList\r
3454\r
3455 def _GetBuildRules(self):\r
4231a819 3456 if self._BuildRules is None:\r
52302d4d
LG
3457 BuildRules = {}\r
3458 BuildRuleDatabase = self.PlatformInfo.BuildRule\r
3459 for Type in BuildRuleDatabase.FileTypeList:\r
3460 #first try getting build rule by BuildRuleFamily\r
3461 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.BuildRuleFamily]\r
3462 if not RuleObject:\r
3463 # build type is always module type, but ...\r
3464 if self.ModuleType != self.BuildType:\r
3465 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.BuildRuleFamily]\r
3466 #second try getting build rule by ToolChainFamily\r
3467 if not RuleObject:\r
3468 RuleObject = BuildRuleDatabase[Type, self.BuildType, self.Arch, self.ToolChainFamily]\r
3469 if not RuleObject:\r
3470 # build type is always module type, but ...\r
3471 if self.ModuleType != self.BuildType:\r
3472 RuleObject = BuildRuleDatabase[Type, self.ModuleType, self.Arch, self.ToolChainFamily]\r
3473 if not RuleObject:\r
3474 continue\r
3475 RuleObject = RuleObject.Instantiate(self.Macros)\r
3476 BuildRules[Type] = RuleObject\r
3477 for Ext in RuleObject.SourceFileExtList:\r
3478 BuildRules[Ext] = RuleObject\r
3479 self._BuildRules = BuildRules\r
3480 return self._BuildRules\r
3481\r
3482 def _ApplyBuildRule(self, File, FileType):\r
4231a819 3483 if self._BuildTargets is None:\r
52302d4d
LG
3484 self._IntroBuildTargetList = set()\r
3485 self._FinalBuildTargetList = set()\r
3486 self._BuildTargets = {}\r
3487 self._FileTypes = {}\r
3488\r
fcd4fbf3
YL
3489 SubDirectory = os.path.join(self.OutputDir, File.SubDir)\r
3490 if not os.path.exists(SubDirectory):\r
3491 CreateDirectory(SubDirectory)\r
52302d4d
LG
3492 LastTarget = None\r
3493 RuleChain = []\r
3494 SourceList = [File]\r
3495 Index = 0\r
fe4bf2f9
YL
3496 #\r
3497 # Make sure to get build rule order value\r
3498 #\r
3499 self._GetModuleBuildOption()\r
3500\r
52302d4d
LG
3501 while Index < len(SourceList):\r
3502 Source = SourceList[Index]\r
3503 Index = Index + 1\r
3504\r
3505 if Source != File:\r
3506 CreateDirectory(Source.Dir)\r
3507\r
4231a819 3508 if File.IsBinary and File == Source and self._BinaryFileList is not None and File in self._BinaryFileList:\r
da92f276
LG
3509 # Skip all files that are not binary libraries\r
3510 if not self.IsLibrary:\r
47fea6af 3511 continue\r
52302d4d
LG
3512 RuleObject = self.BuildRules[TAB_DEFAULT_BINARY_FILE]\r
3513 elif FileType in self.BuildRules:\r
3514 RuleObject = self.BuildRules[FileType]\r
3515 elif Source.Ext in self.BuildRules:\r
3516 RuleObject = self.BuildRules[Source.Ext]\r
3517 else:\r
3518 # stop at no more rules\r
3519 if LastTarget:\r
3520 self._FinalBuildTargetList.add(LastTarget)\r
3521 break\r
3522\r
3523 FileType = RuleObject.SourceFileType\r
3524 if FileType not in self._FileTypes:\r
3525 self._FileTypes[FileType] = set()\r
3526 self._FileTypes[FileType].add(Source)\r
3527\r
3528 # stop at STATIC_LIBRARY for library\r
3529 if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:\r
3530 if LastTarget:\r
3531 self._FinalBuildTargetList.add(LastTarget)\r
3532 break\r
3533\r
fe4bf2f9 3534 Target = RuleObject.Apply(Source, self.BuildRuleOrder)\r
52302d4d
LG
3535 if not Target:\r
3536 if LastTarget:\r
3537 self._FinalBuildTargetList.add(LastTarget)\r
3538 break\r
3539 elif not Target.Outputs:\r
3540 # Only do build for target with outputs\r
3541 self._FinalBuildTargetList.add(Target)\r
3542\r
3543 if FileType not in self._BuildTargets:\r
3544 self._BuildTargets[FileType] = set()\r
3545 self._BuildTargets[FileType].add(Target)\r
3546\r
3547 if not Source.IsBinary and Source == File:\r
3548 self._IntroBuildTargetList.add(Target)\r
3549\r
3550 # to avoid cyclic rule\r
3551 if FileType in RuleChain:\r
3552 break\r
3553\r
3554 RuleChain.append(FileType)\r
3555 SourceList.extend(Target.Outputs)\r
3556 LastTarget = Target\r
3557 FileType = TAB_UNKNOWN_FILE\r
3558\r
3559 def _GetTargets(self):\r
4231a819 3560 if self._BuildTargets is None:\r
52302d4d
LG
3561 self._IntroBuildTargetList = set()\r
3562 self._FinalBuildTargetList = set()\r
3563 self._BuildTargets = {}\r
3564 self._FileTypes = {}\r
3565\r
b36d134f 3566 #TRICK: call _GetSourceFileList to apply build rule for source files\r
52302d4d
LG
3567 if self.SourceFileList:\r
3568 pass\r
3569\r
3570 #TRICK: call _GetBinaryFileList to apply build rule for binary files\r
3571 if self.BinaryFileList:\r
3572 pass\r
3573\r
3574 return self._BuildTargets\r
3575\r
3576 def _GetIntroTargetList(self):\r
3577 self._GetTargets()\r
3578 return self._IntroBuildTargetList\r
3579\r
3580 def _GetFinalTargetList(self):\r
3581 self._GetTargets()\r
3582 return self._FinalBuildTargetList\r
3583\r
3584 def _GetFileTypes(self):\r
3585 self._GetTargets()\r
3586 return self._FileTypes\r
3587\r
3588 ## Get the list of package object the module depends on\r
3589 #\r
3590 # @retval list The package object list\r
3591 #\r
3592 def _GetDependentPackageList(self):\r
3593 return self.Module.Packages\r
3594\r
3595 ## Return the list of auto-generated code file\r
3596 #\r
3597 # @retval list The list of auto-generated file\r
3598 #\r
3599 def _GetAutoGenFileList(self):\r
3600 UniStringAutoGenC = True\r
333ba578 3601 IdfStringAutoGenC = True\r
4234283c 3602 UniStringBinBuffer = StringIO()\r
333ba578 3603 IdfGenBinBuffer = StringIO()\r
52302d4d 3604 if self.BuildType == 'UEFI_HII':\r
52302d4d 3605 UniStringAutoGenC = False\r
333ba578 3606 IdfStringAutoGenC = False\r
4231a819 3607 if self._AutoGenFileList is None:\r
52302d4d
LG
3608 self._AutoGenFileList = {}\r
3609 AutoGenC = TemplateString()\r
3610 AutoGenH = TemplateString()\r
3611 StringH = TemplateString()\r
333ba578
YZ
3612 StringIdf = TemplateString()\r
3613 GenC.CreateCode(self, AutoGenC, AutoGenH, StringH, UniStringAutoGenC, UniStringBinBuffer, StringIdf, IdfStringAutoGenC, IdfGenBinBuffer)\r
07b8564b
YL
3614 #\r
3615 # AutoGen.c is generated if there are library classes in inf, or there are object files\r
3616 #\r
3617 if str(AutoGenC) != "" and (len(self.Module.LibraryClasses) > 0\r
3618 or TAB_OBJECT_FILE in self.FileTypes):\r
52302d4d
LG
3619 AutoFile = PathClass(gAutoGenCodeFileName, self.DebugDir)\r
3620 self._AutoGenFileList[AutoFile] = str(AutoGenC)\r
3621 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3622 if str(AutoGenH) != "":\r
3623 AutoFile = PathClass(gAutoGenHeaderFileName, self.DebugDir)\r
3624 self._AutoGenFileList[AutoFile] = str(AutoGenH)\r
3625 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
3626 if str(StringH) != "":\r
3627 AutoFile = PathClass(gAutoGenStringFileName % {"module_name":self.Name}, self.DebugDir)\r
3628 self._AutoGenFileList[AutoFile] = str(StringH)\r
3629 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
4231a819 3630 if UniStringBinBuffer is not None and UniStringBinBuffer.getvalue() != "":\r
52302d4d
LG
3631 AutoFile = PathClass(gAutoGenStringFormFileName % {"module_name":self.Name}, self.OutputDir)\r
3632 self._AutoGenFileList[AutoFile] = UniStringBinBuffer.getvalue()\r
3633 AutoFile.IsBinary = True\r
3634 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
4231a819 3635 if UniStringBinBuffer is not None:\r
52302d4d 3636 UniStringBinBuffer.close()\r
333ba578
YZ
3637 if str(StringIdf) != "":\r
3638 AutoFile = PathClass(gAutoGenImageDefFileName % {"module_name":self.Name}, self.DebugDir)\r
3639 self._AutoGenFileList[AutoFile] = str(StringIdf)\r
3640 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
4231a819 3641 if IdfGenBinBuffer is not None and IdfGenBinBuffer.getvalue() != "":\r
333ba578
YZ
3642 AutoFile = PathClass(gAutoGenIdfFileName % {"module_name":self.Name}, self.OutputDir)\r
3643 self._AutoGenFileList[AutoFile] = IdfGenBinBuffer.getvalue()\r
3644 AutoFile.IsBinary = True\r
3645 self._ApplyBuildRule(AutoFile, TAB_UNKNOWN_FILE)\r
4231a819 3646 if IdfGenBinBuffer is not None:\r
333ba578 3647 IdfGenBinBuffer.close()\r
52302d4d
LG
3648 return self._AutoGenFileList\r
3649\r
3650 ## Return the list of library modules explicitly or implicityly used by this module\r
3651 def _GetLibraryList(self):\r
4231a819 3652 if self._DependentLibraryList is None:\r
52302d4d
LG
3653 # only merge library classes and PCD for non-library module\r
3654 if self.IsLibrary:\r
3655 self._DependentLibraryList = []\r
3656 else:\r
3657 if self.AutoGenVersion < 0x00010005:\r
3658 self._DependentLibraryList = self.PlatformInfo.ResolveLibraryReference(self.Module)\r
3659 else:\r
3660 self._DependentLibraryList = self.PlatformInfo.ApplyLibraryInstance(self.Module)\r
3661 return self._DependentLibraryList\r
3662\r
e8a47801
LG
3663 @staticmethod\r
3664 def UpdateComments(Recver, Src):\r
3665 for Key in Src:\r
3666 if Key not in Recver:\r
3667 Recver[Key] = []\r
3668 Recver[Key].extend(Src[Key])\r
52302d4d
LG
3669 ## Get the list of PCDs from current module\r
3670 #\r
3671 # @retval list The list of PCD\r
3672 #\r
3673 def _GetModulePcdList(self):\r
4231a819 3674 if self._ModulePcdList is None:\r
52302d4d
LG
3675 # apply PCD settings from platform\r
3676 self._ModulePcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)\r
e8a47801 3677 self.UpdateComments(self._PcdComments, self.Module.PcdComments)\r
52302d4d
LG
3678 return self._ModulePcdList\r
3679\r
3680 ## Get the list of PCDs from dependent libraries\r
3681 #\r
3682 # @retval list The list of PCD\r
3683 #\r
3684 def _GetLibraryPcdList(self):\r
4231a819 3685 if self._LibraryPcdList is None:\r
9006a2c6 3686 Pcds = OrderedDict()\r
52302d4d
LG
3687 if not self.IsLibrary:\r
3688 # get PCDs from dependent libraries\r
3689 for Library in self.DependentLibraryList:\r
e8a47801 3690 self.UpdateComments(self._PcdComments, Library.PcdComments)\r
52302d4d
LG
3691 for Key in Library.Pcds:\r
3692 # skip duplicated PCDs\r
3693 if Key in self.Module.Pcds or Key in Pcds:\r
3694 continue\r
3695 Pcds[Key] = copy.copy(Library.Pcds[Key])\r
3696 # apply PCD settings from platform\r
3697 self._LibraryPcdList = self.PlatformInfo.ApplyPcdSetting(self.Module, Pcds)\r
3698 else:\r
3699 self._LibraryPcdList = []\r
3700 return self._LibraryPcdList\r
3701\r
3702 ## Get the GUID value mapping\r
3703 #\r
3704 # @retval dict The mapping between GUID cname and its value\r
3705 #\r
3706 def _GetGuidList(self):\r
4231a819 3707 if self._GuidList is None:\r
9006a2c6 3708 self._GuidList = OrderedDict()\r
8200fcfe 3709 self._GuidList.update(self.Module.Guids)\r
52302d4d
LG
3710 for Library in self.DependentLibraryList:\r
3711 self._GuidList.update(Library.Guids)\r
e8a47801
LG
3712 self.UpdateComments(self._GuidComments, Library.GuidComments)\r
3713 self.UpdateComments(self._GuidComments, self.Module.GuidComments)\r
52302d4d
LG
3714 return self._GuidList\r
3715\r
e8a47801 3716 def GetGuidsUsedByPcd(self):\r
4231a819 3717 if self._GuidsUsedByPcd is None:\r
9006a2c6 3718 self._GuidsUsedByPcd = OrderedDict()\r
e8a47801
LG
3719 self._GuidsUsedByPcd.update(self.Module.GetGuidsUsedByPcd())\r
3720 for Library in self.DependentLibraryList:\r
3721 self._GuidsUsedByPcd.update(Library.GetGuidsUsedByPcd())\r
3722 return self._GuidsUsedByPcd\r
52302d4d
LG
3723 ## Get the protocol value mapping\r
3724 #\r
3725 # @retval dict The mapping between protocol cname and its value\r
3726 #\r
3727 def _GetProtocolList(self):\r
4231a819 3728 if self._ProtocolList is None:\r
9006a2c6 3729 self._ProtocolList = OrderedDict()\r
8200fcfe 3730 self._ProtocolList.update(self.Module.Protocols)\r
52302d4d
LG
3731 for Library in self.DependentLibraryList:\r
3732 self._ProtocolList.update(Library.Protocols)\r
e8a47801
LG
3733 self.UpdateComments(self._ProtocolComments, Library.ProtocolComments)\r
3734 self.UpdateComments(self._ProtocolComments, self.Module.ProtocolComments)\r
52302d4d
LG
3735 return self._ProtocolList\r
3736\r
3737 ## Get the PPI value mapping\r
3738 #\r
3739 # @retval dict The mapping between PPI cname and its value\r
3740 #\r
3741 def _GetPpiList(self):\r
4231a819 3742 if self._PpiList is None:\r
9006a2c6 3743 self._PpiList = OrderedDict()\r
8200fcfe 3744 self._PpiList.update(self.Module.Ppis)\r
52302d4d
LG
3745 for Library in self.DependentLibraryList:\r
3746 self._PpiList.update(Library.Ppis)\r
e8a47801
LG
3747 self.UpdateComments(self._PpiComments, Library.PpiComments)\r
3748 self.UpdateComments(self._PpiComments, self.Module.PpiComments)\r
52302d4d
LG
3749 return self._PpiList\r
3750\r
3751 ## Get the list of include search path\r
3752 #\r
3753 # @retval list The list path\r
3754 #\r
3755 def _GetIncludePathList(self):\r
4231a819 3756 if self._IncludePathList is None:\r
52302d4d
LG
3757 self._IncludePathList = []\r
3758 if self.AutoGenVersion < 0x00010005:\r
3759 for Inc in self.Module.Includes:\r
3760 if Inc not in self._IncludePathList:\r
3761 self._IncludePathList.append(Inc)\r
b36d134f 3762 # for Edk modules\r
52302d4d
LG
3763 Inc = path.join(Inc, self.Arch.capitalize())\r
3764 if os.path.exists(Inc) and Inc not in self._IncludePathList:\r
3765 self._IncludePathList.append(Inc)\r
b36d134f 3766 # Edk module needs to put DEBUG_DIR at the end of search path and not to use SOURCE_DIR all the time\r
52302d4d
LG
3767 self._IncludePathList.append(self.DebugDir)\r
3768 else:\r
3769 self._IncludePathList.append(self.MetaFile.Dir)\r
3770 self._IncludePathList.append(self.DebugDir)\r
3771\r
3772 for Package in self.Module.Packages:\r
05cc51ad 3773 PackageDir = mws.join(self.WorkspaceDir, Package.MetaFile.Dir)\r
52302d4d
LG
3774 if PackageDir not in self._IncludePathList:\r
3775 self._IncludePathList.append(PackageDir)\r
c28d2e10
YZ
3776 IncludesList = Package.Includes\r
3777 if Package._PrivateIncludes:\r
3778 if not self.MetaFile.Path.startswith(PackageDir):\r
3779 IncludesList = list(set(Package.Includes).difference(set(Package._PrivateIncludes)))\r
3780 for Inc in IncludesList:\r
52302d4d
LG
3781 if Inc not in self._IncludePathList:\r
3782 self._IncludePathList.append(str(Inc))\r
3783 return self._IncludePathList\r
3784\r
725cdb8f
YZ
3785 def _GetIncludePathLength(self):\r
3786 self._IncludePathLength = 0\r
3787 if self._IncludePathList:\r
3788 for inc in self._IncludePathList:\r
3789 self._IncludePathLength += len(' ' + inc)\r
3790 return self._IncludePathLength\r
3791\r
97fa0ee9
YL
3792 ## Get HII EX PCDs which maybe used by VFR\r
3793 #\r
3794 # efivarstore used by VFR may relate with HII EX PCDs\r
3795 # Get the variable name and GUID from efivarstore and HII EX PCD\r
3796 # List the HII EX PCDs in As Built INF if both name and GUID match.\r
3797 #\r
3798 # @retval list HII EX PCDs\r
3799 #\r
3800 def _GetPcdsMaybeUsedByVfr(self):\r
3801 if not self.SourceFileList:\r
3802 return []\r
3803\r
3804 NameGuids = []\r
3805 for SrcFile in self.SourceFileList:\r
3806 if SrcFile.Ext.lower() != '.vfr':\r
3807 continue\r
3808 Vfri = os.path.join(self.OutputDir, SrcFile.BaseName + '.i')\r
3809 if not os.path.exists(Vfri):\r
3810 continue\r
3811 VfriFile = open(Vfri, 'r')\r
3812 Content = VfriFile.read()\r
3813 VfriFile.close()\r
3814 Pos = Content.find('efivarstore')\r
3815 while Pos != -1:\r
3816 #\r
3817 # Make sure 'efivarstore' is the start of efivarstore statement\r
3818 # In case of the value of 'name' (name = efivarstore) is equal to 'efivarstore'\r
3819 #\r
3820 Index = Pos - 1\r
3821 while Index >= 0 and Content[Index] in ' \t\r\n':\r
3822 Index -= 1\r
3823 if Index >= 0 and Content[Index] != ';':\r
3824 Pos = Content.find('efivarstore', Pos + len('efivarstore'))\r
3825 continue\r
3826 #\r
3827 # 'efivarstore' must be followed by name and guid\r
3828 #\r
3829 Name = gEfiVarStoreNamePattern.search(Content, Pos)\r
3830 if not Name:\r
3831 break\r
3832 Guid = gEfiVarStoreGuidPattern.search(Content, Pos)\r
3833 if not Guid:\r
3834 break\r
3835 NameArray = ConvertStringToByteArray('L"' + Name.group(1) + '"')\r
3836 NameGuids.append((NameArray, GuidStructureStringToGuidString(Guid.group(1))))\r
3837 Pos = Content.find('efivarstore', Name.end())\r
3838 if not NameGuids:\r
3839 return []\r
3840 HiiExPcds = []\r
3841 for Pcd in self.PlatformInfo.Platform.Pcds.values():\r
3842 if Pcd.Type != TAB_PCDS_DYNAMIC_EX_HII:\r
3843 continue\r
3844 for SkuName in Pcd.SkuInfoList:\r
3845 SkuInfo = Pcd.SkuInfoList[SkuName]\r
3846 Name = ConvertStringToByteArray(SkuInfo.VariableName)\r
c28d2e10 3847 Value = GuidValue(SkuInfo.VariableGuid, self.PlatformInfo.PackageList, self.MetaFile.Path)\r
97fa0ee9
YL
3848 if not Value:\r
3849 continue\r
3850 Guid = GuidStructureStringToGuidString(Value)\r
3851 if (Name, Guid) in NameGuids and Pcd not in HiiExPcds:\r
3852 HiiExPcds.append(Pcd)\r
3853 break\r
3854\r
3855 return HiiExPcds\r
3856\r
aeaaf754
YL
3857 def _GenOffsetBin(self):\r
3858 VfrUniBaseName = {}\r
3859 for SourceFile in self.Module.Sources:\r
3860 if SourceFile.Type.upper() == ".VFR" :\r
3861 #\r
3862 # search the .map file to find the offset of vfr binary in the PE32+/TE file. \r
3863 #\r
3864 VfrUniBaseName[SourceFile.BaseName] = (SourceFile.BaseName + "Bin")\r
3865 if SourceFile.Type.upper() == ".UNI" :\r
3866 #\r
3867 # search the .map file to find the offset of Uni strings binary in the PE32+/TE file. \r
3868 #\r
3869 VfrUniBaseName["UniOffsetName"] = (self.Name + "Strings")\r
3870\r
3871 if len(VfrUniBaseName) == 0:\r
3872 return None\r
3873 MapFileName = os.path.join(self.OutputDir, self.Name + ".map")\r
3874 EfiFileName = os.path.join(self.OutputDir, self.Name + ".efi")\r
3875 VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrUniBaseName.values())\r
3876 if not VfrUniOffsetList:\r
3877 return None\r
3878\r
3879 OutputName = '%sOffset.bin' % self.Name\r
3880 UniVfrOffsetFileName = os.path.join( self.OutputDir, OutputName)\r
3881\r
3882 try:\r
3883 fInputfile = open(UniVfrOffsetFileName, "wb+", 0)\r
3884 except:\r
3885 EdkLogger.error("build", FILE_OPEN_FAILURE, "File open failed for %s" % UniVfrOffsetFileName,None)\r
3886\r
3887 # Use a instance of StringIO to cache data\r
3888 fStringIO = StringIO('') \r
3889\r
3890 for Item in VfrUniOffsetList:\r
3891 if (Item[0].find("Strings") != -1):\r
3892 #\r
3893 # UNI offset in image.\r
3894 # GUID + Offset\r
3895 # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
3896 #\r
3897 UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66]\r
3898 UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid]\r
3899 fStringIO.write(''.join(UniGuid)) \r
3900 UniValue = pack ('Q', int (Item[1], 16))\r
3901 fStringIO.write (UniValue)\r
3902 else:\r
3903 #\r
3904 # VFR binary offset in image.\r
3905 # GUID + Offset\r
3906 # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
3907 #\r
3908 VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2]\r
3909 VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid]\r
3910 fStringIO.write(''.join(VfrGuid)) \r
3911 type (Item[1]) \r
3912 VfrValue = pack ('Q', int (Item[1], 16))\r
3913 fStringIO.write (VfrValue)\r
3914 #\r
3915 # write data into file.\r
3916 #\r
3917 try : \r
3918 fInputfile.write (fStringIO.getvalue())\r
3919 except:\r
3920 EdkLogger.error("build", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the "\r
3921 "file been locked or using by other applications." %UniVfrOffsetFileName,None)\r
3922\r
3923 fStringIO.close ()\r
3924 fInputfile.close ()\r
3925 return OutputName\r
3926\r
da92f276
LG
3927 ## Create AsBuilt INF file the module\r
3928 #\r
83397f95
YZ
3929 def CreateAsBuiltInf(self, IsOnlyCopy = False):\r
3930 self.OutputFile = []\r
3931 if IsOnlyCopy:\r
3932 if GlobalData.gBinCacheDest:\r
3933 self.CopyModuleToCache()\r
3934 return\r
3935\r
da92f276
LG
3936 if self.IsAsBuiltInfCreated:\r
3937 return\r
3938 \r
3939 # Skip the following code for EDK I inf\r
3940 if self.AutoGenVersion < 0x00010005:\r
3941 return\r
3942 \r
3943 # Skip the following code for libraries\r
3944 if self.IsLibrary:\r
3945 return\r
3946 \r
3947 # Skip the following code for modules with no source files\r
4231a819 3948 if self.SourceFileList is None or self.SourceFileList == []:\r
da92f276
LG
3949 return\r
3950\r
3951 # Skip the following code for modules without any binary files\r
3952 if self.BinaryFileList <> None and self.BinaryFileList <> []:\r
3953 return\r
3954 \r
3955 ### TODO: How to handles mixed source and binary modules\r
3956\r
e8a47801 3957 # Find all DynamicEx and PatchableInModule PCDs used by this module and dependent libraries\r
da92f276
LG
3958 # Also find all packages that the DynamicEx PCDs depend on\r
3959 Pcds = []\r
e5cf9198 3960 PatchablePcds = []\r
47fea6af 3961 Packages = []\r
e8a47801
LG
3962 PcdCheckList = []\r
3963 PcdTokenSpaceList = []\r
da92f276 3964 for Pcd in self.ModulePcdList + self.LibraryPcdList:\r
e8a47801 3965 if Pcd.Type == TAB_PCDS_PATCHABLE_IN_MODULE:\r
e5cf9198 3966 PatchablePcds += [Pcd]\r
e8a47801
LG
3967 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'PatchableInModule'))\r
3968 elif Pcd.Type in GenC.gDynamicExPcd:\r
3969 if Pcd not in Pcds:\r
3970 Pcds += [Pcd]\r
3971 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'DynamicEx'))\r
3972 PcdCheckList.append((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, 'Dynamic'))\r
3973 PcdTokenSpaceList.append(Pcd.TokenSpaceGuidCName)\r
9006a2c6 3974 GuidList = OrderedDict()\r
e8a47801
LG
3975 GuidList.update(self.GuidList)\r
3976 for TokenSpace in self.GetGuidsUsedByPcd():\r
3977 # If token space is not referred by patch PCD or Ex PCD, remove the GUID from GUID list\r
3978 # The GUIDs in GUIDs section should really be the GUIDs in source INF or referred by Ex an patch PCDs\r
3979 if TokenSpace not in PcdTokenSpaceList and TokenSpace in GuidList:\r
3980 GuidList.pop(TokenSpace)\r
3981 CheckList = (GuidList, self.PpiList, self.ProtocolList, PcdCheckList)\r
3982 for Package in self.DerivedPackageList:\r
3983 if Package in Packages:\r
3984 continue\r
3985 BeChecked = (Package.Guids, Package.Ppis, Package.Protocols, Package.Pcds)\r
3986 Found = False\r
3987 for Index in range(len(BeChecked)):\r
3988 for Item in CheckList[Index]:\r
3989 if Item in BeChecked[Index]:\r
3990 Packages += [Package]\r
3991 Found = True\r
3992 break\r
3993 if Found: break\r
da92f276 3994\r
97fa0ee9
YL
3995 VfrPcds = self._GetPcdsMaybeUsedByVfr()\r
3996 for Pkg in self.PlatformInfo.PackageList:\r
3997 if Pkg in Packages:\r
3998 continue\r
3999 for VfrPcd in VfrPcds:\r
4000 if ((VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'DynamicEx') in Pkg.Pcds or\r
4001 (VfrPcd.TokenCName, VfrPcd.TokenSpaceGuidCName, 'Dynamic') in Pkg.Pcds):\r
4002 Packages += [Pkg]\r
4003 break\r
4004\r
da92f276
LG
4005 ModuleType = self.ModuleType\r
4006 if ModuleType == 'UEFI_DRIVER' and self.DepexGenerated:\r
e8a47801
LG
4007 ModuleType = 'DXE_DRIVER'\r
4008\r
4009 DriverType = ''\r
4010 if self.PcdIsDriver != '':\r
4011 DriverType = self.PcdIsDriver\r
da92f276 4012\r
97fa0ee9
YL
4013 Guid = self.Guid\r
4014 MDefs = self.Module.Defines\r
4015\r
da92f276
LG
4016 AsBuiltInfDict = {\r
4017 'module_name' : self.Name,\r
97fa0ee9 4018 'module_guid' : Guid,\r
da92f276 4019 'module_module_type' : ModuleType,\r
97fa0ee9 4020 'module_version_string' : [MDefs['VERSION_STRING']] if 'VERSION_STRING' in MDefs else [],\r
e8a47801 4021 'pcd_is_driver_string' : [],\r
da92f276
LG
4022 'module_uefi_specification_version' : [],\r
4023 'module_pi_specification_version' : [],\r
97fa0ee9
YL
4024 'module_entry_point' : self.Module.ModuleEntryPointList,\r
4025 'module_unload_image' : self.Module.ModuleUnloadImageList,\r
4026 'module_constructor' : self.Module.ConstructorList,\r
4027 'module_destructor' : self.Module.DestructorList,\r
4028 'module_shadow' : [MDefs['SHADOW']] if 'SHADOW' in MDefs else [],\r
4029 'module_pci_vendor_id' : [MDefs['PCI_VENDOR_ID']] if 'PCI_VENDOR_ID' in MDefs else [],\r
4030 'module_pci_device_id' : [MDefs['PCI_DEVICE_ID']] if 'PCI_DEVICE_ID' in MDefs else [],\r
4031 'module_pci_class_code' : [MDefs['PCI_CLASS_CODE']] if 'PCI_CLASS_CODE' in MDefs else [],\r
4032 'module_pci_revision' : [MDefs['PCI_REVISION']] if 'PCI_REVISION' in MDefs else [],\r
4033 'module_build_number' : [MDefs['BUILD_NUMBER']] if 'BUILD_NUMBER' in MDefs else [],\r
4034 'module_spec' : [MDefs['SPEC']] if 'SPEC' in MDefs else [],\r
4035 'module_uefi_hii_resource_section' : [MDefs['UEFI_HII_RESOURCE_SECTION']] if 'UEFI_HII_RESOURCE_SECTION' in MDefs else [],\r
4036 'module_uni_file' : [MDefs['MODULE_UNI_FILE']] if 'MODULE_UNI_FILE' in MDefs else [],\r
da92f276 4037 'module_arch' : self.Arch,\r
47fea6af 4038 'package_item' : ['%s' % (Package.MetaFile.File.replace('\\', '/')) for Package in Packages],\r
da92f276 4039 'binary_item' : [],\r
e8a47801 4040 'patchablepcd_item' : [],\r
da92f276 4041 'pcd_item' : [],\r
e8a47801
LG
4042 'protocol_item' : [],\r
4043 'ppi_item' : [],\r
4044 'guid_item' : [],\r
4045 'flags_item' : [],\r
4046 'libraryclasses_item' : []\r
da92f276 4047 }\r
97fa0ee9 4048\r
78bcd52a
YZ
4049 if 'MODULE_UNI_FILE' in MDefs:\r
4050 UNIFile = os.path.join(self.MetaFile.Dir, MDefs['MODULE_UNI_FILE'])\r
4051 if os.path.isfile(UNIFile):\r
4052 shutil.copy2(UNIFile, self.OutputDir)\r
4053\r
97fa0ee9
YL
4054 if self.AutoGenVersion > int(gInfSpecVersion, 0):\r
4055 AsBuiltInfDict['module_inf_version'] = '0x%08x' % self.AutoGenVersion\r
4056 else:\r
4057 AsBuiltInfDict['module_inf_version'] = gInfSpecVersion\r
4058\r
e8a47801
LG
4059 if DriverType:\r
4060 AsBuiltInfDict['pcd_is_driver_string'] += [DriverType]\r
da92f276
LG
4061\r
4062 if 'UEFI_SPECIFICATION_VERSION' in self.Specification:\r
481252bb 4063 AsBuiltInfDict['module_uefi_specification_version'] += [self.Specification['UEFI_SPECIFICATION_VERSION']]\r
da92f276 4064 if 'PI_SPECIFICATION_VERSION' in self.Specification:\r
481252bb 4065 AsBuiltInfDict['module_pi_specification_version'] += [self.Specification['PI_SPECIFICATION_VERSION']]\r
da92f276 4066\r
47fea6af 4067 OutputDir = self.OutputDir.replace('\\', '/').strip('/')\r
c7c5a6c4 4068 DebugDir = self.DebugDir.replace('\\', '/').strip('/')\r
481252bb 4069 for Item in self.CodaTargetList:\r
90456c3c 4070 File = Item.Target.Path.replace('\\', '/').strip('/').replace(DebugDir, '').replace(OutputDir, '').strip('/')\r
36d083ef
YZ
4071 if File not in self.OutputFile:\r
4072 self.OutputFile.append(File)\r
5e2c0ecd
YZ
4073 if os.path.isabs(File):\r
4074 File = File.replace('\\', '/').strip('/').replace(OutputDir, '').strip('/')\r
47fea6af 4075 if Item.Target.Ext.lower() == '.aml':\r
481252bb 4076 AsBuiltInfDict['binary_item'] += ['ASL|' + File]\r
47fea6af 4077 elif Item.Target.Ext.lower() == '.acpi':\r
481252bb
YZ
4078 AsBuiltInfDict['binary_item'] += ['ACPI|' + File]\r
4079 elif Item.Target.Ext.lower() == '.efi':\r
4080 AsBuiltInfDict['binary_item'] += ['PE32|' + self.Name + '.efi']\r
da92f276 4081 else:\r
481252bb
YZ
4082 AsBuiltInfDict['binary_item'] += ['BIN|' + File]\r
4083 if self.DepexGenerated:\r
36d083ef
YZ
4084 if self.Name + '.depex' not in self.OutputFile:\r
4085 self.OutputFile.append(self.Name + '.depex')\r
da92f276 4086 if self.ModuleType in ['PEIM']:\r
481252bb 4087 AsBuiltInfDict['binary_item'] += ['PEI_DEPEX|' + self.Name + '.depex']\r
47fea6af 4088 if self.ModuleType in ['DXE_DRIVER', 'DXE_RUNTIME_DRIVER', 'DXE_SAL_DRIVER', 'UEFI_DRIVER']:\r
481252bb 4089 AsBuiltInfDict['binary_item'] += ['DXE_DEPEX|' + self.Name + '.depex']\r
da92f276 4090 if self.ModuleType in ['DXE_SMM_DRIVER']:\r
481252bb 4091 AsBuiltInfDict['binary_item'] += ['SMM_DEPEX|' + self.Name + '.depex']\r
da92f276 4092\r
aeaaf754
YL
4093 Bin = self._GenOffsetBin()\r
4094 if Bin:\r
4095 AsBuiltInfDict['binary_item'] += ['BIN|%s' % Bin]\r
36d083ef
YZ
4096 if Bin not in self.OutputFile:\r
4097 self.OutputFile.append(Bin)\r
aeaaf754 4098\r
e8a47801
LG
4099 for Root, Dirs, Files in os.walk(OutputDir):\r
4100 for File in Files:\r
4101 if File.lower().endswith('.pdb'):\r
4102 AsBuiltInfDict['binary_item'] += ['DISPOSABLE|' + File]\r
36d083ef
YZ
4103 if File not in self.OutputFile:\r
4104 self.OutputFile.append(File)\r
e8a47801
LG
4105 HeaderComments = self.Module.HeaderComments\r
4106 StartPos = 0\r
4107 for Index in range(len(HeaderComments)):\r
4108 if HeaderComments[Index].find('@BinaryHeader') != -1:\r
4109 HeaderComments[Index] = HeaderComments[Index].replace('@BinaryHeader', '@file')\r
4110 StartPos = Index\r
4111 break\r
4112 AsBuiltInfDict['header_comments'] = '\n'.join(HeaderComments[StartPos:]).replace(':#', '://')\r
97fa0ee9
YL
4113 AsBuiltInfDict['tail_comments'] = '\n'.join(self.Module.TailComments)\r
4114\r
e8a47801
LG
4115 GenList = [\r
4116 (self.ProtocolList, self._ProtocolComments, 'protocol_item'),\r
4117 (self.PpiList, self._PpiComments, 'ppi_item'),\r
4118 (GuidList, self._GuidComments, 'guid_item')\r
4119 ]\r
4120 for Item in GenList:\r
4121 for CName in Item[0]:\r
4122 Comments = ''\r
4123 if CName in Item[1]:\r
4124 Comments = '\n '.join(Item[1][CName])\r
4125 Entry = CName\r
4126 if Comments:\r
4127 Entry = Comments + '\n ' + CName\r
4128 AsBuiltInfDict[Item[2]].append(Entry)\r
4129 PatchList = parsePcdInfoFromMapFile(\r
4130 os.path.join(self.OutputDir, self.Name + '.map'),\r
4131 os.path.join(self.OutputDir, self.Name + '.efi')\r
4132 )\r
4133 if PatchList:\r
e5cf9198
YZ
4134 for Pcd in PatchablePcds:\r
4135 TokenCName = Pcd.TokenCName\r
4136 for PcdItem in GlobalData.MixedPcd:\r
4137 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
4138 TokenCName = PcdItem[0]\r
4139 break\r
4140 for PatchPcd in PatchList:\r
4141 if TokenCName == PatchPcd[0]:\r
4142 break\r
2a29017e 4143 else:\r
e8a47801 4144 continue\r
e8a47801 4145 PcdValue = ''\r
7ced8bb4
YZ
4146 if Pcd.DatumType == 'BOOLEAN':\r
4147 BoolValue = Pcd.DefaultValue.upper()\r
4148 if BoolValue == 'TRUE':\r
4149 Pcd.DefaultValue = '1'\r
4150 elif BoolValue == 'FALSE':\r
4151 Pcd.DefaultValue = '0'\r
4152\r
ae7b6df8 4153 if Pcd.DatumType in ['UINT8', 'UINT16', 'UINT32', 'UINT64', 'BOOLEAN']:\r
e8a47801
LG
4154 HexFormat = '0x%02x'\r
4155 if Pcd.DatumType == 'UINT16':\r
4156 HexFormat = '0x%04x'\r
4157 elif Pcd.DatumType == 'UINT32':\r
4158 HexFormat = '0x%08x'\r
4159 elif Pcd.DatumType == 'UINT64':\r
4160 HexFormat = '0x%016x'\r
4161 PcdValue = HexFormat % int(Pcd.DefaultValue, 0)\r
4162 else:\r
4231a819 4163 if Pcd.MaxDatumSize is None or Pcd.MaxDatumSize == '':\r
e8a47801 4164 EdkLogger.error("build", AUTOGEN_ERROR,\r
2a29017e 4165 "Unknown [MaxDatumSize] of PCD [%s.%s]" % (Pcd.TokenSpaceGuidCName, TokenCName)\r
e8a47801
LG
4166 )\r
4167 ArraySize = int(Pcd.MaxDatumSize, 0)\r
4168 PcdValue = Pcd.DefaultValue\r
4169 if PcdValue[0] != '{':\r
4170 Unicode = False\r
4171 if PcdValue[0] == 'L':\r
4172 Unicode = True\r
4173 PcdValue = PcdValue.lstrip('L')\r
4174 PcdValue = eval(PcdValue)\r
4175 NewValue = '{'\r
4176 for Index in range(0, len(PcdValue)):\r
4177 if Unicode:\r
4178 CharVal = ord(PcdValue[Index])\r
4179 NewValue = NewValue + '0x%02x' % (CharVal & 0x00FF) + ', ' \\r
4180 + '0x%02x' % (CharVal >> 8) + ', '\r
4181 else:\r
4182 NewValue = NewValue + '0x%02x' % (ord(PcdValue[Index]) % 0x100) + ', '\r
4183 Padding = '0x00, '\r
4184 if Unicode:\r
4185 Padding = Padding * 2\r
4186 ArraySize = ArraySize / 2\r
4187 if ArraySize < (len(PcdValue) + 1):\r
4188 EdkLogger.error("build", AUTOGEN_ERROR,\r
2a29017e 4189 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)\r
e8a47801
LG
4190 )\r
4191 if ArraySize > len(PcdValue) + 1:\r
4192 NewValue = NewValue + Padding * (ArraySize - len(PcdValue) - 1)\r
4193 PcdValue = NewValue + Padding.strip().rstrip(',') + '}'\r
4194 elif len(PcdValue.split(',')) <= ArraySize:\r
4195 PcdValue = PcdValue.rstrip('}') + ', 0x00' * (ArraySize - len(PcdValue.split(',')))\r
4196 PcdValue += '}'\r
4197 else:\r
4198 EdkLogger.error("build", AUTOGEN_ERROR,\r
2a29017e 4199 "The maximum size of VOID* type PCD '%s.%s' is less than its actual size occupied." % (Pcd.TokenSpaceGuidCName, TokenCName)\r
e8a47801
LG
4200 )\r
4201 PcdItem = '%s.%s|%s|0x%X' % \\r
2a29017e 4202 (Pcd.TokenSpaceGuidCName, TokenCName, PcdValue, PatchPcd[1])\r
e8a47801
LG
4203 PcdComments = ''\r
4204 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
4205 PcdComments = '\n '.join(self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName])\r
4206 if PcdComments:\r
4207 PcdItem = PcdComments + '\n ' + PcdItem\r
4208 AsBuiltInfDict['patchablepcd_item'].append(PcdItem)\r
97fa0ee9
YL
4209\r
4210 HiiPcds = []\r
4211 for Pcd in Pcds + VfrPcds:\r
e8a47801
LG
4212 PcdComments = ''\r
4213 PcdCommentList = []\r
4214 HiiInfo = ''\r
97fa0ee9 4215 SkuId = ''\r
2a29017e
YZ
4216 TokenCName = Pcd.TokenCName\r
4217 for PcdItem in GlobalData.MixedPcd:\r
4218 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
4219 TokenCName = PcdItem[0]\r
4220 break\r
e8a47801
LG
4221 if Pcd.Type == TAB_PCDS_DYNAMIC_EX_HII:\r
4222 for SkuName in Pcd.SkuInfoList:\r
4223 SkuInfo = Pcd.SkuInfoList[SkuName]\r
97fa0ee9 4224 SkuId = SkuInfo.SkuId\r
e8a47801
LG
4225 HiiInfo = '## %s|%s|%s' % (SkuInfo.VariableName, SkuInfo.VariableGuid, SkuInfo.VariableOffset)\r
4226 break\r
97fa0ee9
YL
4227 if SkuId:\r
4228 #\r
4229 # Don't generate duplicated HII PCD\r
4230 #\r
4231 if (SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in HiiPcds:\r
4232 continue\r
4233 else:\r
4234 HiiPcds.append((SkuId, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
e8a47801
LG
4235 if (Pcd.TokenSpaceGuidCName, Pcd.TokenCName) in self._PcdComments:\r
4236 PcdCommentList = self._PcdComments[Pcd.TokenSpaceGuidCName, Pcd.TokenCName][:]\r
4237 if HiiInfo:\r
4238 UsageIndex = -1\r
97fa0ee9 4239 UsageStr = ''\r
e8a47801
LG
4240 for Index, Comment in enumerate(PcdCommentList):\r
4241 for Usage in UsageList:\r
4242 if Comment.find(Usage) != -1:\r
97fa0ee9 4243 UsageStr = Usage\r
e8a47801
LG
4244 UsageIndex = Index\r
4245 break\r
4246 if UsageIndex != -1:\r
97fa0ee9 4247 PcdCommentList[UsageIndex] = '## %s %s %s' % (UsageStr, HiiInfo, PcdCommentList[UsageIndex].replace(UsageStr, '')) \r
e8a47801 4248 else:\r
97fa0ee9 4249 PcdCommentList.append('## UNDEFINED ' + HiiInfo)\r
e8a47801 4250 PcdComments = '\n '.join(PcdCommentList)\r
2a29017e 4251 PcdEntry = Pcd.TokenSpaceGuidCName + '.' + TokenCName\r
e8a47801
LG
4252 if PcdComments:\r
4253 PcdEntry = PcdComments + '\n ' + PcdEntry\r
4254 AsBuiltInfDict['pcd_item'] += [PcdEntry]\r
da92f276 4255 for Item in self.BuildOption:\r
481252bb
YZ
4256 if 'FLAGS' in self.BuildOption[Item]:\r
4257 AsBuiltInfDict['flags_item'] += ['%s:%s_%s_%s_%s_FLAGS = %s' % (self.ToolChainFamily, self.BuildTarget, self.ToolChain, self.Arch, Item, self.BuildOption[Item]['FLAGS'].strip())]\r
97fa0ee9
YL
4258\r
4259 # Generated LibraryClasses section in comments.\r
4260 for Library in self.LibraryAutoGenList:\r
4261 AsBuiltInfDict['libraryclasses_item'] += [Library.MetaFile.File.replace('\\', '/')]\r
4262 \r
dfa41b4a
YZ
4263 # Generated UserExtensions TianoCore section.\r
4264 # All tianocore user extensions are copied.\r
4265 UserExtStr = ''\r
4266 for TianoCore in self._GetTianoCoreUserExtensionList():\r
4267 UserExtStr += '\n'.join(TianoCore)\r
4268 ExtensionFile = os.path.join(self.MetaFile.Dir, TianoCore[1])\r
4269 if os.path.isfile(ExtensionFile):\r
4270 shutil.copy2(ExtensionFile, self.OutputDir)\r
4271 AsBuiltInfDict['userextension_tianocore_item'] = UserExtStr\r
4272\r
97fa0ee9
YL
4273 # Generated depex expression section in comments.\r
4274 AsBuiltInfDict['depexsection_item'] = ''\r
4275 DepexExpresion = self._GetDepexExpresionString()\r
4276 if DepexExpresion:\r
4277 AsBuiltInfDict['depexsection_item'] = DepexExpresion\r
da92f276
LG
4278 \r
4279 AsBuiltInf = TemplateString()\r
4280 AsBuiltInf.Append(gAsBuiltInfHeaderString.Replace(AsBuiltInfDict))\r
4281 \r
4282 SaveFileOnChange(os.path.join(self.OutputDir, self.Name + '.inf'), str(AsBuiltInf), False)\r
4283 \r
4284 self.IsAsBuiltInfCreated = True\r
36d083ef
YZ
4285 if GlobalData.gBinCacheDest:\r
4286 self.CopyModuleToCache()\r
4287\r
4288 def CopyModuleToCache(self):\r
4289 FileDir = path.join(GlobalData.gBinCacheDest, self.Arch, self.SourceDir, self.MetaFile.BaseName)\r
4290 CreateDirectory (FileDir)\r
4291 HashFile = path.join(self.BuildDir, self.Name + '.hash')\r
4292 ModuleFile = path.join(self.OutputDir, self.Name + '.inf')\r
4293 if os.path.exists(HashFile):\r
4294 shutil.copy2(HashFile, FileDir)\r
4295 if os.path.exists(ModuleFile):\r
4296 shutil.copy2(ModuleFile, FileDir)\r
83397f95
YZ
4297 if not self.OutputFile:\r
4298 Ma = self.Workspace.BuildDatabase[PathClass(ModuleFile), self.Arch, self.BuildTarget, self.ToolChain]\r
4299 self.OutputFile = Ma.Binaries\r
36d083ef
YZ
4300 if self.OutputFile:\r
4301 for File in self.OutputFile:\r
83397f95 4302 File = str(File)\r
36d083ef
YZ
4303 if not os.path.isabs(File):\r
4304 File = os.path.join(self.OutputDir, File)\r
4305 if os.path.exists(File):\r
4306 shutil.copy2(File, FileDir)\r
4307\r
4308 def AttemptModuleCacheCopy(self):\r
4309 if self.IsBinaryModule:\r
4310 return False\r
4311 FileDir = path.join(GlobalData.gBinCacheSource, self.Arch, self.SourceDir, self.MetaFile.BaseName)\r
4312 HashFile = path.join(FileDir, self.Name + '.hash')\r
4313 if os.path.exists(HashFile):\r
4314 f = open(HashFile, 'r')\r
4315 CacheHash = f.read()\r
4316 f.close()\r
4317 if GlobalData.gModuleHash[self.Arch][self.Name]:\r
4318 if CacheHash == GlobalData.gModuleHash[self.Arch][self.Name]:\r
4319 for root, dir, files in os.walk(FileDir):\r
4320 for f in files:\r
4321 if self.Name + '.hash' in f:\r
4322 shutil.copy2(HashFile, self.BuildDir)\r
4323 else:\r
4324 File = path.join(root, f)\r
4325 shutil.copy2(File, self.OutputDir)\r
4326 if self.Name == "PcdPeim" or self.Name == "PcdDxe":\r
4327 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())\r
4328 return True\r
4329 return False\r
4330\r
52302d4d
LG
4331 ## Create makefile for the module and its dependent libraries\r
4332 #\r
4333 # @param CreateLibraryMakeFile Flag indicating if or not the makefiles of\r
4334 # dependent libraries will be created\r
4335 #\r
37de70b7 4336 def CreateMakeFile(self, CreateLibraryMakeFile=True, GenFfsList = []):\r
fae62ff2 4337 # Ignore generating makefile when it is a binary module\r
a0a2cd1e
FB
4338 if self.IsBinaryModule:\r
4339 return\r
fae62ff2 4340\r
52302d4d
LG
4341 if self.IsMakeFileCreated:\r
4342 return\r
37de70b7 4343 self.GenFfsList = GenFfsList\r
52302d4d
LG
4344 if not self.IsLibrary and CreateLibraryMakeFile:\r
4345 for LibraryAutoGen in self.LibraryAutoGenList:\r
4346 LibraryAutoGen.CreateMakeFile()\r
4347\r
36513f3a
YZ
4348 if self.CanSkip():\r
4349 return\r
4350\r
52302d4d
LG
4351 if len(self.CustomMakefile) == 0:\r
4352 Makefile = GenMake.ModuleMakefile(self)\r
4353 else:\r
4354 Makefile = GenMake.CustomMakefile(self)\r
4355 if Makefile.Generate():\r
4356 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated makefile for module %s [%s]" %\r
4357 (self.Name, self.Arch))\r
4358 else:\r
4359 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of makefile for module %s [%s]" %\r
4360 (self.Name, self.Arch))\r
4361\r
c17956e0 4362 self.CreateTimeStamp(Makefile)\r
52302d4d
LG
4363 self.IsMakeFileCreated = True\r
4364\r
a0a2cd1e
FB
4365 def CopyBinaryFiles(self):\r
4366 for File in self.Module.Binaries:\r
4367 SrcPath = File.Path\r
4368 DstPath = os.path.join(self.OutputDir , os.path.basename(SrcPath))\r
4369 CopyLongFilePath(SrcPath, DstPath)\r
52302d4d
LG
4370 ## Create autogen code for the module and its dependent libraries\r
4371 #\r
4372 # @param CreateLibraryCodeFile Flag indicating if or not the code of\r
4373 # dependent libraries will be created\r
4374 #\r
4375 def CreateCodeFile(self, CreateLibraryCodeFile=True):\r
4376 if self.IsCodeFileCreated:\r
4377 return\r
4378\r
e8a47801
LG
4379 # Need to generate PcdDatabase even PcdDriver is binarymodule\r
4380 if self.IsBinaryModule and self.PcdIsDriver != '':\r
4381 CreatePcdDatabaseCode(self, TemplateString(), TemplateString())\r
4382 return\r
a0a2cd1e 4383 if self.IsBinaryModule:\r
49d9b71d
HC
4384 if self.IsLibrary:\r
4385 self.CopyBinaryFiles()\r
a0a2cd1e 4386 return\r
e8a47801 4387\r
52302d4d
LG
4388 if not self.IsLibrary and CreateLibraryCodeFile:\r
4389 for LibraryAutoGen in self.LibraryAutoGenList:\r
4390 LibraryAutoGen.CreateCodeFile()\r
4391\r
36513f3a
YZ
4392 if self.CanSkip():\r
4393 return\r
4394\r
52302d4d
LG
4395 AutoGenList = []\r
4396 IgoredAutoGenList = []\r
4397\r
4398 for File in self.AutoGenFileList:\r
4399 if GenC.Generate(File.Path, self.AutoGenFileList[File], File.IsBinary):\r
b36d134f 4400 #Ignore Edk AutoGen.c\r
52302d4d
LG
4401 if self.AutoGenVersion < 0x00010005 and File.Name == 'AutoGen.c':\r
4402 continue\r
4403\r
4404 AutoGenList.append(str(File))\r
4405 else:\r
4406 IgoredAutoGenList.append(str(File))\r
4407\r
4408 # Skip the following code for EDK I inf\r
4409 if self.AutoGenVersion < 0x00010005:\r
4410 return\r
4411\r
4412 for ModuleType in self.DepexList:\r
40d841f6
LG
4413 # Ignore empty [depex] section or [depex] section for "USER_DEFINED" module\r
4414 if len(self.DepexList[ModuleType]) == 0 or ModuleType == "USER_DEFINED":\r
52302d4d 4415 continue\r
40d841f6 4416\r
52302d4d
LG
4417 Dpx = GenDepex.DependencyExpression(self.DepexList[ModuleType], ModuleType, True)\r
4418 DpxFile = gAutoGenDepexFileName % {"module_name" : self.Name}\r
4419\r
da92f276 4420 if len(Dpx.PostfixNotation) <> 0:\r
0d2711a6 4421 self.DepexGenerated = True\r
da92f276 4422\r
52302d4d
LG
4423 if Dpx.Generate(path.join(self.OutputDir, DpxFile)):\r
4424 AutoGenList.append(str(DpxFile))\r
4425 else:\r
4426 IgoredAutoGenList.append(str(DpxFile))\r
4427\r
4428 if IgoredAutoGenList == []:\r
4429 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] files for module %s [%s]" %\r
4430 (" ".join(AutoGenList), self.Name, self.Arch))\r
4431 elif AutoGenList == []:\r
4432 EdkLogger.debug(EdkLogger.DEBUG_9, "Skipped the generation of [%s] files for module %s [%s]" %\r
4433 (" ".join(IgoredAutoGenList), self.Name, self.Arch))\r
4434 else:\r
4435 EdkLogger.debug(EdkLogger.DEBUG_9, "Generated [%s] (skipped %s) files for module %s [%s]" %\r
4436 (" ".join(AutoGenList), " ".join(IgoredAutoGenList), self.Name, self.Arch))\r
4437\r
4438 self.IsCodeFileCreated = True\r
4439 return AutoGenList\r
4440\r
4441 ## Summarize the ModuleAutoGen objects of all libraries used by this module\r
4442 def _GetLibraryAutoGenList(self):\r
4231a819 4443 if self._LibraryAutoGenList is None:\r
52302d4d
LG
4444 self._LibraryAutoGenList = []\r
4445 for Library in self.DependentLibraryList:\r
4446 La = ModuleAutoGen(\r
4447 self.Workspace,\r
4448 Library.MetaFile,\r
4449 self.BuildTarget,\r
4450 self.ToolChain,\r
4451 self.Arch,\r
4452 self.PlatformInfo.MetaFile\r
4453 )\r
4454 if La not in self._LibraryAutoGenList:\r
4455 self._LibraryAutoGenList.append(La)\r
4456 for Lib in La.CodaTargetList:\r
4457 self._ApplyBuildRule(Lib.Target, TAB_UNKNOWN_FILE)\r
4458 return self._LibraryAutoGenList\r
4459\r
36d083ef
YZ
4460 def GenModuleHash(self):\r
4461 if self.Arch not in GlobalData.gModuleHash:\r
4462 GlobalData.gModuleHash[self.Arch] = {}\r
4463 m = hashlib.md5()\r
4464 # Add Platform level hash\r
4465 m.update(GlobalData.gPlatformHash)\r
4466 # Add Package level hash\r
4467 if self.DependentPackageList:\r
4468 for Pkg in self.DependentPackageList:\r
4469 if Pkg.PackageName in GlobalData.gPackageHash[self.Arch]:\r
4470 m.update(GlobalData.gPackageHash[self.Arch][Pkg.PackageName])\r
4471\r
4472 # Add Library hash\r
4473 if self.LibraryAutoGenList:\r
4474 for Lib in self.LibraryAutoGenList:\r
4475 if Lib.Name not in GlobalData.gModuleHash[self.Arch]:\r
4476 Lib.GenModuleHash()\r
4477 m.update(GlobalData.gModuleHash[self.Arch][Lib.Name])\r
4478\r
4479 # Add Module self\r
4480 f = open(str(self.MetaFile), 'r')\r
4481 Content = f.read()\r
4482 f.close()\r
4483 m.update(Content)\r
4484 # Add Module's source files\r
4485 if self.SourceFileList:\r
4486 for File in self.SourceFileList:\r
4487 f = open(str(File), 'r')\r
4488 Content = f.read()\r
4489 f.close()\r
4490 m.update(Content)\r
4491\r
4492 ModuleHashFile = path.join(self.BuildDir, self.Name + ".hash")\r
4493 if self.Name not in GlobalData.gModuleHash[self.Arch]:\r
4494 GlobalData.gModuleHash[self.Arch][self.Name] = m.hexdigest()\r
4495 if GlobalData.gBinCacheSource:\r
4496 CacheValid = self.AttemptModuleCacheCopy()\r
4497 if CacheValid:\r
4498 return False\r
4499 return SaveFileOnChange(ModuleHashFile, m.hexdigest(), True)\r
4500\r
4501 ## Decide whether we can skip the ModuleAutoGen process\r
4502 def CanSkipbyHash(self):\r
4503 if GlobalData.gUseHashCache:\r
4504 return not self.GenModuleHash()\r
4505\r
c17956e0 4506 ## Decide whether we can skip the ModuleAutoGen process\r
36d083ef 4507 # If any source file is newer than the module than we cannot skip\r
c17956e0
DL
4508 #\r
4509 def CanSkip(self):\r
4510 if not os.path.exists(self.GetTimeStampPath()):\r
4511 return False\r
4512 #last creation time of the module\r
4513 DstTimeStamp = os.stat(self.GetTimeStampPath())[8]\r
4514\r
4515 SrcTimeStamp = self.Workspace._SrcTimeStamp\r
4516 if SrcTimeStamp > DstTimeStamp:\r
4517 return False\r
4518\r
4519 with open(self.GetTimeStampPath(),'r') as f:\r
4520 for source in f:\r
4521 source = source.rstrip('\n')\r
4a1167df
YZ
4522 if not os.path.exists(source):\r
4523 return False\r
c17956e0
DL
4524 if source not in ModuleAutoGen.TimeDict :\r
4525 ModuleAutoGen.TimeDict[source] = os.stat(source)[8]\r
4526 if ModuleAutoGen.TimeDict[source] > DstTimeStamp:\r
4527 return False\r
4528 return True\r
4529\r
4530 def GetTimeStampPath(self):\r
4231a819 4531 if self._TimeStampPath is None:\r
c17956e0
DL
4532 self._TimeStampPath = os.path.join(self.MakeFileDir, 'AutoGenTimeStamp')\r
4533 return self._TimeStampPath\r
4534 def CreateTimeStamp(self, Makefile):\r
4535\r
4536 FileSet = set()\r
4537\r
4538 FileSet.add (self.MetaFile.Path)\r
4539\r
4540 for SourceFile in self.Module.Sources:\r
4541 FileSet.add (SourceFile.Path)\r
4542\r
4543 for Lib in self.DependentLibraryList:\r
4544 FileSet.add (Lib.MetaFile.Path)\r
4545\r
4546 for f in self.AutoGenDepSet:\r
4547 FileSet.add (f.Path)\r
4548\r
4549 if os.path.exists (self.GetTimeStampPath()):\r
4550 os.remove (self.GetTimeStampPath())\r
4551 with open(self.GetTimeStampPath(), 'w+') as file:\r
4552 for f in FileSet:\r
4553 print >> file, f\r
4554\r
52302d4d
LG
4555 Module = property(_GetModule)\r
4556 Name = property(_GetBaseName)\r
4557 Guid = property(_GetGuid)\r
4558 Version = property(_GetVersion)\r
4559 ModuleType = property(_GetModuleType)\r
4560 ComponentType = property(_GetComponentType)\r
4561 BuildType = property(_GetBuildType)\r
4562 PcdIsDriver = property(_GetPcdIsDriver)\r
4563 AutoGenVersion = property(_GetAutoGenVersion)\r
4564 Macros = property(_GetMacros)\r
4565 Specification = property(_GetSpecification)\r
4566\r
4567 IsLibrary = property(_IsLibrary)\r
e8a47801 4568 IsBinaryModule = property(_IsBinaryModule)\r
52302d4d
LG
4569 BuildDir = property(_GetBuildDir)\r
4570 OutputDir = property(_GetOutputDir)\r
37de70b7 4571 FfsOutputDir = property(_GetFfsOutputDir)\r
52302d4d
LG
4572 DebugDir = property(_GetDebugDir)\r
4573 MakeFileDir = property(_GetMakeFileDir)\r
4574 CustomMakefile = property(_GetCustomMakefile)\r
4575\r
4576 IncludePathList = property(_GetIncludePathList)\r
725cdb8f 4577 IncludePathLength = property(_GetIncludePathLength)\r
52302d4d
LG
4578 AutoGenFileList = property(_GetAutoGenFileList)\r
4579 UnicodeFileList = property(_GetUnicodeFileList)\r
5b97eb4c 4580 VfrFileList = property(_GetVfrFileList)\r
52302d4d
LG
4581 SourceFileList = property(_GetSourceFileList)\r
4582 BinaryFileList = property(_GetBinaryFiles) # FileType : [File List]\r
4583 Targets = property(_GetTargets)\r
4584 IntroTargetList = property(_GetIntroTargetList)\r
4585 CodaTargetList = property(_GetFinalTargetList)\r
4586 FileTypes = property(_GetFileTypes)\r
4587 BuildRules = property(_GetBuildRules)\r
333ba578 4588 IdfFileList = property(_GetIdfFileList)\r
52302d4d
LG
4589\r
4590 DependentPackageList = property(_GetDependentPackageList)\r
4591 DependentLibraryList = property(_GetLibraryList)\r
4592 LibraryAutoGenList = property(_GetLibraryAutoGenList)\r
4593 DerivedPackageList = property(_GetDerivedPackageList)\r
4594\r
4595 ModulePcdList = property(_GetModulePcdList)\r
4596 LibraryPcdList = property(_GetLibraryPcdList)\r
4597 GuidList = property(_GetGuidList)\r
4598 ProtocolList = property(_GetProtocolList)\r
4599 PpiList = property(_GetPpiList)\r
4600 DepexList = property(_GetDepexTokenList)\r
b36d134f 4601 DxsFile = property(_GetDxsFile)\r
52302d4d
LG
4602 DepexExpressionList = property(_GetDepexExpressionTokenList)\r
4603 BuildOption = property(_GetModuleBuildOption)\r
79b74a03 4604 BuildOptionIncPathList = property(_GetBuildOptionIncPathList)\r
52302d4d 4605 BuildCommand = property(_GetBuildCommand)\r
2bc3256c
LG
4606 \r
4607 FixedAtBuildPcds = property(_GetFixedAtBuildPcds)\r
52302d4d
LG
4608\r
4609# This acts like the main() function for the script, unless it is 'import'ed into another script.\r
4610if __name__ == '__main__':\r
4611 pass\r
4612\r