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
18 ## Get Protocol value from given packages
20 # @param CName The CName of the GUID
21 # @param PackageList List of packages looking-up in
22 # @param Inffile The driver file
24 # @retval GuidValue if the CName is found in any given package
25 # @retval None if the CName is not found in all given packages
27 def _ProtocolValue(CName
, PackageList
, Inffile
= None):
29 ProtocolKeys
= list(P
.Protocols
.keys())
30 if Inffile
and P
._PrivateProtocols
:
31 if not Inffile
.startswith(P
.MetaFile
.Dir
):
32 ProtocolKeys
= [x
for x
in P
.Protocols
if x
not in P
._PrivateProtocols
]
33 if CName
in ProtocolKeys
:
34 return P
.Protocols
[CName
]
37 ## Get PPI value from given packages
39 # @param CName The CName of the GUID
40 # @param PackageList List of packages looking-up in
41 # @param Inffile The driver file
43 # @retval GuidValue if the CName is found in any given package
44 # @retval None if the CName is not found in all given packages
46 def _PpiValue(CName
, PackageList
, Inffile
= None):
48 PpiKeys
= list(P
.Ppis
.keys())
49 if Inffile
and P
._PrivatePpis
:
50 if not Inffile
.startswith(P
.MetaFile
.Dir
):
51 PpiKeys
= [x
for x
in P
.Ppis
if x
not in P
._PrivatePpis
]
56 ## Module build information from INF file
58 # This class is used to retrieve information stored in database and convert them
59 # into ModuleBuildClassObject form for easier use for AutoGen.
61 class InfBuildData(ModuleBuildClassObject
):
62 # dict used to convert PCD type in database to string used by build tool
64 MODEL_PCD_FIXED_AT_BUILD
: TAB_PCDS_FIXED_AT_BUILD
,
65 MODEL_PCD_PATCHABLE_IN_MODULE
: TAB_PCDS_PATCHABLE_IN_MODULE
,
66 MODEL_PCD_FEATURE_FLAG
: TAB_PCDS_FEATURE_FLAG
,
67 MODEL_PCD_DYNAMIC
: TAB_PCDS_DYNAMIC
,
68 MODEL_PCD_DYNAMIC_DEFAULT
: TAB_PCDS_DYNAMIC
,
69 MODEL_PCD_DYNAMIC_HII
: TAB_PCDS_DYNAMIC_HII
,
70 MODEL_PCD_DYNAMIC_VPD
: TAB_PCDS_DYNAMIC_VPD
,
71 MODEL_PCD_DYNAMIC_EX
: TAB_PCDS_DYNAMIC_EX
,
72 MODEL_PCD_DYNAMIC_EX_DEFAULT
: TAB_PCDS_DYNAMIC_EX
,
73 MODEL_PCD_DYNAMIC_EX_HII
: TAB_PCDS_DYNAMIC_EX_HII
,
74 MODEL_PCD_DYNAMIC_EX_VPD
: TAB_PCDS_DYNAMIC_EX_VPD
,
77 # dict used to convert part of [Defines] to members of InfBuildData directly
82 TAB_INF_DEFINES_BASE_NAME
: "_BaseName",
83 TAB_INF_DEFINES_FILE_GUID
: "_Guid",
84 TAB_INF_DEFINES_MODULE_TYPE
: "_ModuleType",
88 # TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
89 TAB_INF_DEFINES_COMPONENT_TYPE
: "_ComponentType",
90 TAB_INF_DEFINES_MAKEFILE_NAME
: "_MakefileName",
91 # TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
92 TAB_INF_DEFINES_DPX_SOURCE
:"_DxsFile",
93 TAB_INF_DEFINES_VERSION_NUMBER
: "_Version",
94 TAB_INF_DEFINES_VERSION_STRING
: "_Version",
95 TAB_INF_DEFINES_VERSION
: "_Version",
96 TAB_INF_DEFINES_PCD_IS_DRIVER
: "_PcdIsDriver",
97 TAB_INF_DEFINES_SHADOW
: "_Shadow"
100 # regular expression for converting XXX_FLAGS in [nmake] section to new type
101 _NMAKE_FLAG_PATTERN_
= re
.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re
.UNICODE
)
102 # dict used to convert old tool name used in [nmake] section to new ones
105 BINARY_FILE_TYPE_LIB
: "SLINK",
110 ## Constructor of InfBuildData
112 # Initialize object of InfBuildData
114 # @param FilePath The path of platform description file
115 # @param RawData The raw data of DSC file
116 # @param BuildDataBase Database used to retrieve module/package information
117 # @param Arch The target architecture
118 # @param Platform The name of platform employing this module
119 # @param Macros Macros used for replacement in DSC file
121 def __init__(self
, FilePath
, RawData
, BuildDatabase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
122 self
.MetaFile
= FilePath
123 self
._ModuleDir
= FilePath
.Dir
124 self
._RawData
= RawData
125 self
._Bdb
= BuildDatabase
127 self
._Target
= Target
128 self
._Toolchain
= Toolchain
129 self
._Platform
= TAB_COMMON
130 self
._TailComments
= None
131 self
._BaseName
= None
133 self
._ModuleType
= None
134 self
._ComponentType
= None
135 self
._BuildType
= None
138 self
._PcdIsDriver
= None
139 self
._BinaryModule
= None
141 self
._MakefileName
= None
142 self
._CustomMakefile
= None
143 self
._Specification
= None
144 self
._LibraryClass
= None
145 self
._ModuleEntryPointList
= None
146 self
._ModuleUnloadImageList
= None
147 self
._ConstructorList
= None
148 self
._DestructorList
= None
149 self
._Defs
= OrderedDict()
150 self
._ProtocolComments
= None
151 self
._PpiComments
= None
152 self
._GuidsUsedByPcd
= OrderedDict()
153 self
._GuidComments
= None
154 self
._PcdComments
= None
155 self
._BuildOptions
= None
156 self
._DependencyFileList
= None
157 self
.LibInstances
= []
158 self
.ReferenceModules
= set()
161 def SetReferenceModule(self
,Module
):
162 self
.ReferenceModules
.add(Module
)
166 def __setitem__(self
, key
, value
):
167 self
.__dict
__[self
._PROPERTY
_[key
]] = value
170 def __getitem__(self
, key
):
171 return self
.__dict
__[self
._PROPERTY
_[key
]]
174 def __contains__(self
, key
):
175 return key
in self
._PROPERTY
_
177 ## Get current effective macros
188 ## Return the name of platform employing this module
191 return self
._Platform
194 def HeaderComments(self
):
195 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_HEADER_COMMENT
]]
198 def TailComments(self
):
199 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_TAIL_COMMENT
]]
201 ## Retrieve all information in [Defines] section
203 # (Retrieving all [Defines] information in one-shot is just to save time.)
205 @cached_class_function
206 def _GetHeaderInfo(self
):
207 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
208 for Record
in RecordList
:
209 Name
, Value
= Record
[1], ReplaceMacro(Record
[2], self
._Macros
, False)
210 # items defined _PROPERTY_ don't need additional processing
213 self
._Defs
[Name
] = Value
214 self
._Macros
[Name
] = Value
215 # some special items in [Defines] section need special treatment
216 elif Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
217 if Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
218 Name
= 'UEFI_SPECIFICATION_VERSION'
219 if self
._Specification
is None:
220 self
._Specification
= OrderedDict()
221 self
._Specification
[Name
] = GetHexVerValue(Value
)
222 if self
._Specification
[Name
] is None:
223 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
224 "'%s' format is not supported for %s" % (Value
, Name
),
225 File
=self
.MetaFile
, Line
=Record
[-1])
226 elif Name
== 'LIBRARY_CLASS':
227 if self
._LibraryClass
is None:
228 self
._LibraryClass
= []
229 ValueList
= GetSplitValueList(Value
)
230 LibraryClass
= ValueList
[0]
231 if len(ValueList
) > 1:
232 SupModuleList
= GetSplitValueList(ValueList
[1], ' ')
234 SupModuleList
= SUP_MODULE_LIST
235 self
._LibraryClass
.append(LibraryClassObject(LibraryClass
, SupModuleList
))
236 elif Name
== 'ENTRY_POINT':
237 if self
._ModuleEntryPointList
is None:
238 self
._ModuleEntryPointList
= []
239 self
._ModuleEntryPointList
.append(Value
)
240 elif Name
== 'UNLOAD_IMAGE':
241 if self
._ModuleUnloadImageList
is None:
242 self
._ModuleUnloadImageList
= []
245 self
._ModuleUnloadImageList
.append(Value
)
246 elif Name
== 'CONSTRUCTOR':
247 if self
._ConstructorList
is None:
248 self
._ConstructorList
= []
251 self
._ConstructorList
.append(Value
)
252 elif Name
== 'DESTRUCTOR':
253 if self
._DestructorList
is None:
254 self
._DestructorList
= []
257 self
._DestructorList
.append(Value
)
258 elif Name
== TAB_INF_DEFINES_CUSTOM_MAKEFILE
:
259 TokenList
= GetSplitValueList(Value
)
260 if self
._CustomMakefile
is None:
261 self
._CustomMakefile
= {}
262 if len(TokenList
) < 2:
263 self
._CustomMakefile
[TAB_COMPILER_MSFT
] = TokenList
[0]
264 self
._CustomMakefile
['GCC'] = TokenList
[0]
266 if TokenList
[0] not in [TAB_COMPILER_MSFT
, 'GCC']:
267 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
268 "No supported family [%s]" % TokenList
[0],
269 File
=self
.MetaFile
, Line
=Record
[-1])
270 self
._CustomMakefile
[TokenList
[0]] = TokenList
[1]
272 self
._Defs
[Name
] = Value
273 self
._Macros
[Name
] = Value
276 # Retrieve information in sections specific to Edk.x modules
278 if not self
._ModuleType
:
279 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
280 "MODULE_TYPE is not given", File
=self
.MetaFile
)
281 if self
._ModuleType
not in SUP_MODULE_LIST
:
282 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
283 for Record
in RecordList
:
285 if Name
== "MODULE_TYPE":
288 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
289 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self
._ModuleType
, ' '.join(l
for l
in SUP_MODULE_LIST
)),
290 File
=self
.MetaFile
, Line
=LineNo
)
291 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
292 if self
._ModuleType
== SUP_MODULE_SMM_CORE
:
293 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
)
294 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x00010032):
295 if self
._ModuleType
== SUP_MODULE_MM_CORE_STANDALONE
:
296 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
)
297 if self
._ModuleType
== SUP_MODULE_MM_STANDALONE
:
298 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
)
299 if 'PCI_DEVICE_ID' in self
._Defs
and 'PCI_VENDOR_ID' in self
._Defs \
300 and 'PCI_CLASS_CODE' in self
._Defs
and 'PCI_REVISION' in self
._Defs
:
301 self
._BuildType
= 'UEFI_OPTIONROM'
302 if 'PCI_COMPRESS' in self
._Defs
:
303 if self
._Defs
['PCI_COMPRESS'] not in ('TRUE', 'FALSE'):
304 EdkLogger
.error("build", FORMAT_INVALID
, "Expected TRUE/FALSE for PCI_COMPRESS: %s" % self
.MetaFile
)
306 elif 'UEFI_HII_RESOURCE_SECTION' in self
._Defs \
307 and self
._Defs
['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
308 self
._BuildType
= 'UEFI_HII'
310 self
._BuildType
= self
._ModuleType
.upper()
313 File
= PathClass(NormPath(self
._DxsFile
), self
._ModuleDir
, Arch
=self
._Arch
)
314 # check the file validation
315 ErrorCode
, ErrorInfo
= File
.Validate(".dxs", CaseSensitive
=False)
317 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
,
318 File
=self
.MetaFile
, Line
=LineNo
)
319 if not self
._DependencyFileList
:
320 self
._DependencyFileList
= []
321 self
._DependencyFileList
.append(File
)
323 ## Retrieve file version
325 def AutoGenVersion(self
):
327 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
328 for Record
in RecordList
:
329 if Record
[1] == TAB_INF_DEFINES_INF_VERSION
:
331 ValueList
= Record
[2].split('.')
332 Major
= '%04o' % int(ValueList
[0], 0)
333 Minor
= '%04o' % int(ValueList
[1], 0)
334 RetVal
= int('0x' + Major
+ Minor
, 0)
336 RetVal
= int(Record
[2], 0)
340 ## Retrieve BASE_NAME
343 if self
._BaseName
is None:
344 self
._GetHeaderInfo
()
345 if self
._BaseName
is None:
346 EdkLogger
.error('build', ATTRIBUTE_NOT_AVAILABLE
, "No BASE_NAME name", File
=self
.MetaFile
)
347 return self
._BaseName
352 if self
._DxsFile
is None:
353 self
._GetHeaderInfo
()
354 if self
._DxsFile
is None:
358 ## Retrieve MODULE_TYPE
360 def ModuleType(self
):
361 if self
._ModuleType
is None:
362 self
._GetHeaderInfo
()
363 if self
._ModuleType
is None:
364 self
._ModuleType
= SUP_MODULE_BASE
365 if self
._ModuleType
not in SUP_MODULE_LIST
:
366 self
._ModuleType
= SUP_MODULE_USER_DEFINED
367 return self
._ModuleType
369 ## Retrieve COMPONENT_TYPE
371 def ComponentType(self
):
372 if self
._ComponentType
is None:
373 self
._GetHeaderInfo
()
374 if self
._ComponentType
is None:
375 self
._ComponentType
= SUP_MODULE_USER_DEFINED
376 return self
._ComponentType
378 ## Retrieve "BUILD_TYPE"
381 if self
._BuildType
is None:
382 self
._GetHeaderInfo
()
383 if not self
._BuildType
:
384 self
._BuildType
= SUP_MODULE_BASE
385 return self
._BuildType
387 ## Retrieve file guid
390 if self
._Guid
is None:
391 self
._GetHeaderInfo
()
392 if self
._Guid
is None:
393 self
._Guid
= '00000000-0000-0000-0000-000000000000'
396 ## Retrieve module version
399 if self
._Version
is None:
400 self
._GetHeaderInfo
()
401 if self
._Version
is None:
402 self
._Version
= '0.0'
405 ## Retrieve PCD_IS_DRIVER
407 def PcdIsDriver(self
):
408 if self
._PcdIsDriver
is None:
409 self
._GetHeaderInfo
()
410 if self
._PcdIsDriver
is None:
411 self
._PcdIsDriver
= ''
412 return self
._PcdIsDriver
417 if self
._Shadow
is None:
418 self
._GetHeaderInfo
()
419 if self
._Shadow
and self
._Shadow
.upper() == 'TRUE':
425 ## Retrieve CUSTOM_MAKEFILE
427 def CustomMakefile(self
):
428 if self
._CustomMakefile
is None:
429 self
._GetHeaderInfo
()
430 if self
._CustomMakefile
is None:
431 self
._CustomMakefile
= {}
432 return self
._CustomMakefile
434 ## Retrieve EFI_SPECIFICATION_VERSION
436 def Specification(self
):
437 if self
._Specification
is None:
438 self
._GetHeaderInfo
()
439 if self
._Specification
is None:
440 self
._Specification
= {}
441 return self
._Specification
443 ## Retrieve LIBRARY_CLASS
445 def LibraryClass(self
):
446 if self
._LibraryClass
is None:
447 self
._GetHeaderInfo
()
448 if self
._LibraryClass
is None:
449 self
._LibraryClass
= []
450 return self
._LibraryClass
452 ## Retrieve ENTRY_POINT
454 def ModuleEntryPointList(self
):
455 if self
._ModuleEntryPointList
is None:
456 self
._GetHeaderInfo
()
457 if self
._ModuleEntryPointList
is None:
458 self
._ModuleEntryPointList
= []
459 return self
._ModuleEntryPointList
461 ## Retrieve UNLOAD_IMAGE
463 def ModuleUnloadImageList(self
):
464 if self
._ModuleUnloadImageList
is None:
465 self
._GetHeaderInfo
()
466 if self
._ModuleUnloadImageList
is None:
467 self
._ModuleUnloadImageList
= []
468 return self
._ModuleUnloadImageList
470 ## Retrieve CONSTRUCTOR
472 def ConstructorList(self
):
473 if self
._ConstructorList
is None:
474 self
._GetHeaderInfo
()
475 if self
._ConstructorList
is None:
476 self
._ConstructorList
= []
477 return self
._ConstructorList
479 ## Retrieve DESTRUCTOR
481 def DestructorList(self
):
482 if self
._DestructorList
is None:
483 self
._GetHeaderInfo
()
484 if self
._DestructorList
is None:
485 self
._DestructorList
= []
486 return self
._DestructorList
488 ## Retrieve definies other than above ones
491 self
._GetHeaderInfo
()
494 ## Retrieve binary files
495 @cached_class_function
496 def _GetBinaries(self
):
498 RecordList
= self
._RawData
[MODEL_EFI_BINARY_FILE
, self
._Arch
, self
._Platform
]
499 Macros
= self
._Macros
500 Macros
['PROCESSOR'] = self
._Arch
501 for Record
in RecordList
:
507 TokenList
= GetSplitValueList(Record
[2], TAB_VALUE_SPLIT
)
509 Target
= TokenList
[0]
510 if len(TokenList
) > 1:
511 FeatureFlag
= Record
[1:]
513 File
= PathClass(NormPath(Record
[1], Macros
), self
._ModuleDir
, '', FileType
, True, self
._Arch
, '', Target
)
514 # check the file validation
515 ErrorCode
, ErrorInfo
= File
.Validate()
517 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
521 ## Retrieve binary files with error check.
524 RetVal
= self
._GetBinaries
()
525 if GlobalData
.gIgnoreSource
and not RetVal
:
526 ErrorInfo
= "The INF file does not contain any RetVal to use in creating the image\n"
527 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
)
531 ## Retrieve source files
534 self
._GetHeaderInfo
()
535 # Ignore all source files in a binary build mode
536 if GlobalData
.gIgnoreSource
:
540 RecordList
= self
._RawData
[MODEL_EFI_SOURCE_FILE
, self
._Arch
, self
._Platform
]
541 Macros
= self
._Macros
542 for Record
in RecordList
:
544 ToolChainFamily
= Record
[1]
548 File
= PathClass(NormPath(Record
[0], Macros
), self
._ModuleDir
, '',
549 '', False, self
._Arch
, ToolChainFamily
, '', TagName
, ToolCode
)
550 # check the file validation
551 ErrorCode
, ErrorInfo
= File
.Validate()
553 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
556 # add any previously found dependency files to the source list
557 if self
._DependencyFileList
:
558 RetVal
.extend(self
._DependencyFileList
)
561 ## Retrieve library classes employed by this module
563 def LibraryClasses(self
):
564 RetVal
= OrderedDict()
565 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
, self
._Platform
]
566 for Record
in RecordList
:
570 Instance
= NormPath(Instance
, self
._Macros
)
571 RetVal
[Lib
] = Instance
576 ## Retrieve library names (for Edk.x style of modules)
580 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_INSTANCE
, self
._Arch
, self
._Platform
]
581 for Record
in RecordList
:
582 LibraryName
= ReplaceMacro(Record
[0], self
._Macros
, False)
583 # in case of name with '.lib' extension, which is unusual in Edk.x inf
584 LibraryName
= os
.path
.splitext(LibraryName
)[0]
585 if LibraryName
not in RetVal
:
586 RetVal
.append(LibraryName
)
590 def ProtocolComments(self
):
592 return self
._ProtocolComments
594 ## Retrieve protocols consumed/produced by this module
597 RetVal
= OrderedDict()
598 self
._ProtocolComments
= OrderedDict()
599 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
, self
._Platform
]
600 for Record
in RecordList
:
602 Value
= _ProtocolValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
604 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
605 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
606 "Value of Protocol [%s] is not found under [Protocols] section in" % CName
,
607 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
608 RetVal
[CName
] = Value
609 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
610 self
._ProtocolComments
[CName
] = [a
[0] for a
in CommentRecords
]
614 def PpiComments(self
):
616 return self
._PpiComments
618 ## Retrieve PPIs consumed/produced by this module
621 RetVal
= OrderedDict()
622 self
._PpiComments
= OrderedDict()
623 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
, self
._Platform
]
624 for Record
in RecordList
:
626 Value
= _PpiValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
628 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
629 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
630 "Value of PPI [%s] is not found under [Ppis] section in " % CName
,
631 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
632 RetVal
[CName
] = Value
633 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
634 self
._PpiComments
[CName
] = [a
[0] for a
in CommentRecords
]
638 def GuidComments(self
):
640 return self
._GuidComments
642 ## Retrieve GUIDs consumed/produced by this module
645 RetVal
= OrderedDict()
646 self
._GuidComments
= OrderedDict()
647 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
, self
._Platform
]
648 for Record
in RecordList
:
650 Value
= GuidValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
652 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
653 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
654 "Value of Guid [%s] is not found under [Guids] section in" % CName
,
655 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
656 RetVal
[CName
] = Value
657 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
658 self
._GuidComments
[CName
] = [a
[0] for a
in CommentRecords
]
661 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
665 Macros
= self
._Macros
666 Macros
['PROCESSOR'] = GlobalData
.gEdkGlobal
.get('PROCESSOR', self
._Arch
)
667 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
, self
._Platform
]
668 for Record
in RecordList
:
669 File
= NormPath(Record
[0], Macros
)
671 File
= os
.path
.join(self
._ModuleDir
, File
)
673 File
= mws
.join(GlobalData
.gWorkspace
, File
)
674 File
= RealPath(os
.path
.normpath(File
))
679 ## Retrieve packages this module depends on
683 RecordList
= self
._RawData
[MODEL_META_DATA_PACKAGE
, self
._Arch
, self
._Platform
]
684 Macros
= self
._Macros
685 for Record
in RecordList
:
686 File
= PathClass(NormPath(Record
[0], Macros
), GlobalData
.gWorkspace
, Arch
=self
._Arch
)
687 # check the file validation
688 ErrorCode
, ErrorInfo
= File
.Validate('.dec')
691 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
692 # parse this package now. we need it to get protocol/ppi/guid value
693 RetVal
.append(self
._Bdb
[File
, self
._Arch
, self
._Target
, self
._Toolchain
])
696 ## Retrieve PCD comments
698 def PcdComments(self
):
700 return self
._PcdComments
702 ## Retrieve PCDs used in this module
705 self
._PcdComments
= OrderedDict()
706 RetVal
= OrderedDict()
707 RetVal
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
708 RetVal
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
709 RetVal
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
710 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
711 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
715 def ModulePcdList(self
):
719 def LibraryPcdList(self
):
720 if bool(self
.LibraryClass
):
724 for Library
in self
.LibInstances
:
725 PcdsInLibrary
= OrderedDict()
726 for Key
in Library
.Pcds
:
727 if Key
in self
.Pcds
or Key
in Pcds
:
730 PcdsInLibrary
[Key
] = copy
.copy(Library
.Pcds
[Key
])
731 RetVal
[Library
] = PcdsInLibrary
736 for Type
in (MODEL_PCD_FIXED_AT_BUILD
,MODEL_PCD_PATCHABLE_IN_MODULE
,MODEL_PCD_FEATURE_FLAG
,MODEL_PCD_DYNAMIC
,MODEL_PCD_DYNAMIC_EX
):
737 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
738 for TokenSpaceGuid
, PcdCName
, _
, _
, _
, _
, _
in RecordList
:
739 PcdsName
.add((PcdCName
, TokenSpaceGuid
))
742 ## Retrieve build options specific to this module
744 def BuildOptions(self
):
745 if self
._BuildOptions
is None:
746 self
._BuildOptions
= OrderedDict()
747 RecordList
= self
._RawData
[MODEL_META_DATA_BUILD_OPTION
, self
._Arch
, self
._Platform
]
748 for Record
in RecordList
:
749 ToolChainFamily
= Record
[0]
750 ToolChain
= Record
[1]
752 if (ToolChainFamily
, ToolChain
) not in self
._BuildOptions
or Option
.startswith('='):
753 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = Option
755 # concatenate the option string if they're for the same tool
756 OptionString
= self
._BuildOptions
[ToolChainFamily
, ToolChain
]
757 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = OptionString
+ " " + Option
758 return self
._BuildOptions
760 ## Retrieve dependency expression
763 RetVal
= tdict(False, 2)
765 # If the module has only Binaries and no Sources, then ignore [Depex]
766 if not self
.Sources
and self
.Binaries
:
769 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
770 # PEIM and DXE drivers must have a valid [Depex] section
771 if len(self
.LibraryClass
) == 0 and len(RecordList
) == 0:
772 if self
.ModuleType
== SUP_MODULE_DXE_DRIVER
or self
.ModuleType
== SUP_MODULE_PEIM
or self
.ModuleType
== SUP_MODULE_DXE_SMM_DRIVER
or \
773 self
.ModuleType
== SUP_MODULE_DXE_SAL_DRIVER
or self
.ModuleType
== SUP_MODULE_DXE_RUNTIME_DRIVER
:
774 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
775 % self
.ModuleType
, File
=self
.MetaFile
)
777 if len(RecordList
) != 0 and (self
.ModuleType
== SUP_MODULE_USER_DEFINED
or self
.ModuleType
== SUP_MODULE_HOST_APPLICATION
):
778 for Record
in RecordList
:
779 if Record
[4] not in [SUP_MODULE_PEIM
, SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_SMM_DRIVER
]:
780 EdkLogger
.error('build', FORMAT_INVALID
,
781 "'%s' module must specify the type of [Depex] section" % self
.ModuleType
,
784 TemporaryDictionary
= OrderedDict()
785 for Record
in RecordList
:
786 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
788 ModuleType
= Record
[4]
789 TokenList
= DepexStr
.split()
790 if (Arch
, ModuleType
) not in TemporaryDictionary
:
791 TemporaryDictionary
[Arch
, ModuleType
] = []
792 DepexList
= TemporaryDictionary
[Arch
, ModuleType
]
793 for Token
in TokenList
:
794 if Token
in DEPEX_SUPPORTED_OPCODE_SET
:
795 DepexList
.append(Token
)
796 elif Token
.endswith(".inf"): # module file name
797 ModuleFile
= os
.path
.normpath(Token
)
798 Module
= self
.BuildDatabase
[ModuleFile
]
800 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "Module is not found in active platform",
801 ExtraData
=Token
, File
=self
.MetaFile
, Line
=Record
[-1])
802 DepexList
.append(Module
.Guid
)
804 # it use the Fixed PCD format
806 if tuple(Token
.split('.')[::-1]) not in self
.Pcds
:
807 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])
809 if self
.Pcds
[tuple(Token
.split('.')[::-1])].DatumType
!= TAB_VOID
:
810 EdkLogger
.error('build', FORMAT_INVALID
, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token
), File
=self
.MetaFile
, Line
=Record
[-1])
813 # get the GUID value now
814 Value
= _ProtocolValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
816 Value
= _PpiValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
818 Value
= GuidValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
821 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
822 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
823 "Value of [%s] is not found in" % Token
,
824 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
825 DepexList
.append(Value
)
826 for Arch
, ModuleType
in TemporaryDictionary
:
827 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
830 ## Retrieve dependency expression
832 def DepexExpression(self
):
833 RetVal
= tdict(False, 2)
834 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
835 TemporaryDictionary
= OrderedDict()
836 for Record
in RecordList
:
837 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
839 ModuleType
= Record
[4]
840 TokenList
= DepexStr
.split()
841 if (Arch
, ModuleType
) not in TemporaryDictionary
:
842 TemporaryDictionary
[Arch
, ModuleType
] = ''
843 for Token
in TokenList
:
844 TemporaryDictionary
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
] + Token
.strip() + ' '
845 for Arch
, ModuleType
in TemporaryDictionary
:
846 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
849 module_path
= self
.MetaFile
.File
850 subdir
= os
.path
.split(module_path
)[0]
853 subdir
,TopDir
= os
.path
.split(subdir
)
855 for file_name
in os
.listdir(os
.path
.join(self
.MetaFile
.Root
,TopDir
)):
856 if file_name
.upper().endswith("DEC"):
857 pkg
= os
.path
.join(TopDir
,file_name
)
859 @cached_class_function
860 def GetGuidsUsedByPcd(self
):
862 return self
._GuidsUsedByPcd
864 ## Retrieve PCD for given type
865 def _GetPcd(self
, Type
):
867 PcdDict
= tdict(True, 4)
869 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
870 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, Platform
, Id
, LineNo
in RecordList
:
871 PcdDict
[Arch
, Platform
, PcdCName
, TokenSpaceGuid
] = (Setting
, LineNo
)
872 PcdList
.append((PcdCName
, TokenSpaceGuid
))
874 if TokenSpaceGuid
not in self
.Guids
:
875 Value
= GuidValue(TokenSpaceGuid
, self
.Packages
, self
.MetaFile
.Path
)
877 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
878 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
879 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid
,
880 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=LineNo
)
881 self
.Guids
[TokenSpaceGuid
] = Value
882 self
._GuidsUsedByPcd
[TokenSpaceGuid
] = Value
883 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Id
]
885 for CmtRec
in CommentRecords
:
886 Comments
.append(CmtRec
[0])
887 self
._PcdComments
[TokenSpaceGuid
, PcdCName
] = Comments
889 # resolve PCD type, value, datum info, etc. by getting its definition from package
890 _GuidDict
= self
.Guids
.copy()
891 for PcdCName
, TokenSpaceGuid
in PcdList
:
892 PcdRealName
= PcdCName
893 Setting
, LineNo
= PcdDict
[self
._Arch
, self
.Platform
, PcdCName
, TokenSpaceGuid
]
896 ValueList
= AnalyzePcdData(Setting
)
897 DefaultValue
= ValueList
[0]
898 Pcd
= PcdClassObject(
908 self
.Guids
[TokenSpaceGuid
]
910 if Type
== MODEL_PCD_PATCHABLE_IN_MODULE
and ValueList
[1]:
911 # Patch PCD: TokenSpace.PcdCName|Value|Offset
912 Pcd
.Offset
= ValueList
[1]
914 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
915 for Package
in self
.Packages
:
916 for key
in Package
.Pcds
:
917 if (Package
.Pcds
[key
].TokenCName
, Package
.Pcds
[key
].TokenSpaceGuidCName
) == (PcdRealName
, TokenSpaceGuid
):
918 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
919 Pcd_Type
= item
[0].split('_')[-1]
920 if Pcd_Type
== Package
.Pcds
[key
].Type
:
921 Value
= Package
.Pcds
[key
]
922 Value
.TokenCName
= Package
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
924 newkey
= (Value
.TokenCName
, key
[1])
926 newkey
= (Value
.TokenCName
, key
[1], key
[2])
927 del Package
.Pcds
[key
]
928 Package
.Pcds
[newkey
] = Value
935 # get necessary info from package declaring this PCD
936 for Package
in self
.Packages
:
938 # 'dynamic' in INF means its type is determined by platform;
939 # if platform doesn't give its type, use 'lowest' one in the
940 # following order, if any
942 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
944 _GuidDict
.update(Package
.Guids
)
945 PcdType
= self
._PCD
_TYPE
_STRING
_[Type
]
946 if Type
== MODEL_PCD_DYNAMIC
:
948 for T
in PCD_TYPE_LIST
:
949 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
950 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
951 if str(item
[0]).endswith(T
) and (item
[0], item
[1], T
) in Package
.Pcds
:
959 if (PcdRealName
, TokenSpaceGuid
, T
) in Package
.Pcds
:
965 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
966 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
967 Pcd_Type
= item
[0].split('_')[-1]
968 if Pcd_Type
== PcdType
:
976 if (PcdCName
, TokenSpaceGuid
, PcdType
) in Package
.Pcds
:
977 PcdInPackage
= Package
.Pcds
[PcdCName
, TokenSpaceGuid
, PcdType
]
979 Pcd
.TokenValue
= PcdInPackage
.TokenValue
982 # Check whether the token value exist or not.
984 if Pcd
.TokenValue
is None or Pcd
.TokenValue
== "":
988 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid
, PcdRealName
, str(Package
)),
989 File
=self
.MetaFile
, Line
=LineNo
,
993 # Check hexadecimal token value length and format.
995 ReIsValidPcdTokenValue
= re
.compile(r
"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re
.DOTALL
)
996 if Pcd
.TokenValue
.startswith("0x") or Pcd
.TokenValue
.startswith("0X"):
997 if ReIsValidPcdTokenValue
.match(Pcd
.TokenValue
) is None:
1001 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd
.TokenValue
, TokenSpaceGuid
, PcdRealName
, str(Package
)),
1002 File
=self
.MetaFile
, Line
=LineNo
,
1007 # Check decimal token value length and format.
1011 TokenValueInt
= int (Pcd
.TokenValue
, 10)
1012 if (TokenValueInt
< 0 or TokenValueInt
> 4294967295):
1016 "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
)),
1017 File
=self
.MetaFile
, Line
=LineNo
,
1024 "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
)),
1025 File
=self
.MetaFile
, Line
=LineNo
,
1029 Pcd
.DatumType
= PcdInPackage
.DatumType
1030 Pcd
.MaxDatumSize
= PcdInPackage
.MaxDatumSize
1031 Pcd
.InfDefaultValue
= Pcd
.DefaultValue
1032 if not Pcd
.DefaultValue
:
1033 Pcd
.DefaultValue
= PcdInPackage
.DefaultValue
1036 Pcd
.DefaultValue
= ValueExpressionEx(Pcd
.DefaultValue
, Pcd
.DatumType
, _GuidDict
)(True)
1037 except BadExpression
as Value
:
1038 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid
, PcdRealName
, Pcd
.DefaultValue
, Value
),
1039 File
=self
.MetaFile
, Line
=LineNo
)
1045 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid
, PcdRealName
, self
.MetaFile
),
1046 File
=self
.MetaFile
, Line
=LineNo
,
1047 ExtraData
="\t%s" % '\n\t'.join(str(P
) for P
in self
.Packages
)
1049 Pcds
[PcdCName
, TokenSpaceGuid
] = Pcd
1053 ## check whether current module is binary module
1055 def IsBinaryModule(self
):
1056 if (self
.Binaries
and not self
.Sources
) or GlobalData
.gIgnoreSource
:
1059 def ExtendCopyDictionaryLists(CopyToDict
, CopyFromDict
):
1060 for Key
in CopyFromDict
:
1061 CopyToDict
[Key
].extend(CopyFromDict
[Key
])