BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / AutoGen.py
1 ## @file\r
2 # Generate AutoGen.h, AutoGen.c and *.depex files\r
3 #\r
4 # Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>\r
5 # Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>\r
6 # Copyright (c) 2019, American Megatrends, Inc. All rights reserved.<BR>\r
7 #\r
8 # SPDX-License-Identifier: BSD-2-Clause-Patent\r
9 #\r
10 \r
11 ## Import Modules\r
12 #\r
13 from __future__ import print_function\r
14 from __future__ import absolute_import\r
15 import Common.LongFilePathOs as os\r
16 import re\r
17 import os.path as path\r
18 import copy\r
19 import uuid\r
20 \r
21 from . import GenC\r
22 from . import GenMake\r
23 from . import GenDepex\r
24 from io import BytesIO\r
25 \r
26 from .StrGather import *\r
27 from .BuildEngine import BuildRule\r
28 import shutil\r
29 from Common.LongFilePathSupport import CopyLongFilePath\r
30 from Common.BuildToolError import *\r
31 from Common.DataType import *\r
32 from Common.Misc import *\r
33 from Common.StringUtils import *\r
34 import Common.GlobalData as GlobalData\r
35 from GenFds.FdfParser import *\r
36 from CommonDataClass.CommonClass import SkuInfoClass\r
37 from GenPatchPcdTable.GenPatchPcdTable import parsePcdInfoFromMapFile\r
38 import Common.VpdInfoFile as VpdInfoFile\r
39 from .GenPcdDb import CreatePcdDatabaseCode\r
40 from Workspace.MetaFileCommentParser import UsageList\r
41 from Workspace.WorkspaceCommon import GetModuleLibInstances\r
42 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
43 from . import InfSectionParser\r
44 import datetime\r
45 import hashlib\r
46 from .GenVar import VariableMgr, var_info\r
47 from collections import OrderedDict\r
48 from collections import defaultdict\r
49 from Workspace.WorkspaceCommon import OrderedListDict\r
50 from Common.ToolDefClassObject import gDefaultToolsDefFile\r
51 \r
52 from Common.caching import cached_property, cached_class_function\r
53 \r
54 ## Regular expression for splitting Dependency Expression string into tokens\r
55 gDepexTokenPattern = re.compile("(\(|\)|\w+| \S+\.inf)")\r
56 \r
57 ## Regular expression for match: PCD(xxxx.yyy)\r
58 gPCDAsGuidPattern = re.compile(r"^PCD\(.+\..+\)$")\r
59 \r
60 #\r
61 # Regular expression for finding Include Directories, the difference between MSFT and INTEL/GCC/RVCT\r
62 # is the former use /I , the Latter used -I to specify include directories\r
63 #\r
64 gBuildOptIncludePatternMsft = re.compile(r"(?:.*?)/I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
65 gBuildOptIncludePatternOther = re.compile(r"(?:.*?)-I[ \t]*([^ ]*)", re.MULTILINE | re.DOTALL)\r
66 \r
67 #\r
68 # Match name = variable\r
69 #\r
70 gEfiVarStoreNamePattern = re.compile("\s*name\s*=\s*(\w+)")\r
71 #\r
72 # The format of guid in efivarstore statement likes following and must be correct:\r
73 # guid = {0xA04A27f4, 0xDF00, 0x4D42, {0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D}}\r
74 #\r
75 gEfiVarStoreGuidPattern = re.compile("\s*guid\s*=\s*({.*?{.*?}\s*})")\r
76 \r
77 ## Mapping Makefile type\r
78 gMakeTypeMap = {TAB_COMPILER_MSFT:"nmake", "GCC":"gmake"}\r
79 \r
80 \r
81 ## Build rule configuration file\r
82 gDefaultBuildRuleFile = 'build_rule.txt'\r
83 \r
84 ## Build rule default version\r
85 AutoGenReqBuildRuleVerNum = "0.1"\r
86 \r
87 ## default file name for AutoGen\r
88 gAutoGenCodeFileName = "AutoGen.c"\r
89 gAutoGenHeaderFileName = "AutoGen.h"\r
90 gAutoGenStringFileName = "%(module_name)sStrDefs.h"\r
91 gAutoGenStringFormFileName = "%(module_name)sStrDefs.hpk"\r
92 gAutoGenDepexFileName = "%(module_name)s.depex"\r
93 gAutoGenImageDefFileName = "%(module_name)sImgDefs.h"\r
94 gAutoGenIdfFileName = "%(module_name)sIdf.hpk"\r
95 gInfSpecVersion = "0x00010017"\r
96 \r
97 #\r
98 # Template string to generic AsBuilt INF\r
99 #\r
100 gAsBuiltInfHeaderString = TemplateString("""${header_comments}\r
101 \r
102 # DO NOT EDIT\r
103 # FILE auto-generated\r
104 \r
105 [Defines]\r
106   INF_VERSION                = ${module_inf_version}\r
107   BASE_NAME                  = ${module_name}\r
108   FILE_GUID                  = ${module_guid}\r
109   MODULE_TYPE                = ${module_module_type}${BEGIN}\r
110   VERSION_STRING             = ${module_version_string}${END}${BEGIN}\r
111   PCD_IS_DRIVER              = ${pcd_is_driver_string}${END}${BEGIN}\r
112   UEFI_SPECIFICATION_VERSION = ${module_uefi_specification_version}${END}${BEGIN}\r
113   PI_SPECIFICATION_VERSION   = ${module_pi_specification_version}${END}${BEGIN}\r
114   ENTRY_POINT                = ${module_entry_point}${END}${BEGIN}\r
115   UNLOAD_IMAGE               = ${module_unload_image}${END}${BEGIN}\r
116   CONSTRUCTOR                = ${module_constructor}${END}${BEGIN}\r
117   DESTRUCTOR                 = ${module_destructor}${END}${BEGIN}\r
118   SHADOW                     = ${module_shadow}${END}${BEGIN}\r
119   PCI_VENDOR_ID              = ${module_pci_vendor_id}${END}${BEGIN}\r
120   PCI_DEVICE_ID              = ${module_pci_device_id}${END}${BEGIN}\r
121   PCI_CLASS_CODE             = ${module_pci_class_code}${END}${BEGIN}\r
122   PCI_REVISION               = ${module_pci_revision}${END}${BEGIN}\r
123   BUILD_NUMBER               = ${module_build_number}${END}${BEGIN}\r
124   SPEC                       = ${module_spec}${END}${BEGIN}\r
125   UEFI_HII_RESOURCE_SECTION  = ${module_uefi_hii_resource_section}${END}${BEGIN}\r
126   MODULE_UNI_FILE            = ${module_uni_file}${END}\r
127 \r
128 [Packages.${module_arch}]${BEGIN}\r
129   ${package_item}${END}\r
130 \r
131 [Binaries.${module_arch}]${BEGIN}\r
132   ${binary_item}${END}\r
133 \r
134 [PatchPcd.${module_arch}]${BEGIN}\r
135   ${patchablepcd_item}\r
136 ${END}\r
137 \r
138 [Protocols.${module_arch}]${BEGIN}\r
139   ${protocol_item}\r
140 ${END}\r
141 \r
142 [Ppis.${module_arch}]${BEGIN}\r
143   ${ppi_item}\r
144 ${END}\r
145 \r
146 [Guids.${module_arch}]${BEGIN}\r
147   ${guid_item}\r
148 ${END}\r
149 \r
150 [PcdEx.${module_arch}]${BEGIN}\r
151   ${pcd_item}\r
152 ${END}\r
153 \r
154 [LibraryClasses.${module_arch}]\r
155 ## @LIB_INSTANCES${BEGIN}\r
156 #  ${libraryclasses_item}${END}\r
157 \r
158 ${depexsection_item}\r
159 \r
160 ${userextension_tianocore_item}\r
161 \r
162 ${tail_comments}\r
163 \r
164 [BuildOptions.${module_arch}]\r
165 ## @AsBuilt${BEGIN}\r
166 ##   ${flags_item}${END}\r
167 """)\r
168 ## Split command line option string to list\r
169 #\r
170 # subprocess.Popen needs the args to be a sequence. Otherwise there's problem\r
171 # in non-windows platform to launch command\r
172 #\r
173 def _SplitOption(OptionString):\r
174     OptionList = []\r
175     LastChar = " "\r
176     OptionStart = 0\r
177     QuotationMark = ""\r
178     for Index in range(0, len(OptionString)):\r
179         CurrentChar = OptionString[Index]\r
180         if CurrentChar in ['"', "'"]:\r
181             if QuotationMark == CurrentChar:\r
182                 QuotationMark = ""\r
183             elif QuotationMark == "":\r
184                 QuotationMark = CurrentChar\r
185             continue\r
186         elif QuotationMark:\r
187             continue\r
188 \r
189         if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:\r
190             if Index > OptionStart:\r
191                 OptionList.append(OptionString[OptionStart:Index - 1])\r
192             OptionStart = Index\r
193         LastChar = CurrentChar\r
194     OptionList.append(OptionString[OptionStart:])\r
195     return OptionList\r
196 \r
197 #\r
198 # Convert string to C format array\r
199 #\r
200 def _ConvertStringToByteArray(Value):\r
201     Value = Value.strip()\r
202     if not Value:\r
203         return None\r
204     if Value[0] == '{':\r
205         if not Value.endswith('}'):\r
206             return None\r
207         Value = Value.replace(' ', '').replace('{', '').replace('}', '')\r
208         ValFields = Value.split(',')\r
209         try:\r
210             for Index in range(len(ValFields)):\r
211                 ValFields[Index] = str(int(ValFields[Index], 0))\r
212         except ValueError:\r
213             return None\r
214         Value = '{' + ','.join(ValFields) + '}'\r
215         return Value\r
216 \r
217     Unicode = False\r
218     if Value.startswith('L"'):\r
219         if not Value.endswith('"'):\r
220             return None\r
221         Value = Value[1:]\r
222         Unicode = True\r
223     elif not Value.startswith('"') or not Value.endswith('"'):\r
224         return None\r
225 \r
226     Value = eval(Value)         # translate escape character\r
227     NewValue = '{'\r
228     for Index in range(0, len(Value)):\r
229         if Unicode:\r
230             NewValue = NewValue + str(ord(Value[Index]) % 0x10000) + ','\r
231         else:\r
232             NewValue = NewValue + str(ord(Value[Index]) % 0x100) + ','\r
233     Value = NewValue + '0}'\r
234     return Value\r
235 \r
236 ## Base class for AutoGen\r
237 #\r
238 #   This class just implements the cache mechanism of AutoGen objects.\r
239 #\r
240 class AutoGen(object):\r
241     # database to maintain the objects in each child class\r
242     __ObjectCache = {}    # (BuildTarget, ToolChain, ARCH, platform file): AutoGen object\r
243 \r
244     ## Factory method\r
245     #\r
246     #   @param  Class           class object of real AutoGen class\r
247     #                           (WorkspaceAutoGen, ModuleAutoGen or PlatformAutoGen)\r
248     #   @param  Workspace       Workspace directory or WorkspaceAutoGen object\r
249     #   @param  MetaFile        The path of meta file\r
250     #   @param  Target          Build target\r
251     #   @param  Toolchain       Tool chain name\r
252     #   @param  Arch            Target arch\r
253     #   @param  *args           The specific class related parameters\r
254     #   @param  **kwargs        The specific class related dict parameters\r
255     #\r
256     def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
257         # check if the object has been created\r
258         Key = (Target, Toolchain, Arch, MetaFile)\r
259         if Key in cls.__ObjectCache:\r
260             # if it exists, just return it directly\r
261             return cls.__ObjectCache[Key]\r
262             # it didnt exist. create it, cache it, then return it\r
263         RetVal = cls.__ObjectCache[Key] = super(AutoGen, cls).__new__(cls)\r
264         return RetVal\r
265 \r
266 \r
267     ## hash() operator\r
268     #\r
269     #  The file path of platform file will be used to represent hash value of this object\r
270     #\r
271     #   @retval int     Hash value of the file path of platform file\r
272     #\r
273     def __hash__(self):\r
274         return hash(self.MetaFile)\r
275 \r
276     ## str() operator\r
277     #\r
278     #  The file path of platform file will be used to represent this object\r
279     #\r
280     #   @retval string  String of platform file path\r
281     #\r
282     def __str__(self):\r
283         return str(self.MetaFile)\r
284 \r
285     ## "==" operator\r
286     def __eq__(self, Other):\r
287         return Other and self.MetaFile == Other\r
288 \r
289 ## Workspace AutoGen class\r
290 #\r
291 #   This class is used mainly to control the whole platform build for different\r
292 # architecture. This class will generate top level makefile.\r
293 #\r
294 class WorkspaceAutoGen(AutoGen):\r
295     # call super().__init__ then call the worker function with different parameter count\r
296     def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
297         if not hasattr(self, "_Init"):\r
298             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
299             self._Init = True\r
300 \r
301     ## Initialize WorkspaceAutoGen\r
302     #\r
303     #   @param  WorkspaceDir            Root directory of workspace\r
304     #   @param  ActivePlatform          Meta-file of active platform\r
305     #   @param  Target                  Build target\r
306     #   @param  Toolchain               Tool chain name\r
307     #   @param  ArchList                List of architecture of current build\r
308     #   @param  MetaFileDb              Database containing meta-files\r
309     #   @param  BuildConfig             Configuration of build\r
310     #   @param  ToolDefinition          Tool chain definitions\r
311     #   @param  FlashDefinitionFile     File of flash definition\r
312     #   @param  Fds                     FD list to be generated\r
313     #   @param  Fvs                     FV list to be generated\r
314     #   @param  Caps                    Capsule list to be generated\r
315     #   @param  SkuId                   SKU id from command line\r
316     #\r
317     def _InitWorker(self, WorkspaceDir, ActivePlatform, Target, Toolchain, ArchList, MetaFileDb,\r
318               BuildConfig, ToolDefinition, FlashDefinitionFile='', Fds=None, Fvs=None, Caps=None, SkuId='', UniFlag=None,\r
319               Progress=None, BuildModule=None):\r
320         self.BuildDatabase  = MetaFileDb\r
321         self.MetaFile       = ActivePlatform\r
322         self.WorkspaceDir   = WorkspaceDir\r
323         self.Platform       = self.BuildDatabase[self.MetaFile, TAB_ARCH_COMMON, Target, Toolchain]\r
324         GlobalData.gActivePlatform = self.Platform\r
325         self.BuildTarget    = Target\r
326         self.ToolChain      = Toolchain\r
327         self.ArchList       = ArchList\r
328         self.SkuId          = SkuId\r
329         self.UniFlag        = UniFlag\r
330 \r
331         self.TargetTxt      = BuildConfig\r
332         self.ToolDef        = ToolDefinition\r
333         self.FdfFile        = FlashDefinitionFile\r
334         self.FdTargetList   = Fds if Fds else []\r
335         self.FvTargetList   = Fvs if Fvs else []\r
336         self.CapTargetList  = Caps if Caps else []\r
337         self.AutoGenObjectList = []\r
338         self._GuidDict = {}\r
339 \r
340         # there's many relative directory operations, so ...\r
341         os.chdir(self.WorkspaceDir)\r
342 \r
343         #\r
344         # Merge Arch\r
345         #\r
346         if not self.ArchList:\r
347             ArchList = set(self.Platform.SupArchList)\r
348         else:\r
349             ArchList = set(self.ArchList) & set(self.Platform.SupArchList)\r
350         if not ArchList:\r
351             EdkLogger.error("build", PARAMETER_INVALID,\r
352                             ExtraData = "Invalid ARCH specified. [Valid ARCH: %s]" % (" ".join(self.Platform.SupArchList)))\r
353         elif self.ArchList and len(ArchList) != len(self.ArchList):\r
354             SkippedArchList = set(self.ArchList).symmetric_difference(set(self.Platform.SupArchList))\r
355             EdkLogger.verbose("\nArch [%s] is ignored because the platform supports [%s] only!"\r
356                               % (" ".join(SkippedArchList), " ".join(self.Platform.SupArchList)))\r
357         self.ArchList = tuple(ArchList)\r
358 \r
359         # Validate build target\r
360         if self.BuildTarget not in self.Platform.BuildTargets:\r
361             EdkLogger.error("build", PARAMETER_INVALID,\r
362                             ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"\r
363                                       % (self.BuildTarget, " ".join(self.Platform.BuildTargets)))\r
364 \r
365 \r
366         # parse FDF file to get PCDs in it, if any\r
367         if not self.FdfFile:\r
368             self.FdfFile = self.Platform.FlashDefinition\r
369 \r
370         EdkLogger.info("")\r
371         if self.ArchList:\r
372             EdkLogger.info('%-16s = %s' % ("Architecture(s)", ' '.join(self.ArchList)))\r
373         EdkLogger.info('%-16s = %s' % ("Build target", self.BuildTarget))\r
374         EdkLogger.info('%-16s = %s' % ("Toolchain", self.ToolChain))\r
375 \r
376         EdkLogger.info('\n%-24s = %s' % ("Active Platform", self.Platform))\r
377         if BuildModule:\r
378             EdkLogger.info('%-24s = %s' % ("Active Module", BuildModule))\r
379 \r
380         if self.FdfFile:\r
381             EdkLogger.info('%-24s = %s' % ("Flash Image Definition", self.FdfFile))\r
382 \r
383         EdkLogger.verbose("\nFLASH_DEFINITION = %s" % self.FdfFile)\r
384 \r
385         if Progress:\r
386             Progress.Start("\nProcessing meta-data")\r
387 \r
388         if self.FdfFile:\r
389             #\r
390             # Mark now build in AutoGen Phase\r
391             #\r
392             GlobalData.gAutoGenPhase = True\r
393             Fdf = FdfParser(self.FdfFile.Path)\r
394             Fdf.ParseFile()\r
395             GlobalData.gFdfParser = Fdf\r
396             GlobalData.gAutoGenPhase = False\r
397             PcdSet = Fdf.Profile.PcdDict\r
398             if Fdf.CurrentFdName and Fdf.CurrentFdName in Fdf.Profile.FdDict:\r
399                 FdDict = Fdf.Profile.FdDict[Fdf.CurrentFdName]\r
400                 for FdRegion in FdDict.RegionList:\r
401                     if str(FdRegion.RegionType) is 'FILE' and self.Platform.VpdToolGuid in str(FdRegion.RegionDataList):\r
402                         if int(FdRegion.Offset) % 8 != 0:\r
403                             EdkLogger.error("build", FORMAT_INVALID, 'The VPD Base Address %s must be 8-byte aligned.' % (FdRegion.Offset))\r
404             ModuleList = Fdf.Profile.InfList\r
405             self.FdfProfile = Fdf.Profile\r
406             for fvname in self.FvTargetList:\r
407                 if fvname.upper() not in self.FdfProfile.FvDict:\r
408                     EdkLogger.error("build", OPTION_VALUE_INVALID,\r
409                                     "No such an FV in FDF file: %s" % fvname)\r
410 \r
411             # In DSC file may use FILE_GUID to override the module, then in the Platform.Modules use FILE_GUIDmodule.inf as key,\r
412             # but the path (self.MetaFile.Path) is the real path\r
413             for key in self.FdfProfile.InfDict:\r
414                 if key == 'ArchTBD':\r
415                     MetaFile_cache = defaultdict(set)\r
416                     for Arch in self.ArchList:\r
417                         Current_Platform_cache = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
418                         for Pkey in Current_Platform_cache.Modules:\r
419                             MetaFile_cache[Arch].add(Current_Platform_cache.Modules[Pkey].MetaFile)\r
420                     for Inf in self.FdfProfile.InfDict[key]:\r
421                         ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
422                         for Arch in self.ArchList:\r
423                             if ModuleFile in MetaFile_cache[Arch]:\r
424                                 break\r
425                         else:\r
426                             ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
427                             if not ModuleData.IsBinaryModule:\r
428                                 EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
429 \r
430                 else:\r
431                     for Arch in self.ArchList:\r
432                         if Arch == key:\r
433                             Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
434                             MetaFileList = set()\r
435                             for Pkey in Platform.Modules:\r
436                                 MetaFileList.add(Platform.Modules[Pkey].MetaFile)\r
437                             for Inf in self.FdfProfile.InfDict[key]:\r
438                                 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
439                                 if ModuleFile in MetaFileList:\r
440                                     continue\r
441                                 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
442                                 if not ModuleData.IsBinaryModule:\r
443                                     EdkLogger.error('build', PARSER_ERROR, "Module %s NOT found in DSC file; Is it really a binary module?" % ModuleFile)\r
444 \r
445         else:\r
446             PcdSet = {}\r
447             ModuleList = []\r
448             self.FdfProfile = None\r
449             if self.FdTargetList:\r
450                 EdkLogger.info("No flash definition file found. FD [%s] will be ignored." % " ".join(self.FdTargetList))\r
451                 self.FdTargetList = []\r
452             if self.FvTargetList:\r
453                 EdkLogger.info("No flash definition file found. FV [%s] will be ignored." % " ".join(self.FvTargetList))\r
454                 self.FvTargetList = []\r
455             if self.CapTargetList:\r
456                 EdkLogger.info("No flash definition file found. Capsule [%s] will be ignored." % " ".join(self.CapTargetList))\r
457                 self.CapTargetList = []\r
458 \r
459         # apply SKU and inject PCDs from Flash Definition file\r
460         for Arch in self.ArchList:\r
461             Platform = self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]\r
462             PlatformPcds = Platform.Pcds\r
463             self._GuidDict = Platform._GuidDict\r
464             SourcePcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set(),TAB_PCDS_DYNAMIC:set(),TAB_PCDS_FIXED_AT_BUILD:set()}\r
465             BinaryPcdDict = {TAB_PCDS_DYNAMIC_EX:set(), TAB_PCDS_PATCHABLE_IN_MODULE:set()}\r
466             SourcePcdDict_Keys = SourcePcdDict.keys()\r
467             BinaryPcdDict_Keys = BinaryPcdDict.keys()\r
468 \r
469             # generate the SourcePcdDict and BinaryPcdDict\r
470             PGen = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
471             for BuildData in list(PGen.BuildDatabase._CACHE_.values()):\r
472                 if BuildData.Arch != Arch:\r
473                     continue\r
474                 if BuildData.MetaFile.Ext == '.inf':\r
475                     for key in BuildData.Pcds:\r
476                         if BuildData.Pcds[key].Pending:\r
477                             if key in Platform.Pcds:\r
478                                 PcdInPlatform = Platform.Pcds[key]\r
479                                 if PcdInPlatform.Type:\r
480                                     BuildData.Pcds[key].Type = PcdInPlatform.Type\r
481                                     BuildData.Pcds[key].Pending = False\r
482 \r
483                             if BuildData.MetaFile in Platform.Modules:\r
484                                 PlatformModule = Platform.Modules[str(BuildData.MetaFile)]\r
485                                 if key in PlatformModule.Pcds:\r
486                                     PcdInPlatform = PlatformModule.Pcds[key]\r
487                                     if PcdInPlatform.Type:\r
488                                         BuildData.Pcds[key].Type = PcdInPlatform.Type\r
489                                         BuildData.Pcds[key].Pending = False\r
490                             else:\r
491                                 #Pcd used in Library, Pcd Type from reference module if Pcd Type is Pending\r
492                                 if BuildData.Pcds[key].Pending:\r
493                                     MGen = ModuleAutoGen(self, BuildData.MetaFile, Target, Toolchain, Arch, self.MetaFile)\r
494                                     if MGen and MGen.IsLibrary:\r
495                                         if MGen in PGen.LibraryAutoGenList:\r
496                                             ReferenceModules = MGen.ReferenceModules\r
497                                             for ReferenceModule in ReferenceModules:\r
498                                                 if ReferenceModule.MetaFile in Platform.Modules:\r
499                                                     RefPlatformModule = Platform.Modules[str(ReferenceModule.MetaFile)]\r
500                                                     if key in RefPlatformModule.Pcds:\r
501                                                         PcdInReferenceModule = RefPlatformModule.Pcds[key]\r
502                                                         if PcdInReferenceModule.Type:\r
503                                                             BuildData.Pcds[key].Type = PcdInReferenceModule.Type\r
504                                                             BuildData.Pcds[key].Pending = False\r
505                                                             break\r
506 \r
507                         if TAB_PCDS_DYNAMIC_EX in BuildData.Pcds[key].Type:\r
508                             if BuildData.IsBinaryModule:\r
509                                 BinaryPcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
510                             else:\r
511                                 SourcePcdDict[TAB_PCDS_DYNAMIC_EX].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
512 \r
513                         elif TAB_PCDS_PATCHABLE_IN_MODULE in BuildData.Pcds[key].Type:\r
514                             if BuildData.MetaFile.Ext == '.inf':\r
515                                 if BuildData.IsBinaryModule:\r
516                                     BinaryPcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
517                                 else:\r
518                                     SourcePcdDict[TAB_PCDS_PATCHABLE_IN_MODULE].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
519 \r
520                         elif TAB_PCDS_DYNAMIC in BuildData.Pcds[key].Type:\r
521                             SourcePcdDict[TAB_PCDS_DYNAMIC].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
522                         elif TAB_PCDS_FIXED_AT_BUILD in BuildData.Pcds[key].Type:\r
523                             SourcePcdDict[TAB_PCDS_FIXED_AT_BUILD].add((BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName))\r
524                 else:\r
525                     pass\r
526             #\r
527             # A PCD can only use one type for all source modules\r
528             #\r
529             for i in SourcePcdDict_Keys:\r
530                 for j in SourcePcdDict_Keys:\r
531                     if i != j:\r
532                         Intersections = SourcePcdDict[i].intersection(SourcePcdDict[j])\r
533                         if len(Intersections) > 0:\r
534                             EdkLogger.error(\r
535                             'build',\r
536                             FORMAT_INVALID,\r
537                             "Building modules from source INFs, following PCD use %s and %s access method. It must be corrected to use only one access method." % (i, j),\r
538                             ExtraData='\n\t'.join(str(P[1]+'.'+P[0]) for P in Intersections)\r
539                             )\r
540 \r
541             #\r
542             # intersection the BinaryPCD for Mixed PCD\r
543             #\r
544             for i in BinaryPcdDict_Keys:\r
545                 for j in BinaryPcdDict_Keys:\r
546                     if i != j:\r
547                         Intersections = BinaryPcdDict[i].intersection(BinaryPcdDict[j])\r
548                         for item in Intersections:\r
549                             NewPcd1 = (item[0] + '_' + i, item[1])\r
550                             NewPcd2 = (item[0] + '_' + j, item[1])\r
551                             if item not in GlobalData.MixedPcd:\r
552                                 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
553                             else:\r
554                                 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
555                                     GlobalData.MixedPcd[item].append(NewPcd1)\r
556                                 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
557                                     GlobalData.MixedPcd[item].append(NewPcd2)\r
558 \r
559             #\r
560             # intersection the SourcePCD and BinaryPCD for Mixed PCD\r
561             #\r
562             for i in SourcePcdDict_Keys:\r
563                 for j in BinaryPcdDict_Keys:\r
564                     if i != j:\r
565                         Intersections = SourcePcdDict[i].intersection(BinaryPcdDict[j])\r
566                         for item in Intersections:\r
567                             NewPcd1 = (item[0] + '_' + i, item[1])\r
568                             NewPcd2 = (item[0] + '_' + j, item[1])\r
569                             if item not in GlobalData.MixedPcd:\r
570                                 GlobalData.MixedPcd[item] = [NewPcd1, NewPcd2]\r
571                             else:\r
572                                 if NewPcd1 not in GlobalData.MixedPcd[item]:\r
573                                     GlobalData.MixedPcd[item].append(NewPcd1)\r
574                                 if NewPcd2 not in GlobalData.MixedPcd[item]:\r
575                                     GlobalData.MixedPcd[item].append(NewPcd2)\r
576 \r
577             for BuildData in list(PGen.BuildDatabase._CACHE_.values()):\r
578                 if BuildData.Arch != Arch:\r
579                     continue\r
580                 for key in BuildData.Pcds:\r
581                     for SinglePcd in GlobalData.MixedPcd:\r
582                         if (BuildData.Pcds[key].TokenCName, BuildData.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
583                             for item in GlobalData.MixedPcd[SinglePcd]:\r
584                                 Pcd_Type = item[0].split('_')[-1]\r
585                                 if (Pcd_Type == BuildData.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and BuildData.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \\r
586                                    (Pcd_Type == TAB_PCDS_DYNAMIC and BuildData.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):\r
587                                     Value = BuildData.Pcds[key]\r
588                                     Value.TokenCName = BuildData.Pcds[key].TokenCName + '_' + Pcd_Type\r
589                                     if len(key) == 2:\r
590                                         newkey = (Value.TokenCName, key[1])\r
591                                     elif len(key) == 3:\r
592                                         newkey = (Value.TokenCName, key[1], key[2])\r
593                                     del BuildData.Pcds[key]\r
594                                     BuildData.Pcds[newkey] = Value\r
595                                     break\r
596                             break\r
597 \r
598             # handle the mixed pcd in FDF file\r
599             for key in PcdSet:\r
600                 if key in GlobalData.MixedPcd:\r
601                     Value = PcdSet[key]\r
602                     del PcdSet[key]\r
603                     for item in GlobalData.MixedPcd[key]:\r
604                         PcdSet[item] = Value\r
605 \r
606             #Collect package set information from INF of FDF\r
607             PkgSet = set()\r
608             for Inf in ModuleList:\r
609                 ModuleFile = PathClass(NormPath(Inf), GlobalData.gWorkspace, Arch)\r
610                 if ModuleFile in Platform.Modules:\r
611                     continue\r
612                 ModuleData = self.BuildDatabase[ModuleFile, Arch, Target, Toolchain]\r
613                 PkgSet.update(ModuleData.Packages)\r
614             Pkgs = list(PkgSet) + list(PGen.PackageList)\r
615             DecPcds = set()\r
616             DecPcdsKey = set()\r
617             for Pkg in Pkgs:\r
618                 for Pcd in Pkg.Pcds:\r
619                     DecPcds.add((Pcd[0], Pcd[1]))\r
620                     DecPcdsKey.add((Pcd[0], Pcd[1], Pcd[2]))\r
621 \r
622             Platform.SkuName = self.SkuId\r
623             for Name, Guid,Fileds in PcdSet:\r
624                 if (Name, Guid) not in DecPcds:\r
625                     EdkLogger.error(\r
626                         'build',\r
627                         PARSER_ERROR,\r
628                         "PCD (%s.%s) used in FDF is not declared in DEC files." % (Guid, Name),\r
629                         File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],\r
630                         Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]\r
631                     )\r
632                 else:\r
633                     # Check whether Dynamic or DynamicEx PCD used in FDF file. If used, build break and give a error message.\r
634                     if (Name, Guid, TAB_PCDS_FIXED_AT_BUILD) in DecPcdsKey \\r
635                         or (Name, Guid, TAB_PCDS_PATCHABLE_IN_MODULE) in DecPcdsKey \\r
636                         or (Name, Guid, TAB_PCDS_FEATURE_FLAG) in DecPcdsKey:\r
637                         continue\r
638                     elif (Name, Guid, TAB_PCDS_DYNAMIC) in DecPcdsKey or (Name, Guid, TAB_PCDS_DYNAMIC_EX) in DecPcdsKey:\r
639                         EdkLogger.error(\r
640                                 'build',\r
641                                 PARSER_ERROR,\r
642                                 "Using Dynamic or DynamicEx type of PCD [%s.%s] in FDF file is not allowed." % (Guid, Name),\r
643                                 File = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][0],\r
644                                 Line = self.FdfProfile.PcdFileLineDict[Name, Guid, Fileds][1]\r
645                         )\r
646 \r
647             Pa = PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch)\r
648             #\r
649             # Explicitly collect platform's dynamic PCDs\r
650             #\r
651             Pa.CollectPlatformDynamicPcds()\r
652             Pa.CollectFixedAtBuildPcds()\r
653             self.AutoGenObjectList.append(Pa)\r
654 \r
655             #\r
656             # Generate Package level hash value\r
657             #\r
658             GlobalData.gPackageHash = {}\r
659             if GlobalData.gUseHashCache:\r
660                 for Pkg in Pkgs:\r
661                     self._GenPkgLevelHash(Pkg)\r
662 \r
663         #\r
664         # Check PCDs token value conflict in each DEC file.\r
665         #\r
666         self._CheckAllPcdsTokenValueConflict()\r
667 \r
668         #\r
669         # Check PCD type and definition between DSC and DEC\r
670         #\r
671         self._CheckPcdDefineAndType()\r
672 \r
673         #\r
674         # Create BuildOptions Macro & PCD metafile, also add the Active Platform and FDF file.\r
675         #\r
676         content = 'gCommandLineDefines: '\r
677         content += str(GlobalData.gCommandLineDefines)\r
678         content += TAB_LINE_BREAK\r
679         content += 'BuildOptionPcd: '\r
680         content += str(GlobalData.BuildOptionPcd)\r
681         content += TAB_LINE_BREAK\r
682         content += 'Active Platform: '\r
683         content += str(self.Platform)\r
684         content += TAB_LINE_BREAK\r
685         if self.FdfFile:\r
686             content += 'Flash Image Definition: '\r
687             content += str(self.FdfFile)\r
688             content += TAB_LINE_BREAK\r
689         SaveFileOnChange(os.path.join(self.BuildDir, 'BuildOptions'), content, False)\r
690 \r
691         #\r
692         # Create PcdToken Number file for Dynamic/DynamicEx Pcd.\r
693         #\r
694         PcdTokenNumber = 'PcdTokenNumber: '\r
695         if Pa.PcdTokenNumber:\r
696             if Pa.DynamicPcdList:\r
697                 for Pcd in Pa.DynamicPcdList:\r
698                     PcdTokenNumber += TAB_LINE_BREAK\r
699                     PcdTokenNumber += str((Pcd.TokenCName, Pcd.TokenSpaceGuidCName))\r
700                     PcdTokenNumber += ' : '\r
701                     PcdTokenNumber += str(Pa.PcdTokenNumber[Pcd.TokenCName, Pcd.TokenSpaceGuidCName])\r
702         SaveFileOnChange(os.path.join(self.BuildDir, 'PcdTokenNumber'), PcdTokenNumber, False)\r
703 \r
704         #\r
705         # Get set of workspace metafiles\r
706         #\r
707         AllWorkSpaceMetaFiles = self._GetMetaFiles(Target, Toolchain, Arch)\r
708 \r
709         #\r
710         # Retrieve latest modified time of all metafiles\r
711         #\r
712         SrcTimeStamp = 0\r
713         for f in AllWorkSpaceMetaFiles:\r
714             if os.stat(f)[8] > SrcTimeStamp:\r
715                 SrcTimeStamp = os.stat(f)[8]\r
716         self._SrcTimeStamp = SrcTimeStamp\r
717 \r
718         if GlobalData.gUseHashCache:\r
719             m = hashlib.md5()\r
720             for files in AllWorkSpaceMetaFiles:\r
721                 if files.endswith('.dec'):\r
722                     continue\r
723                 f = open(files, 'rb')\r
724                 Content = f.read()\r
725                 f.close()\r
726                 m.update(Content)\r
727             SaveFileOnChange(os.path.join(self.BuildDir, 'AutoGen.hash'), m.hexdigest(), False)\r
728             GlobalData.gPlatformHash = m.hexdigest()\r
729 \r
730         #\r
731         # Write metafile list to build directory\r
732         #\r
733         AutoGenFilePath = os.path.join(self.BuildDir, 'AutoGen')\r
734         if os.path.exists (AutoGenFilePath):\r
735             os.remove(AutoGenFilePath)\r
736         if not os.path.exists(self.BuildDir):\r
737             os.makedirs(self.BuildDir)\r
738         with open(os.path.join(self.BuildDir, 'AutoGen'), 'w+') as file:\r
739             for f in AllWorkSpaceMetaFiles:\r
740                 print(f, file=file)\r
741         return True\r
742 \r
743     def _GenPkgLevelHash(self, Pkg):\r
744         if Pkg.PackageName in GlobalData.gPackageHash:\r
745             return\r
746 \r
747         PkgDir = os.path.join(self.BuildDir, Pkg.Arch, Pkg.PackageName)\r
748         CreateDirectory(PkgDir)\r
749         HashFile = os.path.join(PkgDir, Pkg.PackageName + '.hash')\r
750         m = hashlib.md5()\r
751         # Get .dec file's hash value\r
752         f = open(Pkg.MetaFile.Path, 'rb')\r
753         Content = f.read()\r
754         f.close()\r
755         m.update(Content)\r
756         # Get include files hash value\r
757         if Pkg.Includes:\r
758             for inc in sorted(Pkg.Includes, key=lambda x: str(x)):\r
759                 for Root, Dirs, Files in os.walk(str(inc)):\r
760                     for File in sorted(Files):\r
761                         File_Path = os.path.join(Root, File)\r
762                         f = open(File_Path, 'rb')\r
763                         Content = f.read()\r
764                         f.close()\r
765                         m.update(Content)\r
766         SaveFileOnChange(HashFile, m.hexdigest(), False)\r
767         GlobalData.gPackageHash[Pkg.PackageName] = m.hexdigest()\r
768 \r
769     def _GetMetaFiles(self, Target, Toolchain, Arch):\r
770         AllWorkSpaceMetaFiles = set()\r
771         #\r
772         # add fdf\r
773         #\r
774         if self.FdfFile:\r
775             AllWorkSpaceMetaFiles.add (self.FdfFile.Path)\r
776             for f in GlobalData.gFdfParser.GetAllIncludedFile():\r
777                 AllWorkSpaceMetaFiles.add (f.FileName)\r
778         #\r
779         # add dsc\r
780         #\r
781         AllWorkSpaceMetaFiles.add(self.MetaFile.Path)\r
782 \r
783         #\r
784         # add build_rule.txt & tools_def.txt\r
785         #\r
786         AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultBuildRuleFile))\r
787         AllWorkSpaceMetaFiles.add(os.path.join(GlobalData.gConfDirectory, gDefaultToolsDefFile))\r
788 \r
789         # add BuildOption metafile\r
790         #\r
791         AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'BuildOptions'))\r
792 \r
793         # add PcdToken Number file for Dynamic/DynamicEx Pcd\r
794         #\r
795         AllWorkSpaceMetaFiles.add(os.path.join(self.BuildDir, 'PcdTokenNumber'))\r
796 \r
797         for Arch in self.ArchList:\r
798             #\r
799             # add dec\r
800             #\r
801             for Package in PlatformAutoGen(self, self.MetaFile, Target, Toolchain, Arch).PackageList:\r
802                 AllWorkSpaceMetaFiles.add(Package.MetaFile.Path)\r
803 \r
804             #\r
805             # add included dsc\r
806             #\r
807             for filePath in self.BuildDatabase[self.MetaFile, Arch, Target, Toolchain]._RawData.IncludedFiles:\r
808                 AllWorkSpaceMetaFiles.add(filePath.Path)\r
809 \r
810         return AllWorkSpaceMetaFiles\r
811 \r
812     def _CheckPcdDefineAndType(self):\r
813         PcdTypeSet = {TAB_PCDS_FIXED_AT_BUILD,\r
814             TAB_PCDS_PATCHABLE_IN_MODULE,\r
815             TAB_PCDS_FEATURE_FLAG,\r
816             TAB_PCDS_DYNAMIC,\r
817             TAB_PCDS_DYNAMIC_EX}\r
818 \r
819         # This dict store PCDs which are not used by any modules with specified arches\r
820         UnusedPcd = OrderedDict()\r
821         for Pa in self.AutoGenObjectList:\r
822             # Key of DSC's Pcds dictionary is PcdCName, TokenSpaceGuid\r
823             for Pcd in Pa.Platform.Pcds:\r
824                 PcdType = Pa.Platform.Pcds[Pcd].Type\r
825 \r
826                 # If no PCD type, this PCD comes from FDF\r
827                 if not PcdType:\r
828                     continue\r
829 \r
830                 # Try to remove Hii and Vpd suffix\r
831                 if PcdType.startswith(TAB_PCDS_DYNAMIC_EX):\r
832                     PcdType = TAB_PCDS_DYNAMIC_EX\r
833                 elif PcdType.startswith(TAB_PCDS_DYNAMIC):\r
834                     PcdType = TAB_PCDS_DYNAMIC\r
835 \r
836                 for Package in Pa.PackageList:\r
837                     # Key of DEC's Pcds dictionary is PcdCName, TokenSpaceGuid, PcdType\r
838                     if (Pcd[0], Pcd[1], PcdType) in Package.Pcds:\r
839                         break\r
840                     for Type in PcdTypeSet:\r
841                         if (Pcd[0], Pcd[1], Type) in Package.Pcds:\r
842                             EdkLogger.error(\r
843                                 'build',\r
844                                 FORMAT_INVALID,\r
845                                 "Type [%s] of PCD [%s.%s] in DSC file doesn't match the type [%s] defined in DEC file." \\r
846                                 % (Pa.Platform.Pcds[Pcd].Type, Pcd[1], Pcd[0], Type),\r
847                                 ExtraData=None\r
848                             )\r
849                             return\r
850                 else:\r
851                     UnusedPcd.setdefault(Pcd, []).append(Pa.Arch)\r
852 \r
853         for Pcd in UnusedPcd:\r
854             EdkLogger.warn(\r
855                 'build',\r
856                 "The PCD was not specified by any INF module in the platform for the given architecture.\n"\r
857                 "\tPCD: [%s.%s]\n\tPlatform: [%s]\n\tArch: %s"\r
858                 % (Pcd[1], Pcd[0], os.path.basename(str(self.MetaFile)), str(UnusedPcd[Pcd])),\r
859                 ExtraData=None\r
860             )\r
861 \r
862     def __repr__(self):\r
863         return "%s [%s]" % (self.MetaFile, ", ".join(self.ArchList))\r
864 \r
865     ## Return the directory to store FV files\r
866     @cached_property\r
867     def FvDir(self):\r
868         return path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
869 \r
870     ## Return the directory to store all intermediate and final files built\r
871     @cached_property\r
872     def BuildDir(self):\r
873         return self.AutoGenObjectList[0].BuildDir\r
874 \r
875     ## Return the build output directory platform specifies\r
876     @cached_property\r
877     def OutputDir(self):\r
878         return self.Platform.OutputDirectory\r
879 \r
880     ## Return platform name\r
881     @cached_property\r
882     def Name(self):\r
883         return self.Platform.PlatformName\r
884 \r
885     ## Return meta-file GUID\r
886     @cached_property\r
887     def Guid(self):\r
888         return self.Platform.Guid\r
889 \r
890     ## Return platform version\r
891     @cached_property\r
892     def Version(self):\r
893         return self.Platform.Version\r
894 \r
895     ## Return paths of tools\r
896     @cached_property\r
897     def ToolDefinition(self):\r
898         return self.AutoGenObjectList[0].ToolDefinition\r
899 \r
900     ## Return directory of platform makefile\r
901     #\r
902     #   @retval     string  Makefile directory\r
903     #\r
904     @cached_property\r
905     def MakeFileDir(self):\r
906         return self.BuildDir\r
907 \r
908     ## Return build command string\r
909     #\r
910     #   @retval     string  Build command string\r
911     #\r
912     @cached_property\r
913     def BuildCommand(self):\r
914         # BuildCommand should be all the same. So just get one from platform AutoGen\r
915         return self.AutoGenObjectList[0].BuildCommand\r
916 \r
917     ## Check the PCDs token value conflict in each DEC file.\r
918     #\r
919     # Will cause build break and raise error message while two PCDs conflict.\r
920     #\r
921     # @return  None\r
922     #\r
923     def _CheckAllPcdsTokenValueConflict(self):\r
924         for Pa in self.AutoGenObjectList:\r
925             for Package in Pa.PackageList:\r
926                 PcdList = list(Package.Pcds.values())\r
927                 PcdList.sort(key=lambda x: int(x.TokenValue, 0))\r
928                 Count = 0\r
929                 while (Count < len(PcdList) - 1) :\r
930                     Item = PcdList[Count]\r
931                     ItemNext = PcdList[Count + 1]\r
932                     #\r
933                     # Make sure in the same token space the TokenValue should be unique\r
934                     #\r
935                     if (int(Item.TokenValue, 0) == int(ItemNext.TokenValue, 0)):\r
936                         SameTokenValuePcdList = []\r
937                         SameTokenValuePcdList.append(Item)\r
938                         SameTokenValuePcdList.append(ItemNext)\r
939                         RemainPcdListLength = len(PcdList) - Count - 2\r
940                         for ValueSameCount in range(RemainPcdListLength):\r
941                             if int(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount].TokenValue, 0) == int(Item.TokenValue, 0):\r
942                                 SameTokenValuePcdList.append(PcdList[len(PcdList) - RemainPcdListLength + ValueSameCount])\r
943                             else:\r
944                                 break;\r
945                         #\r
946                         # Sort same token value PCD list with TokenGuid and TokenCName\r
947                         #\r
948                         SameTokenValuePcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))\r
949                         SameTokenValuePcdListCount = 0\r
950                         while (SameTokenValuePcdListCount < len(SameTokenValuePcdList) - 1):\r
951                             Flag = False\r
952                             TemListItem = SameTokenValuePcdList[SameTokenValuePcdListCount]\r
953                             TemListItemNext = SameTokenValuePcdList[SameTokenValuePcdListCount + 1]\r
954 \r
955                             if (TemListItem.TokenSpaceGuidCName == TemListItemNext.TokenSpaceGuidCName) and (TemListItem.TokenCName != TemListItemNext.TokenCName):\r
956                                 for PcdItem in GlobalData.MixedPcd:\r
957                                     if (TemListItem.TokenCName, TemListItem.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem] or \\r
958                                         (TemListItemNext.TokenCName, TemListItemNext.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
959                                         Flag = True\r
960                                 if not Flag:\r
961                                     EdkLogger.error(\r
962                                                 'build',\r
963                                                 FORMAT_INVALID,\r
964                                                 "The TokenValue [%s] of PCD [%s.%s] is conflict with: [%s.%s] in %s"\\r
965                                                 % (TemListItem.TokenValue, TemListItem.TokenSpaceGuidCName, TemListItem.TokenCName, TemListItemNext.TokenSpaceGuidCName, TemListItemNext.TokenCName, Package),\r
966                                                 ExtraData=None\r
967                                                 )\r
968                             SameTokenValuePcdListCount += 1\r
969                         Count += SameTokenValuePcdListCount\r
970                     Count += 1\r
971 \r
972                 PcdList = list(Package.Pcds.values())\r
973                 PcdList.sort(key=lambda x: "%s.%s" % (x.TokenSpaceGuidCName, x.TokenCName))\r
974                 Count = 0\r
975                 while (Count < len(PcdList) - 1) :\r
976                     Item = PcdList[Count]\r
977                     ItemNext = PcdList[Count + 1]\r
978                     #\r
979                     # Check PCDs with same TokenSpaceGuidCName.TokenCName have same token value as well.\r
980                     #\r
981                     if (Item.TokenSpaceGuidCName == ItemNext.TokenSpaceGuidCName) and (Item.TokenCName == ItemNext.TokenCName) and (int(Item.TokenValue, 0) != int(ItemNext.TokenValue, 0)):\r
982                         EdkLogger.error(\r
983                                     'build',\r
984                                     FORMAT_INVALID,\r
985                                     "The TokenValue [%s] of PCD [%s.%s] in %s defined in two places should be same as well."\\r
986                                     % (Item.TokenValue, Item.TokenSpaceGuidCName, Item.TokenCName, Package),\r
987                                     ExtraData=None\r
988                                     )\r
989                     Count += 1\r
990     ## Generate fds command\r
991     @property\r
992     def GenFdsCommand(self):\r
993         return (GenMake.TopLevelMakefile(self)._TEMPLATE_.Replace(GenMake.TopLevelMakefile(self)._TemplateDict)).strip()\r
994 \r
995     @property\r
996     def GenFdsCommandDict(self):\r
997         FdsCommandDict = {}\r
998         LogLevel = EdkLogger.GetLevel()\r
999         if LogLevel == EdkLogger.VERBOSE:\r
1000             FdsCommandDict["verbose"] = True\r
1001         elif LogLevel <= EdkLogger.DEBUG_9:\r
1002             FdsCommandDict["debug"] = LogLevel - 1\r
1003         elif LogLevel == EdkLogger.QUIET:\r
1004             FdsCommandDict["quiet"] = True\r
1005 \r
1006         if GlobalData.gEnableGenfdsMultiThread:\r
1007             FdsCommandDict["GenfdsMultiThread"] = True\r
1008         if GlobalData.gIgnoreSource:\r
1009             FdsCommandDict["IgnoreSources"] = True\r
1010 \r
1011         FdsCommandDict["OptionPcd"] = []\r
1012         for pcd in GlobalData.BuildOptionPcd:\r
1013             if pcd[2]:\r
1014                 pcdname = '.'.join(pcd[0:3])\r
1015             else:\r
1016                 pcdname = '.'.join(pcd[0:2])\r
1017             if pcd[3].startswith('{'):\r
1018                 FdsCommandDict["OptionPcd"].append(pcdname + '=' + 'H' + '"' + pcd[3] + '"')\r
1019             else:\r
1020                 FdsCommandDict["OptionPcd"].append(pcdname + '=' + pcd[3])\r
1021 \r
1022         MacroList = []\r
1023         # macros passed to GenFds\r
1024         MacroDict = {}\r
1025         MacroDict.update(GlobalData.gGlobalDefines)\r
1026         MacroDict.update(GlobalData.gCommandLineDefines)\r
1027         for MacroName in MacroDict:\r
1028             if MacroDict[MacroName] != "":\r
1029                 MacroList.append('"%s=%s"' % (MacroName, MacroDict[MacroName].replace('\\', '\\\\')))\r
1030             else:\r
1031                 MacroList.append('"%s"' % MacroName)\r
1032         FdsCommandDict["macro"] = MacroList\r
1033 \r
1034         FdsCommandDict["fdf_file"] = [self.FdfFile]\r
1035         FdsCommandDict["build_target"] = self.BuildTarget\r
1036         FdsCommandDict["toolchain_tag"] = self.ToolChain\r
1037         FdsCommandDict["active_platform"] = str(self)\r
1038 \r
1039         FdsCommandDict["conf_directory"] = GlobalData.gConfDirectory\r
1040         FdsCommandDict["build_architecture_list"] = ','.join(self.ArchList)\r
1041         FdsCommandDict["platform_build_directory"] = self.BuildDir\r
1042 \r
1043         FdsCommandDict["fd"] = self.FdTargetList\r
1044         FdsCommandDict["fv"] = self.FvTargetList\r
1045         FdsCommandDict["cap"] = self.CapTargetList\r
1046         return FdsCommandDict\r
1047 \r
1048     ## Create makefile for the platform and modules in it\r
1049     #\r
1050     #   @param      CreateDepsMakeFile      Flag indicating if the makefile for\r
1051     #                                       modules will be created as well\r
1052     #\r
1053     def CreateMakeFile(self, CreateDepsMakeFile=False):\r
1054         if not CreateDepsMakeFile:\r
1055             return\r
1056         for Pa in self.AutoGenObjectList:\r
1057             Pa.CreateMakeFile(True)\r
1058 \r
1059     ## Create autogen code for platform and modules\r
1060     #\r
1061     #  Since there's no autogen code for platform, this method will do nothing\r
1062     #  if CreateModuleCodeFile is set to False.\r
1063     #\r
1064     #   @param      CreateDepsCodeFile      Flag indicating if creating module's\r
1065     #                                       autogen code file or not\r
1066     #\r
1067     def CreateCodeFile(self, CreateDepsCodeFile=False):\r
1068         if not CreateDepsCodeFile:\r
1069             return\r
1070         for Pa in self.AutoGenObjectList:\r
1071             Pa.CreateCodeFile(True)\r
1072 \r
1073     ## Create AsBuilt INF file the platform\r
1074     #\r
1075     def CreateAsBuiltInf(self):\r
1076         return\r
1077 \r
1078 \r
1079 ## AutoGen class for platform\r
1080 #\r
1081 #  PlatformAutoGen class will process the original information in platform\r
1082 #  file in order to generate makefile for platform.\r
1083 #\r
1084 class PlatformAutoGen(AutoGen):\r
1085     # call super().__init__ then call the worker function with different parameter count\r
1086     def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
1087         if not hasattr(self, "_Init"):\r
1088             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
1089             self._Init = True\r
1090     #\r
1091     # Used to store all PCDs for both PEI and DXE phase, in order to generate\r
1092     # correct PCD database\r
1093     #\r
1094     _DynaPcdList_ = []\r
1095     _NonDynaPcdList_ = []\r
1096     _PlatformPcds = {}\r
1097 \r
1098     #\r
1099     # The priority list while override build option\r
1100     #\r
1101     PrioList = {"0x11111"  : 16,     #  TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE (Highest)\r
1102                 "0x01111"  : 15,     #  ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
1103                 "0x10111"  : 14,     #  TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
1104                 "0x00111"  : 13,     #  ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE\r
1105                 "0x11011"  : 12,     #  TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
1106                 "0x01011"  : 11,     #  ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE\r
1107                 "0x10011"  : 10,     #  TARGET_*********_****_COMMANDTYPE_ATTRIBUTE\r
1108                 "0x00011"  : 9,      #  ******_*********_****_COMMANDTYPE_ATTRIBUTE\r
1109                 "0x11101"  : 8,      #  TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
1110                 "0x01101"  : 7,      #  ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE\r
1111                 "0x10101"  : 6,      #  TARGET_*********_ARCH_***********_ATTRIBUTE\r
1112                 "0x00101"  : 5,      #  ******_*********_ARCH_***********_ATTRIBUTE\r
1113                 "0x11001"  : 4,      #  TARGET_TOOLCHAIN_****_***********_ATTRIBUTE\r
1114                 "0x01001"  : 3,      #  ******_TOOLCHAIN_****_***********_ATTRIBUTE\r
1115                 "0x10001"  : 2,      #  TARGET_*********_****_***********_ATTRIBUTE\r
1116                 "0x00001"  : 1}      #  ******_*********_****_***********_ATTRIBUTE (Lowest)\r
1117 \r
1118     ## Initialize PlatformAutoGen\r
1119     #\r
1120     #\r
1121     #   @param      Workspace       WorkspaceAutoGen object\r
1122     #   @param      PlatformFile    Platform file (DSC file)\r
1123     #   @param      Target          Build target (DEBUG, RELEASE)\r
1124     #   @param      Toolchain       Name of tool chain\r
1125     #   @param      Arch            arch of the platform supports\r
1126     #\r
1127     def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
1128         EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
1129         GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
1130 \r
1131         self.MetaFile = PlatformFile\r
1132         self.Workspace = Workspace\r
1133         self.WorkspaceDir = Workspace.WorkspaceDir\r
1134         self.ToolChain = Toolchain\r
1135         self.BuildTarget = Target\r
1136         self.Arch = Arch\r
1137         self.SourceDir = PlatformFile.SubDir\r
1138         self.FdTargetList = self.Workspace.FdTargetList\r
1139         self.FvTargetList = self.Workspace.FvTargetList\r
1140         # get the original module/package/platform objects\r
1141         self.BuildDatabase = Workspace.BuildDatabase\r
1142         self.DscBuildDataObj = Workspace.Platform\r
1143 \r
1144         # flag indicating if the makefile/C-code file has been created or not\r
1145         self.IsMakeFileCreated  = False\r
1146 \r
1147         self._DynamicPcdList = None    # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
1148         self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
1149 \r
1150         self._AsBuildInfList = []\r
1151         self._AsBuildModuleList = []\r
1152 \r
1153         self.VariableInfo = None\r
1154 \r
1155         if GlobalData.gFdfParser is not None:\r
1156             self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
1157             for Inf in self._AsBuildInfList:\r
1158                 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
1159                 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1160                 if not M.IsBinaryModule:\r
1161                     continue\r
1162                 self._AsBuildModuleList.append(InfClass)\r
1163         # get library/modules for build\r
1164         self.LibraryBuildDirectoryList = []\r
1165         self.ModuleBuildDirectoryList = []\r
1166 \r
1167         return True\r
1168 \r
1169     @cached_class_function\r
1170     def __repr__(self):\r
1171         return "%s [%s]" % (self.MetaFile, self.Arch)\r
1172 \r
1173     ## Create autogen code for platform and modules\r
1174     #\r
1175     #  Since there's no autogen code for platform, this method will do nothing\r
1176     #  if CreateModuleCodeFile is set to False.\r
1177     #\r
1178     #   @param      CreateModuleCodeFile    Flag indicating if creating module's\r
1179     #                                       autogen code file or not\r
1180     #\r
1181     @cached_class_function\r
1182     def CreateCodeFile(self, CreateModuleCodeFile=False):\r
1183         # only module has code to be created, so do nothing if CreateModuleCodeFile is False\r
1184         if not CreateModuleCodeFile:\r
1185             return\r
1186 \r
1187         for Ma in self.ModuleAutoGenList:\r
1188             Ma.CreateCodeFile(True)\r
1189 \r
1190     ## Generate Fds Command\r
1191     @cached_property\r
1192     def GenFdsCommand(self):\r
1193         return self.Workspace.GenFdsCommand\r
1194 \r
1195     ## Create makefile for the platform and modules in it\r
1196     #\r
1197     #   @param      CreateModuleMakeFile    Flag indicating if the makefile for\r
1198     #                                       modules will be created as well\r
1199     #\r
1200     def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
1201         if CreateModuleMakeFile:\r
1202             for Ma in self._MaList:\r
1203                 key = (Ma.MetaFile.File, self.Arch)\r
1204                 if key in FfsCommand:\r
1205                     Ma.CreateMakeFile(True, FfsCommand[key])\r
1206                 else:\r
1207                     Ma.CreateMakeFile(True)\r
1208 \r
1209         # no need to create makefile for the platform more than once\r
1210         if self.IsMakeFileCreated:\r
1211             return\r
1212 \r
1213         # create library/module build dirs for platform\r
1214         Makefile = GenMake.PlatformMakefile(self)\r
1215         self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
1216         self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
1217 \r
1218         self.IsMakeFileCreated = True\r
1219 \r
1220     @property\r
1221     def AllPcdList(self):\r
1222         return self.DynamicPcdList + self.NonDynamicPcdList\r
1223     ## Deal with Shared FixedAtBuild Pcds\r
1224     #\r
1225     def CollectFixedAtBuildPcds(self):\r
1226         for LibAuto in self.LibraryAutoGenList:\r
1227             FixedAtBuildPcds = {}\r
1228             ShareFixedAtBuildPcdsSameValue = {}\r
1229             for Module in LibAuto.ReferenceModules:\r
1230                 for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):\r
1231                     DefaultValue = Pcd.DefaultValue\r
1232                     # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib\r
1233                     if Pcd in Module.LibraryPcdList:\r
1234                         Index = Module.LibraryPcdList.index(Pcd)\r
1235                         DefaultValue = Module.LibraryPcdList[Index].DefaultValue\r
1236                     key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1237                     if key not in FixedAtBuildPcds:\r
1238                         ShareFixedAtBuildPcdsSameValue[key] = True\r
1239                         FixedAtBuildPcds[key] = DefaultValue\r
1240                     else:\r
1241                         if FixedAtBuildPcds[key] != DefaultValue:\r
1242                             ShareFixedAtBuildPcdsSameValue[key] = False\r
1243             for Pcd in LibAuto.FixedAtBuildPcds:\r
1244                 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1245                 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
1246                     continue\r
1247                 else:\r
1248                     DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]\r
1249                     if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
1250                         continue\r
1251                 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:\r
1252                     LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]\r
1253 \r
1254     def CollectVariables(self, DynamicPcdSet):\r
1255         VpdRegionSize = 0\r
1256         VpdRegionBase = 0\r
1257         if self.Workspace.FdfFile:\r
1258             FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]\r
1259             for FdRegion in FdDict.RegionList:\r
1260                 for item in FdRegion.RegionDataList:\r
1261                     if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:\r
1262                         VpdRegionSize = FdRegion.Size\r
1263                         VpdRegionBase = FdRegion.Offset\r
1264                         break\r
1265 \r
1266         VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)\r
1267         VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
1268         VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
1269         Index = 0\r
1270         for Pcd in DynamicPcdSet:\r
1271             pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1272             for SkuName in Pcd.SkuInfoList:\r
1273                 Sku = Pcd.SkuInfoList[SkuName]\r
1274                 SkuId = Sku.SkuId\r
1275                 if SkuId is None or SkuId == '':\r
1276                     continue\r
1277                 if len(Sku.VariableName) > 0:\r
1278                     if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:\r
1279                         continue\r
1280                     VariableGuidStructure = Sku.VariableGuidValue\r
1281                     VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
1282                     for StorageName in Sku.DefaultStoreDict:\r
1283                         VariableInfo.append_variable(var_info(Index, pcdname, StorageName, SkuName, StringToArray(Sku.VariableName), VariableGuid, Sku.VariableOffset, Sku.VariableAttribute, Sku.HiiDefaultValue, Sku.DefaultStoreDict[StorageName] if Pcd.DatumType in TAB_PCD_NUMERIC_TYPES else StringToArray(Sku.DefaultStoreDict[StorageName]), Pcd.DatumType, Pcd.CustomAttribute['DscPosition'], Pcd.CustomAttribute.get('IsStru',False)))\r
1284             Index += 1\r
1285         return VariableInfo\r
1286 \r
1287     def UpdateNVStoreMaxSize(self, OrgVpdFile):\r
1288         if self.VariableInfo:\r
1289             VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
1290             PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
1291 \r
1292             if PcdNvStoreDfBuffer:\r
1293                 if os.path.exists(VpdMapFilePath):\r
1294                     OrgVpdFile.Read(VpdMapFilePath)\r
1295                     PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
1296                     NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'\r
1297                 else:\r
1298                     EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
1299 \r
1300                 NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)\r
1301                 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
1302                 maxsize = self.VariableInfo.VpdRegionSize  - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))\r
1303                 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)\r
1304 \r
1305                 if var_data and default_skuobj:\r
1306                     default_skuobj.DefaultValue = var_data\r
1307                     PcdNvStoreDfBuffer[0].DefaultValue = var_data\r
1308                     PcdNvStoreDfBuffer[0].SkuInfoList.clear()\r
1309                     PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj\r
1310                     PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))\r
1311 \r
1312         return OrgVpdFile\r
1313 \r
1314     ## Collect dynamic PCDs\r
1315     #\r
1316     #  Gather dynamic PCDs list from each module and their settings from platform\r
1317     #  This interface should be invoked explicitly when platform action is created.\r
1318     #\r
1319     def CollectPlatformDynamicPcds(self):\r
1320         for key in self.Platform.Pcds:\r
1321             for SinglePcd in GlobalData.MixedPcd:\r
1322                 if (self.Platform.Pcds[key].TokenCName, self.Platform.Pcds[key].TokenSpaceGuidCName) == SinglePcd:\r
1323                     for item in GlobalData.MixedPcd[SinglePcd]:\r
1324                         Pcd_Type = item[0].split('_')[-1]\r
1325                         if (Pcd_Type == self.Platform.Pcds[key].Type) or (Pcd_Type == TAB_PCDS_DYNAMIC_EX and self.Platform.Pcds[key].Type in PCD_DYNAMIC_EX_TYPE_SET) or \\r
1326                            (Pcd_Type == TAB_PCDS_DYNAMIC and self.Platform.Pcds[key].Type in PCD_DYNAMIC_TYPE_SET):\r
1327                             Value = self.Platform.Pcds[key]\r
1328                             Value.TokenCName = self.Platform.Pcds[key].TokenCName + '_' + Pcd_Type\r
1329                             if len(key) == 2:\r
1330                                 newkey = (Value.TokenCName, key[1])\r
1331                             elif len(key) == 3:\r
1332                                 newkey = (Value.TokenCName, key[1], key[2])\r
1333                             del self.Platform.Pcds[key]\r
1334                             self.Platform.Pcds[newkey] = Value\r
1335                             break\r
1336                     break\r
1337 \r
1338         # for gathering error information\r
1339         NoDatumTypePcdList = set()\r
1340         FdfModuleList = []\r
1341         for InfName in self._AsBuildInfList:\r
1342             InfName = mws.join(self.WorkspaceDir, InfName)\r
1343             FdfModuleList.append(os.path.normpath(InfName))\r
1344         for M in self._MaList:\r
1345 #            F is the Module for which M is the module autogen\r
1346             for PcdFromModule in M.ModulePcdList + M.LibraryPcdList:\r
1347                 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
1348                 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
1349                     NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))\r
1350 \r
1351                 # Check the PCD from Binary INF or Source INF\r
1352                 if M.IsBinaryModule == True:\r
1353                     PcdFromModule.IsFromBinaryInf = True\r
1354 \r
1355                 # Check the PCD from DSC or not\r
1356                 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds\r
1357 \r
1358                 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1359                     if M.MetaFile.Path not in FdfModuleList:\r
1360                         # If one of the Source built modules listed in the DSC is not listed\r
1361                         # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic\r
1362                         # access method (it is only listed in the DEC file that declares the\r
1363                         # PCD as PcdsDynamic), then build tool will report warning message\r
1364                         # notify the PI that they are attempting to build a module that must\r
1365                         # be included in a flash image in order to be functional. These Dynamic\r
1366                         # PCD will not be added into the Database unless it is used by other\r
1367                         # modules that are included in the FDF file.\r
1368                         if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \\r
1369                             PcdFromModule.IsFromBinaryInf == False:\r
1370                             # Print warning message to let the developer make a determine.\r
1371                             continue\r
1372                         # If one of the Source built modules listed in the DSC is not listed in\r
1373                         # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx\r
1374                         # access method (it is only listed in the DEC file that declares the\r
1375                         # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the\r
1376                         # PCD to the Platform's PCD Database.\r
1377                         if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1378                             continue\r
1379                     #\r
1380                     # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
1381                     # it should be stored in Pcd PEI database, If a dynamic only\r
1382                     # used by DXE module, it should be stored in DXE PCD database.\r
1383                     # The default Phase is DXE\r
1384                     #\r
1385                     if M.ModuleType in SUP_MODULE_SET_PEI:\r
1386                         PcdFromModule.Phase = "PEI"\r
1387                     if PcdFromModule not in self._DynaPcdList_:\r
1388                         self._DynaPcdList_.append(PcdFromModule)\r
1389                     elif PcdFromModule.Phase == 'PEI':\r
1390                         # overwrite any the same PCD existing, if Phase is PEI\r
1391                         Index = self._DynaPcdList_.index(PcdFromModule)\r
1392                         self._DynaPcdList_[Index] = PcdFromModule\r
1393                 elif PcdFromModule not in self._NonDynaPcdList_:\r
1394                     self._NonDynaPcdList_.append(PcdFromModule)\r
1395                 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
1396                     Index = self._NonDynaPcdList_.index(PcdFromModule)\r
1397                     if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
1398                         #The PCD from Binary INF will override the same one from source INF\r
1399                         self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
1400                         PcdFromModule.Pending = False\r
1401                         self._NonDynaPcdList_.append (PcdFromModule)\r
1402         DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}\r
1403         # add the PCD from modules that listed in FDF but not in DSC to Database\r
1404         for InfName in FdfModuleList:\r
1405             if InfName not in DscModuleSet:\r
1406                 InfClass = PathClass(InfName)\r
1407                 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
1408                 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)\r
1409                 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.\r
1410                 # For binary module, if in current arch, we need to list the PCDs into database.\r
1411                 if not M.IsBinaryModule:\r
1412                     continue\r
1413                 # Override the module PCD setting by platform setting\r
1414                 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
1415                 for PcdFromModule in ModulePcdList:\r
1416                     PcdFromModule.IsFromBinaryInf = True\r
1417                     PcdFromModule.IsFromDsc = False\r
1418                     # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
1419                     if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1420                         EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1421                                         File=self.MetaFile,\r
1422                                         ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
1423                                         % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
1424                     # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
1425                     if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
1426                         NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
1427                     if M.ModuleType in SUP_MODULE_SET_PEI:\r
1428                         PcdFromModule.Phase = "PEI"\r
1429                     if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1430                         self._DynaPcdList_.append(PcdFromModule)\r
1431                     elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
1432                         self._NonDynaPcdList_.append(PcdFromModule)\r
1433                     if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1434                         # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
1435                         # It is to solve the case that a dynamic PCD used by a PEM module/PEI\r
1436                         # module & DXE module at a same time.\r
1437                         # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
1438                         # INF file as DynamicEx.\r
1439                         Index = self._DynaPcdList_.index(PcdFromModule)\r
1440                         self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
1441                         self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
1442         for PcdFromModule in self._NonDynaPcdList_:\r
1443             # If a PCD is not listed in the DSC file, but binary INF files used by\r
1444             # this platform all (that use this PCD) list the PCD in a [PatchPcds]\r
1445             # section, AND all source INF files used by this platform the build\r
1446             # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]\r
1447             # section, then the tools must NOT add the PCD to the Platform's PCD\r
1448             # Database; the build must assign the access method for this PCD as\r
1449             # PcdsPatchableInModule.\r
1450             if PcdFromModule not in self._DynaPcdList_:\r
1451                 continue\r
1452             Index = self._DynaPcdList_.index(PcdFromModule)\r
1453             if PcdFromModule.IsFromDsc == False and \\r
1454                 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
1455                 PcdFromModule.IsFromBinaryInf == True and \\r
1456                 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
1457                 Index = self._DynaPcdList_.index(PcdFromModule)\r
1458                 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
1459 \r
1460         # print out error information and break the build, if error found\r
1461         if len(NoDatumTypePcdList) > 0:\r
1462             NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
1463             EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
1464                             File=self.MetaFile,\r
1465                             ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
1466                                       % NoDatumTypePcdListString)\r
1467         self._NonDynamicPcdList = self._NonDynaPcdList_\r
1468         self._DynamicPcdList = self._DynaPcdList_\r
1469         #\r
1470         # Sort dynamic PCD list to:\r
1471         # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should\r
1472         #    try to be put header of dynamicd List\r
1473         # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
1474         #\r
1475         # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
1476         #\r
1477         UnicodePcdArray = set()\r
1478         HiiPcdArray     = set()\r
1479         OtherPcdArray   = set()\r
1480         VpdPcdDict      = {}\r
1481         VpdFile               = VpdInfoFile.VpdInfoFile()\r
1482         NeedProcessVpdMapFile = False\r
1483 \r
1484         for pcd in self.Platform.Pcds:\r
1485             if pcd not in self._PlatformPcds:\r
1486                 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]\r
1487 \r
1488         for item in self._PlatformPcds:\r
1489             if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
1490                 self._PlatformPcds[item].DatumType = TAB_VOID\r
1491 \r
1492         if (self.Workspace.ArchList[-1] == self.Arch):\r
1493             for Pcd in self._DynamicPcdList:\r
1494                 # just pick the a value to determine whether is unicode string type\r
1495                 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
1496                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1497 \r
1498                 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
1499                     Pcd.DatumType = TAB_VOID\r
1500 \r
1501                     # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
1502                     # if found HII type PCD then insert to right of UnicodeIndex\r
1503                 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
1504                     VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
1505 \r
1506             #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer\r
1507             PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))\r
1508             if PcdNvStoreDfBuffer:\r
1509                 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
1510                 vardump = self.VariableInfo.dump()\r
1511                 if vardump:\r
1512                     #\r
1513                     #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,\r
1514                     #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).\r
1515                     #typedef UINT16 SIZE_INFO;\r
1516                     #//SIZE_INFO  SizeTable[];\r
1517                     if len(vardump.split(",")) > 0xffff:\r
1518                         EdkLogger.error("build", RESOURCE_OVERFLOW, 'The current length of PCD %s value is %d, it exceeds to the max size of String PCD.' %(".".join([PcdNvStoreDfBuffer.TokenSpaceGuidCName,PcdNvStoreDfBuffer.TokenCName]) ,len(vardump.split(","))))\r
1519                     PcdNvStoreDfBuffer.DefaultValue = vardump\r
1520                     for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
1521                         PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
1522                         PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
1523             else:\r
1524                 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd\r
1525                 if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:\r
1526                     EdkLogger.warn("build", "PcdNvStoreDefaultValueBuffer should be defined as PcdsDynamicExVpd in dsc file since the DefaultStores is enabled for this platform.\n%s" %self.Platform.MetaFile.Path)\r
1527             PlatformPcds = sorted(self._PlatformPcds.keys())\r
1528             #\r
1529             # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
1530             #\r
1531             VpdSkuMap = {}\r
1532             for PcdKey in PlatformPcds:\r
1533                 Pcd = self._PlatformPcds[PcdKey]\r
1534                 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
1535                    PcdKey in VpdPcdDict:\r
1536                     Pcd = VpdPcdDict[PcdKey]\r
1537                     SkuValueMap = {}\r
1538                     DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
1539                     if DefaultSku:\r
1540                         PcdValue = DefaultSku.DefaultValue\r
1541                         if PcdValue not in SkuValueMap:\r
1542                             SkuValueMap[PcdValue] = []\r
1543                             VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)\r
1544                         SkuValueMap[PcdValue].append(DefaultSku)\r
1545 \r
1546                     for (SkuName, Sku) in Pcd.SkuInfoList.items():\r
1547                         Sku.VpdOffset = Sku.VpdOffset.strip()\r
1548                         PcdValue = Sku.DefaultValue\r
1549                         if PcdValue == "":\r
1550                             PcdValue  = Pcd.DefaultValue\r
1551                         if Sku.VpdOffset != TAB_STAR:\r
1552                             if PcdValue.startswith("{"):\r
1553                                 Alignment = 8\r
1554                             elif PcdValue.startswith("L"):\r
1555                                 Alignment = 2\r
1556                             else:\r
1557                                 Alignment = 1\r
1558                             try:\r
1559                                 VpdOffset = int(Sku.VpdOffset)\r
1560                             except:\r
1561                                 try:\r
1562                                     VpdOffset = int(Sku.VpdOffset, 16)\r
1563                                 except:\r
1564                                     EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
1565                             if VpdOffset % Alignment != 0:\r
1566                                 if PcdValue.startswith("{"):\r
1567                                     EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
1568                                 else:\r
1569                                     EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))\r
1570                         if PcdValue not in SkuValueMap:\r
1571                             SkuValueMap[PcdValue] = []\r
1572                             VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)\r
1573                         SkuValueMap[PcdValue].append(Sku)\r
1574                         # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
1575                         if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
1576                             NeedProcessVpdMapFile = True\r
1577                             if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
1578                                 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
1579                                                 "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
1580 \r
1581                     VpdSkuMap[PcdKey] = SkuValueMap\r
1582             #\r
1583             # Fix the PCDs define in VPD PCD section that never referenced by module.\r
1584             # An example is PCD for signature usage.\r
1585             #\r
1586             for DscPcd in PlatformPcds:\r
1587                 DscPcdEntry = self._PlatformPcds[DscPcd]\r
1588                 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
1589                     if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):\r
1590                         FoundFlag = False\r
1591                         for VpdPcd in VpdFile._VpdArray:\r
1592                             # This PCD has been referenced by module\r
1593                             if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1594                                (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
1595                                     FoundFlag = True\r
1596 \r
1597                         # Not found, it should be signature\r
1598                         if not FoundFlag :\r
1599                             # just pick the a value to determine whether is unicode string type\r
1600                             SkuValueMap = {}\r
1601                             SkuObjList = list(DscPcdEntry.SkuInfoList.items())\r
1602                             DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)\r
1603                             if DefaultSku:\r
1604                                 defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))\r
1605                                 SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]\r
1606                             for (SkuName, Sku) in SkuObjList:\r
1607                                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1608 \r
1609                                 # Need to iterate DEC pcd information to get the value & datumtype\r
1610                                 for eachDec in self.PackageList:\r
1611                                     for DecPcd in eachDec.Pcds:\r
1612                                         DecPcdEntry = eachDec.Pcds[DecPcd]\r
1613                                         if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
1614                                            (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
1615                                             # Print warning message to let the developer make a determine.\r
1616                                             EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
1617                                                             File=self.MetaFile, \\r
1618                                                             ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
1619                                                             %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))\r
1620 \r
1621                                             DscPcdEntry.DatumType    = DecPcdEntry.DatumType\r
1622                                             DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
1623                                             DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
1624                                             DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
1625                                             # Only fix the value while no value provided in DSC file.\r
1626                                             if not Sku.DefaultValue:\r
1627                                                 DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue\r
1628 \r
1629                                 if DscPcdEntry not in self._DynamicPcdList:\r
1630                                     self._DynamicPcdList.append(DscPcdEntry)\r
1631                                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1632                                 PcdValue = Sku.DefaultValue\r
1633                                 if PcdValue == "":\r
1634                                     PcdValue  = DscPcdEntry.DefaultValue\r
1635                                 if Sku.VpdOffset != TAB_STAR:\r
1636                                     if PcdValue.startswith("{"):\r
1637                                         Alignment = 8\r
1638                                     elif PcdValue.startswith("L"):\r
1639                                         Alignment = 2\r
1640                                     else:\r
1641                                         Alignment = 1\r
1642                                     try:\r
1643                                         VpdOffset = int(Sku.VpdOffset)\r
1644                                     except:\r
1645                                         try:\r
1646                                             VpdOffset = int(Sku.VpdOffset, 16)\r
1647                                         except:\r
1648                                             EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
1649                                     if VpdOffset % Alignment != 0:\r
1650                                         if PcdValue.startswith("{"):\r
1651                                             EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
1652                                         else:\r
1653                                             EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))\r
1654                                 if PcdValue not in SkuValueMap:\r
1655                                     SkuValueMap[PcdValue] = []\r
1656                                     VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)\r
1657                                 SkuValueMap[PcdValue].append(Sku)\r
1658                                 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
1659                                     NeedProcessVpdMapFile = True\r
1660                             if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
1661                                 UnicodePcdArray.add(DscPcdEntry)\r
1662                             elif len(Sku.VariableName) > 0:\r
1663                                 HiiPcdArray.add(DscPcdEntry)\r
1664                             else:\r
1665                                 OtherPcdArray.add(DscPcdEntry)\r
1666 \r
1667                                 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
1668                             VpdSkuMap[DscPcd] = SkuValueMap\r
1669             if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
1670                VpdFile.GetCount() != 0:\r
1671                 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,\r
1672                                 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
1673 \r
1674             if VpdFile.GetCount() != 0:\r
1675 \r
1676                 self.FixVpdOffset(VpdFile)\r
1677 \r
1678                 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
1679                 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
1680                 if PcdNvStoreDfBuffer:\r
1681                     PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName\r
1682                     if (PcdName,PcdGuid) in VpdSkuMap:\r
1683                         DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
1684                         VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}\r
1685 \r
1686                 # Process VPD map file generated by third party BPDG tool\r
1687                 if NeedProcessVpdMapFile:\r
1688                     VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
1689                     if os.path.exists(VpdMapFilePath):\r
1690                         VpdFile.Read(VpdMapFilePath)\r
1691 \r
1692                         # Fixup TAB_STAR offset\r
1693                         for pcd in VpdSkuMap:\r
1694                             vpdinfo = VpdFile.GetVpdInfo(pcd)\r
1695                             if vpdinfo is None:\r
1696                             # just pick the a value to determine whether is unicode string type\r
1697                                 continue\r
1698                             for pcdvalue in VpdSkuMap[pcd]:\r
1699                                 for sku in VpdSkuMap[pcd][pcdvalue]:\r
1700                                     for item in vpdinfo:\r
1701                                         if item[2] == pcdvalue:\r
1702                                             sku.VpdOffset = item[1]\r
1703                     else:\r
1704                         EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
1705 \r
1706             # Delete the DynamicPcdList At the last time enter into this function\r
1707             for Pcd in self._DynamicPcdList:\r
1708                 # just pick the a value to determine whether is unicode string type\r
1709                 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
1710                 Sku.VpdOffset = Sku.VpdOffset.strip()\r
1711 \r
1712                 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
1713                     Pcd.DatumType = TAB_VOID\r
1714 \r
1715                 PcdValue = Sku.DefaultValue\r
1716                 if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
1717                     # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
1718                     UnicodePcdArray.add(Pcd)\r
1719                 elif len(Sku.VariableName) > 0:\r
1720                     # if found HII type PCD then insert to right of UnicodeIndex\r
1721                     HiiPcdArray.add(Pcd)\r
1722                 else:\r
1723                     OtherPcdArray.add(Pcd)\r
1724             del self._DynamicPcdList[:]\r
1725         self._DynamicPcdList.extend(list(UnicodePcdArray))\r
1726         self._DynamicPcdList.extend(list(HiiPcdArray))\r
1727         self._DynamicPcdList.extend(list(OtherPcdArray))\r
1728         allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]\r
1729         for pcd in self._DynamicPcdList:\r
1730             if len(pcd.SkuInfoList) == 1:\r
1731                 for (SkuName, SkuId) in allskuset:\r
1732                     if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:\r
1733                         continue\r
1734                     pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])\r
1735                     pcd.SkuInfoList[SkuName].SkuId = SkuId\r
1736                     pcd.SkuInfoList[SkuName].SkuIdName = SkuName\r
1737 \r
1738     def FixVpdOffset(self, VpdFile ):\r
1739         FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
1740         if not os.path.exists(FvPath):\r
1741             try:\r
1742                 os.makedirs(FvPath)\r
1743             except:\r
1744                 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
1745 \r
1746         VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
1747 \r
1748         if VpdFile.Write(VpdFilePath):\r
1749             # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
1750             BPDGToolName = None\r
1751             for ToolDef in self.ToolDefinition.values():\r
1752                 if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:\r
1753                     if "PATH" not in ToolDef:\r
1754                         EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
1755                     BPDGToolName = ToolDef["PATH"]\r
1756                     break\r
1757             # Call third party GUID BPDG tool.\r
1758             if BPDGToolName is not None:\r
1759                 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
1760             else:\r
1761                 EdkLogger.error("Build", FILE_NOT_FOUND, "Fail to find third-party BPDG tool to process VPD PCDs. BPDG Guid tool need to be defined in tools_def.txt and VPD_TOOL_GUID need to be provided in DSC file.")\r
1762 \r
1763     ## Return the platform build data object\r
1764     @cached_property\r
1765     def Platform(self):\r
1766         return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
1767 \r
1768     ## Return platform name\r
1769     @cached_property\r
1770     def Name(self):\r
1771         return self.Platform.PlatformName\r
1772 \r
1773     ## Return the meta file GUID\r
1774     @cached_property\r
1775     def Guid(self):\r
1776         return self.Platform.Guid\r
1777 \r
1778     ## Return the platform version\r
1779     @cached_property\r
1780     def Version(self):\r
1781         return self.Platform.Version\r
1782 \r
1783     ## Return the FDF file name\r
1784     @cached_property\r
1785     def FdfFile(self):\r
1786         if self.Workspace.FdfFile:\r
1787             RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
1788         else:\r
1789             RetVal = ''\r
1790         return RetVal\r
1791 \r
1792     ## Return the build output directory platform specifies\r
1793     @cached_property\r
1794     def OutputDir(self):\r
1795         return self.Platform.OutputDirectory\r
1796 \r
1797     ## Return the directory to store all intermediate and final files built\r
1798     @cached_property\r
1799     def BuildDir(self):\r
1800         if os.path.isabs(self.OutputDir):\r
1801             GlobalData.gBuildDirectory = RetVal = path.join(\r
1802                                         path.abspath(self.OutputDir),\r
1803                                         self.BuildTarget + "_" + self.ToolChain,\r
1804                                         )\r
1805         else:\r
1806             GlobalData.gBuildDirectory = RetVal = path.join(\r
1807                                         self.WorkspaceDir,\r
1808                                         self.OutputDir,\r
1809                                         self.BuildTarget + "_" + self.ToolChain,\r
1810                                         )\r
1811         return RetVal\r
1812 \r
1813     ## Return directory of platform makefile\r
1814     #\r
1815     #   @retval     string  Makefile directory\r
1816     #\r
1817     @cached_property\r
1818     def MakeFileDir(self):\r
1819         return path.join(self.BuildDir, self.Arch)\r
1820 \r
1821     ## Return build command string\r
1822     #\r
1823     #   @retval     string  Build command string\r
1824     #\r
1825     @cached_property\r
1826     def BuildCommand(self):\r
1827         RetVal = []\r
1828         if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
1829             RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
1830             if "FLAGS" in self.ToolDefinition["MAKE"]:\r
1831                 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
1832                 if NewOption != '':\r
1833                     RetVal += _SplitOption(NewOption)\r
1834             if "MAKE" in self.EdkIIBuildOption:\r
1835                 if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
1836                     Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
1837                     if Flags.startswith('='):\r
1838                         RetVal = [RetVal[0]] + [Flags[1:]]\r
1839                     else:\r
1840                         RetVal.append(Flags)\r
1841         return RetVal\r
1842 \r
1843     ## Get tool chain definition\r
1844     #\r
1845     #  Get each tool definition for given tool chain from tools_def.txt and platform\r
1846     #\r
1847     @cached_property\r
1848     def ToolDefinition(self):\r
1849         ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
1850         if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
1851             EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
1852                             ExtraData="[%s]" % self.MetaFile)\r
1853         RetVal = {}\r
1854         DllPathList = set()\r
1855         for Def in ToolDefinition:\r
1856             Target, Tag, Arch, Tool, Attr = Def.split("_")\r
1857             if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
1858                 continue\r
1859 \r
1860             Value = ToolDefinition[Def]\r
1861             # don't record the DLL\r
1862             if Attr == "DLL":\r
1863                 DllPathList.add(Value)\r
1864                 continue\r
1865 \r
1866             if Tool not in RetVal:\r
1867                 RetVal[Tool] = {}\r
1868             RetVal[Tool][Attr] = Value\r
1869 \r
1870         ToolsDef = ''\r
1871         if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:\r
1872             if "FLAGS" not in RetVal["MAKE"]:\r
1873                 RetVal["MAKE"]["FLAGS"] = ""\r
1874             RetVal["MAKE"]["FLAGS"] += " -s"\r
1875         MakeFlags = ''\r
1876         for Tool in RetVal:\r
1877             for Attr in RetVal[Tool]:\r
1878                 Value = RetVal[Tool][Attr]\r
1879                 if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:\r
1880                     # check if override is indicated\r
1881                     if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):\r
1882                         Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]\r
1883                     else:\r
1884                         if Attr != 'PATH':\r
1885                             Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
1886                         else:\r
1887                             Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
1888 \r
1889                 if Attr == "PATH":\r
1890                     # Don't put MAKE definition in the file\r
1891                     if Tool != "MAKE":\r
1892                         ToolsDef += "%s = %s\n" % (Tool, Value)\r
1893                 elif Attr != "DLL":\r
1894                     # Don't put MAKE definition in the file\r
1895                     if Tool == "MAKE":\r
1896                         if Attr == "FLAGS":\r
1897                             MakeFlags = Value\r
1898                     else:\r
1899                         ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
1900             ToolsDef += "\n"\r
1901 \r
1902         SaveFileOnChange(self.ToolDefinitionFile, ToolsDef, False)\r
1903         for DllPath in DllPathList:\r
1904             os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
1905         os.environ["MAKE_FLAGS"] = MakeFlags\r
1906 \r
1907         return RetVal\r
1908 \r
1909     ## Return the paths of tools\r
1910     @cached_property\r
1911     def ToolDefinitionFile(self):\r
1912         return os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
1913 \r
1914     ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
1915     @cached_property\r
1916     def ToolChainFamily(self):\r
1917         ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1918         if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
1919            or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
1920            or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
1921             EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1922                                % self.ToolChain)\r
1923             RetVal = TAB_COMPILER_MSFT\r
1924         else:\r
1925             RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
1926         return RetVal\r
1927 \r
1928     @cached_property\r
1929     def BuildRuleFamily(self):\r
1930         ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
1931         if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
1932            or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
1933            or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
1934             EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
1935                                % self.ToolChain)\r
1936             return TAB_COMPILER_MSFT\r
1937 \r
1938         return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
1939 \r
1940     ## Return the build options specific for all modules in this platform\r
1941     @cached_property\r
1942     def BuildOption(self):\r
1943         return self._ExpandBuildOption(self.Platform.BuildOptions)\r
1944 \r
1945     def _BuildOptionWithToolDef(self, ToolDef):\r
1946         return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)\r
1947 \r
1948     ## Return the build options specific for EDK modules in this platform\r
1949     @cached_property\r
1950     def EdkBuildOption(self):\r
1951         return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
1952 \r
1953     ## Return the build options specific for EDKII modules in this platform\r
1954     @cached_property\r
1955     def EdkIIBuildOption(self):\r
1956         return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
1957 \r
1958     ## Parse build_rule.txt in Conf Directory.\r
1959     #\r
1960     #   @retval     BuildRule object\r
1961     #\r
1962     @cached_property\r
1963     def BuildRule(self):\r
1964         BuildRuleFile = None\r
1965         if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
1966             BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
1967         if not BuildRuleFile:\r
1968             BuildRuleFile = gDefaultBuildRuleFile\r
1969         RetVal = BuildRule(BuildRuleFile)\r
1970         if RetVal._FileVersion == "":\r
1971             RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r
1972         else:\r
1973             if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :\r
1974                 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
1975                 EdkLogger.error("build", AUTOGEN_ERROR,\r
1976                                 ExtraData="The version number [%s] of build_rule.txt is less than the version number required by the AutoGen.(the minimum required version number is [%s])"\\r
1977                                  % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))\r
1978         return RetVal\r
1979 \r
1980     ## Summarize the packages used by modules in this platform\r
1981     @cached_property\r
1982     def PackageList(self):\r
1983         RetVal = set()\r
1984         for La in self.LibraryAutoGenList:\r
1985             RetVal.update(La.DependentPackageList)\r
1986         for Ma in self.ModuleAutoGenList:\r
1987             RetVal.update(Ma.DependentPackageList)\r
1988         #Collect package set information from INF of FDF\r
1989         for ModuleFile in self._AsBuildModuleList:\r
1990             if ModuleFile in self.Platform.Modules:\r
1991                 continue\r
1992             ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
1993             RetVal.update(ModuleData.Packages)\r
1994         return list(RetVal)\r
1995 \r
1996     @cached_property\r
1997     def NonDynamicPcdDict(self):\r
1998         return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}\r
1999 \r
2000     ## Get list of non-dynamic PCDs\r
2001     @property\r
2002     def NonDynamicPcdList(self):\r
2003         if not self._NonDynamicPcdList:\r
2004             self.CollectPlatformDynamicPcds()\r
2005         return self._NonDynamicPcdList\r
2006 \r
2007     ## Get list of dynamic PCDs\r
2008     @property\r
2009     def DynamicPcdList(self):\r
2010         if not self._DynamicPcdList:\r
2011             self.CollectPlatformDynamicPcds()\r
2012         return self._DynamicPcdList\r
2013 \r
2014     ## Generate Token Number for all PCD\r
2015     @cached_property\r
2016     def PcdTokenNumber(self):\r
2017         RetVal = OrderedDict()\r
2018         TokenNumber = 1\r
2019         #\r
2020         # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.\r
2021         # Such as:\r
2022         #\r
2023         # Dynamic PCD:\r
2024         # TokenNumber 0 ~ 10\r
2025         # DynamicEx PCD:\r
2026         # TokeNumber 11 ~ 20\r
2027         #\r
2028         for Pcd in self.DynamicPcdList:\r
2029             if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
2030                 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2031                 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2032                 TokenNumber += 1\r
2033 \r
2034         for Pcd in self.DynamicPcdList:\r
2035             if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
2036                 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2037                 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2038                 TokenNumber += 1\r
2039 \r
2040         for Pcd in self.DynamicPcdList:\r
2041             if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
2042                 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2043                 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2044                 TokenNumber += 1\r
2045 \r
2046         for Pcd in self.DynamicPcdList:\r
2047             if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
2048                 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
2049                 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2050                 TokenNumber += 1\r
2051 \r
2052         for Pcd in self.NonDynamicPcdList:\r
2053             RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
2054             TokenNumber += 1\r
2055         return RetVal\r
2056 \r
2057     @cached_property\r
2058     def _MaList(self):\r
2059         for ModuleFile in self.Platform.Modules:\r
2060             Ma = ModuleAutoGen(\r
2061                   self.Workspace,\r
2062                   ModuleFile,\r
2063                   self.BuildTarget,\r
2064                   self.ToolChain,\r
2065                   self.Arch,\r
2066                   self.MetaFile\r
2067                   )\r
2068             self.Platform.Modules[ModuleFile].M = Ma\r
2069         return [x.M for x in self.Platform.Modules.values()]\r
2070 \r
2071     ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
2072     @cached_property\r
2073     def ModuleAutoGenList(self):\r
2074         RetVal = []\r
2075         for Ma in self._MaList:\r
2076             if Ma not in RetVal:\r
2077                 RetVal.append(Ma)\r
2078         return RetVal\r
2079 \r
2080     ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
2081     @cached_property\r
2082     def LibraryAutoGenList(self):\r
2083         RetVal = []\r
2084         for Ma in self._MaList:\r
2085             for La in Ma.LibraryAutoGenList:\r
2086                 if La not in RetVal:\r
2087                     RetVal.append(La)\r
2088                 if Ma not in La.ReferenceModules:\r
2089                     La.ReferenceModules.append(Ma)\r
2090         return RetVal\r
2091 \r
2092     ## Test if a module is supported by the platform\r
2093     #\r
2094     #  An error will be raised directly if the module or its arch is not supported\r
2095     #  by the platform or current configuration\r
2096     #\r
2097     def ValidModule(self, Module):\r
2098         return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
2099             or Module in self._AsBuildModuleList\r
2100 \r
2101     ## Resolve the library classes in a module to library instances\r
2102     #\r
2103     # This method will not only resolve library classes but also sort the library\r
2104     # instances according to the dependency-ship.\r
2105     #\r
2106     #   @param  Module      The module from which the library classes will be resolved\r
2107     #\r
2108     #   @retval library_list    List of library instances sorted\r
2109     #\r
2110     def ApplyLibraryInstance(self, Module):\r
2111         # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly\r
2112         if str(Module) not in self.Platform.Modules:\r
2113             return []\r
2114 \r
2115         return GetModuleLibInstances(Module,\r
2116                                      self.Platform,\r
2117                                      self.BuildDatabase,\r
2118                                      self.Arch,\r
2119                                      self.BuildTarget,\r
2120                                      self.ToolChain,\r
2121                                      self.MetaFile,\r
2122                                      EdkLogger)\r
2123 \r
2124     ## Override PCD setting (type, value, ...)\r
2125     #\r
2126     #   @param  ToPcd       The PCD to be overridden\r
2127     #   @param  FromPcd     The PCD overriding from\r
2128     #\r
2129     def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
2130         #\r
2131         # in case there's PCDs coming from FDF file, which have no type given.\r
2132         # at this point, ToPcd.Type has the type found from dependent\r
2133         # package\r
2134         #\r
2135         TokenCName = ToPcd.TokenCName\r
2136         for PcdItem in GlobalData.MixedPcd:\r
2137             if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
2138                 TokenCName = PcdItem[0]\r
2139                 break\r
2140         if FromPcd is not None:\r
2141             if ToPcd.Pending and FromPcd.Type:\r
2142                 ToPcd.Type = FromPcd.Type\r
2143             elif ToPcd.Type and FromPcd.Type\\r
2144                 and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:\r
2145                 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r
2146                     ToPcd.Type = FromPcd.Type\r
2147             elif ToPcd.Type and FromPcd.Type \\r
2148                 and ToPcd.Type != FromPcd.Type:\r
2149                 if Library:\r
2150                     Module = str(Module) + " 's library file (" + str(Library) + ")"\r
2151                 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
2152                                 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r
2153                                           % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
2154                                              ToPcd.Type, Module, FromPcd.Type, Msg),\r
2155                                           File=self.MetaFile)\r
2156 \r
2157             if FromPcd.MaxDatumSize:\r
2158                 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
2159                 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r
2160             if FromPcd.DefaultValue:\r
2161                 ToPcd.DefaultValue = FromPcd.DefaultValue\r
2162             if FromPcd.TokenValue:\r
2163                 ToPcd.TokenValue = FromPcd.TokenValue\r
2164             if FromPcd.DatumType:\r
2165                 ToPcd.DatumType = FromPcd.DatumType\r
2166             if FromPcd.SkuInfoList:\r
2167                 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
2168             if FromPcd.UserDefinedDefaultStoresFlag:\r
2169                 ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r
2170             # Add Flexible PCD format parse\r
2171             if ToPcd.DefaultValue:\r
2172                 try:\r
2173                     ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Workspace._GuidDict)(True)\r
2174                 except BadExpression as Value:\r
2175                     EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
2176                                         File=self.MetaFile)\r
2177 \r
2178             # check the validation of datum\r
2179             IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
2180             if not IsValid:\r
2181                 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
2182                                 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
2183             ToPcd.validateranges = FromPcd.validateranges\r
2184             ToPcd.validlists = FromPcd.validlists\r
2185             ToPcd.expressions = FromPcd.expressions\r
2186             ToPcd.CustomAttribute = FromPcd.CustomAttribute\r
2187 \r
2188         if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
2189             EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
2190                             % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
2191             Value = ToPcd.DefaultValue\r
2192             if not Value:\r
2193                 ToPcd.MaxDatumSize = '1'\r
2194             elif Value[0] == 'L':\r
2195                 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
2196             elif Value[0] == '{':\r
2197                 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
2198             else:\r
2199                 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
2200 \r
2201         # apply default SKU for dynamic PCDS if specified one is not available\r
2202         if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r
2203             and not ToPcd.SkuInfoList:\r
2204             if self.Platform.SkuName in self.Platform.SkuIds:\r
2205                 SkuName = self.Platform.SkuName\r
2206             else:\r
2207                 SkuName = TAB_DEFAULT\r
2208             ToPcd.SkuInfoList = {\r
2209                 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
2210             }\r
2211 \r
2212     ## Apply PCD setting defined platform to a module\r
2213     #\r
2214     #   @param  Module  The module from which the PCD setting will be overridden\r
2215     #\r
2216     #   @retval PCD_list    The list PCDs with settings from platform\r
2217     #\r
2218     def ApplyPcdSetting(self, Module, Pcds, Library=""):\r
2219         # for each PCD in module\r
2220         for Name, Guid in Pcds:\r
2221             PcdInModule = Pcds[Name, Guid]\r
2222             # find out the PCD setting in platform\r
2223             if (Name, Guid) in self.Platform.Pcds:\r
2224                 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
2225             else:\r
2226                 PcdInPlatform = None\r
2227             # then override the settings if any\r
2228             self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r
2229             # resolve the VariableGuid value\r
2230             for SkuId in PcdInModule.SkuInfoList:\r
2231                 Sku = PcdInModule.SkuInfoList[SkuId]\r
2232                 if Sku.VariableGuid == '': continue\r
2233                 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
2234                 if Sku.VariableGuidValue is None:\r
2235                     PackageList = "\n\t".join(str(P) for P in self.PackageList)\r
2236                     EdkLogger.error(\r
2237                                 'build',\r
2238                                 RESOURCE_NOT_AVAILABLE,\r
2239                                 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
2240                                 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
2241                                                         % (Guid, Name, str(Module)),\r
2242                                 File=self.MetaFile\r
2243                                 )\r
2244 \r
2245         # override PCD settings with module specific setting\r
2246         if Module in self.Platform.Modules:\r
2247             PlatformModule = self.Platform.Modules[str(Module)]\r
2248             for Key  in PlatformModule.Pcds:\r
2249                 if GlobalData.BuildOptionPcd:\r
2250                     for pcd in GlobalData.BuildOptionPcd:\r
2251                         (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r
2252                         if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r
2253                             PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r
2254                             PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r
2255                             break\r
2256                 Flag = False\r
2257                 if Key in Pcds:\r
2258                     ToPcd = Pcds[Key]\r
2259                     Flag = True\r
2260                 elif Key in GlobalData.MixedPcd:\r
2261                     for PcdItem in GlobalData.MixedPcd[Key]:\r
2262                         if PcdItem in Pcds:\r
2263                             ToPcd = Pcds[PcdItem]\r
2264                             Flag = True\r
2265                             break\r
2266                 if Flag:\r
2267                     self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r
2268         # use PCD value to calculate the MaxDatumSize when it is not specified\r
2269         for Name, Guid in Pcds:\r
2270             Pcd = Pcds[Name, Guid]\r
2271             if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r
2272                 Pcd.MaxSizeUserSet = None\r
2273                 Value = Pcd.DefaultValue\r
2274                 if not Value:\r
2275                     Pcd.MaxDatumSize = '1'\r
2276                 elif Value[0] == 'L':\r
2277                     Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
2278                 elif Value[0] == '{':\r
2279                     Pcd.MaxDatumSize = str(len(Value.split(',')))\r
2280                 else:\r
2281                     Pcd.MaxDatumSize = str(len(Value) - 1)\r
2282         return list(Pcds.values())\r
2283 \r
2284 \r
2285 \r
2286     ## Calculate the priority value of the build option\r
2287     #\r
2288     # @param    Key    Build option definition contain: TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2289     #\r
2290     # @retval   Value  Priority value based on the priority list.\r
2291     #\r
2292     def CalculatePriorityValue(self, Key):\r
2293         Target, ToolChain, Arch, CommandType, Attr = Key.split('_')\r
2294         PriorityValue = 0x11111\r
2295         if Target == TAB_STAR:\r
2296             PriorityValue &= 0x01111\r
2297         if ToolChain == TAB_STAR:\r
2298             PriorityValue &= 0x10111\r
2299         if Arch == TAB_STAR:\r
2300             PriorityValue &= 0x11011\r
2301         if CommandType == TAB_STAR:\r
2302             PriorityValue &= 0x11101\r
2303         if Attr == TAB_STAR:\r
2304             PriorityValue &= 0x11110\r
2305 \r
2306         return self.PrioList["0x%0.5x" % PriorityValue]\r
2307 \r
2308 \r
2309     ## Expand * in build option key\r
2310     #\r
2311     #   @param  Options     Options to be expanded\r
2312     #   @param  ToolDef     Use specified ToolDef instead of full version.\r
2313     #                       This is needed during initialization to prevent\r
2314     #                       infinite recursion betweeh BuildOptions,\r
2315     #                       ToolDefinition, and this function.\r
2316     #\r
2317     #   @retval options     Options expanded\r
2318     #\r
2319     def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):\r
2320         if not ToolDef:\r
2321             ToolDef = self.ToolDefinition\r
2322         BuildOptions = {}\r
2323         FamilyMatch  = False\r
2324         FamilyIsNull = True\r
2325 \r
2326         OverrideList = {}\r
2327         #\r
2328         # Construct a list contain the build options which need override.\r
2329         #\r
2330         for Key in Options:\r
2331             #\r
2332             # Key[0] -- tool family\r
2333             # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
2334             #\r
2335             if (Key[0] == self.BuildRuleFamily and\r
2336                 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
2337                 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
2338                 if (Target == self.BuildTarget or Target == TAB_STAR) and\\r
2339                     (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\\r
2340                     (Arch == self.Arch or Arch == TAB_STAR) and\\r
2341                     Options[Key].startswith("="):\r
2342 \r
2343                     if OverrideList.get(Key[1]) is not None:\r
2344                         OverrideList.pop(Key[1])\r
2345                     OverrideList[Key[1]] = Options[Key]\r
2346 \r
2347         #\r
2348         # Use the highest priority value.\r
2349         #\r
2350         if (len(OverrideList) >= 2):\r
2351             KeyList = list(OverrideList.keys())\r
2352             for Index in range(len(KeyList)):\r
2353                 NowKey = KeyList[Index]\r
2354                 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
2355                 for Index1 in range(len(KeyList) - Index - 1):\r
2356                     NextKey = KeyList[Index1 + Index + 1]\r
2357                     #\r
2358                     # Compare two Key, if one is included by another, choose the higher priority one\r
2359                     #\r
2360                     Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
2361                     if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\\r
2362                         (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\\r
2363                         (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\\r
2364                         (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\\r
2365                         (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):\r
2366 \r
2367                         if self.CalculatePriorityValue(NowKey) > self.CalculatePriorityValue(NextKey):\r
2368                             if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
2369                                 Options.pop((self.BuildRuleFamily, NextKey))\r
2370                         else:\r
2371                             if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
2372                                 Options.pop((self.BuildRuleFamily, NowKey))\r
2373 \r
2374         for Key in Options:\r
2375             if ModuleStyle is not None and len (Key) > 2:\r
2376                 # Check Module style is EDK or EDKII.\r
2377                 # Only append build option for the matched style module.\r
2378                 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2379                     continue\r
2380                 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2381                     continue\r
2382             Family = Key[0]\r
2383             Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2384             # if tool chain family doesn't match, skip it\r
2385             if Tool in ToolDef and Family != "":\r
2386                 FamilyIsNull = False\r
2387                 if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
2388                     if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
2389                         continue\r
2390                 elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2391                     continue\r
2392                 FamilyMatch = True\r
2393             # expand any wildcard\r
2394             if Target == TAB_STAR or Target == self.BuildTarget:\r
2395                 if Tag == TAB_STAR or Tag == self.ToolChain:\r
2396                     if Arch == TAB_STAR or Arch == self.Arch:\r
2397                         if Tool not in BuildOptions:\r
2398                             BuildOptions[Tool] = {}\r
2399                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
2400                             BuildOptions[Tool][Attr] = Options[Key]\r
2401                         else:\r
2402                             # append options for the same tool except PATH\r
2403                             if Attr != 'PATH':\r
2404                                 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2405                             else:\r
2406                                 BuildOptions[Tool][Attr] = Options[Key]\r
2407         # Build Option Family has been checked, which need't to be checked again for family.\r
2408         if FamilyMatch or FamilyIsNull:\r
2409             return BuildOptions\r
2410 \r
2411         for Key in Options:\r
2412             if ModuleStyle is not None and len (Key) > 2:\r
2413                 # Check Module style is EDK or EDKII.\r
2414                 # Only append build option for the matched style module.\r
2415                 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
2416                     continue\r
2417                 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
2418                     continue\r
2419             Family = Key[0]\r
2420             Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
2421             # if tool chain family doesn't match, skip it\r
2422             if Tool not in ToolDef or Family == "":\r
2423                 continue\r
2424             # option has been added before\r
2425             if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
2426                 continue\r
2427 \r
2428             # expand any wildcard\r
2429             if Target == TAB_STAR or Target == self.BuildTarget:\r
2430                 if Tag == TAB_STAR or Tag == self.ToolChain:\r
2431                     if Arch == TAB_STAR or Arch == self.Arch:\r
2432                         if Tool not in BuildOptions:\r
2433                             BuildOptions[Tool] = {}\r
2434                         if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
2435                             BuildOptions[Tool][Attr] = Options[Key]\r
2436                         else:\r
2437                             # append options for the same tool except PATH\r
2438                             if Attr != 'PATH':\r
2439                                 BuildOptions[Tool][Attr] += " " + Options[Key]\r
2440                             else:\r
2441                                 BuildOptions[Tool][Attr] = Options[Key]\r
2442         return BuildOptions\r
2443 \r
2444     ## Append build options in platform to a module\r
2445     #\r
2446     #   @param  Module  The module to which the build options will be appended\r
2447     #\r
2448     #   @retval options     The options appended with build options in platform\r
2449     #\r
2450     def ApplyBuildOption(self, Module):\r
2451         # Get the different options for the different style module\r
2452         PlatformOptions = self.EdkIIBuildOption\r
2453         ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
2454         ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
2455         ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
2456         if Module in self.Platform.Modules:\r
2457             PlatformModule = self.Platform.Modules[str(Module)]\r
2458             PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
2459         else:\r
2460             PlatformModuleOptions = {}\r
2461 \r
2462         BuildRuleOrder = None\r
2463         for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
2464             for Tool in Options:\r
2465                 for Attr in Options[Tool]:\r
2466                     if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2467                         BuildRuleOrder = Options[Tool][Attr]\r
2468 \r
2469         AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r
2470                        list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r
2471                        list(self.ToolDefinition.keys()))\r
2472         BuildOptions = defaultdict(lambda: defaultdict(str))\r
2473         for Tool in AllTools:\r
2474             for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
2475                 if Tool not in Options:\r
2476                     continue\r
2477                 for Attr in Options[Tool]:\r
2478                     #\r
2479                     # Do not generate it in Makefile\r
2480                     #\r
2481                     if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
2482                         continue\r
2483                     Value = Options[Tool][Attr]\r
2484                     # check if override is indicated\r
2485                     if Value.startswith('='):\r
2486                         BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])\r
2487                     else:\r
2488                         if Attr != 'PATH':\r
2489                             BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)\r
2490                         else:\r
2491                             BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
2492 \r
2493         return BuildOptions, BuildRuleOrder\r
2494 \r
2495 #\r
2496 # extend lists contained in a dictionary with lists stored in another dictionary\r
2497 # if CopyToDict is not derived from DefaultDict(list) then this may raise exception\r
2498 #\r
2499 def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):\r
2500     for Key in CopyFromDict:\r
2501         CopyToDict[Key].extend(CopyFromDict[Key])\r
2502 \r
2503 # Create a directory specified by a set of path elements and return the full path\r
2504 def _MakeDir(PathList):\r
2505     RetVal = path.join(*PathList)\r
2506     CreateDirectory(RetVal)\r
2507     return RetVal\r
2508 \r
2509 ## ModuleAutoGen class\r
2510 #\r
2511 # This class encapsules the AutoGen behaviors for the build tools. In addition to\r
2512 # the generation of AutoGen.h and AutoGen.c, it will generate *.depex file according\r
2513 # to the [depex] section in module's inf file.\r
2514 #\r
2515 class ModuleAutoGen(AutoGen):\r
2516     # call super().__init__ then call the worker function with different parameter count\r
2517     def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
2518         if not hasattr(self, "_Init"):\r
2519             self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch, *args)\r
2520             self._Init = True\r
2521 \r
2522     ## Cache the timestamps of metafiles of every module in a class attribute\r
2523     #\r
2524     TimeDict = {}\r
2525 \r
2526     def __new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
2527         # check if this module is employed by active platform\r
2528         if not PlatformAutoGen(Workspace, args[0], Target, Toolchain, Arch).ValidModule(MetaFile):\r
2529             EdkLogger.verbose("Module [%s] for [%s] is not employed by active platform\n" \\r
2530                               % (MetaFile, Arch))\r
2531             return None\r
2532         return super(ModuleAutoGen, cls).__new__(cls, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs)\r
2533 \r
2534     ## Initialize ModuleAutoGen\r
2535     #\r
2536     #   @param      Workspace           EdkIIWorkspaceBuild object\r
2537     #   @param      ModuleFile          The path of module file\r
2538     #   @param      Target              Build target (DEBUG, RELEASE)\r
2539     #   @param      Toolchain           Name of tool chain\r
2540     #   @param      Arch                The arch the module supports\r
2541     #   @param      PlatformFile        Platform meta-file\r
2542     #\r
2543     def _InitWorker(self, Workspace, ModuleFile, Target, Toolchain, Arch, PlatformFile):\r
2544         EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen module [%s] [%s]" % (ModuleFile, Arch))\r
2545         GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (ModuleFile, Arch, Toolchain, Target)\r
2546 \r
2547         self.Workspace = Workspace\r
2548         self.WorkspaceDir = Workspace.WorkspaceDir\r
2549         self.MetaFile = ModuleFile\r
2550         self.PlatformInfo = PlatformAutoGen(Workspace, PlatformFile, Target, Toolchain, Arch)\r
2551 \r
2552         self.SourceDir = self.MetaFile.SubDir\r
2553         self.SourceDir = mws.relpath(self.SourceDir, self.WorkspaceDir)\r
2554 \r
2555         self.ToolChain = Toolchain\r
2556         self.BuildTarget = Target\r
2557         self.Arch = Arch\r
2558         self.ToolChainFamily = self.PlatformInfo.ToolChainFamily\r
2559         self.BuildRuleFamily = self.PlatformInfo.BuildRuleFamily\r
2560 \r
2561         self.IsCodeFileCreated = False\r
2562         self.IsAsBuiltInfCreated = False\r
2563         self.DepexGenerated = False\r
2564 \r
2565         self.BuildDatabase = self.Workspace.BuildDatabase\r
2566         self.BuildRuleOrder = None\r
2567         self.BuildTime      = 0\r
2568 \r
2569         self._PcdComments = OrderedListDict()\r
2570         self._GuidComments = OrderedListDict()\r
2571         self._ProtocolComments = OrderedListDict()\r
2572         self._PpiComments = OrderedListDict()\r
2573         self._BuildTargets            = None\r
2574         self._IntroBuildTargetList    = None\r
2575         self._FinalBuildTargetList    = None\r
2576         self._FileTypes               = None\r
2577 \r
2578         self.AutoGenDepSet = set()\r
2579         self.ReferenceModules = []\r
2580         self.ConstPcd                  = {}\r
2581 \r
2582 \r
2583     def __repr__(self):\r
2584         return "%s [%s]" % (self.MetaFile, self.Arch)\r
2585 \r
2586     # Get FixedAtBuild Pcds of this Module\r
2587     @cached_property\r
2588     def FixedAtBuildPcds(self):\r
2589         RetVal = []\r
2590         for Pcd in self.ModulePcdList:\r
2591             if Pcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
2592                 continue\r
2593             if Pcd not in RetVal:\r
2594                 RetVal.append(Pcd)\r
2595         return RetVal\r
2596 \r
2597     @cached_property\r
2598     def FixedVoidTypePcds(self):\r
2599         RetVal = {}\r
2600         for Pcd in self.FixedAtBuildPcds:\r
2601             if Pcd.DatumType == TAB_VOID:\r
2602                 if '{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName) not in RetVal:\r
2603                     RetVal['{}.{}'.format(Pcd.TokenSpaceGuidCName, Pcd.TokenCName)] = Pcd.DefaultValue\r
2604         return RetVal\r
2605 \r
2606     @property\r
2607     def UniqueBaseName(self):\r
2608         BaseName = self.Name\r
2609         for Module in self.PlatformInfo.ModuleAutoGenList:\r
2610             if Module.MetaFile == self.MetaFile:\r
2611                 continue\r
2612             if Module.Name == self.Name:\r
2613                 if uuid.UUID(Module.Guid) == uuid.UUID(self.Guid):\r
2614                     EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
2615                                     '  %s\n  %s' % (Module.MetaFile, self.MetaFile))\r
2616                 BaseName = '%s_%s' % (self.Name, self.Guid)\r
2617         return BaseName\r
2618 \r
2619     # Macros could be used in build_rule.txt (also Makefile)\r
2620     @cached_property\r
2621     def Macros(self):\r
2622         return OrderedDict((\r
2623             ("WORKSPACE" ,self.WorkspaceDir),\r
2624             ("MODULE_NAME" ,self.Name),\r
2625             ("MODULE_NAME_GUID" ,self.UniqueBaseName),\r
2626             ("MODULE_GUID" ,self.Guid),\r
2627             ("MODULE_VERSION" ,self.Version),\r
2628             ("MODULE_TYPE" ,self.ModuleType),\r
2629             ("MODULE_FILE" ,str(self.MetaFile)),\r
2630             ("MODULE_FILE_BASE_NAME" ,self.MetaFile.BaseName),\r
2631             ("MODULE_RELATIVE_DIR" ,self.SourceDir),\r
2632             ("MODULE_DIR" ,self.SourceDir),\r
2633             ("BASE_NAME" ,self.Name),\r
2634             ("ARCH" ,self.Arch),\r
2635             ("TOOLCHAIN" ,self.ToolChain),\r
2636             ("TOOLCHAIN_TAG" ,self.ToolChain),\r
2637             ("TOOL_CHAIN_TAG" ,self.ToolChain),\r
2638             ("TARGET" ,self.BuildTarget),\r
2639             ("BUILD_DIR" ,self.PlatformInfo.BuildDir),\r
2640             ("BIN_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),\r
2641             ("LIB_DIR" ,os.path.join(self.PlatformInfo.BuildDir, self.Arch)),\r
2642             ("MODULE_BUILD_DIR" ,self.BuildDir),\r
2643             ("OUTPUT_DIR" ,self.OutputDir),\r
2644             ("DEBUG_DIR" ,self.DebugDir),\r
2645             ("DEST_DIR_OUTPUT" ,self.OutputDir),\r
2646             ("DEST_DIR_DEBUG" ,self.DebugDir),\r
2647             ("PLATFORM_NAME" ,self.PlatformInfo.Name),\r
2648             ("PLATFORM_GUID" ,self.PlatformInfo.Guid),\r
2649             ("PLATFORM_VERSION" ,self.PlatformInfo.Version),\r
2650             ("PLATFORM_RELATIVE_DIR" ,self.PlatformInfo.SourceDir),\r
2651             ("PLATFORM_DIR" ,mws.join(self.WorkspaceDir, self.PlatformInfo.SourceDir)),\r
2652             ("PLATFORM_OUTPUT_DIR" ,self.PlatformInfo.OutputDir),\r
2653             ("FFS_OUTPUT_DIR" ,self.FfsOutputDir)\r
2654             ))\r