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