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
9 from __future__
import absolute_import
10 from Common
.DataType
import *
11 from Common
.Misc
import *
12 from Common
.caching
import cached_property
, cached_class_function
14 from .MetaFileParser
import *
15 from collections
import OrderedDict
16 from Workspace
.BuildClassObject
import ModuleBuildClassObject
, LibraryClassObject
, PcdClassObject
17 from Common
.Expression
import ValueExpressionEx
, PcdPattern
19 ## Get Protocol value from given packages
21 # @param CName The CName of the GUID
22 # @param PackageList List of packages looking-up in
23 # @param Inffile The driver file
25 # @retval GuidValue if the CName is found in any given package
26 # @retval None if the CName is not found in all given packages
28 def _ProtocolValue(CName
, PackageList
, Inffile
= None):
30 ProtocolKeys
= list(P
.Protocols
.keys())
31 if Inffile
and P
._PrivateProtocols
:
32 if not Inffile
.startswith(P
.MetaFile
.Dir
):
33 ProtocolKeys
= [x
for x
in P
.Protocols
if x
not in P
._PrivateProtocols
]
34 if CName
in ProtocolKeys
:
35 return P
.Protocols
[CName
]
38 ## Get PPI value from given packages
40 # @param CName The CName of the GUID
41 # @param PackageList List of packages looking-up in
42 # @param Inffile The driver file
44 # @retval GuidValue if the CName is found in any given package
45 # @retval None if the CName is not found in all given packages
47 def _PpiValue(CName
, PackageList
, Inffile
= None):
49 PpiKeys
= list(P
.Ppis
.keys())
50 if Inffile
and P
._PrivatePpis
:
51 if not Inffile
.startswith(P
.MetaFile
.Dir
):
52 PpiKeys
= [x
for x
in P
.Ppis
if x
not in P
._PrivatePpis
]
57 ## Module build information from INF file
59 # This class is used to retrieve information stored in database and convert them
60 # into ModuleBuildClassObject form for easier use for AutoGen.
62 class InfBuildData(ModuleBuildClassObject
):
64 # dict used to convert part of [Defines] to members of InfBuildData directly
69 TAB_INF_DEFINES_BASE_NAME
: "_BaseName",
70 TAB_INF_DEFINES_FILE_GUID
: "_Guid",
71 TAB_INF_DEFINES_MODULE_TYPE
: "_ModuleType",
75 # TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
76 TAB_INF_DEFINES_COMPONENT_TYPE
: "_ComponentType",
77 TAB_INF_DEFINES_MAKEFILE_NAME
: "_MakefileName",
78 # TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
79 TAB_INF_DEFINES_DPX_SOURCE
:"_DxsFile",
80 TAB_INF_DEFINES_VERSION_NUMBER
: "_Version",
81 TAB_INF_DEFINES_VERSION_STRING
: "_Version",
82 TAB_INF_DEFINES_VERSION
: "_Version",
83 TAB_INF_DEFINES_PCD_IS_DRIVER
: "_PcdIsDriver",
84 TAB_INF_DEFINES_SHADOW
: "_Shadow"
87 # regular expression for converting XXX_FLAGS in [nmake] section to new type
88 _NMAKE_FLAG_PATTERN_
= re
.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re
.UNICODE
)
89 # dict used to convert old tool name used in [nmake] section to new ones
92 BINARY_FILE_TYPE_LIB
: "SLINK",
97 ## Constructor of InfBuildData
99 # Initialize object of InfBuildData
101 # @param FilePath The path of platform description file
102 # @param RawData The raw data of DSC file
103 # @param BuildDataBase Database used to retrieve module/package information
104 # @param Arch The target architecture
105 # @param Platform The name of platform employing this module
106 # @param Macros Macros used for replacement in DSC file
108 def __init__(self
, FilePath
, RawData
, BuildDatabase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
109 self
.MetaFile
= FilePath
110 self
._ModuleDir
= FilePath
.Dir
111 self
._RawData
= RawData
112 self
._Bdb
= BuildDatabase
114 self
._Target
= Target
115 self
._Toolchain
= Toolchain
116 self
._Platform
= TAB_COMMON
117 self
._TailComments
= None
118 self
._BaseName
= None
120 self
._ModuleType
= None
121 self
._ComponentType
= None
122 self
._BuildType
= None
125 self
._PcdIsDriver
= None
126 self
._BinaryModule
= None
128 self
._MakefileName
= None
129 self
._CustomMakefile
= None
130 self
._Specification
= None
131 self
._LibraryClass
= None
132 self
._ModuleEntryPointList
= None
133 self
._ModuleUnloadImageList
= None
134 self
._ConstructorList
= None
135 self
._DestructorList
= None
136 self
._Defs
= OrderedDict()
137 self
._ProtocolComments
= None
138 self
._PpiComments
= None
139 self
._GuidsUsedByPcd
= OrderedDict()
140 self
._GuidComments
= None
141 self
._PcdComments
= None
142 self
._BuildOptions
= None
143 self
._DependencyFileList
= None
144 self
.UpdatePcdTypeDict()
145 self
.LibInstances
= []
146 self
.ReferenceModules
= set()
148 def SetReferenceModule(self
,Module
):
149 self
.ReferenceModules
.add(Module
)
153 def __setitem__(self
, key
, value
):
154 self
.__dict
__[self
._PROPERTY
_[key
]] = value
157 def __getitem__(self
, key
):
158 return self
.__dict
__[self
._PROPERTY
_[key
]]
161 def __contains__(self
, key
):
162 return key
in self
._PROPERTY
_
164 ## Get current effective macros
175 ## Return the name of platform employing this module
178 return self
._Platform
181 def HeaderComments(self
):
182 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_HEADER_COMMENT
]]
185 def TailComments(self
):
186 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_TAIL_COMMENT
]]
188 ## Retrieve all information in [Defines] section
190 # (Retrieving all [Defines] information in one-shot is just to save time.)
192 @cached_class_function
193 def _GetHeaderInfo(self
):
194 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
195 for Record
in RecordList
:
196 Name
, Value
= Record
[1], ReplaceMacro(Record
[2], self
._Macros
, False)
197 # items defined _PROPERTY_ don't need additional processing
200 self
._Defs
[Name
] = Value
201 self
._Macros
[Name
] = Value
202 # some special items in [Defines] section need special treatment
203 elif Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
204 if Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
205 Name
= 'UEFI_SPECIFICATION_VERSION'
206 if self
._Specification
is None:
207 self
._Specification
= OrderedDict()
208 self
._Specification
[Name
] = GetHexVerValue(Value
)
209 if self
._Specification
[Name
] is None:
210 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
211 "'%s' format is not supported for %s" % (Value
, Name
),
212 File
=self
.MetaFile
, Line
=Record
[-1])
213 elif Name
== 'LIBRARY_CLASS':
214 if self
._LibraryClass
is None:
215 self
._LibraryClass
= []
216 ValueList
= GetSplitValueList(Value
)
217 LibraryClass
= ValueList
[0]
218 if len(ValueList
) > 1:
219 SupModuleList
= GetSplitValueList(ValueList
[1], ' ')
221 SupModuleList
= SUP_MODULE_LIST
222 self
._LibraryClass
.append(LibraryClassObject(LibraryClass
, SupModuleList
))
223 elif Name
== 'ENTRY_POINT':
224 if self
._ModuleEntryPointList
is None:
225 self
._ModuleEntryPointList
= []
226 self
._ModuleEntryPointList
.append(Value
)
227 elif Name
== 'UNLOAD_IMAGE':
228 if self
._ModuleUnloadImageList
is None:
229 self
._ModuleUnloadImageList
= []
232 self
._ModuleUnloadImageList
.append(Value
)
233 elif Name
== 'CONSTRUCTOR':
234 if self
._ConstructorList
is None:
235 self
._ConstructorList
= []
238 self
._ConstructorList
.append(Value
)
239 elif Name
== 'DESTRUCTOR':
240 if self
._DestructorList
is None:
241 self
._DestructorList
= []
244 self
._DestructorList
.append(Value
)
245 elif Name
== TAB_INF_DEFINES_CUSTOM_MAKEFILE
:
246 TokenList
= GetSplitValueList(Value
)
247 if self
._CustomMakefile
is None:
248 self
._CustomMakefile
= {}
249 if len(TokenList
) < 2:
250 self
._CustomMakefile
[TAB_COMPILER_MSFT
] = TokenList
[0]
251 self
._CustomMakefile
['GCC'] = TokenList
[0]
253 if TokenList
[0] not in [TAB_COMPILER_MSFT
, 'GCC']:
254 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
255 "No supported family [%s]" % TokenList
[0],
256 File
=self
.MetaFile
, Line
=Record
[-1])
257 self
._CustomMakefile
[TokenList
[0]] = TokenList
[1]
259 self
._Defs
[Name
] = Value
260 self
._Macros
[Name
] = Value
263 # Retrieve information in sections specific to Edk.x modules
265 if not self
._ModuleType
:
266 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
267 "MODULE_TYPE is not given", File
=self
.MetaFile
)
268 if self
._ModuleType
not in SUP_MODULE_LIST
:
269 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
270 for Record
in RecordList
:
272 if Name
== "MODULE_TYPE":
275 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
276 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self
._ModuleType
, ' '.join(l
for l
in SUP_MODULE_LIST
)),
277 File
=self
.MetaFile
, Line
=LineNo
)
278 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
279 if self
._ModuleType
== SUP_MODULE_SMM_CORE
:
280 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File
=self
.MetaFile
)
281 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x00010032):
282 if self
._ModuleType
== SUP_MODULE_MM_CORE_STANDALONE
:
283 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File
=self
.MetaFile
)
284 if self
._ModuleType
== SUP_MODULE_MM_STANDALONE
:
285 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
, "MM_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File
=self
.MetaFile
)
286 if 'PCI_DEVICE_ID' in self
._Defs
and 'PCI_VENDOR_ID' in self
._Defs \
287 and 'PCI_CLASS_CODE' in self
._Defs
and 'PCI_REVISION' in self
._Defs
:
288 self
._BuildType
= 'UEFI_OPTIONROM'
289 if 'PCI_COMPRESS' in self
._Defs
:
290 if self
._Defs
['PCI_COMPRESS'] not in ('TRUE', 'FALSE'):
291 EdkLogger
.error("build", FORMAT_INVALID
, "Expected TRUE/FALSE for PCI_COMPRESS: %s" % self
.MetaFile
)
293 elif 'UEFI_HII_RESOURCE_SECTION' in self
._Defs \
294 and self
._Defs
['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
295 self
._BuildType
= 'UEFI_HII'
297 self
._BuildType
= self
._ModuleType
.upper()
300 File
= PathClass(NormPath(self
._DxsFile
), self
._ModuleDir
, Arch
=self
._Arch
)
301 # check the file validation
302 ErrorCode
, ErrorInfo
= File
.Validate(".dxs", CaseSensitive
=False)
304 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
,
305 File
=self
.MetaFile
, Line
=LineNo
)
306 if not self
._DependencyFileList
:
307 self
._DependencyFileList
= []
308 self
._DependencyFileList
.append(File
)
310 ## Retrieve file version
312 def AutoGenVersion(self
):
314 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
315 for Record
in RecordList
:
316 if Record
[1] == TAB_INF_DEFINES_INF_VERSION
:
318 ValueList
= Record
[2].split('.')
319 Major
= '%04o' % int(ValueList
[0], 0)
320 Minor
= '%04o' % int(ValueList
[1], 0)
321 RetVal
= int('0x' + Major
+ Minor
, 0)
323 RetVal
= int(Record
[2], 0)
327 ## Retrieve BASE_NAME
330 if self
._BaseName
is None:
331 self
._GetHeaderInfo
()
332 if self
._BaseName
is None:
333 EdkLogger
.error('build', ATTRIBUTE_NOT_AVAILABLE
, "No BASE_NAME name", File
=self
.MetaFile
)
334 return self
._BaseName
339 if self
._DxsFile
is None:
340 self
._GetHeaderInfo
()
341 if self
._DxsFile
is None:
345 ## Retrieve MODULE_TYPE
347 def ModuleType(self
):
348 if self
._ModuleType
is None:
349 self
._GetHeaderInfo
()
350 if self
._ModuleType
is None:
351 self
._ModuleType
= SUP_MODULE_BASE
352 if self
._ModuleType
not in SUP_MODULE_LIST
:
353 self
._ModuleType
= SUP_MODULE_USER_DEFINED
354 return self
._ModuleType
356 ## Retrieve COMPONENT_TYPE
358 def ComponentType(self
):
359 if self
._ComponentType
is None:
360 self
._GetHeaderInfo
()
361 if self
._ComponentType
is None:
362 self
._ComponentType
= SUP_MODULE_USER_DEFINED
363 return self
._ComponentType
365 ## Retrieve "BUILD_TYPE"
368 if self
._BuildType
is None:
369 self
._GetHeaderInfo
()
370 if not self
._BuildType
:
371 self
._BuildType
= SUP_MODULE_BASE
372 return self
._BuildType
374 ## Retrieve file guid
377 if self
._Guid
is None:
378 self
._GetHeaderInfo
()
379 if self
._Guid
is None:
380 self
._Guid
= '00000000-0000-0000-0000-000000000000'
383 ## Retrieve module version
386 if self
._Version
is None:
387 self
._GetHeaderInfo
()
388 if self
._Version
is None:
389 self
._Version
= '0.0'
392 ## Retrieve PCD_IS_DRIVER
394 def PcdIsDriver(self
):
395 if self
._PcdIsDriver
is None:
396 self
._GetHeaderInfo
()
397 if self
._PcdIsDriver
is None:
398 self
._PcdIsDriver
= ''
399 return self
._PcdIsDriver
404 if self
._Shadow
is None:
405 self
._GetHeaderInfo
()
406 if self
._Shadow
and self
._Shadow
.upper() == 'TRUE':
412 ## Retrieve CUSTOM_MAKEFILE
414 def CustomMakefile(self
):
415 if self
._CustomMakefile
is None:
416 self
._GetHeaderInfo
()
417 if self
._CustomMakefile
is None:
418 self
._CustomMakefile
= {}
419 return self
._CustomMakefile
421 ## Retrieve EFI_SPECIFICATION_VERSION
423 def Specification(self
):
424 if self
._Specification
is None:
425 self
._GetHeaderInfo
()
426 if self
._Specification
is None:
427 self
._Specification
= {}
428 return self
._Specification
430 ## Retrieve LIBRARY_CLASS
432 def LibraryClass(self
):
433 if self
._LibraryClass
is None:
434 self
._GetHeaderInfo
()
435 if self
._LibraryClass
is None:
436 self
._LibraryClass
= []
437 return self
._LibraryClass
439 ## Retrieve ENTRY_POINT
441 def ModuleEntryPointList(self
):
442 if self
._ModuleEntryPointList
is None:
443 self
._GetHeaderInfo
()
444 if self
._ModuleEntryPointList
is None:
445 self
._ModuleEntryPointList
= []
446 return self
._ModuleEntryPointList
448 ## Retrieve UNLOAD_IMAGE
450 def ModuleUnloadImageList(self
):
451 if self
._ModuleUnloadImageList
is None:
452 self
._GetHeaderInfo
()
453 if self
._ModuleUnloadImageList
is None:
454 self
._ModuleUnloadImageList
= []
455 return self
._ModuleUnloadImageList
457 ## Retrieve CONSTRUCTOR
459 def ConstructorList(self
):
460 if self
._ConstructorList
is None:
461 self
._GetHeaderInfo
()
462 if self
._ConstructorList
is None:
463 self
._ConstructorList
= []
464 return self
._ConstructorList
466 ## Retrieve DESTRUCTOR
468 def DestructorList(self
):
469 if self
._DestructorList
is None:
470 self
._GetHeaderInfo
()
471 if self
._DestructorList
is None:
472 self
._DestructorList
= []
473 return self
._DestructorList
475 ## Retrieve definies other than above ones
478 self
._GetHeaderInfo
()
481 ## Retrieve binary files
482 @cached_class_function
483 def _GetBinaries(self
):
485 RecordList
= self
._RawData
[MODEL_EFI_BINARY_FILE
, self
._Arch
, self
._Platform
]
486 Macros
= self
._Macros
487 Macros
['PROCESSOR'] = self
._Arch
488 for Record
in RecordList
:
494 TokenList
= GetSplitValueList(Record
[2], TAB_VALUE_SPLIT
)
496 Target
= TokenList
[0]
497 if len(TokenList
) > 1:
498 FeatureFlag
= Record
[1:]
500 File
= PathClass(NormPath(Record
[1], Macros
), self
._ModuleDir
, '', FileType
, True, self
._Arch
, '', Target
)
501 # check the file validation
502 ErrorCode
, ErrorInfo
= File
.Validate()
504 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
508 ## Retrieve binary files with error check.
511 RetVal
= self
._GetBinaries
()
512 if GlobalData
.gIgnoreSource
and not RetVal
:
513 ErrorInfo
= "The INF file does not contain any RetVal to use in creating the image\n"
514 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
)
518 ## Retrieve source files
521 self
._GetHeaderInfo
()
522 # Ignore all source files in a binary build mode
523 if GlobalData
.gIgnoreSource
:
527 RecordList
= self
._RawData
[MODEL_EFI_SOURCE_FILE
, self
._Arch
, self
._Platform
]
528 Macros
= self
._Macros
529 for Record
in RecordList
:
531 ToolChainFamily
= Record
[1]
532 # OptionsList := [TagName, ToolCode, FeatureFlag]
533 OptionsList
= ['', '', '']
534 TokenList
= GetSplitValueList(Record
[2], TAB_VALUE_SPLIT
)
535 for Index
in range(len(TokenList
)):
536 OptionsList
[Index
] = TokenList
[Index
]
538 FeaturePcdExpression
= self
.CheckFeatureFlagPcd(OptionsList
[2])
539 if not FeaturePcdExpression
:
541 File
= PathClass(NormPath(Record
[0], Macros
), self
._ModuleDir
, '',
542 '', False, self
._Arch
, ToolChainFamily
, '', OptionsList
[0], OptionsList
[1])
543 # check the file validation
544 ErrorCode
, ErrorInfo
= File
.Validate()
546 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
549 # add any previously found dependency files to the source list
550 if self
._DependencyFileList
:
551 RetVal
.extend(self
._DependencyFileList
)
554 ## Retrieve library classes employed by this module
556 def LibraryClasses(self
):
557 RetVal
= OrderedDict()
558 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
, self
._Platform
]
559 for Record
in RecordList
:
563 Instance
= NormPath(Instance
, self
._Macros
)
564 RetVal
[Lib
] = Instance
569 ## Retrieve library names (for Edk.x style of modules)
573 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_INSTANCE
, self
._Arch
, self
._Platform
]
574 for Record
in RecordList
:
575 LibraryName
= ReplaceMacro(Record
[0], self
._Macros
, False)
576 # in case of name with '.lib' extension, which is unusual in Edk.x inf
577 LibraryName
= os
.path
.splitext(LibraryName
)[0]
578 if LibraryName
not in RetVal
:
579 RetVal
.append(LibraryName
)
583 def ProtocolComments(self
):
585 return self
._ProtocolComments
587 ## Retrieve protocols consumed/produced by this module
590 RetVal
= OrderedDict()
591 self
._ProtocolComments
= OrderedDict()
592 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
, self
._Platform
]
593 for Record
in RecordList
:
595 Value
= _ProtocolValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
597 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
598 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
599 "Value of Protocol [%s] is not found under [Protocols] section in" % CName
,
600 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
601 RetVal
[CName
] = Value
602 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
603 self
._ProtocolComments
[CName
] = [a
[0] for a
in CommentRecords
]
607 def PpiComments(self
):
609 return self
._PpiComments
611 ## Retrieve PPIs consumed/produced by this module
614 RetVal
= OrderedDict()
615 self
._PpiComments
= OrderedDict()
616 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
, self
._Platform
]
617 for Record
in RecordList
:
619 Value
= _PpiValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
621 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
622 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
623 "Value of PPI [%s] is not found under [Ppis] section in " % CName
,
624 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
625 RetVal
[CName
] = Value
626 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
627 self
._PpiComments
[CName
] = [a
[0] for a
in CommentRecords
]
631 def GuidComments(self
):
633 return self
._GuidComments
635 ## Retrieve GUIDs consumed/produced by this module
638 RetVal
= OrderedDict()
639 self
._GuidComments
= OrderedDict()
640 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
, self
._Platform
]
641 for Record
in RecordList
:
643 Value
= GuidValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
645 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
646 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
647 "Value of Guid [%s] is not found under [Guids] section in" % CName
,
648 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
649 RetVal
[CName
] = Value
650 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
651 self
._GuidComments
[CName
] = [a
[0] for a
in CommentRecords
]
653 for Type
in [MODEL_PCD_FIXED_AT_BUILD
,MODEL_PCD_PATCHABLE_IN_MODULE
,MODEL_PCD_FEATURE_FLAG
,MODEL_PCD_DYNAMIC
,MODEL_PCD_DYNAMIC_EX
]:
654 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
655 for TokenSpaceGuid
, _
, _
, _
, _
, _
, LineNo
in RecordList
:
657 if TokenSpaceGuid
not in RetVal
:
658 Value
= GuidValue(TokenSpaceGuid
, self
.Packages
, self
.MetaFile
.Path
)
660 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
661 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
662 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid
,
663 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=LineNo
)
664 RetVal
[TokenSpaceGuid
] = Value
665 self
._GuidsUsedByPcd
[TokenSpaceGuid
] = Value
668 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
672 Macros
= self
._Macros
673 Macros
['PROCESSOR'] = GlobalData
.gEdkGlobal
.get('PROCESSOR', self
._Arch
)
674 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
, self
._Platform
]
675 for Record
in RecordList
:
676 File
= NormPath(Record
[0], Macros
)
678 File
= os
.path
.join(self
._ModuleDir
, File
)
680 File
= mws
.join(GlobalData
.gWorkspace
, File
)
681 File
= RealPath(os
.path
.normpath(File
))
686 ## Retrieve packages this module depends on
690 RecordList
= self
._RawData
[MODEL_META_DATA_PACKAGE
, self
._Arch
, self
._Platform
]
691 Macros
= self
._Macros
692 for Record
in RecordList
:
693 File
= PathClass(NormPath(Record
[0], Macros
), GlobalData
.gWorkspace
, Arch
=self
._Arch
)
694 # check the file validation
695 ErrorCode
, ErrorInfo
= File
.Validate('.dec')
698 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
699 # parse this package now. we need it to get protocol/ppi/guid value
700 RetVal
.append(self
._Bdb
[File
, self
._Arch
, self
._Target
, self
._Toolchain
])
703 ## Retrieve PCD comments
705 def PcdComments(self
):
707 return self
._PcdComments
709 ## Retrieve PCDs used in this module
712 self
._PcdComments
= OrderedDict()
713 RetVal
= OrderedDict()
714 RetVal
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
715 RetVal
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
716 RetVal
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
717 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
718 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
722 def ModulePcdList(self
):
726 def LibraryPcdList(self
):
727 if bool(self
.LibraryClass
):
731 for Library
in self
.LibInstances
:
732 PcdsInLibrary
= OrderedDict()
733 for Key
in Library
.Pcds
:
734 if Key
in self
.Pcds
or Key
in Pcds
:
737 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
738 RetVal
[Library
] = PcdsInLibrary
743 for Type
in (MODEL_PCD_FIXED_AT_BUILD
,MODEL_PCD_PATCHABLE_IN_MODULE
,MODEL_PCD_FEATURE_FLAG
,MODEL_PCD_DYNAMIC
,MODEL_PCD_DYNAMIC_EX
):
744 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
745 for TokenSpaceGuid
, PcdCName
, _
, _
, _
, _
, _
in RecordList
:
746 PcdsName
.add((PcdCName
, TokenSpaceGuid
))
749 ## Retrieve build options specific to this module
751 def BuildOptions(self
):
752 if self
._BuildOptions
is None:
753 self
._BuildOptions
= OrderedDict()
754 RecordList
= self
._RawData
[MODEL_META_DATA_BUILD_OPTION
, self
._Arch
, self
._Platform
]
755 for Record
in RecordList
:
756 ToolChainFamily
= Record
[0]
757 ToolChain
= Record
[1]
759 if (ToolChainFamily
, ToolChain
) not in self
._BuildOptions
or Option
.startswith('='):
760 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = Option
762 # concatenate the option string if they're for the same tool
763 OptionString
= self
._BuildOptions
[ToolChainFamily
, ToolChain
]
764 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = OptionString
+ " " + Option
765 return self
._BuildOptions
767 ## Retrieve dependency expression
770 RetVal
= tdict(False, 2)
772 # If the module has only Binaries and no Sources, then ignore [Depex]
773 if not self
.Sources
and self
.Binaries
:
776 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
777 # PEIM and DXE drivers must have a valid [Depex] section
778 if len(self
.LibraryClass
) == 0 and len(RecordList
) == 0:
779 if self
.ModuleType
== SUP_MODULE_DXE_DRIVER
or self
.ModuleType
== SUP_MODULE_PEIM
or self
.ModuleType
== SUP_MODULE_DXE_SMM_DRIVER
or \
780 self
.ModuleType
== SUP_MODULE_DXE_SAL_DRIVER
or self
.ModuleType
== SUP_MODULE_DXE_RUNTIME_DRIVER
:
781 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
782 % self
.ModuleType
, File
=self
.MetaFile
)
784 if len(RecordList
) != 0 and (self
.ModuleType
== SUP_MODULE_USER_DEFINED
or self
.ModuleType
== SUP_MODULE_HOST_APPLICATION
):
785 for Record
in RecordList
:
786 if Record
[4] not in [SUP_MODULE_PEIM
, SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_SMM_DRIVER
]:
787 EdkLogger
.error('build', FORMAT_INVALID
,
788 "'%s' module must specify the type of [Depex] section" % self
.ModuleType
,
791 TemporaryDictionary
= OrderedDict()
792 for Record
in RecordList
:
793 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
795 ModuleType
= Record
[4]
796 TokenList
= DepexStr
.split()
797 if (Arch
, ModuleType
) not in TemporaryDictionary
:
798 TemporaryDictionary
[Arch
, ModuleType
] = []
799 DepexList
= TemporaryDictionary
[Arch
, ModuleType
]
800 for Token
in TokenList
:
801 if Token
in DEPEX_SUPPORTED_OPCODE_SET
:
802 DepexList
.append(Token
)
803 elif Token
.endswith(".inf"): # module file name
804 ModuleFile
= os
.path
.normpath(Token
)
805 Module
= self
.BuildDatabase
[ModuleFile
]
807 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "Module is not found in active platform",
808 ExtraData
=Token
, File
=self
.MetaFile
, Line
=Record
[-1])
809 DepexList
.append(Module
.Guid
)
811 # it use the Fixed PCD format
813 if tuple(Token
.split('.')[::-1]) not in self
.Pcds
:
814 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "PCD [{}] used in [Depex] section should be listed in module PCD section".format(Token
), File
=self
.MetaFile
, Line
=Record
[-1])
816 if self
.Pcds
[tuple(Token
.split('.')[::-1])].DatumType
!= TAB_VOID
:
817 EdkLogger
.error('build', FORMAT_INVALID
, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token
), File
=self
.MetaFile
, Line
=Record
[-1])
820 # get the GUID value now
821 Value
= _ProtocolValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
823 Value
= _PpiValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
825 Value
= GuidValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
828 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
829 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
830 "Value of [%s] is not found in" % Token
,
831 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
832 DepexList
.append(Value
)
833 for Arch
, ModuleType
in TemporaryDictionary
:
834 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
837 ## Retrieve dependency expression
839 def DepexExpression(self
):
840 RetVal
= tdict(False, 2)
841 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
842 TemporaryDictionary
= OrderedDict()
843 for Record
in RecordList
:
844 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
846 ModuleType
= Record
[4]
847 TokenList
= DepexStr
.split()
848 if (Arch
, ModuleType
) not in TemporaryDictionary
:
849 TemporaryDictionary
[Arch
, ModuleType
] = ''
850 for Token
in TokenList
:
851 TemporaryDictionary
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
] + Token
.strip() + ' '
852 for Arch
, ModuleType
in TemporaryDictionary
:
853 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
856 module_path
= self
.MetaFile
.File
857 subdir
= os
.path
.split(module_path
)[0]
860 subdir
,TopDir
= os
.path
.split(subdir
)
862 for file_name
in os
.listdir(os
.path
.join(self
.MetaFile
.Root
,TopDir
)):
863 if file_name
.upper().endswith("DEC"):
864 pkg
= os
.path
.join(TopDir
,file_name
)
866 @cached_class_function
867 def GetGuidsUsedByPcd(self
):
869 return self
._GuidsUsedByPcd
871 ## Retrieve PCD for given type
872 def _GetPcd(self
, Type
):
874 PcdDict
= tdict(True, 4)
876 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
877 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, Platform
, Id
, LineNo
in RecordList
:
878 PcdDict
[Arch
, Platform
, PcdCName
, TokenSpaceGuid
] = (Setting
, LineNo
)
879 PcdList
.append((PcdCName
, TokenSpaceGuid
))
880 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Id
]
882 for CmtRec
in CommentRecords
:
883 Comments
.append(CmtRec
[0])
884 self
._PcdComments
[TokenSpaceGuid
, PcdCName
] = Comments
886 # resolve PCD type, value, datum info, etc. by getting its definition from package
887 _GuidDict
= self
.Guids
.copy()
888 for PcdCName
, TokenSpaceGuid
in PcdList
:
889 PcdRealName
= PcdCName
890 Setting
, LineNo
= PcdDict
[self
._Arch
, self
.Platform
, PcdCName
, TokenSpaceGuid
]
893 ValueList
= AnalyzePcdData(Setting
)
894 DefaultValue
= ValueList
[0]
895 Pcd
= PcdClassObject(
905 self
.Guids
[TokenSpaceGuid
]
907 if Type
== MODEL_PCD_PATCHABLE_IN_MODULE
and ValueList
[1]:
908 # Patch PCD: TokenSpace.PcdCName|Value|Offset
909 Pcd
.Offset
= ValueList
[1]
911 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
912 for Package
in self
.Packages
:
913 for key
in Package
.Pcds
:
914 if (Package
.Pcds
[key
].TokenCName
, Package
.Pcds
[key
].TokenSpaceGuidCName
) == (PcdRealName
, TokenSpaceGuid
):
915 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
916 Pcd_Type
= item
[0].split('_')[-1]
917 if Pcd_Type
== Package
.Pcds
[key
].Type
:
918 Value
= Package
.Pcds
[key
]
919 Value
.TokenCName
= Package
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
921 newkey
= (Value
.TokenCName
, key
[1])
923 newkey
= (Value
.TokenCName
, key
[1], key
[2])
924 del Package
.Pcds
[key
]
925 Package
.Pcds
[newkey
] = Value
932 # get necessary info from package declaring this PCD
933 for Package
in self
.Packages
:
935 # 'dynamic' in INF means its type is determined by platform;
936 # if platform doesn't give its type, use 'lowest' one in the
937 # following order, if any
939 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
941 _GuidDict
.update(Package
.Guids
)
942 PcdType
= self
._PCD
_TYPE
_STRING
_[Type
]
943 if Type
== MODEL_PCD_DYNAMIC
:
945 for T
in PCD_TYPE_LIST
:
946 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
947 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
948 if str(item
[0]).endswith(T
) and (item
[0], item
[1], T
) in Package
.Pcds
:
956 if (PcdRealName
, TokenSpaceGuid
, T
) in Package
.Pcds
:
962 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
963 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
964 Pcd_Type
= item
[0].split('_')[-1]
965 if Pcd_Type
== PcdType
:
973 if (PcdCName
, TokenSpaceGuid
, PcdType
) in Package
.Pcds
:
974 PcdInPackage
= Package
.Pcds
[PcdCName
, TokenSpaceGuid
, PcdType
]
976 Pcd
.TokenValue
= PcdInPackage
.TokenValue
979 # Check whether the token value exist or not.
981 if Pcd
.TokenValue
is None or Pcd
.TokenValue
== "":
985 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid
, PcdRealName
, str(Package
)),
986 File
=self
.MetaFile
, Line
=LineNo
,
990 # Check hexadecimal token value length and format.
992 ReIsValidPcdTokenValue
= re
.compile(r
"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re
.DOTALL
)
993 if Pcd
.TokenValue
.startswith("0x") or Pcd
.TokenValue
.startswith("0X"):
994 if ReIsValidPcdTokenValue
.match(Pcd
.TokenValue
) is None:
998 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd
.TokenValue
, TokenSpaceGuid
, PcdRealName
, str(Package
)),
999 File
=self
.MetaFile
, Line
=LineNo
,
1004 # Check decimal token value length and format.
1008 TokenValueInt
= int (Pcd
.TokenValue
, 10)
1009 if (TokenValueInt
< 0 or TokenValueInt
> 4294967295):
1013 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, as a decimal it should between: 0 - 4294967295!" % (Pcd
.TokenValue
, TokenSpaceGuid
, PcdRealName
, str(Package
)),
1014 File
=self
.MetaFile
, Line
=LineNo
,
1021 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, it should be hexadecimal or decimal!" % (Pcd
.TokenValue
, TokenSpaceGuid
, PcdRealName
, str(Package
)),
1022 File
=self
.MetaFile
, Line
=LineNo
,
1026 Pcd
.DatumType
= PcdInPackage
.DatumType
1027 Pcd
.MaxDatumSize
= PcdInPackage
.MaxDatumSize
1028 Pcd
.InfDefaultValue
= Pcd
.DefaultValue
1029 if not Pcd
.DefaultValue
:
1030 Pcd
.DefaultValue
= PcdInPackage
.DefaultValue
1033 Pcd
.DefaultValue
= ValueExpressionEx(Pcd
.DefaultValue
, Pcd
.DatumType
, _GuidDict
)(True)
1034 except BadExpression
as Value
:
1035 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid
, PcdRealName
, Pcd
.DefaultValue
, Value
),
1036 File
=self
.MetaFile
, Line
=LineNo
)
1042 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid
, PcdRealName
, self
.MetaFile
),
1043 File
=self
.MetaFile
, Line
=LineNo
,
1044 ExtraData
="\t%s" % '\n\t'.join(str(P
) for P
in self
.Packages
)
1046 Pcds
[PcdCName
, TokenSpaceGuid
] = Pcd
1050 ## check whether current module is binary module
1052 def IsBinaryModule(self
):
1053 if (self
.Binaries
and not self
.Sources
) or GlobalData
.gIgnoreSource
:
1056 def CheckFeatureFlagPcd(self
,Instance
):
1057 Pcds
= GlobalData
.gPlatformFinalPcds
.copy()
1058 if PcdPattern
.search(Instance
):
1059 PcdTuple
= tuple(Instance
.split('.')[::-1])
1060 if PcdTuple
in self
.Pcds
:
1061 if not (self
.Pcds
[PcdTuple
].Type
== 'FeatureFlag' or self
.Pcds
[PcdTuple
].Type
== 'FixedAtBuild'):
1062 EdkLogger
.error('build', FORMAT_INVALID
,
1063 "\nFeatureFlagPcd must be defined in a [PcdsFeatureFlag] or [PcdsFixedAtBuild] section of Dsc or Dec file",
1064 File
=str(self
), ExtraData
=Instance
)
1065 if not Instance
in Pcds
:
1066 Pcds
[Instance
] = self
.Pcds
[PcdTuple
].DefaultValue
1067 else: #if PcdTuple not in self.Pcds:
1068 EdkLogger
.error('build', FORMAT_INVALID
,
1069 "\nFeatureFlagPcd must be defined in [FeaturePcd] or [FixedPcd] of Inf file",
1070 File
=str(self
), ExtraData
=Instance
)
1071 if Instance
in Pcds
:
1072 if Pcds
[Instance
] == '0':
1074 elif Pcds
[Instance
] == '1':
1077 Value
= ValueExpression(Instance
, Pcds
)()
1082 EdkLogger
.warn('build', FORMAT_INVALID
,"The FeatureFlagExpression cannot be evaluated", File
=str(self
), ExtraData
=Instance
)
1085 for Name
, Guid
in self
.Pcds
:
1086 if self
.Pcds
[(Name
, Guid
)].Type
== 'FeatureFlag' or self
.Pcds
[(Name
, Guid
)].Type
== 'FixedAtBuild':
1087 PcdFullName
= '%s.%s' % (Guid
, Name
);
1088 if not PcdFullName
in Pcds
:
1089 Pcds
[PcdFullName
] = self
.Pcds
[(Name
, Guid
)].DefaultValue
1091 Value
= ValueExpression(Instance
, Pcds
)()
1096 EdkLogger
.warn('build', FORMAT_INVALID
, "The FeatureFlagExpression cannot be evaluated", File
=str(self
), ExtraData
=Instance
)
1098 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
1099 for Key
in CopyFromDict
:
1100 CopyToDict
[Key
].extend(CopyFromDict
[Key
])