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