]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/DecBuildData.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / DecBuildData.py
1 ## @file
2 # This file is used to create a database used by build tool
3 #
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8 from Common.StringUtils import *
9 from Common.DataType import *
10 from Common.Misc import *
11 from types import *
12 from collections import OrderedDict
13 from CommonDataClass.DataClass import *
14 from Workspace.BuildClassObject import PackageBuildClassObject, StructurePcd, PcdClassObject
15 from Common.GlobalData import gGlobalDefines
16 from re import compile
17
18 ## Platform build information from DEC file
19 #
20 # This class is used to retrieve information stored in database and convert them
21 # into PackageBuildClassObject form for easier use for AutoGen.
22 #
23 class DecBuildData(PackageBuildClassObject):
24
25 # dict used to convert part of [Defines] to members of DecBuildData directly
26 _PROPERTY_ = {
27 #
28 # Required Fields
29 #
30 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",
31 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",
32 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",
33 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",
34 }
35
36 ## Constructor of DecBuildData
37 #
38 # Initialize object of DecBuildData
39 #
40 # @param FilePath The path of package description file
41 # @param RawData The raw data of DEC file
42 # @param BuildDataBase Database used to retrieve module information
43 # @param Arch The target architecture
44 # @param Platform (not used for DecBuildData)
45 # @param Macros Macros used for replacement in DSC file
46 #
47 def __init__(self, File, RawData, BuildDataBase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
48 self.MetaFile = File
49 self._PackageDir = File.Dir
50 self._RawData = RawData
51 self._Bdb = BuildDataBase
52 self._Arch = Arch
53 self._Target = Target
54 self._Toolchain = Toolchain
55 self._Clear()
56 self.UpdatePcdTypeDict()
57
58 ## XXX[key] = value
59 def __setitem__(self, key, value):
60 self.__dict__[self._PROPERTY_[key]] = value
61
62 ## value = XXX[key]
63 def __getitem__(self, key):
64 return self.__dict__[self._PROPERTY_[key]]
65
66 ## "in" test support
67 def __contains__(self, key):
68 return key in self._PROPERTY_
69
70 ## Set all internal used members of DecBuildData to None
71 def _Clear(self):
72 self._Header = None
73 self._PackageName = None
74 self._Guid = None
75 self._Version = None
76 self._PkgUniFile = None
77 self._Protocols = None
78 self._Ppis = None
79 self._Guids = None
80 self._Includes = None
81 self._CommonIncludes = None
82 self._LibraryClasses = None
83 self._Pcds = None
84 self._MacroDict = None
85 self._PrivateProtocols = None
86 self._PrivatePpis = None
87 self._PrivateGuids = None
88 self._PrivateIncludes = None
89
90 ## Get current effective macros
91 @property
92 def _Macros(self):
93 if self._MacroDict is None:
94 self._MacroDict = dict(gGlobalDefines)
95 return self._MacroDict
96
97 ## Get architecture
98 @property
99 def Arch(self):
100 return self._Arch
101
102 ## Retrieve all information in [Defines] section
103 #
104 # (Retrieving all [Defines] information in one-shot is just to save time.)
105 #
106 def _GetHeaderInfo(self):
107 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
108 for Record in RecordList:
109 Name = Record[1]
110 if Name in self:
111 self[Name] = Record[2]
112 self._Header = 'DUMMY'
113
114 ## Retrieve package name
115 @property
116 def PackageName(self):
117 if self._PackageName is None:
118 if self._Header is None:
119 self._GetHeaderInfo()
120 if self._PackageName is None:
121 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
122 return self._PackageName
123
124 ## Retrieve file guid
125 @property
126 def PackageName(self):
127 if self._Guid is None:
128 if self._Header is None:
129 self._GetHeaderInfo()
130 if self._Guid is None:
131 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
132 return self._Guid
133
134 ## Retrieve package version
135 @property
136 def Version(self):
137 if self._Version is None:
138 if self._Header is None:
139 self._GetHeaderInfo()
140 if self._Version is None:
141 self._Version = ''
142 return self._Version
143
144 ## Retrieve protocol definitions (name/value pairs)
145 @property
146 def Protocols(self):
147 if self._Protocols is None:
148 #
149 # tdict is a special kind of dict, used for selecting correct
150 # protocol definition for given ARCH
151 #
152 ProtocolDict = tdict(True)
153 PrivateProtocolDict = tdict(True)
154 NameList = []
155 PrivateNameList = []
156 PublicNameList = []
157 # find out all protocol definitions for specific and 'common' arch
158 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
159 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
160 if PrivateFlag == 'PRIVATE':
161 if Name not in PrivateNameList:
162 PrivateNameList.append(Name)
163 PrivateProtocolDict[Arch, Name] = Guid
164 if Name in PublicNameList:
165 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
166 else:
167 if Name not in PublicNameList:
168 PublicNameList.append(Name)
169 if Name in PrivateNameList:
170 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
171 if Name not in NameList:
172 NameList.append(Name)
173 ProtocolDict[Arch, Name] = Guid
174 # use OrderedDict to keep the order
175 self._Protocols = OrderedDict()
176 self._PrivateProtocols = OrderedDict()
177 for Name in NameList:
178 #
179 # limit the ARCH to self._Arch, if no self._Arch found, tdict
180 # will automatically turn to 'common' ARCH for trying
181 #
182 self._Protocols[Name] = ProtocolDict[self._Arch, Name]
183 for Name in PrivateNameList:
184 self._PrivateProtocols[Name] = PrivateProtocolDict[self._Arch, Name]
185 return self._Protocols
186
187 ## Retrieve PPI definitions (name/value pairs)
188 @property
189 def Ppis(self):
190 if self._Ppis is None:
191 #
192 # tdict is a special kind of dict, used for selecting correct
193 # PPI definition for given ARCH
194 #
195 PpiDict = tdict(True)
196 PrivatePpiDict = tdict(True)
197 NameList = []
198 PrivateNameList = []
199 PublicNameList = []
200 # find out all PPI definitions for specific arch and 'common' arch
201 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
202 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
203 if PrivateFlag == 'PRIVATE':
204 if Name not in PrivateNameList:
205 PrivateNameList.append(Name)
206 PrivatePpiDict[Arch, Name] = Guid
207 if Name in PublicNameList:
208 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
209 else:
210 if Name not in PublicNameList:
211 PublicNameList.append(Name)
212 if Name in PrivateNameList:
213 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
214 if Name not in NameList:
215 NameList.append(Name)
216 PpiDict[Arch, Name] = Guid
217 # use OrderedDict to keep the order
218 self._Ppis = OrderedDict()
219 self._PrivatePpis = OrderedDict()
220 for Name in NameList:
221 #
222 # limit the ARCH to self._Arch, if no self._Arch found, tdict
223 # will automatically turn to 'common' ARCH for trying
224 #
225 self._Ppis[Name] = PpiDict[self._Arch, Name]
226 for Name in PrivateNameList:
227 self._PrivatePpis[Name] = PrivatePpiDict[self._Arch, Name]
228 return self._Ppis
229
230 ## Retrieve GUID definitions (name/value pairs)
231 @property
232 def Guids(self):
233 if self._Guids is None:
234 #
235 # tdict is a special kind of dict, used for selecting correct
236 # GUID definition for given ARCH
237 #
238 GuidDict = tdict(True)
239 PrivateGuidDict = tdict(True)
240 NameList = []
241 PrivateNameList = []
242 PublicNameList = []
243 # find out all protocol definitions for specific and 'common' arch
244 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
245 for Name, Guid, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
246 if PrivateFlag == 'PRIVATE':
247 if Name not in PrivateNameList:
248 PrivateNameList.append(Name)
249 PrivateGuidDict[Arch, Name] = Guid
250 if Name in PublicNameList:
251 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
252 else:
253 if Name not in PublicNameList:
254 PublicNameList.append(Name)
255 if Name in PrivateNameList:
256 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % Name, File=self.MetaFile, Line=LineNo)
257 if Name not in NameList:
258 NameList.append(Name)
259 GuidDict[Arch, Name] = Guid
260 # use OrderedDict to keep the order
261 self._Guids = OrderedDict()
262 self._PrivateGuids = OrderedDict()
263 for Name in NameList:
264 #
265 # limit the ARCH to self._Arch, if no self._Arch found, tdict
266 # will automatically turn to 'common' ARCH for trying
267 #
268 self._Guids[Name] = GuidDict[self._Arch, Name]
269 for Name in PrivateNameList:
270 self._PrivateGuids[Name] = PrivateGuidDict[self._Arch, Name]
271 return self._Guids
272
273 ## Retrieve public include paths declared in this package
274 @property
275 def Includes(self):
276 if self._Includes is None or self._CommonIncludes is None:
277 self._CommonIncludes = []
278 self._Includes = []
279 self._PrivateIncludes = []
280 PublicInclues = []
281 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
282 Macros = self._Macros
283 for Record in RecordList:
284 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
285 LineNo = Record[-1]
286 # validate the path
287 ErrorCode, ErrorInfo = File.Validate()
288 if ErrorCode != 0:
289 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
290
291 # avoid duplicate include path
292 if File not in self._Includes:
293 self._Includes.append(File)
294 if Record[4] == 'PRIVATE':
295 if File not in self._PrivateIncludes:
296 self._PrivateIncludes.append(File)
297 if File in PublicInclues:
298 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)
299 else:
300 if File not in PublicInclues:
301 PublicInclues.append(File)
302 if File in self._PrivateIncludes:
303 EdkLogger.error('build', OPTION_CONFLICT, "Can't determine %s's attribute, it is both defined as Private and non-Private attribute in DEC file." % File, File=self.MetaFile, Line=LineNo)
304 if Record[3] == TAB_COMMON:
305 self._CommonIncludes.append(File)
306 return self._Includes
307
308 ## Retrieve library class declarations (not used in build at present)
309 @property
310 def LibraryClasses(self):
311 if self._LibraryClasses is None:
312 #
313 # tdict is a special kind of dict, used for selecting correct
314 # library class declaration for given ARCH
315 #
316 LibraryClassDict = tdict(True)
317 LibraryClassSet = set()
318 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
319 Macros = self._Macros
320 for LibraryClass, File, Dummy, Arch, PrivateFlag, ID, LineNo in RecordList:
321 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
322 # check the file validation
323 ErrorCode, ErrorInfo = File.Validate()
324 if ErrorCode != 0:
325 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
326 LibraryClassSet.add(LibraryClass)
327 LibraryClassDict[Arch, LibraryClass] = File
328 self._LibraryClasses = OrderedDict()
329 for LibraryClass in LibraryClassSet:
330 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
331 return self._LibraryClasses
332
333 ## Retrieve PCD declarations
334 @property
335 def Pcds(self):
336 if self._Pcds is None:
337 self._Pcds = OrderedDict()
338 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
339 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
340 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
341 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
342 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
343 return self._Pcds
344
345 def ParsePcdName(self,TokenCName):
346 TokenCName = TokenCName.strip()
347 if TokenCName.startswith("["):
348 if "." in TokenCName:
349 Demesionattr = TokenCName[:TokenCName.index(".")]
350 Fields = TokenCName[TokenCName.index(".")+1:]
351 else:
352 Demesionattr = TokenCName
353 Fields = ""
354 else:
355 Demesionattr = ""
356 Fields = TokenCName
357
358 return Demesionattr,Fields
359
360 def ProcessStructurePcd(self, StructurePcdRawDataSet):
361 s_pcd_set = OrderedDict()
362 for s_pcd, LineNo in StructurePcdRawDataSet:
363 if s_pcd.TokenSpaceGuidCName not in s_pcd_set:
364 s_pcd_set[s_pcd.TokenSpaceGuidCName] = []
365 s_pcd_set[s_pcd.TokenSpaceGuidCName].append((s_pcd, LineNo))
366
367 str_pcd_set = []
368 for pcdname in s_pcd_set:
369 dep_pkgs = []
370 struct_pcd = StructurePcd()
371 for item, LineNo in s_pcd_set[pcdname]:
372 if not item.TokenCName:
373 continue
374 if "<HeaderFiles>" in item.TokenCName:
375 struct_pcd.StructuredPcdIncludeFile.append(item.DefaultValue)
376 elif "<Packages>" in item.TokenCName:
377 dep_pkgs.append(item.DefaultValue)
378 elif item.DatumType == item.TokenCName:
379 struct_pcd.copy(item)
380 struct_pcd.TokenValue = struct_pcd.TokenValue.strip("{").strip()
381 struct_pcd.TokenSpaceGuidCName, struct_pcd.TokenCName = pcdname.split(".")
382 struct_pcd.PcdDefineLineNo = LineNo
383 struct_pcd.PkgPath = self.MetaFile.File
384 struct_pcd.SetDecDefaultValue(item.DefaultValue,self.MetaFile.File,LineNo)
385 else:
386 DemesionAttr, Fields = self.ParsePcdName(item.TokenCName)
387 struct_pcd.AddDefaultValue(Fields, item.DefaultValue, self.MetaFile.File, LineNo,DemesionAttr)
388
389 struct_pcd.PackageDecs = dep_pkgs
390 str_pcd_set.append(struct_pcd)
391 return str_pcd_set
392
393 ## Retrieve PCD declarations for given type
394 def _GetPcd(self, Type):
395 Pcds = OrderedDict()
396 #
397 # tdict is a special kind of dict, used for selecting correct
398 # PCD declaration for given ARCH
399 #
400 PcdDict = tdict(True, 3)
401 # for summarizing PCD
402 PcdSet = []
403 # find out all PCDs of the 'type'
404
405 StrPcdSet = []
406 RecordList = self._RawData[Type, self._Arch]
407 for TokenSpaceGuid, PcdCName, Setting, Arch, PrivateFlag, Dummy1, Dummy2 in RecordList:
408 PcdDict[Arch, PcdCName, TokenSpaceGuid] = (Setting, Dummy2)
409 if not (PcdCName, TokenSpaceGuid) in PcdSet:
410 PcdSet.append((PcdCName, TokenSpaceGuid))
411
412 DefinitionPosition = {}
413 for PcdCName, TokenSpaceGuid in PcdSet:
414 #
415 # limit the ARCH to self._Arch, if no self._Arch found, tdict
416 # will automatically turn to 'common' ARCH and try again
417 #
418 Setting, LineNo = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
419 if Setting is None:
420 continue
421
422 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
423 validateranges, validlists, expressions = self._RawData.GetValidExpression(TokenSpaceGuid, PcdCName)
424 PcdObj = PcdClassObject(
425 PcdCName,
426 TokenSpaceGuid,
427 self._PCD_TYPE_STRING_[Type],
428 DatumType,
429 DefaultValue,
430 TokenNumber,
431 '',
432 {},
433 False,
434 None,
435 list(validateranges),
436 list(validlists),
437 list(expressions)
438 )
439 DefinitionPosition[PcdObj] = (self.MetaFile.File, LineNo)
440 if "." in TokenSpaceGuid:
441 StrPcdSet.append((PcdObj, LineNo))
442 else:
443 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdObj
444
445 StructurePcds = self.ProcessStructurePcd(StrPcdSet)
446 for pcd in StructurePcds:
447 Pcds[pcd.TokenCName, pcd.TokenSpaceGuidCName, self._PCD_TYPE_STRING_[Type]] = pcd
448 StructPattern = compile(r'[_a-zA-Z][0-9A-Za-z_]*$')
449 for pcd in Pcds.values():
450 if pcd.DatumType not in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64, TAB_VOID, "BOOLEAN"]:
451 if not pcd.IsAggregateDatumType():
452 EdkLogger.error('build', FORMAT_INVALID, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", DefinitionPosition[pcd][0], DefinitionPosition[pcd][1])
453 elif not pcd.IsArray() and not pcd.StructuredPcdIncludeFile:
454 EdkLogger.error("build", PCD_STRUCTURE_PCD_ERROR, "The structure Pcd %s.%s header file is not found in %s line %s \n" % (pcd.TokenSpaceGuidCName, pcd.TokenCName, pcd.DefinitionPosition[0], pcd.DefinitionPosition[1] ))
455 return Pcds
456
457 @property
458 def CommonIncludes(self):
459 if self._CommonIncludes is None:
460 self.Includes
461 return self._CommonIncludes