]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
BaseTools: remove unnecessary calls of os.exist
[mirror_edk2.git] / BaseTools / Source / Python / AutoGen / PlatformAutoGen.py
CommitLineData
e8449e1d
FB
1## @file\r
2# Create makefile for MS nmake and GNU make\r
3#\r
4# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
5# SPDX-License-Identifier: BSD-2-Clause-Patent\r
6#\r
7\r
8## Import Modules\r
9#\r
10from __future__ import print_function\r
11from __future__ import absolute_import\r
12import os.path as path\r
13import copy\r
14from collections import defaultdict\r
15\r
16from .BuildEngine import BuildRule,gDefaultBuildRuleFile,AutoGenReqBuildRuleVerNum\r
17from .GenVar import VariableMgr, var_info\r
18from . import GenMake\r
19from AutoGen.DataPipe import MemoryDataPipe\r
20from AutoGen.ModuleAutoGen import ModuleAutoGen\r
21from AutoGen.AutoGen import AutoGen\r
22from AutoGen.AutoGen import CalculatePriorityValue\r
23from Workspace.WorkspaceCommon import GetModuleLibInstances\r
24from CommonDataClass.CommonClass import SkuInfoClass\r
25from Common.caching import cached_class_function\r
26from Common.Expression import ValueExpressionEx\r
27from Common.StringUtils import StringToArray,NormPath\r
28from Common.BuildToolError import *\r
29from Common.DataType import *\r
30from Common.Misc import *\r
31import Common.VpdInfoFile as VpdInfoFile\r
32\r
33## Split command line option string to list\r
34#\r
35# subprocess.Popen needs the args to be a sequence. Otherwise there's problem\r
36# in non-windows platform to launch command\r
37#\r
38def _SplitOption(OptionString):\r
39 OptionList = []\r
40 LastChar = " "\r
41 OptionStart = 0\r
42 QuotationMark = ""\r
43 for Index in range(0, len(OptionString)):\r
44 CurrentChar = OptionString[Index]\r
45 if CurrentChar in ['"', "'"]:\r
46 if QuotationMark == CurrentChar:\r
47 QuotationMark = ""\r
48 elif QuotationMark == "":\r
49 QuotationMark = CurrentChar\r
50 continue\r
51 elif QuotationMark:\r
52 continue\r
53\r
54 if CurrentChar in ["/", "-"] and LastChar in [" ", "\t", "\r", "\n"]:\r
55 if Index > OptionStart:\r
56 OptionList.append(OptionString[OptionStart:Index - 1])\r
57 OptionStart = Index\r
58 LastChar = CurrentChar\r
59 OptionList.append(OptionString[OptionStart:])\r
60 return OptionList\r
61\r
62## AutoGen class for platform\r
63#\r
64# PlatformAutoGen class will process the original information in platform\r
65# file in order to generate makefile for platform.\r
66#\r
67class PlatformAutoGen(AutoGen):\r
68 # call super().__init__ then call the worker function with different parameter count\r
69 def __init__(self, Workspace, MetaFile, Target, Toolchain, Arch, *args, **kwargs):\r
70 if not hasattr(self, "_Init"):\r
71 self._InitWorker(Workspace, MetaFile, Target, Toolchain, Arch)\r
72 self._Init = True\r
73 #\r
74 # Used to store all PCDs for both PEI and DXE phase, in order to generate\r
75 # correct PCD database\r
76 #\r
77 _DynaPcdList_ = []\r
78 _NonDynaPcdList_ = []\r
79 _PlatformPcds = {}\r
80\r
81\r
82\r
83 ## Initialize PlatformAutoGen\r
84 #\r
85 #\r
86 # @param Workspace WorkspaceAutoGen object\r
87 # @param PlatformFile Platform file (DSC file)\r
88 # @param Target Build target (DEBUG, RELEASE)\r
89 # @param Toolchain Name of tool chain\r
90 # @param Arch arch of the platform supports\r
91 #\r
92 def _InitWorker(self, Workspace, PlatformFile, Target, Toolchain, Arch):\r
93 EdkLogger.debug(EdkLogger.DEBUG_9, "AutoGen platform [%s] [%s]" % (PlatformFile, Arch))\r
94 GlobalData.gProcessingFile = "%s [%s, %s, %s]" % (PlatformFile, Arch, Toolchain, Target)\r
95\r
96 self.MetaFile = PlatformFile\r
97 self.Workspace = Workspace\r
98 self.WorkspaceDir = Workspace.WorkspaceDir\r
99 self.ToolChain = Toolchain\r
100 self.BuildTarget = Target\r
101 self.Arch = Arch\r
102 self.SourceDir = PlatformFile.SubDir\r
103 self.FdTargetList = self.Workspace.FdTargetList\r
104 self.FvTargetList = self.Workspace.FvTargetList\r
105 # get the original module/package/platform objects\r
106 self.BuildDatabase = Workspace.BuildDatabase\r
107 self.DscBuildDataObj = Workspace.Platform\r
108\r
109 # flag indicating if the makefile/C-code file has been created or not\r
110 self.IsMakeFileCreated = False\r
111\r
112 self._DynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
113 self._NonDynamicPcdList = None # [(TokenCName1, TokenSpaceGuidCName1), (TokenCName2, TokenSpaceGuidCName2), ...]\r
114\r
115 self._AsBuildInfList = []\r
116 self._AsBuildModuleList = []\r
117\r
118 self.VariableInfo = None\r
119\r
120 if GlobalData.gFdfParser is not None:\r
121 self._AsBuildInfList = GlobalData.gFdfParser.Profile.InfList\r
122 for Inf in self._AsBuildInfList:\r
123 InfClass = PathClass(NormPath(Inf), GlobalData.gWorkspace, self.Arch)\r
124 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
125 if not M.IsBinaryModule:\r
126 continue\r
127 self._AsBuildModuleList.append(InfClass)\r
128 # get library/modules for build\r
129 self.LibraryBuildDirectoryList = []\r
130 self.ModuleBuildDirectoryList = []\r
131\r
132 self.DataPipe = MemoryDataPipe(self.BuildDir)\r
133 self.DataPipe.FillData(self)\r
134\r
135 return True\r
673d09a2
FB
136 def FillData_LibConstPcd(self):\r
137 libConstPcd = {}\r
138 for LibAuto in self.LibraryAutoGenList:\r
139 if LibAuto.ConstPcd:\r
140 libConstPcd[(LibAuto.MetaFile.File,LibAuto.MetaFile.Root,LibAuto.Arch,LibAuto.MetaFile.Path)] = LibAuto.ConstPcd\r
141 self.DataPipe.DataContainer = {"LibConstPcd":libConstPcd}\r
e8449e1d
FB
142 ## hash() operator of PlatformAutoGen\r
143 #\r
144 # The platform file path and arch string will be used to represent\r
145 # hash value of this object\r
146 #\r
147 # @retval int Hash value of the platform file path and arch\r
148 #\r
149 @cached_class_function\r
150 def __hash__(self):\r
151 return hash((self.MetaFile, self.Arch))\r
152 @cached_class_function\r
153 def __repr__(self):\r
154 return "%s [%s]" % (self.MetaFile, self.Arch)\r
155\r
156 ## Create autogen code for platform and modules\r
157 #\r
158 # Since there's no autogen code for platform, this method will do nothing\r
159 # if CreateModuleCodeFile is set to False.\r
160 #\r
161 # @param CreateModuleCodeFile Flag indicating if creating module's\r
162 # autogen code file or not\r
163 #\r
164 @cached_class_function\r
165 def CreateCodeFile(self, CreateModuleCodeFile=False):\r
166 # only module has code to be created, so do nothing if CreateModuleCodeFile is False\r
167 if not CreateModuleCodeFile:\r
168 return\r
169\r
170 for Ma in self.ModuleAutoGenList:\r
673d09a2 171 Ma.CreateCodeFile(CreateModuleCodeFile)\r
e8449e1d
FB
172\r
173 ## Generate Fds Command\r
174 @cached_property\r
175 def GenFdsCommand(self):\r
176 return self.Workspace.GenFdsCommand\r
177\r
178 ## Create makefile for the platform and modules in it\r
179 #\r
180 # @param CreateModuleMakeFile Flag indicating if the makefile for\r
181 # modules will be created as well\r
182 #\r
183 def CreateMakeFile(self, CreateModuleMakeFile=False, FfsCommand = {}):\r
184 if CreateModuleMakeFile:\r
185 for Ma in self._MaList:\r
186 key = (Ma.MetaFile.File, self.Arch)\r
187 if key in FfsCommand:\r
673d09a2 188 Ma.CreateMakeFile(CreateModuleMakeFile, FfsCommand[key])\r
e8449e1d 189 else:\r
673d09a2 190 Ma.CreateMakeFile(CreateModuleMakeFile)\r
373298ca 191 self.CreateLibModuelDirs()\r
e8449e1d 192\r
373298ca 193 def CreateLibModuelDirs(self):\r
e8449e1d
FB
194 # no need to create makefile for the platform more than once\r
195 if self.IsMakeFileCreated:\r
196 return\r
197\r
198 # create library/module build dirs for platform\r
199 Makefile = GenMake.PlatformMakefile(self)\r
200 self.LibraryBuildDirectoryList = Makefile.GetLibraryBuildDirectoryList()\r
201 self.ModuleBuildDirectoryList = Makefile.GetModuleBuildDirectoryList()\r
202\r
203 self.IsMakeFileCreated = True\r
204\r
205 @property\r
206 def AllPcdList(self):\r
207 return self.DynamicPcdList + self.NonDynamicPcdList\r
208 ## Deal with Shared FixedAtBuild Pcds\r
209 #\r
210 def CollectFixedAtBuildPcds(self):\r
211 for LibAuto in self.LibraryAutoGenList:\r
212 FixedAtBuildPcds = {}\r
213 ShareFixedAtBuildPcdsSameValue = {}\r
214 for Module in LibAuto.ReferenceModules:\r
215 for Pcd in set(Module.FixedAtBuildPcds + LibAuto.FixedAtBuildPcds):\r
216 DefaultValue = Pcd.DefaultValue\r
217 # Cover the case: DSC component override the Pcd value and the Pcd only used in one Lib\r
218 if Pcd in Module.LibraryPcdList:\r
219 Index = Module.LibraryPcdList.index(Pcd)\r
220 DefaultValue = Module.LibraryPcdList[Index].DefaultValue\r
221 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
222 if key not in FixedAtBuildPcds:\r
223 ShareFixedAtBuildPcdsSameValue[key] = True\r
224 FixedAtBuildPcds[key] = DefaultValue\r
225 else:\r
226 if FixedAtBuildPcds[key] != DefaultValue:\r
227 ShareFixedAtBuildPcdsSameValue[key] = False\r
228 for Pcd in LibAuto.FixedAtBuildPcds:\r
229 key = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
230 if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName) not in self.NonDynamicPcdDict:\r
231 continue\r
232 else:\r
233 DscPcd = self.NonDynamicPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]\r
234 if DscPcd.Type != TAB_PCDS_FIXED_AT_BUILD:\r
235 continue\r
236 if key in ShareFixedAtBuildPcdsSameValue and ShareFixedAtBuildPcdsSameValue[key]:\r
237 LibAuto.ConstPcd[key] = FixedAtBuildPcds[key]\r
238\r
239 def CollectVariables(self, DynamicPcdSet):\r
240 VpdRegionSize = 0\r
241 VpdRegionBase = 0\r
242 if self.Workspace.FdfFile:\r
243 FdDict = self.Workspace.FdfProfile.FdDict[GlobalData.gFdfParser.CurrentFdName]\r
244 for FdRegion in FdDict.RegionList:\r
245 for item in FdRegion.RegionDataList:\r
246 if self.Platform.VpdToolGuid.strip() and self.Platform.VpdToolGuid in item:\r
247 VpdRegionSize = FdRegion.Size\r
248 VpdRegionBase = FdRegion.Offset\r
249 break\r
250\r
251 VariableInfo = VariableMgr(self.DscBuildDataObj._GetDefaultStores(), self.DscBuildDataObj.SkuIds)\r
252 VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)\r
253 VariableInfo.SetVpdRegionOffset(VpdRegionBase)\r
254 Index = 0\r
255 for Pcd in DynamicPcdSet:\r
256 pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
257 for SkuName in Pcd.SkuInfoList:\r
258 Sku = Pcd.SkuInfoList[SkuName]\r
259 SkuId = Sku.SkuId\r
260 if SkuId is None or SkuId == '':\r
261 continue\r
262 if len(Sku.VariableName) > 0:\r
263 if Sku.VariableAttribute and 'NV' not in Sku.VariableAttribute:\r
264 continue\r
265 VariableGuidStructure = Sku.VariableGuidValue\r
266 VariableGuid = GuidStructureStringToGuidString(VariableGuidStructure)\r
267 for StorageName in Sku.DefaultStoreDict:\r
268 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
269 Index += 1\r
270 return VariableInfo\r
271\r
272 def UpdateNVStoreMaxSize(self, OrgVpdFile):\r
273 if self.VariableInfo:\r
274 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
275 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
276\r
277 if PcdNvStoreDfBuffer:\r
0075ab2c 278 try:\r
e8449e1d
FB
279 OrgVpdFile.Read(VpdMapFilePath)\r
280 PcdItems = OrgVpdFile.GetOffset(PcdNvStoreDfBuffer[0])\r
281 NvStoreOffset = list(PcdItems.values())[0].strip() if PcdItems else '0'\r
0075ab2c 282 except:\r
e8449e1d
FB
283 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
284\r
285 NvStoreOffset = int(NvStoreOffset, 16) if NvStoreOffset.upper().startswith("0X") else int(NvStoreOffset)\r
286 default_skuobj = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
287 maxsize = self.VariableInfo.VpdRegionSize - NvStoreOffset if self.VariableInfo.VpdRegionSize else len(default_skuobj.DefaultValue.split(","))\r
288 var_data = self.VariableInfo.PatchNVStoreDefaultMaxSize(maxsize)\r
289\r
290 if var_data and default_skuobj:\r
291 default_skuobj.DefaultValue = var_data\r
292 PcdNvStoreDfBuffer[0].DefaultValue = var_data\r
293 PcdNvStoreDfBuffer[0].SkuInfoList.clear()\r
294 PcdNvStoreDfBuffer[0].SkuInfoList[TAB_DEFAULT] = default_skuobj\r
295 PcdNvStoreDfBuffer[0].MaxDatumSize = str(len(default_skuobj.DefaultValue.split(",")))\r
296\r
297 return OrgVpdFile\r
298\r
299 ## Collect dynamic PCDs\r
300 #\r
301 # Gather dynamic PCDs list from each module and their settings from platform\r
302 # This interface should be invoked explicitly when platform action is created.\r
303 #\r
304 def CollectPlatformDynamicPcds(self):\r
305 self.CategoryPcds()\r
306 self.SortDynamicPcd()\r
307\r
308 def CategoryPcds(self):\r
309 # Category Pcds into DynamicPcds and NonDynamicPcds\r
310 # for gathering error information\r
311 NoDatumTypePcdList = set()\r
312 FdfModuleList = []\r
313 for InfName in self._AsBuildInfList:\r
314 InfName = mws.join(self.WorkspaceDir, InfName)\r
315 FdfModuleList.append(os.path.normpath(InfName))\r
316 for M in self._MbList:\r
317# F is the Module for which M is the module autogen\r
318 ModPcdList = self.ApplyPcdSetting(M, M.ModulePcdList)\r
319 LibPcdList = []\r
320 for lib in M.LibraryPcdList:\r
321 LibPcdList.extend(self.ApplyPcdSetting(M, M.LibraryPcdList[lib], lib))\r
322 for PcdFromModule in ModPcdList + LibPcdList:\r
323\r
324 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
325 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
326 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, M.MetaFile))\r
327\r
328 # Check the PCD from Binary INF or Source INF\r
329 if M.IsBinaryModule == True:\r
330 PcdFromModule.IsFromBinaryInf = True\r
331\r
332 # Check the PCD from DSC or not\r
333 PcdFromModule.IsFromDsc = (PcdFromModule.TokenCName, PcdFromModule.TokenSpaceGuidCName) in self.Platform.Pcds\r
334\r
335 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET or PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
336 if M.MetaFile.Path not in FdfModuleList:\r
337 # If one of the Source built modules listed in the DSC is not listed\r
338 # in FDF modules, and the INF lists a PCD can only use the PcdsDynamic\r
339 # access method (it is only listed in the DEC file that declares the\r
340 # PCD as PcdsDynamic), then build tool will report warning message\r
341 # notify the PI that they are attempting to build a module that must\r
342 # be included in a flash image in order to be functional. These Dynamic\r
343 # PCD will not be added into the Database unless it is used by other\r
344 # modules that are included in the FDF file.\r
345 if PcdFromModule.Type in PCD_DYNAMIC_TYPE_SET and \\r
346 PcdFromModule.IsFromBinaryInf == False:\r
347 # Print warning message to let the developer make a determine.\r
348 continue\r
349 # If one of the Source built modules listed in the DSC is not listed in\r
350 # FDF modules, and the INF lists a PCD can only use the PcdsDynamicEx\r
351 # access method (it is only listed in the DEC file that declares the\r
352 # PCD as PcdsDynamicEx), then DO NOT break the build; DO NOT add the\r
353 # PCD to the Platform's PCD Database.\r
354 if PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
355 continue\r
356 #\r
357 # If a dynamic PCD used by a PEM module/PEI module & DXE module,\r
358 # it should be stored in Pcd PEI database, If a dynamic only\r
359 # used by DXE module, it should be stored in DXE PCD database.\r
360 # The default Phase is DXE\r
361 #\r
362 if M.ModuleType in SUP_MODULE_SET_PEI:\r
363 PcdFromModule.Phase = "PEI"\r
364 if PcdFromModule not in self._DynaPcdList_:\r
365 self._DynaPcdList_.append(PcdFromModule)\r
366 elif PcdFromModule.Phase == 'PEI':\r
367 # overwrite any the same PCD existing, if Phase is PEI\r
368 Index = self._DynaPcdList_.index(PcdFromModule)\r
369 self._DynaPcdList_[Index] = PcdFromModule\r
370 elif PcdFromModule not in self._NonDynaPcdList_:\r
371 self._NonDynaPcdList_.append(PcdFromModule)\r
372 elif PcdFromModule in self._NonDynaPcdList_ and PcdFromModule.IsFromBinaryInf == True:\r
373 Index = self._NonDynaPcdList_.index(PcdFromModule)\r
374 if self._NonDynaPcdList_[Index].IsFromBinaryInf == False:\r
375 #The PCD from Binary INF will override the same one from source INF\r
376 self._NonDynaPcdList_.remove (self._NonDynaPcdList_[Index])\r
377 PcdFromModule.Pending = False\r
378 self._NonDynaPcdList_.append (PcdFromModule)\r
379 DscModuleSet = {os.path.normpath(ModuleInf.Path) for ModuleInf in self.Platform.Modules}\r
380 # add the PCD from modules that listed in FDF but not in DSC to Database\r
381 for InfName in FdfModuleList:\r
382 if InfName not in DscModuleSet:\r
383 InfClass = PathClass(InfName)\r
384 M = self.BuildDatabase[InfClass, self.Arch, self.BuildTarget, self.ToolChain]\r
385 # If a module INF in FDF but not in current arch's DSC module list, it must be module (either binary or source)\r
386 # for different Arch. PCDs in source module for different Arch is already added before, so skip the source module here.\r
387 # For binary module, if in current arch, we need to list the PCDs into database.\r
388 if not M.IsBinaryModule:\r
389 continue\r
390 # Override the module PCD setting by platform setting\r
391 ModulePcdList = self.ApplyPcdSetting(M, M.Pcds)\r
392 for PcdFromModule in ModulePcdList:\r
393 PcdFromModule.IsFromBinaryInf = True\r
394 PcdFromModule.IsFromDsc = False\r
395 # Only allow the DynamicEx and Patchable PCD in AsBuild INF\r
396 if PcdFromModule.Type not in PCD_DYNAMIC_EX_TYPE_SET and PcdFromModule.Type not in TAB_PCDS_PATCHABLE_IN_MODULE:\r
397 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
398 File=self.MetaFile,\r
399 ExtraData="\n\tExisted %s PCD %s in:\n\t\t%s\n"\r
400 % (PcdFromModule.Type, PcdFromModule.TokenCName, InfName))\r
401 # make sure that the "VOID*" kind of datum has MaxDatumSize set\r
402 if PcdFromModule.DatumType == TAB_VOID and not PcdFromModule.MaxDatumSize:\r
403 NoDatumTypePcdList.add("%s.%s [%s]" % (PcdFromModule.TokenSpaceGuidCName, PcdFromModule.TokenCName, InfName))\r
404 if M.ModuleType in SUP_MODULE_SET_PEI:\r
405 PcdFromModule.Phase = "PEI"\r
406 if PcdFromModule not in self._DynaPcdList_ and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
407 self._DynaPcdList_.append(PcdFromModule)\r
408 elif PcdFromModule not in self._NonDynaPcdList_ and PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE:\r
409 self._NonDynaPcdList_.append(PcdFromModule)\r
410 if PcdFromModule in self._DynaPcdList_ and PcdFromModule.Phase == 'PEI' and PcdFromModule.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
411 # Overwrite the phase of any the same PCD existing, if Phase is PEI.\r
412 # It is to solve the case that a dynamic PCD used by a PEM module/PEI\r
413 # module & DXE module at a same time.\r
414 # Overwrite the type of the PCDs in source INF by the type of AsBuild\r
415 # INF file as DynamicEx.\r
416 Index = self._DynaPcdList_.index(PcdFromModule)\r
417 self._DynaPcdList_[Index].Phase = PcdFromModule.Phase\r
418 self._DynaPcdList_[Index].Type = PcdFromModule.Type\r
419 for PcdFromModule in self._NonDynaPcdList_:\r
420 # If a PCD is not listed in the DSC file, but binary INF files used by\r
421 # this platform all (that use this PCD) list the PCD in a [PatchPcds]\r
422 # section, AND all source INF files used by this platform the build\r
423 # that use the PCD list the PCD in either a [Pcds] or [PatchPcds]\r
424 # section, then the tools must NOT add the PCD to the Platform's PCD\r
425 # Database; the build must assign the access method for this PCD as\r
426 # PcdsPatchableInModule.\r
427 if PcdFromModule not in self._DynaPcdList_:\r
428 continue\r
429 Index = self._DynaPcdList_.index(PcdFromModule)\r
430 if PcdFromModule.IsFromDsc == False and \\r
431 PcdFromModule.Type in TAB_PCDS_PATCHABLE_IN_MODULE and \\r
432 PcdFromModule.IsFromBinaryInf == True and \\r
433 self._DynaPcdList_[Index].IsFromBinaryInf == False:\r
434 Index = self._DynaPcdList_.index(PcdFromModule)\r
435 self._DynaPcdList_.remove (self._DynaPcdList_[Index])\r
436\r
437 # print out error information and break the build, if error found\r
438 if len(NoDatumTypePcdList) > 0:\r
439 NoDatumTypePcdListString = "\n\t\t".join(NoDatumTypePcdList)\r
440 EdkLogger.error("build", AUTOGEN_ERROR, "PCD setting error",\r
441 File=self.MetaFile,\r
442 ExtraData="\n\tPCD(s) without MaxDatumSize:\n\t\t%s\n"\r
443 % NoDatumTypePcdListString)\r
000ab985 444 self._NonDynamicPcdList = sorted(self._NonDynaPcdList_)\r
e8449e1d
FB
445 self._DynamicPcdList = self._DynaPcdList_\r
446\r
447 def SortDynamicPcd(self):\r
448 #\r
449 # Sort dynamic PCD list to:\r
450 # 1) If PCD's datum type is VOID* and value is unicode string which starts with L, the PCD item should\r
451 # try to be put header of dynamicd List\r
452 # 2) If PCD is HII type, the PCD item should be put after unicode type PCD\r
453 #\r
454 # The reason of sorting is make sure the unicode string is in double-byte alignment in string table.\r
455 #\r
456 UnicodePcdArray = set()\r
457 HiiPcdArray = set()\r
458 OtherPcdArray = set()\r
459 VpdPcdDict = {}\r
460 VpdFile = VpdInfoFile.VpdInfoFile()\r
461 NeedProcessVpdMapFile = False\r
462\r
463 for pcd in self.Platform.Pcds:\r
464 if pcd not in self._PlatformPcds:\r
465 self._PlatformPcds[pcd] = self.Platform.Pcds[pcd]\r
466\r
467 for item in self._PlatformPcds:\r
468 if self._PlatformPcds[item].DatumType and self._PlatformPcds[item].DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
469 self._PlatformPcds[item].DatumType = TAB_VOID\r
470\r
471 if (self.Workspace.ArchList[-1] == self.Arch):\r
472 for Pcd in self._DynamicPcdList:\r
473 # just pick the a value to determine whether is unicode string type\r
474 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
475 Sku.VpdOffset = Sku.VpdOffset.strip()\r
476\r
477 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
478 Pcd.DatumType = TAB_VOID\r
479\r
480 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
481 # if found HII type PCD then insert to right of UnicodeIndex\r
482 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
483 VpdPcdDict[(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)] = Pcd\r
484\r
485 #Collect DynamicHii PCD values and assign it to DynamicExVpd PCD gEfiMdeModulePkgTokenSpaceGuid.PcdNvStoreDefaultValueBuffer\r
486 PcdNvStoreDfBuffer = VpdPcdDict.get(("PcdNvStoreDefaultValueBuffer", "gEfiMdeModulePkgTokenSpaceGuid"))\r
487 if PcdNvStoreDfBuffer:\r
488 self.VariableInfo = self.CollectVariables(self._DynamicPcdList)\r
489 vardump = self.VariableInfo.dump()\r
490 if vardump:\r
491 #\r
492 #According to PCD_DATABASE_INIT in edk2\MdeModulePkg\Include\Guid\PcdDataBaseSignatureGuid.h,\r
493 #the max size for string PCD should not exceed USHRT_MAX 65535(0xffff).\r
494 #typedef UINT16 SIZE_INFO;\r
495 #//SIZE_INFO SizeTable[];\r
496 if len(vardump.split(",")) > 0xffff:\r
497 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
498 PcdNvStoreDfBuffer.DefaultValue = vardump\r
499 for skuname in PcdNvStoreDfBuffer.SkuInfoList:\r
500 PcdNvStoreDfBuffer.SkuInfoList[skuname].DefaultValue = vardump\r
501 PcdNvStoreDfBuffer.MaxDatumSize = str(len(vardump.split(",")))\r
502 else:\r
503 #If the end user define [DefaultStores] and [XXX.Menufacturing] in DSC, but forget to configure PcdNvStoreDefaultValueBuffer to PcdsDynamicVpd\r
504 if [Pcd for Pcd in self._DynamicPcdList if Pcd.UserDefinedDefaultStoresFlag]:\r
505 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
506 PlatformPcds = sorted(self._PlatformPcds.keys())\r
507 #\r
508 # Add VPD type PCD into VpdFile and determine whether the VPD PCD need to be fixed up.\r
509 #\r
510 VpdSkuMap = {}\r
511 for PcdKey in PlatformPcds:\r
512 Pcd = self._PlatformPcds[PcdKey]\r
513 if Pcd.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD] and \\r
514 PcdKey in VpdPcdDict:\r
515 Pcd = VpdPcdDict[PcdKey]\r
516 SkuValueMap = {}\r
517 DefaultSku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
518 if DefaultSku:\r
519 PcdValue = DefaultSku.DefaultValue\r
520 if PcdValue not in SkuValueMap:\r
521 SkuValueMap[PcdValue] = []\r
522 VpdFile.Add(Pcd, TAB_DEFAULT, DefaultSku.VpdOffset)\r
523 SkuValueMap[PcdValue].append(DefaultSku)\r
524\r
525 for (SkuName, Sku) in Pcd.SkuInfoList.items():\r
526 Sku.VpdOffset = Sku.VpdOffset.strip()\r
527 PcdValue = Sku.DefaultValue\r
528 if PcdValue == "":\r
529 PcdValue = Pcd.DefaultValue\r
530 if Sku.VpdOffset != TAB_STAR:\r
531 if PcdValue.startswith("{"):\r
532 Alignment = 8\r
533 elif PcdValue.startswith("L"):\r
534 Alignment = 2\r
535 else:\r
536 Alignment = 1\r
537 try:\r
538 VpdOffset = int(Sku.VpdOffset)\r
539 except:\r
540 try:\r
541 VpdOffset = int(Sku.VpdOffset, 16)\r
542 except:\r
543 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, Pcd.TokenSpaceGuidCName, Pcd.TokenCName))\r
544 if VpdOffset % Alignment != 0:\r
545 if PcdValue.startswith("{"):\r
546 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(Pcd.TokenSpaceGuidCName, Pcd.TokenCName), File=self.MetaFile)\r
547 else:\r
548 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Alignment))\r
549 if PcdValue not in SkuValueMap:\r
550 SkuValueMap[PcdValue] = []\r
551 VpdFile.Add(Pcd, SkuName, Sku.VpdOffset)\r
552 SkuValueMap[PcdValue].append(Sku)\r
553 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
554 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
555 NeedProcessVpdMapFile = True\r
556 if self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == '':\r
557 EdkLogger.error("Build", FILE_NOT_FOUND, \\r
558 "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
559\r
560 VpdSkuMap[PcdKey] = SkuValueMap\r
561 #\r
562 # Fix the PCDs define in VPD PCD section that never referenced by module.\r
563 # An example is PCD for signature usage.\r
564 #\r
565 for DscPcd in PlatformPcds:\r
566 DscPcdEntry = self._PlatformPcds[DscPcd]\r
567 if DscPcdEntry.Type in [TAB_PCDS_DYNAMIC_VPD, TAB_PCDS_DYNAMIC_EX_VPD]:\r
568 if not (self.Platform.VpdToolGuid is None or self.Platform.VpdToolGuid == ''):\r
569 FoundFlag = False\r
570 for VpdPcd in VpdFile._VpdArray:\r
571 # This PCD has been referenced by module\r
572 if (VpdPcd.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
573 (VpdPcd.TokenCName == DscPcdEntry.TokenCName):\r
574 FoundFlag = True\r
575\r
576 # Not found, it should be signature\r
577 if not FoundFlag :\r
578 # just pick the a value to determine whether is unicode string type\r
579 SkuValueMap = {}\r
580 SkuObjList = list(DscPcdEntry.SkuInfoList.items())\r
581 DefaultSku = DscPcdEntry.SkuInfoList.get(TAB_DEFAULT)\r
582 if DefaultSku:\r
583 defaultindex = SkuObjList.index((TAB_DEFAULT, DefaultSku))\r
584 SkuObjList[0], SkuObjList[defaultindex] = SkuObjList[defaultindex], SkuObjList[0]\r
585 for (SkuName, Sku) in SkuObjList:\r
586 Sku.VpdOffset = Sku.VpdOffset.strip()\r
587\r
588 # Need to iterate DEC pcd information to get the value & datumtype\r
589 for eachDec in self.PackageList:\r
590 for DecPcd in eachDec.Pcds:\r
591 DecPcdEntry = eachDec.Pcds[DecPcd]\r
592 if (DecPcdEntry.TokenSpaceGuidCName == DscPcdEntry.TokenSpaceGuidCName) and \\r
593 (DecPcdEntry.TokenCName == DscPcdEntry.TokenCName):\r
594 # Print warning message to let the developer make a determine.\r
595 EdkLogger.warn("build", "Unreferenced vpd pcd used!",\r
596 File=self.MetaFile, \\r
597 ExtraData = "PCD: %s.%s used in the DSC file %s is unreferenced." \\r
598 %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, self.Platform.MetaFile.Path))\r
599\r
600 DscPcdEntry.DatumType = DecPcdEntry.DatumType\r
601 DscPcdEntry.DefaultValue = DecPcdEntry.DefaultValue\r
602 DscPcdEntry.TokenValue = DecPcdEntry.TokenValue\r
603 DscPcdEntry.TokenSpaceGuidValue = eachDec.Guids[DecPcdEntry.TokenSpaceGuidCName]\r
604 # Only fix the value while no value provided in DSC file.\r
605 if not Sku.DefaultValue:\r
606 DscPcdEntry.SkuInfoList[list(DscPcdEntry.SkuInfoList.keys())[0]].DefaultValue = DecPcdEntry.DefaultValue\r
607\r
608 if DscPcdEntry not in self._DynamicPcdList:\r
609 self._DynamicPcdList.append(DscPcdEntry)\r
610 Sku.VpdOffset = Sku.VpdOffset.strip()\r
611 PcdValue = Sku.DefaultValue\r
612 if PcdValue == "":\r
613 PcdValue = DscPcdEntry.DefaultValue\r
614 if Sku.VpdOffset != TAB_STAR:\r
615 if PcdValue.startswith("{"):\r
616 Alignment = 8\r
617 elif PcdValue.startswith("L"):\r
618 Alignment = 2\r
619 else:\r
620 Alignment = 1\r
621 try:\r
622 VpdOffset = int(Sku.VpdOffset)\r
623 except:\r
624 try:\r
625 VpdOffset = int(Sku.VpdOffset, 16)\r
626 except:\r
627 EdkLogger.error("build", FORMAT_INVALID, "Invalid offset value %s for PCD %s.%s." % (Sku.VpdOffset, DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName))\r
628 if VpdOffset % Alignment != 0:\r
629 if PcdValue.startswith("{"):\r
630 EdkLogger.warn("build", "The offset value of PCD %s.%s is not 8-byte aligned!" %(DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName), File=self.MetaFile)\r
631 else:\r
632 EdkLogger.error("build", FORMAT_INVALID, 'The offset value of PCD %s.%s should be %s-byte aligned.' % (DscPcdEntry.TokenSpaceGuidCName, DscPcdEntry.TokenCName, Alignment))\r
633 if PcdValue not in SkuValueMap:\r
634 SkuValueMap[PcdValue] = []\r
635 VpdFile.Add(DscPcdEntry, SkuName, Sku.VpdOffset)\r
636 SkuValueMap[PcdValue].append(Sku)\r
637 if not NeedProcessVpdMapFile and Sku.VpdOffset == TAB_STAR:\r
638 NeedProcessVpdMapFile = True\r
639 if DscPcdEntry.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
640 UnicodePcdArray.add(DscPcdEntry)\r
641 elif len(Sku.VariableName) > 0:\r
642 HiiPcdArray.add(DscPcdEntry)\r
643 else:\r
644 OtherPcdArray.add(DscPcdEntry)\r
645\r
646 # if the offset of a VPD is *, then it need to be fixed up by third party tool.\r
647 VpdSkuMap[DscPcd] = SkuValueMap\r
648 if (self.Platform.FlashDefinition is None or self.Platform.FlashDefinition == '') and \\r
649 VpdFile.GetCount() != 0:\r
650 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,\r
651 "Fail to get FLASH_DEFINITION definition in DSC file %s which is required when DSC contains VPD PCD." % str(self.Platform.MetaFile))\r
652\r
653 if VpdFile.GetCount() != 0:\r
654\r
655 self.FixVpdOffset(VpdFile)\r
656\r
657 self.FixVpdOffset(self.UpdateNVStoreMaxSize(VpdFile))\r
658 PcdNvStoreDfBuffer = [item for item in self._DynamicPcdList if item.TokenCName == "PcdNvStoreDefaultValueBuffer" and item.TokenSpaceGuidCName == "gEfiMdeModulePkgTokenSpaceGuid"]\r
659 if PcdNvStoreDfBuffer:\r
660 PcdName,PcdGuid = PcdNvStoreDfBuffer[0].TokenCName, PcdNvStoreDfBuffer[0].TokenSpaceGuidCName\r
661 if (PcdName,PcdGuid) in VpdSkuMap:\r
662 DefaultSku = PcdNvStoreDfBuffer[0].SkuInfoList.get(TAB_DEFAULT)\r
663 VpdSkuMap[(PcdName,PcdGuid)] = {DefaultSku.DefaultValue:[SkuObj for SkuObj in PcdNvStoreDfBuffer[0].SkuInfoList.values() ]}\r
664\r
665 # Process VPD map file generated by third party BPDG tool\r
666 if NeedProcessVpdMapFile:\r
667 VpdMapFilePath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY, "%s.map" % self.Platform.VpdToolGuid)\r
0075ab2c 668 try:\r
e8449e1d
FB
669 VpdFile.Read(VpdMapFilePath)\r
670\r
671 # Fixup TAB_STAR offset\r
672 for pcd in VpdSkuMap:\r
673 vpdinfo = VpdFile.GetVpdInfo(pcd)\r
674 if vpdinfo is None:\r
675 # just pick the a value to determine whether is unicode string type\r
676 continue\r
677 for pcdvalue in VpdSkuMap[pcd]:\r
678 for sku in VpdSkuMap[pcd][pcdvalue]:\r
679 for item in vpdinfo:\r
680 if item[2] == pcdvalue:\r
681 sku.VpdOffset = item[1]\r
0075ab2c 682 except:\r
e8449e1d
FB
683 EdkLogger.error("build", FILE_READ_FAILURE, "Can not find VPD map file %s to fix up VPD offset." % VpdMapFilePath)\r
684\r
685 # Delete the DynamicPcdList At the last time enter into this function\r
686 for Pcd in self._DynamicPcdList:\r
687 # just pick the a value to determine whether is unicode string type\r
688 Sku = Pcd.SkuInfoList.get(TAB_DEFAULT)\r
689 Sku.VpdOffset = Sku.VpdOffset.strip()\r
690\r
691 if Pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:\r
692 Pcd.DatumType = TAB_VOID\r
693\r
694 PcdValue = Sku.DefaultValue\r
695 if Pcd.DatumType == TAB_VOID and PcdValue.startswith("L"):\r
696 # if found PCD which datum value is unicode string the insert to left size of UnicodeIndex\r
697 UnicodePcdArray.add(Pcd)\r
698 elif len(Sku.VariableName) > 0:\r
699 # if found HII type PCD then insert to right of UnicodeIndex\r
700 HiiPcdArray.add(Pcd)\r
701 else:\r
702 OtherPcdArray.add(Pcd)\r
703 del self._DynamicPcdList[:]\r
704 self._DynamicPcdList.extend(list(UnicodePcdArray))\r
705 self._DynamicPcdList.extend(list(HiiPcdArray))\r
706 self._DynamicPcdList.extend(list(OtherPcdArray))\r
000ab985 707 self._DynamicPcdList.sort()\r
e8449e1d
FB
708 allskuset = [(SkuName, Sku.SkuId) for pcd in self._DynamicPcdList for (SkuName, Sku) in pcd.SkuInfoList.items()]\r
709 for pcd in self._DynamicPcdList:\r
710 if len(pcd.SkuInfoList) == 1:\r
711 for (SkuName, SkuId) in allskuset:\r
712 if isinstance(SkuId, str) and eval(SkuId) == 0 or SkuId == 0:\r
713 continue\r
714 pcd.SkuInfoList[SkuName] = copy.deepcopy(pcd.SkuInfoList[TAB_DEFAULT])\r
715 pcd.SkuInfoList[SkuName].SkuId = SkuId\r
716 pcd.SkuInfoList[SkuName].SkuIdName = SkuName\r
717\r
718 def FixVpdOffset(self, VpdFile ):\r
719 FvPath = os.path.join(self.BuildDir, TAB_FV_DIRECTORY)\r
720 if not os.path.exists(FvPath):\r
721 try:\r
722 os.makedirs(FvPath)\r
723 except:\r
724 EdkLogger.error("build", FILE_WRITE_FAILURE, "Fail to create FV folder under %s" % self.BuildDir)\r
725\r
726 VpdFilePath = os.path.join(FvPath, "%s.txt" % self.Platform.VpdToolGuid)\r
727\r
728 if VpdFile.Write(VpdFilePath):\r
729 # retrieve BPDG tool's path from tool_def.txt according to VPD_TOOL_GUID defined in DSC file.\r
730 BPDGToolName = None\r
731 for ToolDef in self.ToolDefinition.values():\r
732 if TAB_GUID in ToolDef and ToolDef[TAB_GUID] == self.Platform.VpdToolGuid:\r
733 if "PATH" not in ToolDef:\r
734 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "PATH attribute was not provided for BPDG guid tool %s in tools_def.txt" % self.Platform.VpdToolGuid)\r
735 BPDGToolName = ToolDef["PATH"]\r
736 break\r
737 # Call third party GUID BPDG tool.\r
738 if BPDGToolName is not None:\r
739 VpdInfoFile.CallExtenalBPDGTool(BPDGToolName, VpdFilePath)\r
740 else:\r
741 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
742\r
743 ## Return the platform build data object\r
744 @cached_property\r
745 def Platform(self):\r
746 return self.BuildDatabase[self.MetaFile, self.Arch, self.BuildTarget, self.ToolChain]\r
747\r
748 ## Return platform name\r
749 @cached_property\r
750 def Name(self):\r
751 return self.Platform.PlatformName\r
752\r
753 ## Return the meta file GUID\r
754 @cached_property\r
755 def Guid(self):\r
756 return self.Platform.Guid\r
757\r
758 ## Return the platform version\r
759 @cached_property\r
760 def Version(self):\r
761 return self.Platform.Version\r
762\r
763 ## Return the FDF file name\r
764 @cached_property\r
765 def FdfFile(self):\r
766 if self.Workspace.FdfFile:\r
767 RetVal= mws.join(self.WorkspaceDir, self.Workspace.FdfFile)\r
768 else:\r
769 RetVal = ''\r
770 return RetVal\r
771\r
772 ## Return the build output directory platform specifies\r
773 @cached_property\r
774 def OutputDir(self):\r
775 return self.Platform.OutputDirectory\r
776\r
777 ## Return the directory to store all intermediate and final files built\r
778 @cached_property\r
779 def BuildDir(self):\r
780 if os.path.isabs(self.OutputDir):\r
781 GlobalData.gBuildDirectory = RetVal = path.join(\r
782 path.abspath(self.OutputDir),\r
783 self.BuildTarget + "_" + self.ToolChain,\r
784 )\r
785 else:\r
786 GlobalData.gBuildDirectory = RetVal = path.join(\r
787 self.WorkspaceDir,\r
788 self.OutputDir,\r
789 self.BuildTarget + "_" + self.ToolChain,\r
790 )\r
791 return RetVal\r
792\r
793 ## Return directory of platform makefile\r
794 #\r
795 # @retval string Makefile directory\r
796 #\r
797 @cached_property\r
798 def MakeFileDir(self):\r
799 return path.join(self.BuildDir, self.Arch)\r
800\r
801 ## Return build command string\r
802 #\r
803 # @retval string Build command string\r
804 #\r
805 @cached_property\r
806 def BuildCommand(self):\r
807 RetVal = []\r
808 if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
809 RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
810 if "FLAGS" in self.ToolDefinition["MAKE"]:\r
811 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
812 if NewOption != '':\r
813 RetVal += _SplitOption(NewOption)\r
814 if "MAKE" in self.EdkIIBuildOption:\r
815 if "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
816 Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
817 if Flags.startswith('='):\r
818 RetVal = [RetVal[0]] + [Flags[1:]]\r
819 else:\r
820 RetVal.append(Flags)\r
821 return RetVal\r
822\r
823 ## Get tool chain definition\r
824 #\r
825 # Get each tool definition for given tool chain from tools_def.txt and platform\r
826 #\r
827 @cached_property\r
828 def ToolDefinition(self):\r
829 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
830 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
831 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
832 ExtraData="[%s]" % self.MetaFile)\r
833 RetVal = OrderedDict()\r
834 DllPathList = set()\r
835 for Def in ToolDefinition:\r
836 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
837 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
838 continue\r
839\r
840 Value = ToolDefinition[Def]\r
841 # don't record the DLL\r
842 if Attr == "DLL":\r
843 DllPathList.add(Value)\r
844 continue\r
845\r
846 if Tool not in RetVal:\r
847 RetVal[Tool] = OrderedDict()\r
848 RetVal[Tool][Attr] = Value\r
849\r
850 ToolsDef = ''\r
851 if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:\r
852 if "FLAGS" not in RetVal["MAKE"]:\r
853 RetVal["MAKE"]["FLAGS"] = ""\r
854 RetVal["MAKE"]["FLAGS"] += " -s"\r
855 MakeFlags = ''\r
856 for Tool in RetVal:\r
857 for Attr in RetVal[Tool]:\r
858 Value = RetVal[Tool][Attr]\r
859 if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:\r
860 # check if override is indicated\r
861 if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):\r
862 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]\r
863 else:\r
864 if Attr != 'PATH':\r
865 Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
866 else:\r
867 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
868\r
869 if Attr == "PATH":\r
870 # Don't put MAKE definition in the file\r
871 if Tool != "MAKE":\r
872 ToolsDef += "%s = %s\n" % (Tool, Value)\r
873 elif Attr != "DLL":\r
874 # Don't put MAKE definition in the file\r
875 if Tool == "MAKE":\r
876 if Attr == "FLAGS":\r
877 MakeFlags = Value\r
878 else:\r
879 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
880 ToolsDef += "\n"\r
881\r
882 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
883 SaveFileOnChange(tool_def_file, ToolsDef, False)\r
884 for DllPath in DllPathList:\r
885 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
886 os.environ["MAKE_FLAGS"] = MakeFlags\r
887\r
888 return RetVal\r
889\r
890 ## Return the paths of tools\r
891 @cached_property\r
892 def ToolDefinitionFile(self):\r
893 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
894 if not os.path.exists(tool_def_file):\r
895 self.ToolDefinition\r
896 return tool_def_file\r
897\r
898 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
899 @cached_property\r
900 def ToolChainFamily(self):\r
901 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
902 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
903 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
904 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
905 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
906 % self.ToolChain)\r
907 RetVal = TAB_COMPILER_MSFT\r
908 else:\r
909 RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
910 return RetVal\r
911\r
912 @cached_property\r
913 def BuildRuleFamily(self):\r
914 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
915 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
916 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
917 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
918 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
919 % self.ToolChain)\r
920 return TAB_COMPILER_MSFT\r
921\r
922 return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
923\r
924 ## Return the build options specific for all modules in this platform\r
925 @cached_property\r
926 def BuildOption(self):\r
927 return self._ExpandBuildOption(self.Platform.BuildOptions)\r
928\r
929 def _BuildOptionWithToolDef(self, ToolDef):\r
930 return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)\r
931\r
932 ## Return the build options specific for EDK modules in this platform\r
933 @cached_property\r
934 def EdkBuildOption(self):\r
935 return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
936\r
937 ## Return the build options specific for EDKII modules in this platform\r
938 @cached_property\r
939 def EdkIIBuildOption(self):\r
940 return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
941\r
942 ## Parse build_rule.txt in Conf Directory.\r
943 #\r
944 # @retval BuildRule object\r
945 #\r
946 @cached_property\r
947 def BuildRule(self):\r
948 BuildRuleFile = None\r
949 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
950 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
951 if not BuildRuleFile:\r
952 BuildRuleFile = gDefaultBuildRuleFile\r
953 RetVal = BuildRule(BuildRuleFile)\r
954 if RetVal._FileVersion == "":\r
955 RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r
956 else:\r
957 if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :\r
958 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
959 EdkLogger.error("build", AUTOGEN_ERROR,\r
960 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
961 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))\r
962 return RetVal\r
963\r
964 ## Summarize the packages used by modules in this platform\r
965 @cached_property\r
966 def PackageList(self):\r
967 RetVal = set()\r
968 for Mb in self._MbList:\r
969 RetVal.update(Mb.Packages)\r
970 for lb in Mb.LibInstances:\r
971 RetVal.update(lb.Packages)\r
972 #Collect package set information from INF of FDF\r
973 for ModuleFile in self._AsBuildModuleList:\r
974 if ModuleFile in self.Platform.Modules:\r
975 continue\r
976 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
977 RetVal.update(ModuleData.Packages)\r
978 return list(RetVal)\r
979\r
980 @cached_property\r
981 def NonDynamicPcdDict(self):\r
982 return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}\r
983\r
984 ## Get list of non-dynamic PCDs\r
985 @property\r
986 def NonDynamicPcdList(self):\r
987 if not self._NonDynamicPcdList:\r
988 self.CollectPlatformDynamicPcds()\r
989 return self._NonDynamicPcdList\r
990\r
991 ## Get list of dynamic PCDs\r
992 @property\r
993 def DynamicPcdList(self):\r
994 if not self._DynamicPcdList:\r
995 self.CollectPlatformDynamicPcds()\r
996 return self._DynamicPcdList\r
997\r
998 ## Generate Token Number for all PCD\r
999 @cached_property\r
1000 def PcdTokenNumber(self):\r
1001 RetVal = OrderedDict()\r
1002 TokenNumber = 1\r
1003 #\r
1004 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.\r
1005 # Such as:\r
1006 #\r
1007 # Dynamic PCD:\r
1008 # TokenNumber 0 ~ 10\r
1009 # DynamicEx PCD:\r
1010 # TokeNumber 11 ~ 20\r
1011 #\r
1012 for Pcd in self.DynamicPcdList:\r
1013 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
1014 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1015 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1016 TokenNumber += 1\r
1017\r
1018 for Pcd in self.DynamicPcdList:\r
1019 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1020 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1021 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1022 TokenNumber += 1\r
1023\r
1024 for Pcd in self.DynamicPcdList:\r
1025 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
1026 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1027 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1028 TokenNumber += 1\r
1029\r
1030 for Pcd in self.DynamicPcdList:\r
1031 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1032 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1033 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1034 TokenNumber += 1\r
1035\r
1036 for Pcd in self.NonDynamicPcdList:\r
1037 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1038 TokenNumber += 1\r
1039 return RetVal\r
1040\r
1041 @cached_property\r
1042 def _MbList(self):\r
1043 return [self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]\r
1044\r
1045 @cached_property\r
1046 def _MaList(self):\r
1047 for ModuleFile in self.Platform.Modules:\r
1048 Ma = ModuleAutoGen(\r
1049 self.Workspace,\r
1050 ModuleFile,\r
1051 self.BuildTarget,\r
1052 self.ToolChain,\r
1053 self.Arch,\r
1054 self.MetaFile,\r
1055 self.DataPipe\r
1056 )\r
1057 self.Platform.Modules[ModuleFile].M = Ma\r
1058 return [x.M for x in self.Platform.Modules.values()]\r
1059\r
1060 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
1061 @cached_property\r
1062 def ModuleAutoGenList(self):\r
1063 RetVal = []\r
1064 for Ma in self._MaList:\r
1065 if Ma not in RetVal:\r
1066 RetVal.append(Ma)\r
1067 return RetVal\r
1068\r
1069 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
1070 @cached_property\r
1071 def LibraryAutoGenList(self):\r
1072 RetVal = []\r
1073 for Ma in self._MaList:\r
1074 for La in Ma.LibraryAutoGenList:\r
1075 if La not in RetVal:\r
1076 RetVal.append(La)\r
1077 if Ma not in La.ReferenceModules:\r
1078 La.ReferenceModules.append(Ma)\r
1079 return RetVal\r
1080\r
1081 ## Test if a module is supported by the platform\r
1082 #\r
1083 # An error will be raised directly if the module or its arch is not supported\r
1084 # by the platform or current configuration\r
1085 #\r
1086 def ValidModule(self, Module):\r
1087 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
1088 or Module in self._AsBuildModuleList\r
1089 @cached_property\r
1090 def GetAllModuleInfo(self,WithoutPcd=True):\r
1091 ModuleLibs = set()\r
1092 for m in self.Platform.Modules:\r
1093 module_obj = self.BuildDatabase[m,self.Arch,self.BuildTarget,self.ToolChain]\r
1094 if not bool(module_obj.LibraryClass):\r
abc0155b 1095 Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain,self.MetaFile,EdkLogger)\r
e8449e1d
FB
1096 else:\r
1097 Libs = []\r
673d09a2 1098 ModuleLibs.update( set([(l.MetaFile.File,l.MetaFile.Root,l.MetaFile.Path,l.MetaFile.BaseName,l.MetaFile.OriginalPath,l.Arch,True) for l in Libs]))\r
e8449e1d
FB
1099 if WithoutPcd and module_obj.PcdIsDriver:\r
1100 continue\r
673d09a2 1101 ModuleLibs.add((m.File,m.Root,m.Path,m.BaseName,m.OriginalPath,module_obj.Arch,bool(module_obj.LibraryClass)))\r
e8449e1d
FB
1102\r
1103 return ModuleLibs\r
1104\r
1105 ## Resolve the library classes in a module to library instances\r
1106 #\r
1107 # This method will not only resolve library classes but also sort the library\r
1108 # instances according to the dependency-ship.\r
1109 #\r
1110 # @param Module The module from which the library classes will be resolved\r
1111 #\r
1112 # @retval library_list List of library instances sorted\r
1113 #\r
1114 def ApplyLibraryInstance(self, Module):\r
1115 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly\r
1116 if str(Module) not in self.Platform.Modules:\r
1117 return []\r
1118\r
1119 return GetModuleLibInstances(Module,\r
1120 self.Platform,\r
1121 self.BuildDatabase,\r
1122 self.Arch,\r
1123 self.BuildTarget,\r
1124 self.ToolChain,\r
1125 self.MetaFile,\r
1126 EdkLogger)\r
1127\r
1128 ## Override PCD setting (type, value, ...)\r
1129 #\r
1130 # @param ToPcd The PCD to be overridden\r
1131 # @param FromPcd The PCD overriding from\r
1132 #\r
1133 def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
1134 #\r
1135 # in case there's PCDs coming from FDF file, which have no type given.\r
1136 # at this point, ToPcd.Type has the type found from dependent\r
1137 # package\r
1138 #\r
1139 TokenCName = ToPcd.TokenCName\r
1140 for PcdItem in GlobalData.MixedPcd:\r
1141 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
1142 TokenCName = PcdItem[0]\r
1143 break\r
1144 if FromPcd is not None:\r
1145 if ToPcd.Pending and FromPcd.Type:\r
1146 ToPcd.Type = FromPcd.Type\r
1147 elif ToPcd.Type and FromPcd.Type\\r
1148 and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:\r
1149 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r
1150 ToPcd.Type = FromPcd.Type\r
1151 elif ToPcd.Type and FromPcd.Type \\r
1152 and ToPcd.Type != FromPcd.Type:\r
1153 if Library:\r
1154 Module = str(Module) + " 's library file (" + str(Library) + ")"\r
1155 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
1156 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r
1157 % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
1158 ToPcd.Type, Module, FromPcd.Type, Msg),\r
1159 File=self.MetaFile)\r
1160\r
1161 if FromPcd.MaxDatumSize:\r
1162 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1163 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r
1164 if FromPcd.DefaultValue:\r
1165 ToPcd.DefaultValue = FromPcd.DefaultValue\r
1166 if FromPcd.TokenValue:\r
1167 ToPcd.TokenValue = FromPcd.TokenValue\r
1168 if FromPcd.DatumType:\r
1169 ToPcd.DatumType = FromPcd.DatumType\r
1170 if FromPcd.SkuInfoList:\r
1171 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
1172 if FromPcd.UserDefinedDefaultStoresFlag:\r
1173 ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r
1174 # Add Flexible PCD format parse\r
1175 if ToPcd.DefaultValue:\r
1176 try:\r
1177 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Platform._GuidDict)(True)\r
1178 except BadExpression as Value:\r
1179 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
1180 File=self.MetaFile)\r
1181\r
1182 # check the validation of datum\r
1183 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
1184 if not IsValid:\r
1185 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
1186 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
1187 ToPcd.validateranges = FromPcd.validateranges\r
1188 ToPcd.validlists = FromPcd.validlists\r
1189 ToPcd.expressions = FromPcd.expressions\r
1190 ToPcd.CustomAttribute = FromPcd.CustomAttribute\r
1191\r
1192 if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
1193 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
1194 % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
1195 Value = ToPcd.DefaultValue\r
1196 if not Value:\r
1197 ToPcd.MaxDatumSize = '1'\r
1198 elif Value[0] == 'L':\r
1199 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
1200 elif Value[0] == '{':\r
1201 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
1202 else:\r
1203 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
1204\r
1205 # apply default SKU for dynamic PCDS if specified one is not available\r
1206 if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r
1207 and not ToPcd.SkuInfoList:\r
1208 if self.Platform.SkuName in self.Platform.SkuIds:\r
1209 SkuName = self.Platform.SkuName\r
1210 else:\r
1211 SkuName = TAB_DEFAULT\r
1212 ToPcd.SkuInfoList = {\r
1213 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
1214 }\r
1215\r
1216 ## Apply PCD setting defined platform to a module\r
1217 #\r
1218 # @param Module The module from which the PCD setting will be overridden\r
1219 #\r
1220 # @retval PCD_list The list PCDs with settings from platform\r
1221 #\r
1222 def ApplyPcdSetting(self, Module, Pcds, Library=""):\r
1223 # for each PCD in module\r
1224 for Name, Guid in Pcds:\r
1225 PcdInModule = Pcds[Name, Guid]\r
1226 # find out the PCD setting in platform\r
1227 if (Name, Guid) in self.Platform.Pcds:\r
1228 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
1229 else:\r
1230 PcdInPlatform = None\r
1231 # then override the settings if any\r
1232 self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r
1233 # resolve the VariableGuid value\r
1234 for SkuId in PcdInModule.SkuInfoList:\r
1235 Sku = PcdInModule.SkuInfoList[SkuId]\r
1236 if Sku.VariableGuid == '': continue\r
1237 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
1238 if Sku.VariableGuidValue is None:\r
1239 PackageList = "\n\t".join(str(P) for P in self.PackageList)\r
1240 EdkLogger.error(\r
1241 'build',\r
1242 RESOURCE_NOT_AVAILABLE,\r
1243 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
1244 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
1245 % (Guid, Name, str(Module)),\r
1246 File=self.MetaFile\r
1247 )\r
1248\r
1249 # override PCD settings with module specific setting\r
1250 if Module in self.Platform.Modules:\r
1251 PlatformModule = self.Platform.Modules[str(Module)]\r
1252 for Key in PlatformModule.Pcds:\r
1253 if GlobalData.BuildOptionPcd:\r
1254 for pcd in GlobalData.BuildOptionPcd:\r
1255 (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r
1256 if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r
1257 PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r
1258 PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r
1259 break\r
1260 Flag = False\r
1261 if Key in Pcds:\r
1262 ToPcd = Pcds[Key]\r
1263 Flag = True\r
1264 elif Key in GlobalData.MixedPcd:\r
1265 for PcdItem in GlobalData.MixedPcd[Key]:\r
1266 if PcdItem in Pcds:\r
1267 ToPcd = Pcds[PcdItem]\r
1268 Flag = True\r
1269 break\r
1270 if Flag:\r
1271 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r
1272 # use PCD value to calculate the MaxDatumSize when it is not specified\r
1273 for Name, Guid in Pcds:\r
1274 Pcd = Pcds[Name, Guid]\r
1275 if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r
1276 Pcd.MaxSizeUserSet = None\r
1277 Value = Pcd.DefaultValue\r
1278 if not Value:\r
1279 Pcd.MaxDatumSize = '1'\r
1280 elif Value[0] == 'L':\r
1281 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
1282 elif Value[0] == '{':\r
1283 Pcd.MaxDatumSize = str(len(Value.split(',')))\r
1284 else:\r
1285 Pcd.MaxDatumSize = str(len(Value) - 1)\r
1286 return list(Pcds.values())\r
1287\r
1288 ## Append build options in platform to a module\r
1289 #\r
1290 # @param Module The module to which the build options will be appended\r
1291 #\r
1292 # @retval options The options appended with build options in platform\r
1293 #\r
1294 def ApplyBuildOption(self, Module):\r
1295 # Get the different options for the different style module\r
1296 PlatformOptions = self.EdkIIBuildOption\r
1297 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
1298 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
1299 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
1300 if Module in self.Platform.Modules:\r
1301 PlatformModule = self.Platform.Modules[str(Module)]\r
1302 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1303 else:\r
1304 PlatformModuleOptions = {}\r
1305\r
1306 BuildRuleOrder = None\r
1307 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
1308 for Tool in Options:\r
1309 for Attr in Options[Tool]:\r
1310 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
1311 BuildRuleOrder = Options[Tool][Attr]\r
1312\r
1313 AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r
1314 list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r
1315 list(self.ToolDefinition.keys()))\r
1316 BuildOptions = defaultdict(lambda: defaultdict(str))\r
1317 for Tool in AllTools:\r
1318 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
1319 if Tool not in Options:\r
1320 continue\r
1321 for Attr in Options[Tool]:\r
1322 #\r
1323 # Do not generate it in Makefile\r
1324 #\r
1325 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
1326 continue\r
1327 Value = Options[Tool][Attr]\r
1328 # check if override is indicated\r
1329 if Value.startswith('='):\r
1330 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])\r
1331 else:\r
1332 if Attr != 'PATH':\r
1333 BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)\r
1334 else:\r
1335 BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)\r
1336\r
1337 return BuildOptions, BuildRuleOrder\r
1338\r
1339\r
1340 def GetGlobalBuildOptions(self,Module):\r
1341 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
1342 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
1343\r
1344 if Module in self.Platform.Modules:\r
1345 PlatformModule = self.Platform.Modules[str(Module)]\r
1346 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1347 else:\r
1348 PlatformModuleOptions = {}\r
1349\r
1350 return ModuleTypeOptions,PlatformModuleOptions\r
1351 def ModuleGuid(self,Module):\r
1352 if os.path.basename(Module.MetaFile.File) != os.path.basename(Module.MetaFile.Path):\r
1353 #\r
1354 # Length of GUID is 36\r
1355 #\r
1356 return os.path.basename(Module.MetaFile.Path)[:36]\r
1357 return Module.Guid\r
1358 @cached_property\r
1359 def UniqueBaseName(self):\r
1360 retVal ={}\r
1361 ModuleNameDict = {}\r
1362 UniqueName = {}\r
1363 for Module in self._MbList:\r
1364 unique_base_name = '%s_%s' % (Module.BaseName,self.ModuleGuid(Module))\r
1365 if unique_base_name not in ModuleNameDict:\r
1366 ModuleNameDict[unique_base_name] = []\r
1367 ModuleNameDict[unique_base_name].append(Module.MetaFile)\r
1368 if Module.BaseName not in UniqueName:\r
1369 UniqueName[Module.BaseName] = set()\r
1370 UniqueName[Module.BaseName].add((self.ModuleGuid(Module),Module.MetaFile))\r
1371 for module_paths in ModuleNameDict.values():\r
76e12fa3 1372 if len(set(module_paths))>1:\r
e8449e1d
FB
1373 samemodules = list(set(module_paths))\r
1374 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
1375 ' %s\n %s' % (samemodules[0], samemodules[1]))\r
1376 for name in UniqueName:\r
1377 Guid_Path = UniqueName[name]\r
1378 if len(Guid_Path) > 1:\r
76e12fa3
FB
1379 for guid,mpath in Guid_Path:\r
1380 retVal[(name,mpath)] = '%s_%s' % (name,guid)\r
e8449e1d
FB
1381 return retVal\r
1382 ## Expand * in build option key\r
1383 #\r
1384 # @param Options Options to be expanded\r
1385 # @param ToolDef Use specified ToolDef instead of full version.\r
1386 # This is needed during initialization to prevent\r
1387 # infinite recursion betweeh BuildOptions,\r
1388 # ToolDefinition, and this function.\r
1389 #\r
1390 # @retval options Options expanded\r
1391 #\r
1392 def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):\r
1393 if not ToolDef:\r
1394 ToolDef = self.ToolDefinition\r
1395 BuildOptions = {}\r
1396 FamilyMatch = False\r
1397 FamilyIsNull = True\r
1398\r
1399 OverrideList = {}\r
1400 #\r
1401 # Construct a list contain the build options which need override.\r
1402 #\r
1403 for Key in Options:\r
1404 #\r
1405 # Key[0] -- tool family\r
1406 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
1407 #\r
1408 if (Key[0] == self.BuildRuleFamily and\r
1409 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
1410 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
1411 if (Target == self.BuildTarget or Target == TAB_STAR) and\\r
1412 (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\\r
1413 (Arch == self.Arch or Arch == TAB_STAR) and\\r
1414 Options[Key].startswith("="):\r
1415\r
1416 if OverrideList.get(Key[1]) is not None:\r
1417 OverrideList.pop(Key[1])\r
1418 OverrideList[Key[1]] = Options[Key]\r
1419\r
1420 #\r
1421 # Use the highest priority value.\r
1422 #\r
1423 if (len(OverrideList) >= 2):\r
1424 KeyList = list(OverrideList.keys())\r
1425 for Index in range(len(KeyList)):\r
1426 NowKey = KeyList[Index]\r
1427 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
1428 for Index1 in range(len(KeyList) - Index - 1):\r
1429 NextKey = KeyList[Index1 + Index + 1]\r
1430 #\r
1431 # Compare two Key, if one is included by another, choose the higher priority one\r
1432 #\r
1433 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
1434 if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\\r
1435 (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\\r
1436 (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\\r
1437 (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\\r
1438 (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):\r
1439\r
1440 if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):\r
1441 if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
1442 Options.pop((self.BuildRuleFamily, NextKey))\r
1443 else:\r
1444 if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
1445 Options.pop((self.BuildRuleFamily, NowKey))\r
1446\r
1447 for Key in Options:\r
1448 if ModuleStyle is not None and len (Key) > 2:\r
1449 # Check Module style is EDK or EDKII.\r
1450 # Only append build option for the matched style module.\r
1451 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1452 continue\r
1453 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1454 continue\r
1455 Family = Key[0]\r
1456 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1457 # if tool chain family doesn't match, skip it\r
1458 if Tool in ToolDef and Family != "":\r
1459 FamilyIsNull = False\r
1460 if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":\r
1461 if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
1462 continue\r
1463 elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1464 continue\r
1465 FamilyMatch = True\r
1466 # expand any wildcard\r
1467 if Target == TAB_STAR or Target == self.BuildTarget:\r
1468 if Tag == TAB_STAR or Tag == self.ToolChain:\r
1469 if Arch == TAB_STAR or Arch == self.Arch:\r
1470 if Tool not in BuildOptions:\r
1471 BuildOptions[Tool] = {}\r
1472 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
1473 BuildOptions[Tool][Attr] = Options[Key]\r
1474 else:\r
1475 # append options for the same tool except PATH\r
1476 if Attr != 'PATH':\r
1477 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1478 else:\r
1479 BuildOptions[Tool][Attr] = Options[Key]\r
1480 # Build Option Family has been checked, which need't to be checked again for family.\r
1481 if FamilyMatch or FamilyIsNull:\r
1482 return BuildOptions\r
1483\r
1484 for Key in Options:\r
1485 if ModuleStyle is not None and len (Key) > 2:\r
1486 # Check Module style is EDK or EDKII.\r
1487 # Only append build option for the matched style module.\r
1488 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1489 continue\r
1490 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1491 continue\r
1492 Family = Key[0]\r
1493 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1494 # if tool chain family doesn't match, skip it\r
1495 if Tool not in ToolDef or Family == "":\r
1496 continue\r
1497 # option has been added before\r
1498 if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1499 continue\r
1500\r
1501 # expand any wildcard\r
1502 if Target == TAB_STAR or Target == self.BuildTarget:\r
1503 if Tag == TAB_STAR or Tag == self.ToolChain:\r
1504 if Arch == TAB_STAR or Arch == self.Arch:\r
1505 if Tool not in BuildOptions:\r
1506 BuildOptions[Tool] = {}\r
1507 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
1508 BuildOptions[Tool][Attr] = Options[Key]\r
1509 else:\r
1510 # append options for the same tool except PATH\r
1511 if Attr != 'PATH':\r
1512 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1513 else:\r
1514 BuildOptions[Tool][Attr] = Options[Key]\r
1515 return BuildOptions\r