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