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