2 # This file is used to create a database used by build tool
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
8 from Common
.StringUtils
import *
9 from Common
.DataType
import *
10 from Common
.Misc
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
18 ## Platform build information from DEC file
20 # This class is used to retrieve information stored in database and convert them
21 # into PackageBuildClassObject form for easier use for AutoGen.
23 class DecBuildData(PackageBuildClassObject
):
24 # dict used to convert PCD type in database to string used by build tool
26 MODEL_PCD_FIXED_AT_BUILD
: TAB_PCDS_FIXED_AT_BUILD
,
27 MODEL_PCD_PATCHABLE_IN_MODULE
: TAB_PCDS_PATCHABLE_IN_MODULE
,
28 MODEL_PCD_FEATURE_FLAG
: TAB_PCDS_FEATURE_FLAG
,
29 MODEL_PCD_DYNAMIC
: TAB_PCDS_DYNAMIC
,
30 MODEL_PCD_DYNAMIC_DEFAULT
: TAB_PCDS_DYNAMIC
,
31 MODEL_PCD_DYNAMIC_HII
: TAB_PCDS_DYNAMIC_HII
,
32 MODEL_PCD_DYNAMIC_VPD
: TAB_PCDS_DYNAMIC_VPD
,
33 MODEL_PCD_DYNAMIC_EX
: TAB_PCDS_DYNAMIC_EX
,
34 MODEL_PCD_DYNAMIC_EX_DEFAULT
: TAB_PCDS_DYNAMIC_EX
,
35 MODEL_PCD_DYNAMIC_EX_HII
: TAB_PCDS_DYNAMIC_EX_HII
,
36 MODEL_PCD_DYNAMIC_EX_VPD
: TAB_PCDS_DYNAMIC_EX_VPD
,
39 # dict used to convert part of [Defines] to members of DecBuildData directly
44 TAB_DEC_DEFINES_PACKAGE_NAME
: "_PackageName",
45 TAB_DEC_DEFINES_PACKAGE_GUID
: "_Guid",
46 TAB_DEC_DEFINES_PACKAGE_VERSION
: "_Version",
47 TAB_DEC_DEFINES_PKG_UNI_FILE
: "_PkgUniFile",
51 ## Constructor of DecBuildData
53 # Initialize object of DecBuildData
55 # @param FilePath The path of package description file
56 # @param RawData The raw data of DEC file
57 # @param BuildDataBase Database used to retrieve module information
58 # @param Arch The target architecture
59 # @param Platform (not used for DecBuildData)
60 # @param Macros Macros used for replacement in DSC file
62 def __init__(self
, File
, RawData
, BuildDataBase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
64 self
._PackageDir
= File
.Dir
65 self
._RawData
= RawData
66 self
._Bdb
= BuildDataBase
69 self
._Toolchain
= Toolchain
73 def __setitem__(self
, key
, value
):
74 self
.__dict
__[self
._PROPERTY
_[key
]] = value
77 def __getitem__(self
, key
):
78 return self
.__dict
__[self
._PROPERTY
_[key
]]
81 def __contains__(self
, key
):
82 return key
in self
._PROPERTY
_
84 ## Set all internal used members of DecBuildData to None
87 self
._PackageName
= None
90 self
._PkgUniFile
= None
91 self
._Protocols
= None
95 self
._CommonIncludes
= None
96 self
._LibraryClasses
= None
98 self
._MacroDict
= None
99 self
._PrivateProtocols
= None
100 self
._PrivatePpis
= None
101 self
._PrivateGuids
= None
102 self
._PrivateIncludes
= None
104 ## Get current effective macros
107 if self
._MacroDict
is None:
108 self
._MacroDict
= dict(gGlobalDefines
)
109 return self
._MacroDict
116 ## Retrieve all information in [Defines] section
118 # (Retrieving all [Defines] information in one-shot is just to save time.)
120 def _GetHeaderInfo(self
):
121 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
]
122 for Record
in RecordList
:
125 self
[Name
] = Record
[2]
126 self
._Header
= 'DUMMY'
128 ## Retrieve package name
130 def PackageName(self
):
131 if self
._PackageName
is None:
132 if self
._Header
is None:
133 self
._GetHeaderInfo
()
134 if self
._PackageName
is None:
135 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_NAME", File
=self
.MetaFile
)
136 return self
._PackageName
138 ## Retrieve file guid
140 def PackageName(self
):
141 if self
._Guid
is None:
142 if self
._Header
is None:
143 self
._GetHeaderInfo
()
144 if self
._Guid
is None:
145 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_GUID", File
=self
.MetaFile
)
148 ## Retrieve package version
151 if self
._Version
is None:
152 if self
._Header
is None:
153 self
._GetHeaderInfo
()
154 if self
._Version
is None:
158 ## Retrieve protocol definitions (name/value pairs)
161 if self
._Protocols
is None:
163 # tdict is a special kind of dict, used for selecting correct
164 # protocol definition for given ARCH
166 ProtocolDict
= tdict(True)
167 PrivateProtocolDict
= tdict(True)
171 # find out all protocol definitions for specific and 'common' arch
172 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
]
173 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
174 if PrivateFlag
== 'PRIVATE':
175 if Name
not in PrivateNameList
:
176 PrivateNameList
.append(Name
)
177 PrivateProtocolDict
[Arch
, Name
] = Guid
178 if Name
in PublicNameList
:
179 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
)
181 if Name
not in PublicNameList
:
182 PublicNameList
.append(Name
)
183 if Name
in PrivateNameList
:
184 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
)
185 if Name
not in NameList
:
186 NameList
.append(Name
)
187 ProtocolDict
[Arch
, Name
] = Guid
188 # use OrderedDict to keep the order
189 self
._Protocols
= OrderedDict()
190 self
._PrivateProtocols
= OrderedDict()
191 for Name
in NameList
:
193 # limit the ARCH to self._Arch, if no self._Arch found, tdict
194 # will automatically turn to 'common' ARCH for trying
196 self
._Protocols
[Name
] = ProtocolDict
[self
._Arch
, Name
]
197 for Name
in PrivateNameList
:
198 self
._PrivateProtocols
[Name
] = PrivateProtocolDict
[self
._Arch
, Name
]
199 return self
._Protocols
201 ## Retrieve PPI definitions (name/value pairs)
204 if self
._Ppis
is None:
206 # tdict is a special kind of dict, used for selecting correct
207 # PPI definition for given ARCH
209 PpiDict
= tdict(True)
210 PrivatePpiDict
= tdict(True)
214 # find out all PPI definitions for specific arch and 'common' arch
215 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
]
216 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
217 if PrivateFlag
== 'PRIVATE':
218 if Name
not in PrivateNameList
:
219 PrivateNameList
.append(Name
)
220 PrivatePpiDict
[Arch
, Name
] = Guid
221 if Name
in PublicNameList
:
222 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
)
224 if Name
not in PublicNameList
:
225 PublicNameList
.append(Name
)
226 if Name
in PrivateNameList
:
227 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
)
228 if Name
not in NameList
:
229 NameList
.append(Name
)
230 PpiDict
[Arch
, Name
] = Guid
231 # use OrderedDict to keep the order
232 self
._Ppis
= OrderedDict()
233 self
._PrivatePpis
= OrderedDict()
234 for Name
in NameList
:
236 # limit the ARCH to self._Arch, if no self._Arch found, tdict
237 # will automatically turn to 'common' ARCH for trying
239 self
._Ppis
[Name
] = PpiDict
[self
._Arch
, Name
]
240 for Name
in PrivateNameList
:
241 self
._PrivatePpis
[Name
] = PrivatePpiDict
[self
._Arch
, Name
]
244 ## Retrieve GUID definitions (name/value pairs)
247 if self
._Guids
is None:
249 # tdict is a special kind of dict, used for selecting correct
250 # GUID definition for given ARCH
252 GuidDict
= tdict(True)
253 PrivateGuidDict
= tdict(True)
257 # find out all protocol definitions for specific and 'common' arch
258 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
]
259 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
260 if PrivateFlag
== 'PRIVATE':
261 if Name
not in PrivateNameList
:
262 PrivateNameList
.append(Name
)
263 PrivateGuidDict
[Arch
, Name
] = Guid
264 if Name
in PublicNameList
:
265 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
)
267 if Name
not in PublicNameList
:
268 PublicNameList
.append(Name
)
269 if Name
in PrivateNameList
:
270 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
)
271 if Name
not in NameList
:
272 NameList
.append(Name
)
273 GuidDict
[Arch
, Name
] = Guid
274 # use OrderedDict to keep the order
275 self
._Guids
= OrderedDict()
276 self
._PrivateGuids
= OrderedDict()
277 for Name
in NameList
:
279 # limit the ARCH to self._Arch, if no self._Arch found, tdict
280 # will automatically turn to 'common' ARCH for trying
282 self
._Guids
[Name
] = GuidDict
[self
._Arch
, Name
]
283 for Name
in PrivateNameList
:
284 self
._PrivateGuids
[Name
] = PrivateGuidDict
[self
._Arch
, Name
]
287 ## Retrieve public include paths declared in this package
290 if self
._Includes
is None or self
._CommonIncludes
is None:
291 self
._CommonIncludes
= []
293 self
._PrivateIncludes
= []
295 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
]
296 Macros
= self
._Macros
297 for Record
in RecordList
:
298 File
= PathClass(NormPath(Record
[0], Macros
), self
._PackageDir
, Arch
=self
._Arch
)
301 ErrorCode
, ErrorInfo
= File
.Validate()
303 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
305 # avoid duplicate include path
306 if File
not in self
._Includes
:
307 self
._Includes
.append(File
)
308 if Record
[4] == 'PRIVATE':
309 if File
not in self
._PrivateIncludes
:
310 self
._PrivateIncludes
.append(File
)
311 if File
in PublicInclues
:
312 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
)
314 if File
not in PublicInclues
:
315 PublicInclues
.append(File
)
316 if File
in self
._PrivateIncludes
:
317 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
)
318 if Record
[3] == TAB_COMMON
:
319 self
._CommonIncludes
.append(File
)
320 return self
._Includes
322 ## Retrieve library class declarations (not used in build at present)
324 def LibraryClasses(self
):
325 if self
._LibraryClasses
is None:
327 # tdict is a special kind of dict, used for selecting correct
328 # library class declaration for given ARCH
330 LibraryClassDict
= tdict(True)
331 LibraryClassSet
= set()
332 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
]
333 Macros
= self
._Macros
334 for LibraryClass
, File
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
335 File
= PathClass(NormPath(File
, Macros
), self
._PackageDir
, Arch
=self
._Arch
)
336 # check the file validation
337 ErrorCode
, ErrorInfo
= File
.Validate()
339 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
340 LibraryClassSet
.add(LibraryClass
)
341 LibraryClassDict
[Arch
, LibraryClass
] = File
342 self
._LibraryClasses
= OrderedDict()
343 for LibraryClass
in LibraryClassSet
:
344 self
._LibraryClasses
[LibraryClass
] = LibraryClassDict
[self
._Arch
, LibraryClass
]
345 return self
._LibraryClasses
347 ## Retrieve PCD declarations
350 if self
._Pcds
is None:
351 self
._Pcds
= OrderedDict()
352 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
353 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
354 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
355 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
356 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
359 def ParsePcdName(self
,TokenCName
):
360 TokenCName
= TokenCName
.strip()
361 if TokenCName
.startswith("["):
362 if "." in TokenCName
:
363 Demesionattr
= TokenCName
[:TokenCName
.index(".")]
364 Fields
= TokenCName
[TokenCName
.index(".")+1:]
366 Demesionattr
= TokenCName
372 return Demesionattr
,Fields
374 def ProcessStructurePcd(self
, StructurePcdRawDataSet
):
375 s_pcd_set
= OrderedDict()
376 for s_pcd
, LineNo
in StructurePcdRawDataSet
:
377 if s_pcd
.TokenSpaceGuidCName
not in s_pcd_set
:
378 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
] = []
379 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
].append((s_pcd
, LineNo
))
382 for pcdname
in s_pcd_set
:
384 struct_pcd
= StructurePcd()
385 for item
, LineNo
in s_pcd_set
[pcdname
]:
386 if not item
.TokenCName
:
388 if "<HeaderFiles>" in item
.TokenCName
:
389 struct_pcd
.StructuredPcdIncludeFile
.append(item
.DefaultValue
)
390 elif "<Packages>" in item
.TokenCName
:
391 dep_pkgs
.append(item
.DefaultValue
)
392 elif item
.DatumType
== item
.TokenCName
:
393 struct_pcd
.copy(item
)
394 struct_pcd
.TokenValue
= struct_pcd
.TokenValue
.strip("{").strip()
395 struct_pcd
.TokenSpaceGuidCName
, struct_pcd
.TokenCName
= pcdname
.split(".")
396 struct_pcd
.PcdDefineLineNo
= LineNo
397 struct_pcd
.PkgPath
= self
.MetaFile
.File
398 struct_pcd
.SetDecDefaultValue(item
.DefaultValue
)
400 DemesionAttr
, Fields
= self
.ParsePcdName(item
.TokenCName
)
401 struct_pcd
.AddDefaultValue(Fields
, item
.DefaultValue
, self
.MetaFile
.File
, LineNo
,DemesionAttr
)
403 struct_pcd
.PackageDecs
= dep_pkgs
404 str_pcd_set
.append(struct_pcd
)
407 ## Retrieve PCD declarations for given type
408 def _GetPcd(self
, Type
):
411 # tdict is a special kind of dict, used for selecting correct
412 # PCD declaration for given ARCH
414 PcdDict
= tdict(True, 3)
415 # for summarizing PCD
417 # find out all PCDs of the 'type'
420 RecordList
= self
._RawData
[Type
, self
._Arch
]
421 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, PrivateFlag
, Dummy1
, Dummy2
in RecordList
:
422 PcdDict
[Arch
, PcdCName
, TokenSpaceGuid
] = (Setting
, Dummy2
)
423 if not (PcdCName
, TokenSpaceGuid
) in PcdSet
:
424 PcdSet
.append((PcdCName
, TokenSpaceGuid
))
426 DefinitionPosition
= {}
427 for PcdCName
, TokenSpaceGuid
in PcdSet
:
429 # limit the ARCH to self._Arch, if no self._Arch found, tdict
430 # will automatically turn to 'common' ARCH and try again
432 Setting
, LineNo
= PcdDict
[self
._Arch
, PcdCName
, TokenSpaceGuid
]
436 DefaultValue
, DatumType
, TokenNumber
= AnalyzePcdData(Setting
)
437 validateranges
, validlists
, expressions
= self
._RawData
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
438 PcdObj
= PcdClassObject(
441 self
._PCD
_TYPE
_STRING
_[Type
],
449 list(validateranges
),
453 DefinitionPosition
[PcdObj
] = (self
.MetaFile
.File
, LineNo
)
454 if "." in TokenSpaceGuid
:
455 StrPcdSet
.append((PcdObj
, LineNo
))
457 Pcds
[PcdCName
, TokenSpaceGuid
, self
._PCD
_TYPE
_STRING
_[Type
]] = PcdObj
459 StructurePcds
= self
.ProcessStructurePcd(StrPcdSet
)
460 for pcd
in StructurePcds
:
461 Pcds
[pcd
.TokenCName
, pcd
.TokenSpaceGuidCName
, self
._PCD
_TYPE
_STRING
_[Type
]] = pcd
462 StructPattern
= compile(r
'[_a-zA-Z][0-9A-Za-z_]*$')
463 for pcd
in Pcds
.values():
464 if pcd
.DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
465 if not pcd
.IsAggregateDatumType():
466 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])
467 elif not pcd
.IsArray() and not pcd
.StructuredPcdIncludeFile
:
468 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] ))
472 def CommonIncludes(self
):
473 if self
._CommonIncludes
is None:
475 return self
._CommonIncludes