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 # This program and the accompanying materials
7 # are licensed and made available under the terms and conditions of the BSD License
8 # which accompanies this distribution. The full text of the license may be found at
9 # http://opensource.org/licenses/bsd-license.php
11 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 from Common
.String
import *
15 from Common
.DataType
import *
16 from Common
.Misc
import *
19 from Workspace
.BuildClassObject
import PackageBuildClassObject
, StructurePcd
, PcdClassObject
21 ## Platform build information from DEC file
23 # This class is used to retrieve information stored in database and convert them
24 # into PackageBuildClassObject form for easier use for AutoGen.
26 class DecBuildData(PackageBuildClassObject
):
27 # dict used to convert PCD type in database to string used by build tool
29 MODEL_PCD_FIXED_AT_BUILD
: "FixedAtBuild",
30 MODEL_PCD_PATCHABLE_IN_MODULE
: "PatchableInModule",
31 MODEL_PCD_FEATURE_FLAG
: "FeatureFlag",
32 MODEL_PCD_DYNAMIC
: "Dynamic",
33 MODEL_PCD_DYNAMIC_DEFAULT
: "Dynamic",
34 MODEL_PCD_DYNAMIC_HII
: "DynamicHii",
35 MODEL_PCD_DYNAMIC_VPD
: "DynamicVpd",
36 MODEL_PCD_DYNAMIC_EX
: "DynamicEx",
37 MODEL_PCD_DYNAMIC_EX_DEFAULT
: "DynamicEx",
38 MODEL_PCD_DYNAMIC_EX_HII
: "DynamicExHii",
39 MODEL_PCD_DYNAMIC_EX_VPD
: "DynamicExVpd",
42 # dict used to convert part of [Defines] to members of DecBuildData directly
47 TAB_DEC_DEFINES_PACKAGE_NAME
: "_PackageName",
48 TAB_DEC_DEFINES_PACKAGE_GUID
: "_Guid",
49 TAB_DEC_DEFINES_PACKAGE_VERSION
: "_Version",
50 TAB_DEC_DEFINES_PKG_UNI_FILE
: "_PkgUniFile",
54 ## Constructor of DecBuildData
56 # Initialize object of DecBuildData
58 # @param FilePath The path of package description file
59 # @param RawData The raw data of DEC file
60 # @param BuildDataBase Database used to retrieve module information
61 # @param Arch The target architecture
62 # @param Platform (not used for DecBuildData)
63 # @param Macros Macros used for replacement in DSC file
65 def __init__(self
, File
, RawData
, BuildDataBase
, Arch
='COMMON', Target
=None, Toolchain
=None):
67 self
._PackageDir
= File
.Dir
68 self
._RawData
= RawData
69 self
._Bdb
= BuildDataBase
72 self
._Toolchain
= Toolchain
76 def __setitem__(self
, key
, value
):
77 self
.__dict
__[self
._PROPERTY
_[key
]] = value
80 def __getitem__(self
, key
):
81 return self
.__dict
__[self
._PROPERTY
_[key
]]
84 def __contains__(self
, key
):
85 return key
in self
._PROPERTY
_
87 ## Set all internal used members of DecBuildData to None
90 self
._PackageName
= None
93 self
._PkgUniFile
= None
94 self
._Protocols
= None
98 self
._LibraryClasses
= None
101 self
._PrivateProtocols
= None
102 self
._PrivatePpis
= None
103 self
._PrivateGuids
= None
104 self
._PrivateIncludes
= None
106 ## Get current effective macros
107 def _GetMacros(self
):
108 if self
.__Macros
== None:
110 self
.__Macros
.update(GlobalData
.gGlobalDefines
)
119 # Changing the default ARCH to another may affect all other information
120 # because all information in a platform may be ARCH-related. That's
121 # why we need to clear all internal used members, in order to cause all
122 # information to be re-retrieved.
124 # @param Value The value of ARCH
126 def _SetArch(self
, Value
):
127 if self
._Arch
== Value
:
132 ## Retrieve all information in [Defines] section
134 # (Retriving all [Defines] information in one-shot is just to save time.)
136 def _GetHeaderInfo(self
):
137 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
]
138 for Record
in RecordList
:
141 self
[Name
] = Record
[2]
142 self
._Header
= 'DUMMY'
144 ## Retrieve package name
145 def _GetPackageName(self
):
146 if self
._PackageName
== None:
147 if self
._Header
== None:
148 self
._GetHeaderInfo
()
149 if self
._PackageName
== None:
150 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_NAME", File
=self
.MetaFile
)
151 return self
._PackageName
153 ## Retrieve file guid
154 def _GetFileGuid(self
):
155 if self
._Guid
== None:
156 if self
._Header
== None:
157 self
._GetHeaderInfo
()
158 if self
._Guid
== None:
159 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
, "No PACKAGE_GUID", File
=self
.MetaFile
)
162 ## Retrieve package version
163 def _GetVersion(self
):
164 if self
._Version
== None:
165 if self
._Header
== None:
166 self
._GetHeaderInfo
()
167 if self
._Version
== None:
171 ## Retrieve protocol definitions (name/value pairs)
172 def _GetProtocol(self
):
173 if self
._Protocols
== None:
175 # tdict is a special kind of dict, used for selecting correct
176 # protocol defition for given ARCH
178 ProtocolDict
= tdict(True)
179 PrivateProtocolDict
= tdict(True)
183 # find out all protocol definitions for specific and 'common' arch
184 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
]
185 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
186 if PrivateFlag
== 'PRIVATE':
187 if Name
not in PrivateNameList
:
188 PrivateNameList
.append(Name
)
189 PrivateProtocolDict
[Arch
, Name
] = Guid
190 if Name
in PublicNameList
:
191 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
)
193 if Name
not in PublicNameList
:
194 PublicNameList
.append(Name
)
195 if Name
in PrivateNameList
:
196 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
)
197 if Name
not in NameList
:
198 NameList
.append(Name
)
199 ProtocolDict
[Arch
, Name
] = Guid
200 # use sdict to keep the order
201 self
._Protocols
= sdict()
202 self
._PrivateProtocols
= sdict()
203 for Name
in NameList
:
205 # limit the ARCH to self._Arch, if no self._Arch found, tdict
206 # will automatically turn to 'common' ARCH for trying
208 self
._Protocols
[Name
] = ProtocolDict
[self
._Arch
, Name
]
209 for Name
in PrivateNameList
:
210 self
._PrivateProtocols
[Name
] = PrivateProtocolDict
[self
._Arch
, Name
]
211 return self
._Protocols
213 ## Retrieve PPI definitions (name/value pairs)
215 if self
._Ppis
== None:
217 # tdict is a special kind of dict, used for selecting correct
218 # PPI defition for given ARCH
220 PpiDict
= tdict(True)
221 PrivatePpiDict
= tdict(True)
225 # find out all PPI definitions for specific arch and 'common' arch
226 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
]
227 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
228 if PrivateFlag
== 'PRIVATE':
229 if Name
not in PrivateNameList
:
230 PrivateNameList
.append(Name
)
231 PrivatePpiDict
[Arch
, Name
] = Guid
232 if Name
in PublicNameList
:
233 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
)
235 if Name
not in PublicNameList
:
236 PublicNameList
.append(Name
)
237 if Name
in PrivateNameList
:
238 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
)
239 if Name
not in NameList
:
240 NameList
.append(Name
)
241 PpiDict
[Arch
, Name
] = Guid
242 # use sdict to keep the order
244 self
._PrivatePpis
= sdict()
245 for Name
in NameList
:
247 # limit the ARCH to self._Arch, if no self._Arch found, tdict
248 # will automatically turn to 'common' ARCH for trying
250 self
._Ppis
[Name
] = PpiDict
[self
._Arch
, Name
]
251 for Name
in PrivateNameList
:
252 self
._PrivatePpis
[Name
] = PrivatePpiDict
[self
._Arch
, Name
]
255 ## Retrieve GUID definitions (name/value pairs)
257 if self
._Guids
== None:
259 # tdict is a special kind of dict, used for selecting correct
260 # GUID defition for given ARCH
262 GuidDict
= tdict(True)
263 PrivateGuidDict
= tdict(True)
267 # find out all protocol definitions for specific and 'common' arch
268 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
]
269 for Name
, Guid
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
270 if PrivateFlag
== 'PRIVATE':
271 if Name
not in PrivateNameList
:
272 PrivateNameList
.append(Name
)
273 PrivateGuidDict
[Arch
, Name
] = Guid
274 if Name
in PublicNameList
:
275 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
)
277 if Name
not in PublicNameList
:
278 PublicNameList
.append(Name
)
279 if Name
in PrivateNameList
:
280 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
)
281 if Name
not in NameList
:
282 NameList
.append(Name
)
283 GuidDict
[Arch
, Name
] = Guid
284 # use sdict to keep the order
285 self
._Guids
= sdict()
286 self
._PrivateGuids
= sdict()
287 for Name
in NameList
:
289 # limit the ARCH to self._Arch, if no self._Arch found, tdict
290 # will automatically turn to 'common' ARCH for trying
292 self
._Guids
[Name
] = GuidDict
[self
._Arch
, Name
]
293 for Name
in PrivateNameList
:
294 self
._PrivateGuids
[Name
] = PrivateGuidDict
[self
._Arch
, Name
]
297 ## Retrieve public include paths declared in this package
298 def _GetInclude(self
):
299 if self
._Includes
== None:
301 self
._PrivateIncludes
= []
303 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
]
304 Macros
= self
._Macros
305 Macros
["EDK_SOURCE"] = GlobalData
.gEcpSource
306 for Record
in RecordList
:
307 File
= PathClass(NormPath(Record
[0], Macros
), self
._PackageDir
, Arch
=self
._Arch
)
310 ErrorCode
, ErrorInfo
= File
.Validate()
312 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
314 # avoid duplicate include path
315 if File
not in self
._Includes
:
316 self
._Includes
.append(File
)
317 if Record
[4] == 'PRIVATE':
318 if File
not in self
._PrivateIncludes
:
319 self
._PrivateIncludes
.append(File
)
320 if File
in PublicInclues
:
321 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
)
323 if File
not in PublicInclues
:
324 PublicInclues
.append(File
)
325 if File
in self
._PrivateIncludes
:
326 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
)
328 return self
._Includes
330 ## Retrieve library class declarations (not used in build at present)
331 def _GetLibraryClass(self
):
332 if self
._LibraryClasses
== None:
334 # tdict is a special kind of dict, used for selecting correct
335 # library class declaration for given ARCH
337 LibraryClassDict
= tdict(True)
338 LibraryClassSet
= set()
339 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
]
340 Macros
= self
._Macros
341 for LibraryClass
, File
, Dummy
, Arch
, PrivateFlag
, ID
, LineNo
in RecordList
:
342 File
= PathClass(NormPath(File
, Macros
), self
._PackageDir
, Arch
=self
._Arch
)
343 # check the file validation
344 ErrorCode
, ErrorInfo
= File
.Validate()
346 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
347 LibraryClassSet
.add(LibraryClass
)
348 LibraryClassDict
[Arch
, LibraryClass
] = File
349 self
._LibraryClasses
= sdict()
350 for LibraryClass
in LibraryClassSet
:
351 self
._LibraryClasses
[LibraryClass
] = LibraryClassDict
[self
._Arch
, LibraryClass
]
352 return self
._LibraryClasses
354 ## Retrieve PCD declarations
356 if self
._Pcds
== None:
358 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
359 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
360 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
361 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
362 self
._Pcds
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
366 def ProcessStructurePcd(self
, StructurePcdRawDataSet
):
368 for s_pcd
,LineNo
in StructurePcdRawDataSet
:
369 if s_pcd
.TokenSpaceGuidCName
not in s_pcd_set
:
370 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
] = []
371 s_pcd_set
[s_pcd
.TokenSpaceGuidCName
].append((s_pcd
,LineNo
))
374 for pcdname
in s_pcd_set
:
376 struct_pcd
= StructurePcd()
377 for item
,LineNo
in s_pcd_set
[pcdname
]:
378 if "<HeaderFiles>" in item
.TokenCName
:
379 struct_pcd
.StructuredPcdIncludeFile
.append(item
.DefaultValue
)
380 elif "<Packages>" in item
.TokenCName
:
381 dep_pkgs
.append(item
.DefaultValue
)
382 elif item
.DatumType
== item
.TokenCName
:
383 struct_pcd
.copy(item
)
384 struct_pcd
.TokenValue
= struct_pcd
.TokenValue
.strip("{").strip()
385 struct_pcd
.TokenSpaceGuidCName
, struct_pcd
.TokenCName
= pcdname
.split(".")
386 struct_pcd
.PcdDefineLineNo
= LineNo
387 struct_pcd
.PkgPath
= self
.MetaFile
.File
389 struct_pcd
.AddDefaultValue(item
.TokenCName
, item
.DefaultValue
,self
.MetaFile
.File
,LineNo
)
391 struct_pcd
.PackageDecs
= dep_pkgs
393 str_pcd_set
.append(struct_pcd
)
397 ## Retrieve PCD declarations for given type
398 def _GetPcd(self
, Type
):
401 # tdict is a special kind of dict, used for selecting correct
402 # PCD declaration for given ARCH
404 PcdDict
= tdict(True, 3)
405 # for summarizing PCD
407 # find out all PCDs of the 'type'
410 RecordList
= self
._RawData
[Type
, self
._Arch
]
411 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, PrivateFlag
, Dummy1
, Dummy2
in RecordList
:
412 PcdDict
[Arch
, PcdCName
, TokenSpaceGuid
] = (Setting
,Dummy2
)
413 if not (PcdCName
, TokenSpaceGuid
) in PcdSet
:
414 PcdSet
.append((PcdCName
, TokenSpaceGuid
))
416 for PcdCName
, TokenSpaceGuid
in PcdSet
:
418 # limit the ARCH to self._Arch, if no self._Arch found, tdict
419 # will automatically turn to 'common' ARCH and try again
421 Setting
,LineNo
= PcdDict
[self
._Arch
, PcdCName
, TokenSpaceGuid
]
425 DefaultValue
, DatumType
, TokenNumber
= AnalyzePcdData(Setting
)
426 if DatumType
not in [TAB_UINT8
, TAB_UINT16
, TAB_UINT32
, TAB_UINT64
, TAB_VOID
, "BOOLEAN"]:
427 StructPattern
= re
.compile(r
'[_a-zA-Z][0-9A-Za-z_]*$')
428 if StructPattern
.match(DatumType
) == None:
429 EdkLogger
.error('build', FORMAT_INVALID
, "DatumType only support BOOLEAN, UINT8, UINT16, UINT32, UINT64, VOID* or a valid struct name.", File
=self
.MetaFile
, Line
=LineNo
)
431 validateranges
, validlists
, expressions
= self
._RawData
.GetValidExpression(TokenSpaceGuid
, PcdCName
)
432 PcdObj
= PcdClassObject(
435 self
._PCD
_TYPE
_STRING
_[Type
],
443 list(validateranges
),
447 if "." in TokenSpaceGuid
:
448 StrPcdSet
.append((PcdObj
,LineNo
))
450 Pcds
[PcdCName
, TokenSpaceGuid
, self
._PCD
_TYPE
_STRING
_[Type
]] = PcdObj
452 StructurePcds
= self
.ProcessStructurePcd(StrPcdSet
)
453 for pcd
in StructurePcds
:
454 Pcds
[pcd
.TokenCName
, pcd
.TokenSpaceGuidCName
, self
._PCD
_TYPE
_STRING
_[Type
]] = pcd
459 _Macros
= property(_GetMacros
)
460 Arch
= property(_GetArch
, _SetArch
)
461 PackageName
= property(_GetPackageName
)
462 Guid
= property(_GetFileGuid
)
463 Version
= property(_GetVersion
)
465 Protocols
= property(_GetProtocol
)
466 Ppis
= property(_GetPpi
)
467 Guids
= property(_GetGuid
)
468 Includes
= property(_GetInclude
)
469 LibraryClasses
= property(_GetLibraryClass
)
470 Pcds
= property(_GetPcds
)