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