]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
c055be5b 4# Copyright (c) 2019 - 2021, 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
859e0952 256 for Pcd in sorted(DynamicPcdSet):\r
e8449e1d
FB
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
c055be5b
MK
808 if "MAKE" in self.EdkIIBuildOption and "PATH" in self.EdkIIBuildOption["MAKE"]:\r
809 # MAKE_PATH in DSC [BuildOptions] section is higher priority\r
810 Path = self.EdkIIBuildOption["MAKE"]["PATH"]\r
811 if Path.startswith('='):\r
812 Path = Path[1:].strip()\r
813 RetVal = _SplitOption(Path)\r
814 elif "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:\r
815 RetVal = _SplitOption(self.ToolDefinition["MAKE"]["PATH"])\r
816 else:\r
817 return []\r
818 if "MAKE" in self.ToolDefinition and "FLAGS" in self.ToolDefinition["MAKE"]:\r
819 NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()\r
820 if NewOption != '':\r
821 RetVal += _SplitOption(NewOption)\r
822 if "MAKE" in self.EdkIIBuildOption and "FLAGS" in self.EdkIIBuildOption["MAKE"]:\r
823 Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]\r
824 if Flags.startswith('='):\r
825 RetVal = [RetVal[0]] + _SplitOption(Flags[1:].strip())\r
826 else:\r
827 RetVal = RetVal + _SplitOption(Flags.strip())\r
e8449e1d
FB
828 return RetVal\r
829\r
ab957f03
MK
830 ## Compute a tool defintion key priority value in range 0..15\r
831 #\r
832 # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE 15\r
833 # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE 14\r
834 # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE 13\r
835 # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE 12\r
836 # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE 11\r
837 # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE 10\r
838 # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE 9\r
839 # ******_*********_****_COMMANDTYPE_ATTRIBUTE 8\r
840 # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE 7\r
841 # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE 6\r
842 # TARGET_*********_ARCH_***********_ATTRIBUTE 5\r
843 # ******_*********_ARCH_***********_ATTRIBUTE 4\r
844 # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE 3\r
845 # ******_TOOLCHAIN_****_***********_ATTRIBUTE 2\r
846 # TARGET_*********_****_***********_ATTRIBUTE 1\r
847 # ******_*********_****_***********_ATTRIBUTE 0\r
848 #\r
849 def ToolDefinitionPriority (self,Key):\r
850 KeyList = Key.split('_')\r
851 Priority = 0\r
852 for Index in range (0, min(4, len(KeyList))):\r
853 if KeyList[Index] != '*':\r
854 Priority += (1 << Index)\r
855 return Priority\r
856\r
e8449e1d
FB
857 ## Get tool chain definition\r
858 #\r
859 # Get each tool definition for given tool chain from tools_def.txt and platform\r
860 #\r
861 @cached_property\r
862 def ToolDefinition(self):\r
863 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDictionary\r
864 if TAB_TOD_DEFINES_COMMAND_TYPE not in self.Workspace.ToolDef.ToolsDefTxtDatabase:\r
865 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No tools found in configuration",\r
866 ExtraData="[%s]" % self.MetaFile)\r
867 RetVal = OrderedDict()\r
868 DllPathList = set()\r
ab957f03
MK
869\r
870 PrioritizedDefList = sorted(ToolDefinition.keys(), key=self.ToolDefinitionPriority, reverse=True)\r
871 for Def in PrioritizedDefList:\r
e8449e1d 872 Target, Tag, Arch, Tool, Attr = Def.split("_")\r
ab957f03
MK
873 if Target == TAB_STAR:\r
874 Target = self.BuildTarget\r
875 if Tag == TAB_STAR:\r
876 Tag = self.ToolChain\r
877 if Arch == TAB_STAR:\r
878 Arch = self.Arch\r
e8449e1d
FB
879 if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:\r
880 continue\r
881\r
882 Value = ToolDefinition[Def]\r
883 # don't record the DLL\r
884 if Attr == "DLL":\r
885 DllPathList.add(Value)\r
886 continue\r
887\r
ab957f03
MK
888 #\r
889 # ToolDefinition is sorted from highest priority to lowest priority.\r
890 # Only add the first(highest priority) match to RetVal\r
891 #\r
e8449e1d
FB
892 if Tool not in RetVal:\r
893 RetVal[Tool] = OrderedDict()\r
ab957f03
MK
894 if Attr not in RetVal[Tool]:\r
895 RetVal[Tool][Attr] = Value\r
e8449e1d
FB
896\r
897 ToolsDef = ''\r
898 if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:\r
899 if "FLAGS" not in RetVal["MAKE"]:\r
900 RetVal["MAKE"]["FLAGS"] = ""\r
901 RetVal["MAKE"]["FLAGS"] += " -s"\r
902 MakeFlags = ''\r
ab957f03
MK
903\r
904 ToolList = list(RetVal.keys())\r
905 ToolList.sort()\r
906 for Tool in ToolList:\r
907 if Tool == TAB_STAR:\r
908 continue\r
909 AttrList = list(RetVal[Tool].keys())\r
910 if TAB_STAR in ToolList:\r
911 AttrList += list(RetVal[TAB_STAR])\r
912 AttrList.sort()\r
913 for Attr in AttrList:\r
914 if Attr in RetVal[Tool]:\r
915 Value = RetVal[Tool][Attr]\r
916 else:\r
917 Value = RetVal[TAB_STAR][Attr]\r
e8449e1d
FB
918 if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:\r
919 # check if override is indicated\r
920 if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):\r
ef3840c1 921 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:].strip()\r
e8449e1d 922 else:\r
ef3840c1
MK
923 # Do not append PATH or GUID\r
924 if Attr != 'PATH' and Attr != 'GUID':\r
e8449e1d
FB
925 Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
926 else:\r
927 Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]\r
e8449e1d
FB
928 if Attr == "PATH":\r
929 # Don't put MAKE definition in the file\r
930 if Tool != "MAKE":\r
ab957f03 931 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
e8449e1d
FB
932 elif Attr != "DLL":\r
933 # Don't put MAKE definition in the file\r
934 if Tool == "MAKE":\r
935 if Attr == "FLAGS":\r
936 MakeFlags = Value\r
937 else:\r
938 ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)\r
939 ToolsDef += "\n"\r
940\r
941 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
942 SaveFileOnChange(tool_def_file, ToolsDef, False)\r
943 for DllPath in DllPathList:\r
944 os.environ["PATH"] = DllPath + os.pathsep + os.environ["PATH"]\r
945 os.environ["MAKE_FLAGS"] = MakeFlags\r
946\r
947 return RetVal\r
948\r
949 ## Return the paths of tools\r
950 @cached_property\r
951 def ToolDefinitionFile(self):\r
952 tool_def_file = os.path.join(self.MakeFileDir, "TOOLS_DEF." + self.Arch)\r
953 if not os.path.exists(tool_def_file):\r
954 self.ToolDefinition\r
955 return tool_def_file\r
956\r
957 ## Retrieve the toolchain family of given toolchain tag. Default to 'MSFT'.\r
958 @cached_property\r
959 def ToolChainFamily(self):\r
960 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
961 if TAB_TOD_DEFINES_FAMILY not in ToolDefinition \\r
962 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_FAMILY] \\r
963 or not ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]:\r
964 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
965 % self.ToolChain)\r
966 RetVal = TAB_COMPILER_MSFT\r
967 else:\r
968 RetVal = ToolDefinition[TAB_TOD_DEFINES_FAMILY][self.ToolChain]\r
969 return RetVal\r
970\r
971 @cached_property\r
972 def BuildRuleFamily(self):\r
973 ToolDefinition = self.Workspace.ToolDef.ToolsDefTxtDatabase\r
974 if TAB_TOD_DEFINES_BUILDRULEFAMILY not in ToolDefinition \\r
975 or self.ToolChain not in ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY] \\r
976 or not ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]:\r
977 EdkLogger.verbose("No tool chain family found in configuration for %s. Default to MSFT." \\r
978 % self.ToolChain)\r
979 return TAB_COMPILER_MSFT\r
980\r
981 return ToolDefinition[TAB_TOD_DEFINES_BUILDRULEFAMILY][self.ToolChain]\r
982\r
983 ## Return the build options specific for all modules in this platform\r
984 @cached_property\r
985 def BuildOption(self):\r
986 return self._ExpandBuildOption(self.Platform.BuildOptions)\r
987\r
988 def _BuildOptionWithToolDef(self, ToolDef):\r
989 return self._ExpandBuildOption(self.Platform.BuildOptions, ToolDef=ToolDef)\r
990\r
991 ## Return the build options specific for EDK modules in this platform\r
992 @cached_property\r
993 def EdkBuildOption(self):\r
994 return self._ExpandBuildOption(self.Platform.BuildOptions, EDK_NAME)\r
995\r
996 ## Return the build options specific for EDKII modules in this platform\r
997 @cached_property\r
998 def EdkIIBuildOption(self):\r
999 return self._ExpandBuildOption(self.Platform.BuildOptions, EDKII_NAME)\r
1000\r
1001 ## Parse build_rule.txt in Conf Directory.\r
1002 #\r
1003 # @retval BuildRule object\r
1004 #\r
1005 @cached_property\r
1006 def BuildRule(self):\r
1007 BuildRuleFile = None\r
1008 if TAB_TAT_DEFINES_BUILD_RULE_CONF in self.Workspace.TargetTxt.TargetTxtDictionary:\r
1009 BuildRuleFile = self.Workspace.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_BUILD_RULE_CONF]\r
1010 if not BuildRuleFile:\r
1011 BuildRuleFile = gDefaultBuildRuleFile\r
1012 RetVal = BuildRule(BuildRuleFile)\r
1013 if RetVal._FileVersion == "":\r
1014 RetVal._FileVersion = AutoGenReqBuildRuleVerNum\r
1015 else:\r
1016 if RetVal._FileVersion < AutoGenReqBuildRuleVerNum :\r
1017 # If Build Rule's version is less than the version number required by the tools, halting the build.\r
1018 EdkLogger.error("build", AUTOGEN_ERROR,\r
1019 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
1020 % (RetVal._FileVersion, AutoGenReqBuildRuleVerNum))\r
1021 return RetVal\r
1022\r
1023 ## Summarize the packages used by modules in this platform\r
1024 @cached_property\r
1025 def PackageList(self):\r
1026 RetVal = set()\r
1027 for Mb in self._MbList:\r
1028 RetVal.update(Mb.Packages)\r
1029 for lb in Mb.LibInstances:\r
1030 RetVal.update(lb.Packages)\r
1031 #Collect package set information from INF of FDF\r
1032 for ModuleFile in self._AsBuildModuleList:\r
1033 if ModuleFile in self.Platform.Modules:\r
1034 continue\r
1035 ModuleData = self.BuildDatabase[ModuleFile, self.Arch, self.BuildTarget, self.ToolChain]\r
1036 RetVal.update(ModuleData.Packages)\r
bf1ea933 1037 RetVal.update(self.Platform.Packages)\r
e8449e1d
FB
1038 return list(RetVal)\r
1039\r
1040 @cached_property\r
1041 def NonDynamicPcdDict(self):\r
1042 return {(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):Pcd for Pcd in self.NonDynamicPcdList}\r
1043\r
1044 ## Get list of non-dynamic PCDs\r
1045 @property\r
1046 def NonDynamicPcdList(self):\r
1047 if not self._NonDynamicPcdList:\r
1048 self.CollectPlatformDynamicPcds()\r
1049 return self._NonDynamicPcdList\r
1050\r
1051 ## Get list of dynamic PCDs\r
1052 @property\r
1053 def DynamicPcdList(self):\r
1054 if not self._DynamicPcdList:\r
1055 self.CollectPlatformDynamicPcds()\r
1056 return self._DynamicPcdList\r
1057\r
1058 ## Generate Token Number for all PCD\r
1059 @cached_property\r
1060 def PcdTokenNumber(self):\r
1061 RetVal = OrderedDict()\r
1062 TokenNumber = 1\r
1063 #\r
1064 # Make the Dynamic and DynamicEx PCD use within different TokenNumber area.\r
1065 # Such as:\r
1066 #\r
1067 # Dynamic PCD:\r
1068 # TokenNumber 0 ~ 10\r
1069 # DynamicEx PCD:\r
1070 # TokeNumber 11 ~ 20\r
1071 #\r
1072 for Pcd in self.DynamicPcdList:\r
1073 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
1074 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1075 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1076 TokenNumber += 1\r
1077\r
1078 for Pcd in self.DynamicPcdList:\r
1079 if Pcd.Phase == "PEI" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1080 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1081 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1082 TokenNumber += 1\r
1083\r
1084 for Pcd in self.DynamicPcdList:\r
1085 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_TYPE_SET:\r
1086 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1087 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1088 TokenNumber += 1\r
1089\r
1090 for Pcd in self.DynamicPcdList:\r
1091 if Pcd.Phase == "DXE" and Pcd.Type in PCD_DYNAMIC_EX_TYPE_SET:\r
1092 EdkLogger.debug(EdkLogger.DEBUG_5, "%s %s (%s) -> %d" % (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Pcd.Phase, TokenNumber))\r
1093 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber\r
1094 TokenNumber += 1\r
1095\r
1096 for Pcd in self.NonDynamicPcdList:\r
d15d0d3d 1097 RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = 0\r
e8449e1d
FB
1098 return RetVal\r
1099\r
1100 @cached_property\r
1101 def _MbList(self):\r
09af9bd9
BF
1102 ModuleList = []\r
1103 for m in self.Platform.Modules:\r
1104 component = self.Platform.Modules[m]\r
1105 module = self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain]\r
1106 module.Guid = component.Guid\r
1107 ModuleList.append(module)\r
1108 return ModuleList\r
e8449e1d
FB
1109\r
1110 @cached_property\r
1111 def _MaList(self):\r
1112 for ModuleFile in self.Platform.Modules:\r
1113 Ma = ModuleAutoGen(\r
1114 self.Workspace,\r
1115 ModuleFile,\r
1116 self.BuildTarget,\r
1117 self.ToolChain,\r
1118 self.Arch,\r
1119 self.MetaFile,\r
1120 self.DataPipe\r
1121 )\r
1122 self.Platform.Modules[ModuleFile].M = Ma\r
1123 return [x.M for x in self.Platform.Modules.values()]\r
1124\r
1125 ## Summarize ModuleAutoGen objects of all modules to be built for this platform\r
1126 @cached_property\r
1127 def ModuleAutoGenList(self):\r
1128 RetVal = []\r
1129 for Ma in self._MaList:\r
1130 if Ma not in RetVal:\r
1131 RetVal.append(Ma)\r
1132 return RetVal\r
1133\r
1134 ## Summarize ModuleAutoGen objects of all libraries to be built for this platform\r
1135 @cached_property\r
1136 def LibraryAutoGenList(self):\r
1137 RetVal = []\r
1138 for Ma in self._MaList:\r
1139 for La in Ma.LibraryAutoGenList:\r
1140 if La not in RetVal:\r
1141 RetVal.append(La)\r
1142 if Ma not in La.ReferenceModules:\r
1143 La.ReferenceModules.append(Ma)\r
1144 return RetVal\r
1145\r
1146 ## Test if a module is supported by the platform\r
1147 #\r
1148 # An error will be raised directly if the module or its arch is not supported\r
1149 # by the platform or current configuration\r
1150 #\r
1151 def ValidModule(self, Module):\r
1152 return Module in self.Platform.Modules or Module in self.Platform.LibraryInstances \\r
1153 or Module in self._AsBuildModuleList\r
1154 @cached_property\r
1155 def GetAllModuleInfo(self,WithoutPcd=True):\r
1156 ModuleLibs = set()\r
1157 for m in self.Platform.Modules:\r
1158 module_obj = self.BuildDatabase[m,self.Arch,self.BuildTarget,self.ToolChain]\r
1159 if not bool(module_obj.LibraryClass):\r
abc0155b 1160 Libs = GetModuleLibInstances(module_obj, self.Platform, self.BuildDatabase, self.Arch,self.BuildTarget,self.ToolChain,self.MetaFile,EdkLogger)\r
e8449e1d
FB
1161 else:\r
1162 Libs = []\r
673d09a2 1163 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
1164 if WithoutPcd and module_obj.PcdIsDriver:\r
1165 continue\r
673d09a2 1166 ModuleLibs.add((m.File,m.Root,m.Path,m.BaseName,m.OriginalPath,module_obj.Arch,bool(module_obj.LibraryClass)))\r
e8449e1d
FB
1167\r
1168 return ModuleLibs\r
1169\r
1170 ## Resolve the library classes in a module to library instances\r
1171 #\r
1172 # This method will not only resolve library classes but also sort the library\r
1173 # instances according to the dependency-ship.\r
1174 #\r
1175 # @param Module The module from which the library classes will be resolved\r
1176 #\r
1177 # @retval library_list List of library instances sorted\r
1178 #\r
1179 def ApplyLibraryInstance(self, Module):\r
1180 # Cover the case that the binary INF file is list in the FDF file but not DSC file, return empty list directly\r
1181 if str(Module) not in self.Platform.Modules:\r
1182 return []\r
1183\r
1184 return GetModuleLibInstances(Module,\r
1185 self.Platform,\r
1186 self.BuildDatabase,\r
1187 self.Arch,\r
1188 self.BuildTarget,\r
1189 self.ToolChain,\r
1190 self.MetaFile,\r
1191 EdkLogger)\r
1192\r
1193 ## Override PCD setting (type, value, ...)\r
1194 #\r
1195 # @param ToPcd The PCD to be overridden\r
1196 # @param FromPcd The PCD overriding from\r
1197 #\r
1198 def _OverridePcd(self, ToPcd, FromPcd, Module="", Msg="", Library=""):\r
1199 #\r
1200 # in case there's PCDs coming from FDF file, which have no type given.\r
1201 # at this point, ToPcd.Type has the type found from dependent\r
1202 # package\r
1203 #\r
1204 TokenCName = ToPcd.TokenCName\r
1205 for PcdItem in GlobalData.MixedPcd:\r
1206 if (ToPcd.TokenCName, ToPcd.TokenSpaceGuidCName) in GlobalData.MixedPcd[PcdItem]:\r
1207 TokenCName = PcdItem[0]\r
1208 break\r
1209 if FromPcd is not None:\r
1210 if ToPcd.Pending and FromPcd.Type:\r
1211 ToPcd.Type = FromPcd.Type\r
1212 elif ToPcd.Type and FromPcd.Type\\r
1213 and ToPcd.Type != FromPcd.Type and ToPcd.Type in FromPcd.Type:\r
1214 if ToPcd.Type.strip() == TAB_PCDS_DYNAMIC_EX:\r
1215 ToPcd.Type = FromPcd.Type\r
1216 elif ToPcd.Type and FromPcd.Type \\r
1217 and ToPcd.Type != FromPcd.Type:\r
1218 if Library:\r
1219 Module = str(Module) + " 's library file (" + str(Library) + ")"\r
1220 EdkLogger.error("build", OPTION_CONFLICT, "Mismatched PCD type",\r
1221 ExtraData="%s.%s is used as [%s] in module %s, but as [%s] in %s."\\r
1222 % (ToPcd.TokenSpaceGuidCName, TokenCName,\r
1223 ToPcd.Type, Module, FromPcd.Type, Msg),\r
1224 File=self.MetaFile)\r
1225\r
1226 if FromPcd.MaxDatumSize:\r
1227 ToPcd.MaxDatumSize = FromPcd.MaxDatumSize\r
1228 ToPcd.MaxSizeUserSet = FromPcd.MaxDatumSize\r
1229 if FromPcd.DefaultValue:\r
1230 ToPcd.DefaultValue = FromPcd.DefaultValue\r
1231 if FromPcd.TokenValue:\r
1232 ToPcd.TokenValue = FromPcd.TokenValue\r
1233 if FromPcd.DatumType:\r
1234 ToPcd.DatumType = FromPcd.DatumType\r
1235 if FromPcd.SkuInfoList:\r
1236 ToPcd.SkuInfoList = FromPcd.SkuInfoList\r
1237 if FromPcd.UserDefinedDefaultStoresFlag:\r
1238 ToPcd.UserDefinedDefaultStoresFlag = FromPcd.UserDefinedDefaultStoresFlag\r
1239 # Add Flexible PCD format parse\r
1240 if ToPcd.DefaultValue:\r
1241 try:\r
1242 ToPcd.DefaultValue = ValueExpressionEx(ToPcd.DefaultValue, ToPcd.DatumType, self.Platform._GuidDict)(True)\r
1243 except BadExpression as Value:\r
1244 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(ToPcd.TokenSpaceGuidCName, ToPcd.TokenCName, ToPcd.DefaultValue, Value),\r
1245 File=self.MetaFile)\r
1246\r
1247 # check the validation of datum\r
1248 IsValid, Cause = CheckPcdDatum(ToPcd.DatumType, ToPcd.DefaultValue)\r
1249 if not IsValid:\r
1250 EdkLogger.error('build', FORMAT_INVALID, Cause, File=self.MetaFile,\r
1251 ExtraData="%s.%s" % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
1252 ToPcd.validateranges = FromPcd.validateranges\r
1253 ToPcd.validlists = FromPcd.validlists\r
1254 ToPcd.expressions = FromPcd.expressions\r
1255 ToPcd.CustomAttribute = FromPcd.CustomAttribute\r
1256\r
1257 if FromPcd is not None and ToPcd.DatumType == TAB_VOID and not ToPcd.MaxDatumSize:\r
1258 EdkLogger.debug(EdkLogger.DEBUG_9, "No MaxDatumSize specified for PCD %s.%s" \\r
1259 % (ToPcd.TokenSpaceGuidCName, TokenCName))\r
1260 Value = ToPcd.DefaultValue\r
1261 if not Value:\r
1262 ToPcd.MaxDatumSize = '1'\r
1263 elif Value[0] == 'L':\r
1264 ToPcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
1265 elif Value[0] == '{':\r
1266 ToPcd.MaxDatumSize = str(len(Value.split(',')))\r
1267 else:\r
1268 ToPcd.MaxDatumSize = str(len(Value) - 1)\r
1269\r
1270 # apply default SKU for dynamic PCDS if specified one is not available\r
1271 if (ToPcd.Type in PCD_DYNAMIC_TYPE_SET or ToPcd.Type in PCD_DYNAMIC_EX_TYPE_SET) \\r
1272 and not ToPcd.SkuInfoList:\r
1273 if self.Platform.SkuName in self.Platform.SkuIds:\r
1274 SkuName = self.Platform.SkuName\r
1275 else:\r
1276 SkuName = TAB_DEFAULT\r
1277 ToPcd.SkuInfoList = {\r
1278 SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)\r
1279 }\r
1280\r
1281 ## Apply PCD setting defined platform to a module\r
1282 #\r
1283 # @param Module The module from which the PCD setting will be overridden\r
1284 #\r
1285 # @retval PCD_list The list PCDs with settings from platform\r
1286 #\r
1287 def ApplyPcdSetting(self, Module, Pcds, Library=""):\r
1288 # for each PCD in module\r
1289 for Name, Guid in Pcds:\r
1290 PcdInModule = Pcds[Name, Guid]\r
1291 # find out the PCD setting in platform\r
1292 if (Name, Guid) in self.Platform.Pcds:\r
1293 PcdInPlatform = self.Platform.Pcds[Name, Guid]\r
1294 else:\r
1295 PcdInPlatform = None\r
1296 # then override the settings if any\r
1297 self._OverridePcd(PcdInModule, PcdInPlatform, Module, Msg="DSC PCD sections", Library=Library)\r
1298 # resolve the VariableGuid value\r
1299 for SkuId in PcdInModule.SkuInfoList:\r
1300 Sku = PcdInModule.SkuInfoList[SkuId]\r
1301 if Sku.VariableGuid == '': continue\r
1302 Sku.VariableGuidValue = GuidValue(Sku.VariableGuid, self.PackageList, self.MetaFile.Path)\r
1303 if Sku.VariableGuidValue is None:\r
1304 PackageList = "\n\t".join(str(P) for P in self.PackageList)\r
1305 EdkLogger.error(\r
1306 'build',\r
1307 RESOURCE_NOT_AVAILABLE,\r
1308 "Value of GUID [%s] is not found in" % Sku.VariableGuid,\r
1309 ExtraData=PackageList + "\n\t(used with %s.%s from module %s)" \\r
1310 % (Guid, Name, str(Module)),\r
1311 File=self.MetaFile\r
1312 )\r
1313\r
1314 # override PCD settings with module specific setting\r
1315 if Module in self.Platform.Modules:\r
1316 PlatformModule = self.Platform.Modules[str(Module)]\r
1317 for Key in PlatformModule.Pcds:\r
1318 if GlobalData.BuildOptionPcd:\r
1319 for pcd in GlobalData.BuildOptionPcd:\r
1320 (TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd\r
1321 if (TokenCName, TokenSpaceGuidCName) == Key and FieldName =="":\r
1322 PlatformModule.Pcds[Key].DefaultValue = pcdvalue\r
1323 PlatformModule.Pcds[Key].PcdValueFromComm = pcdvalue\r
1324 break\r
1325 Flag = False\r
1326 if Key in Pcds:\r
1327 ToPcd = Pcds[Key]\r
1328 Flag = True\r
1329 elif Key in GlobalData.MixedPcd:\r
1330 for PcdItem in GlobalData.MixedPcd[Key]:\r
1331 if PcdItem in Pcds:\r
1332 ToPcd = Pcds[PcdItem]\r
1333 Flag = True\r
1334 break\r
1335 if Flag:\r
1336 self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)\r
1337 # use PCD value to calculate the MaxDatumSize when it is not specified\r
1338 for Name, Guid in Pcds:\r
1339 Pcd = Pcds[Name, Guid]\r
1340 if Pcd.DatumType == TAB_VOID and not Pcd.MaxDatumSize:\r
1341 Pcd.MaxSizeUserSet = None\r
1342 Value = Pcd.DefaultValue\r
1343 if not Value:\r
1344 Pcd.MaxDatumSize = '1'\r
1345 elif Value[0] == 'L':\r
1346 Pcd.MaxDatumSize = str((len(Value) - 2) * 2)\r
1347 elif Value[0] == '{':\r
1348 Pcd.MaxDatumSize = str(len(Value.split(',')))\r
1349 else:\r
1350 Pcd.MaxDatumSize = str(len(Value) - 1)\r
1351 return list(Pcds.values())\r
1352\r
1353 ## Append build options in platform to a module\r
1354 #\r
1355 # @param Module The module to which the build options will be appended\r
1356 #\r
1357 # @retval options The options appended with build options in platform\r
1358 #\r
1359 def ApplyBuildOption(self, Module):\r
1360 # Get the different options for the different style module\r
1361 PlatformOptions = self.EdkIIBuildOption\r
1362 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
1363 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
1364 ModuleOptions = self._ExpandBuildOption(Module.BuildOptions)\r
1365 if Module in self.Platform.Modules:\r
1366 PlatformModule = self.Platform.Modules[str(Module)]\r
1367 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1368 else:\r
1369 PlatformModuleOptions = {}\r
1370\r
1371 BuildRuleOrder = None\r
1372 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
1373 for Tool in Options:\r
1374 for Attr in Options[Tool]:\r
1375 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
1376 BuildRuleOrder = Options[Tool][Attr]\r
1377\r
1378 AllTools = set(list(ModuleOptions.keys()) + list(PlatformOptions.keys()) +\r
1379 list(PlatformModuleOptions.keys()) + list(ModuleTypeOptions.keys()) +\r
1380 list(self.ToolDefinition.keys()))\r
1381 BuildOptions = defaultdict(lambda: defaultdict(str))\r
1382 for Tool in AllTools:\r
1383 for Options in [self.ToolDefinition, ModuleOptions, PlatformOptions, ModuleTypeOptions, PlatformModuleOptions]:\r
1384 if Tool not in Options:\r
1385 continue\r
1386 for Attr in Options[Tool]:\r
1387 #\r
1388 # Do not generate it in Makefile\r
1389 #\r
1390 if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:\r
1391 continue\r
1392 Value = Options[Tool][Attr]\r
8c8f49f0
MK
1393 ToolList = [Tool]\r
1394 if Tool == TAB_STAR:\r
1395 ToolList = list(AllTools)\r
1396 ToolList.remove(TAB_STAR)\r
1397 for ExpandedTool in ToolList:\r
1398 # check if override is indicated\r
1399 if Value.startswith('='):\r
1400 BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value[1:])\r
e8449e1d 1401 else:\r
8c8f49f0
MK
1402 if Attr != 'PATH':\r
1403 BuildOptions[ExpandedTool][Attr] += " " + mws.handleWsMacro(Value)\r
1404 else:\r
1405 BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value)\r
e8449e1d
FB
1406\r
1407 return BuildOptions, BuildRuleOrder\r
1408\r
1409\r
1410 def GetGlobalBuildOptions(self,Module):\r
1411 ModuleTypeOptions = self.Platform.GetBuildOptionsByModuleType(EDKII_NAME, Module.ModuleType)\r
1412 ModuleTypeOptions = self._ExpandBuildOption(ModuleTypeOptions)\r
1413\r
1414 if Module in self.Platform.Modules:\r
1415 PlatformModule = self.Platform.Modules[str(Module)]\r
1416 PlatformModuleOptions = self._ExpandBuildOption(PlatformModule.BuildOptions)\r
1417 else:\r
1418 PlatformModuleOptions = {}\r
1419\r
1420 return ModuleTypeOptions,PlatformModuleOptions\r
1421 def ModuleGuid(self,Module):\r
1422 if os.path.basename(Module.MetaFile.File) != os.path.basename(Module.MetaFile.Path):\r
1423 #\r
1424 # Length of GUID is 36\r
1425 #\r
1426 return os.path.basename(Module.MetaFile.Path)[:36]\r
1427 return Module.Guid\r
1428 @cached_property\r
1429 def UniqueBaseName(self):\r
1430 retVal ={}\r
1431 ModuleNameDict = {}\r
1432 UniqueName = {}\r
1433 for Module in self._MbList:\r
1434 unique_base_name = '%s_%s' % (Module.BaseName,self.ModuleGuid(Module))\r
1435 if unique_base_name not in ModuleNameDict:\r
1436 ModuleNameDict[unique_base_name] = []\r
1437 ModuleNameDict[unique_base_name].append(Module.MetaFile)\r
1438 if Module.BaseName not in UniqueName:\r
1439 UniqueName[Module.BaseName] = set()\r
1440 UniqueName[Module.BaseName].add((self.ModuleGuid(Module),Module.MetaFile))\r
1441 for module_paths in ModuleNameDict.values():\r
76e12fa3 1442 if len(set(module_paths))>1:\r
e8449e1d
FB
1443 samemodules = list(set(module_paths))\r
1444 EdkLogger.error("build", FILE_DUPLICATED, 'Modules have same BaseName and FILE_GUID:\n'\r
1445 ' %s\n %s' % (samemodules[0], samemodules[1]))\r
1446 for name in UniqueName:\r
1447 Guid_Path = UniqueName[name]\r
1448 if len(Guid_Path) > 1:\r
76e12fa3
FB
1449 for guid,mpath in Guid_Path:\r
1450 retVal[(name,mpath)] = '%s_%s' % (name,guid)\r
e8449e1d
FB
1451 return retVal\r
1452 ## Expand * in build option key\r
1453 #\r
1454 # @param Options Options to be expanded\r
1455 # @param ToolDef Use specified ToolDef instead of full version.\r
1456 # This is needed during initialization to prevent\r
1457 # infinite recursion betweeh BuildOptions,\r
1458 # ToolDefinition, and this function.\r
1459 #\r
1460 # @retval options Options expanded\r
1461 #\r
1462 def _ExpandBuildOption(self, Options, ModuleStyle=None, ToolDef=None):\r
1463 if not ToolDef:\r
1464 ToolDef = self.ToolDefinition\r
1465 BuildOptions = {}\r
1466 FamilyMatch = False\r
1467 FamilyIsNull = True\r
1468\r
1469 OverrideList = {}\r
1470 #\r
1471 # Construct a list contain the build options which need override.\r
1472 #\r
1473 for Key in Options:\r
1474 #\r
1475 # Key[0] -- tool family\r
1476 # Key[1] -- TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE\r
1477 #\r
1478 if (Key[0] == self.BuildRuleFamily and\r
1479 (ModuleStyle is None or len(Key) < 3 or (len(Key) > 2 and Key[2] == ModuleStyle))):\r
1480 Target, ToolChain, Arch, CommandType, Attr = Key[1].split('_')\r
1481 if (Target == self.BuildTarget or Target == TAB_STAR) and\\r
1482 (ToolChain == self.ToolChain or ToolChain == TAB_STAR) and\\r
1483 (Arch == self.Arch or Arch == TAB_STAR) and\\r
1484 Options[Key].startswith("="):\r
1485\r
1486 if OverrideList.get(Key[1]) is not None:\r
1487 OverrideList.pop(Key[1])\r
1488 OverrideList[Key[1]] = Options[Key]\r
1489\r
1490 #\r
1491 # Use the highest priority value.\r
1492 #\r
1493 if (len(OverrideList) >= 2):\r
1494 KeyList = list(OverrideList.keys())\r
1495 for Index in range(len(KeyList)):\r
1496 NowKey = KeyList[Index]\r
1497 Target1, ToolChain1, Arch1, CommandType1, Attr1 = NowKey.split("_")\r
1498 for Index1 in range(len(KeyList) - Index - 1):\r
1499 NextKey = KeyList[Index1 + Index + 1]\r
1500 #\r
1501 # Compare two Key, if one is included by another, choose the higher priority one\r
1502 #\r
1503 Target2, ToolChain2, Arch2, CommandType2, Attr2 = NextKey.split("_")\r
1504 if (Target1 == Target2 or Target1 == TAB_STAR or Target2 == TAB_STAR) and\\r
1505 (ToolChain1 == ToolChain2 or ToolChain1 == TAB_STAR or ToolChain2 == TAB_STAR) and\\r
1506 (Arch1 == Arch2 or Arch1 == TAB_STAR or Arch2 == TAB_STAR) and\\r
1507 (CommandType1 == CommandType2 or CommandType1 == TAB_STAR or CommandType2 == TAB_STAR) and\\r
1508 (Attr1 == Attr2 or Attr1 == TAB_STAR or Attr2 == TAB_STAR):\r
1509\r
1510 if CalculatePriorityValue(NowKey) > CalculatePriorityValue(NextKey):\r
1511 if Options.get((self.BuildRuleFamily, NextKey)) is not None:\r
1512 Options.pop((self.BuildRuleFamily, NextKey))\r
1513 else:\r
1514 if Options.get((self.BuildRuleFamily, NowKey)) is not None:\r
1515 Options.pop((self.BuildRuleFamily, NowKey))\r
1516\r
1517 for Key in Options:\r
1518 if ModuleStyle is not None and len (Key) > 2:\r
1519 # Check Module style is EDK or EDKII.\r
1520 # Only append build option for the matched style module.\r
1521 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1522 continue\r
1523 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1524 continue\r
1525 Family = Key[0]\r
1526 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1527 # if tool chain family doesn't match, skip it\r
ab957f03
MK
1528 if Family != "":\r
1529 Found = False\r
1530 if Tool in ToolDef:\r
1531 FamilyIsNull = False\r
1532 if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[Tool]:\r
1533 if Family == ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
1534 FamilyMatch = True\r
1535 Found = True\r
ab957f03
MK
1536 if TAB_STAR in ToolDef:\r
1537 FamilyIsNull = False\r
1538 if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[TAB_STAR]:\r
1539 if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_BUILDRULEFAMILY]:\r
1540 FamilyMatch = True\r
1541 Found = True\r
ab957f03
MK
1542 if not Found:\r
1543 continue\r
1544\r
e8449e1d
FB
1545 # expand any wildcard\r
1546 if Target == TAB_STAR or Target == self.BuildTarget:\r
1547 if Tag == TAB_STAR or Tag == self.ToolChain:\r
1548 if Arch == TAB_STAR or Arch == self.Arch:\r
1549 if Tool not in BuildOptions:\r
1550 BuildOptions[Tool] = {}\r
1551 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
1552 BuildOptions[Tool][Attr] = Options[Key]\r
1553 else:\r
1554 # append options for the same tool except PATH\r
1555 if Attr != 'PATH':\r
1556 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1557 else:\r
1558 BuildOptions[Tool][Attr] = Options[Key]\r
1559 # Build Option Family has been checked, which need't to be checked again for family.\r
1560 if FamilyMatch or FamilyIsNull:\r
1561 return BuildOptions\r
1562\r
1563 for Key in Options:\r
1564 if ModuleStyle is not None and len (Key) > 2:\r
1565 # Check Module style is EDK or EDKII.\r
1566 # Only append build option for the matched style module.\r
1567 if ModuleStyle == EDK_NAME and Key[2] != EDK_NAME:\r
1568 continue\r
1569 elif ModuleStyle == EDKII_NAME and Key[2] != EDKII_NAME:\r
1570 continue\r
1571 Family = Key[0]\r
1572 Target, Tag, Arch, Tool, Attr = Key[1].split("_")\r
1573 # if tool chain family doesn't match, skip it\r
ab957f03 1574 if Family == "":\r
e8449e1d
FB
1575 continue\r
1576 # option has been added before\r
ab957f03
MK
1577 Found = False\r
1578 if Tool in ToolDef:\r
1579 if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:\r
1580 if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:\r
1581 Found = True\r
1582 if TAB_STAR in ToolDef:\r
1583 if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:\r
1584 if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:\r
1585 Found = True\r
1586 if not Found:\r
e8449e1d
FB
1587 continue\r
1588\r
1589 # expand any wildcard\r
1590 if Target == TAB_STAR or Target == self.BuildTarget:\r
1591 if Tag == TAB_STAR or Tag == self.ToolChain:\r
1592 if Arch == TAB_STAR or Arch == self.Arch:\r
1593 if Tool not in BuildOptions:\r
1594 BuildOptions[Tool] = {}\r
1595 if Attr != "FLAGS" or Attr not in BuildOptions[Tool] or Options[Key].startswith('='):\r
1596 BuildOptions[Tool][Attr] = Options[Key]\r
1597 else:\r
1598 # append options for the same tool except PATH\r
1599 if Attr != 'PATH':\r
1600 BuildOptions[Tool][Attr] += " " + Options[Key]\r
1601 else:\r
1602 BuildOptions[Tool][Attr] = Options[Key]\r
1603 return BuildOptions\r