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.
15 from __future__
import absolute_import
16 from Common
.DataType
import *
17 from Common
.Misc
import *
18 from Common
.caching
import cached_property
, cached_class_function
20 from .MetaFileParser
import *
21 from collections
import OrderedDict
22 from Workspace
.BuildClassObject
import ModuleBuildClassObject
, LibraryClassObject
, PcdClassObject
24 ## Get Protocol value from given packages
26 # @param CName The CName of the GUID
27 # @param PackageList List of packages looking-up in
28 # @param Inffile The driver file
30 # @retval GuidValue if the CName is found in any given package
31 # @retval None if the CName is not found in all given packages
33 def _ProtocolValue(CName
, PackageList
, Inffile
= None):
35 ProtocolKeys
= list(P
.Protocols
.keys())
36 if Inffile
and P
._PrivateProtocols
:
37 if not Inffile
.startswith(P
.MetaFile
.Dir
):
38 ProtocolKeys
= [x
for x
in P
.Protocols
if x
not in P
._PrivateProtocols
]
39 if CName
in ProtocolKeys
:
40 return P
.Protocols
[CName
]
43 ## Get PPI value from given packages
45 # @param CName The CName of the GUID
46 # @param PackageList List of packages looking-up in
47 # @param Inffile The driver file
49 # @retval GuidValue if the CName is found in any given package
50 # @retval None if the CName is not found in all given packages
52 def _PpiValue(CName
, PackageList
, Inffile
= None):
54 PpiKeys
= list(P
.Ppis
.keys())
55 if Inffile
and P
._PrivatePpis
:
56 if not Inffile
.startswith(P
.MetaFile
.Dir
):
57 PpiKeys
= [x
for x
in P
.Ppis
if x
not in P
._PrivatePpis
]
62 ## Module build information from INF file
64 # This class is used to retrieve information stored in database and convert them
65 # into ModuleBuildClassObject form for easier use for AutoGen.
67 class InfBuildData(ModuleBuildClassObject
):
68 # dict used to convert PCD type in database to string used by build tool
70 MODEL_PCD_FIXED_AT_BUILD
: TAB_PCDS_FIXED_AT_BUILD
,
71 MODEL_PCD_PATCHABLE_IN_MODULE
: TAB_PCDS_PATCHABLE_IN_MODULE
,
72 MODEL_PCD_FEATURE_FLAG
: TAB_PCDS_FEATURE_FLAG
,
73 MODEL_PCD_DYNAMIC
: TAB_PCDS_DYNAMIC
,
74 MODEL_PCD_DYNAMIC_DEFAULT
: TAB_PCDS_DYNAMIC
,
75 MODEL_PCD_DYNAMIC_HII
: TAB_PCDS_DYNAMIC_HII
,
76 MODEL_PCD_DYNAMIC_VPD
: TAB_PCDS_DYNAMIC_VPD
,
77 MODEL_PCD_DYNAMIC_EX
: TAB_PCDS_DYNAMIC_EX
,
78 MODEL_PCD_DYNAMIC_EX_DEFAULT
: TAB_PCDS_DYNAMIC_EX
,
79 MODEL_PCD_DYNAMIC_EX_HII
: TAB_PCDS_DYNAMIC_EX_HII
,
80 MODEL_PCD_DYNAMIC_EX_VPD
: TAB_PCDS_DYNAMIC_EX_VPD
,
83 # dict used to convert part of [Defines] to members of InfBuildData directly
88 TAB_INF_DEFINES_BASE_NAME
: "_BaseName",
89 TAB_INF_DEFINES_FILE_GUID
: "_Guid",
90 TAB_INF_DEFINES_MODULE_TYPE
: "_ModuleType",
94 # TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
95 TAB_INF_DEFINES_COMPONENT_TYPE
: "_ComponentType",
96 TAB_INF_DEFINES_MAKEFILE_NAME
: "_MakefileName",
97 # TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
98 TAB_INF_DEFINES_DPX_SOURCE
:"_DxsFile",
99 TAB_INF_DEFINES_VERSION_NUMBER
: "_Version",
100 TAB_INF_DEFINES_VERSION_STRING
: "_Version",
101 TAB_INF_DEFINES_VERSION
: "_Version",
102 TAB_INF_DEFINES_PCD_IS_DRIVER
: "_PcdIsDriver",
103 TAB_INF_DEFINES_SHADOW
: "_Shadow"
106 # regular expression for converting XXX_FLAGS in [nmake] section to new type
107 _NMAKE_FLAG_PATTERN_
= re
.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re
.UNICODE
)
108 # dict used to convert old tool name used in [nmake] section to new ones
111 BINARY_FILE_TYPE_LIB
: "SLINK",
116 ## Constructor of InfBuildData
118 # Initialize object of InfBuildData
120 # @param FilePath The path of platform description file
121 # @param RawData The raw data of DSC file
122 # @param BuildDataBase Database used to retrieve module/package information
123 # @param Arch The target architecture
124 # @param Platform The name of platform employing this module
125 # @param Macros Macros used for replacement in DSC file
127 def __init__(self
, FilePath
, RawData
, BuildDatabase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
128 self
.MetaFile
= FilePath
129 self
._ModuleDir
= FilePath
.Dir
130 self
._RawData
= RawData
131 self
._Bdb
= BuildDatabase
133 self
._Target
= Target
134 self
._Toolchain
= Toolchain
135 self
._Platform
= TAB_COMMON
136 self
._TailComments
= None
137 self
._BaseName
= None
139 self
._ModuleType
= None
140 self
._ComponentType
= None
141 self
._BuildType
= None
144 self
._PcdIsDriver
= None
145 self
._BinaryModule
= None
147 self
._MakefileName
= None
148 self
._CustomMakefile
= None
149 self
._Specification
= None
150 self
._LibraryClass
= None
151 self
._ModuleEntryPointList
= None
152 self
._ModuleUnloadImageList
= None
153 self
._ConstructorList
= None
154 self
._DestructorList
= None
155 self
._Defs
= OrderedDict()
156 self
._ProtocolComments
= None
157 self
._PpiComments
= None
158 self
._GuidsUsedByPcd
= OrderedDict()
159 self
._GuidComments
= None
160 self
._PcdComments
= None
161 self
._BuildOptions
= None
162 self
._DependencyFileList
= None
165 def __setitem__(self
, key
, value
):
166 self
.__dict
__[self
._PROPERTY
_[key
]] = value
169 def __getitem__(self
, key
):
170 return self
.__dict
__[self
._PROPERTY
_[key
]]
173 def __contains__(self
, key
):
174 return key
in self
._PROPERTY
_
176 ## Get current effective macros
187 ## Return the name of platform employing this module
190 return self
._Platform
193 def HeaderComments(self
):
194 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_HEADER_COMMENT
]]
197 def TailComments(self
):
198 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_TAIL_COMMENT
]]
200 ## Retrieve all information in [Defines] section
202 # (Retrieving all [Defines] information in one-shot is just to save time.)
204 @cached_class_function
205 def _GetHeaderInfo(self
):
206 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
207 for Record
in RecordList
:
208 Name
, Value
= Record
[1], ReplaceMacro(Record
[2], self
._Macros
, False)
209 # items defined _PROPERTY_ don't need additional processing
212 self
._Defs
[Name
] = Value
213 self
._Macros
[Name
] = Value
214 # some special items in [Defines] section need special treatment
215 elif Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
216 if Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
217 Name
= 'UEFI_SPECIFICATION_VERSION'
218 if self
._Specification
is None:
219 self
._Specification
= OrderedDict()
220 self
._Specification
[Name
] = GetHexVerValue(Value
)
221 if self
._Specification
[Name
] is None:
222 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
223 "'%s' format is not supported for %s" % (Value
, Name
),
224 File
=self
.MetaFile
, Line
=Record
[-1])
225 elif Name
== 'LIBRARY_CLASS':
226 if self
._LibraryClass
is None:
227 self
._LibraryClass
= []
228 ValueList
= GetSplitValueList(Value
)
229 LibraryClass
= ValueList
[0]
230 if len(ValueList
) > 1:
231 SupModuleList
= GetSplitValueList(ValueList
[1], ' ')
233 SupModuleList
= SUP_MODULE_LIST
234 self
._LibraryClass
.append(LibraryClassObject(LibraryClass
, SupModuleList
))
235 elif Name
== 'ENTRY_POINT':
236 if self
._ModuleEntryPointList
is None:
237 self
._ModuleEntryPointList
= []
238 self
._ModuleEntryPointList
.append(Value
)
239 elif Name
== 'UNLOAD_IMAGE':
240 if self
._ModuleUnloadImageList
is None:
241 self
._ModuleUnloadImageList
= []
244 self
._ModuleUnloadImageList
.append(Value
)
245 elif Name
== 'CONSTRUCTOR':
246 if self
._ConstructorList
is None:
247 self
._ConstructorList
= []
250 self
._ConstructorList
.append(Value
)
251 elif Name
== 'DESTRUCTOR':
252 if self
._DestructorList
is None:
253 self
._DestructorList
= []
256 self
._DestructorList
.append(Value
)
257 elif Name
== TAB_INF_DEFINES_CUSTOM_MAKEFILE
:
258 TokenList
= GetSplitValueList(Value
)
259 if self
._CustomMakefile
is None:
260 self
._CustomMakefile
= {}
261 if len(TokenList
) < 2:
262 self
._CustomMakefile
[TAB_COMPILER_MSFT
] = TokenList
[0]
263 self
._CustomMakefile
['GCC'] = TokenList
[0]
265 if TokenList
[0] not in [TAB_COMPILER_MSFT
, 'GCC']:
266 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
267 "No supported family [%s]" % TokenList
[0],
268 File
=self
.MetaFile
, Line
=Record
[-1])
269 self
._CustomMakefile
[TokenList
[0]] = TokenList
[1]
271 self
._Defs
[Name
] = Value
272 self
._Macros
[Name
] = Value
275 # Retrieve information in sections specific to Edk.x modules
277 if not self
._ModuleType
:
278 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
279 "MODULE_TYPE is not given", File
=self
.MetaFile
)
280 if self
._ModuleType
not in SUP_MODULE_LIST
:
281 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
282 for Record
in RecordList
:
284 if Name
== "MODULE_TYPE":
287 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
288 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self
._ModuleType
, ' '.join(l
for l
in SUP_MODULE_LIST
)),
289 File
=self
.MetaFile
, Line
=LineNo
)
290 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
291 if self
._ModuleType
== SUP_MODULE_SMM_CORE
:
292 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
)
293 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x00010032):
294 if self
._ModuleType
== SUP_MODULE_MM_CORE_STANDALONE
:
295 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
)
296 if self
._ModuleType
== SUP_MODULE_MM_STANDALONE
:
297 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
)
298 if 'PCI_DEVICE_ID' in self
._Defs
and 'PCI_VENDOR_ID' in self
._Defs \
299 and 'PCI_CLASS_CODE' in self
._Defs
and 'PCI_REVISION' in self
._Defs
:
300 self
._BuildType
= 'UEFI_OPTIONROM'
301 if 'PCI_COMPRESS' in self
._Defs
:
302 if self
._Defs
['PCI_COMPRESS'] not in ('TRUE', 'FALSE'):
303 EdkLogger
.error("build", FORMAT_INVALID
, "Expected TRUE/FALSE for PCI_COMPRESS: %s" % self
.MetaFile
)
305 elif 'UEFI_HII_RESOURCE_SECTION' in self
._Defs \
306 and self
._Defs
['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
307 self
._BuildType
= 'UEFI_HII'
309 self
._BuildType
= self
._ModuleType
.upper()
312 File
= PathClass(NormPath(self
._DxsFile
), self
._ModuleDir
, Arch
=self
._Arch
)
313 # check the file validation
314 ErrorCode
, ErrorInfo
= File
.Validate(".dxs", CaseSensitive
=False)
316 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
,
317 File
=self
.MetaFile
, Line
=LineNo
)
318 if not self
._DependencyFileList
:
319 self
._DependencyFileList
= []
320 self
._DependencyFileList
.append(File
)
322 ## Retrieve file version
324 def AutoGenVersion(self
):
326 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
327 for Record
in RecordList
:
328 if Record
[1] == TAB_INF_DEFINES_INF_VERSION
:
330 ValueList
= Record
[2].split('.')
331 Major
= '%04o' % int(ValueList
[0], 0)
332 Minor
= '%04o' % int(ValueList
[1], 0)
333 RetVal
= int('0x' + Major
+ Minor
, 0)
335 RetVal
= int(Record
[2], 0)
339 ## Retrieve BASE_NAME
342 if self
._BaseName
is None:
343 self
._GetHeaderInfo
()
344 if self
._BaseName
is None:
345 EdkLogger
.error('build', ATTRIBUTE_NOT_AVAILABLE
, "No BASE_NAME name", File
=self
.MetaFile
)
346 return self
._BaseName
351 if self
._DxsFile
is None:
352 self
._GetHeaderInfo
()
353 if self
._DxsFile
is None:
357 ## Retrieve MODULE_TYPE
359 def ModuleType(self
):
360 if self
._ModuleType
is None:
361 self
._GetHeaderInfo
()
362 if self
._ModuleType
is None:
363 self
._ModuleType
= SUP_MODULE_BASE
364 if self
._ModuleType
not in SUP_MODULE_LIST
:
365 self
._ModuleType
= SUP_MODULE_USER_DEFINED
366 return self
._ModuleType
368 ## Retrieve COMPONENT_TYPE
370 def ComponentType(self
):
371 if self
._ComponentType
is None:
372 self
._GetHeaderInfo
()
373 if self
._ComponentType
is None:
374 self
._ComponentType
= SUP_MODULE_USER_DEFINED
375 return self
._ComponentType
377 ## Retrieve "BUILD_TYPE"
380 if self
._BuildType
is None:
381 self
._GetHeaderInfo
()
382 if not self
._BuildType
:
383 self
._BuildType
= SUP_MODULE_BASE
384 return self
._BuildType
386 ## Retrieve file guid
389 if self
._Guid
is None:
390 self
._GetHeaderInfo
()
391 if self
._Guid
is None:
392 self
._Guid
= '00000000-0000-0000-0000-000000000000'
395 ## Retrieve module version
398 if self
._Version
is None:
399 self
._GetHeaderInfo
()
400 if self
._Version
is None:
401 self
._Version
= '0.0'
404 ## Retrieve PCD_IS_DRIVER
406 def PcdIsDriver(self
):
407 if self
._PcdIsDriver
is None:
408 self
._GetHeaderInfo
()
409 if self
._PcdIsDriver
is None:
410 self
._PcdIsDriver
= ''
411 return self
._PcdIsDriver
416 if self
._Shadow
is None:
417 self
._GetHeaderInfo
()
418 if self
._Shadow
and self
._Shadow
.upper() == 'TRUE':
424 ## Retrieve CUSTOM_MAKEFILE
426 def CustomMakefile(self
):
427 if self
._CustomMakefile
is None:
428 self
._GetHeaderInfo
()
429 if self
._CustomMakefile
is None:
430 self
._CustomMakefile
= {}
431 return self
._CustomMakefile
433 ## Retrieve EFI_SPECIFICATION_VERSION
435 def Specification(self
):
436 if self
._Specification
is None:
437 self
._GetHeaderInfo
()
438 if self
._Specification
is None:
439 self
._Specification
= {}
440 return self
._Specification
442 ## Retrieve LIBRARY_CLASS
444 def LibraryClass(self
):
445 if self
._LibraryClass
is None:
446 self
._GetHeaderInfo
()
447 if self
._LibraryClass
is None:
448 self
._LibraryClass
= []
449 return self
._LibraryClass
451 ## Retrieve ENTRY_POINT
453 def ModuleEntryPointList(self
):
454 if self
._ModuleEntryPointList
is None:
455 self
._GetHeaderInfo
()
456 if self
._ModuleEntryPointList
is None:
457 self
._ModuleEntryPointList
= []
458 return self
._ModuleEntryPointList
460 ## Retrieve UNLOAD_IMAGE
462 def ModuleUnloadImageList(self
):
463 if self
._ModuleUnloadImageList
is None:
464 self
._GetHeaderInfo
()
465 if self
._ModuleUnloadImageList
is None:
466 self
._ModuleUnloadImageList
= []
467 return self
._ModuleUnloadImageList
469 ## Retrieve CONSTRUCTOR
471 def ConstructorList(self
):
472 if self
._ConstructorList
is None:
473 self
._GetHeaderInfo
()
474 if self
._ConstructorList
is None:
475 self
._ConstructorList
= []
476 return self
._ConstructorList
478 ## Retrieve DESTRUCTOR
480 def DestructorList(self
):
481 if self
._DestructorList
is None:
482 self
._GetHeaderInfo
()
483 if self
._DestructorList
is None:
484 self
._DestructorList
= []
485 return self
._DestructorList
487 ## Retrieve definies other than above ones
490 self
._GetHeaderInfo
()
493 ## Retrieve binary files
494 @cached_class_function
495 def _GetBinaries(self
):
497 RecordList
= self
._RawData
[MODEL_EFI_BINARY_FILE
, self
._Arch
, self
._Platform
]
498 Macros
= self
._Macros
499 Macros
['PROCESSOR'] = self
._Arch
500 for Record
in RecordList
:
506 TokenList
= GetSplitValueList(Record
[2], TAB_VALUE_SPLIT
)
508 Target
= TokenList
[0]
509 if len(TokenList
) > 1:
510 FeatureFlag
= Record
[1:]
512 File
= PathClass(NormPath(Record
[1], Macros
), self
._ModuleDir
, '', FileType
, True, self
._Arch
, '', Target
)
513 # check the file validation
514 ErrorCode
, ErrorInfo
= File
.Validate()
516 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
520 ## Retrieve binary files with error check.
523 RetVal
= self
._GetBinaries
()
524 if GlobalData
.gIgnoreSource
and not RetVal
:
525 ErrorInfo
= "The INF file does not contain any RetVal to use in creating the image\n"
526 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
)
530 ## Retrieve source files
533 self
._GetHeaderInfo
()
534 # Ignore all source files in a binary build mode
535 if GlobalData
.gIgnoreSource
:
539 RecordList
= self
._RawData
[MODEL_EFI_SOURCE_FILE
, self
._Arch
, self
._Platform
]
540 Macros
= self
._Macros
541 for Record
in RecordList
:
543 ToolChainFamily
= Record
[1]
547 File
= PathClass(NormPath(Record
[0], Macros
), self
._ModuleDir
, '',
548 '', False, self
._Arch
, ToolChainFamily
, '', TagName
, ToolCode
)
549 # check the file validation
550 ErrorCode
, ErrorInfo
= File
.Validate()
552 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
555 # add any previously found dependency files to the source list
556 if self
._DependencyFileList
:
557 RetVal
.extend(self
._DependencyFileList
)
560 ## Retrieve library classes employed by this module
562 def LibraryClasses(self
):
563 RetVal
= OrderedDict()
564 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
, self
._Platform
]
565 for Record
in RecordList
:
569 Instance
= NormPath(Instance
, self
._Macros
)
570 RetVal
[Lib
] = Instance
575 ## Retrieve library names (for Edk.x style of modules)
579 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_INSTANCE
, self
._Arch
, self
._Platform
]
580 for Record
in RecordList
:
581 LibraryName
= ReplaceMacro(Record
[0], self
._Macros
, False)
582 # in case of name with '.lib' extension, which is unusual in Edk.x inf
583 LibraryName
= os
.path
.splitext(LibraryName
)[0]
584 if LibraryName
not in RetVal
:
585 RetVal
.append(LibraryName
)
589 def ProtocolComments(self
):
591 return self
._ProtocolComments
593 ## Retrieve protocols consumed/produced by this module
596 RetVal
= OrderedDict()
597 self
._ProtocolComments
= OrderedDict()
598 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
, self
._Platform
]
599 for Record
in RecordList
:
601 Value
= _ProtocolValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
603 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
604 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
605 "Value of Protocol [%s] is not found under [Protocols] section in" % CName
,
606 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
607 RetVal
[CName
] = Value
608 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
609 self
._ProtocolComments
[CName
] = [a
[0] for a
in CommentRecords
]
613 def PpiComments(self
):
615 return self
._PpiComments
617 ## Retrieve PPIs consumed/produced by this module
620 RetVal
= OrderedDict()
621 self
._PpiComments
= OrderedDict()
622 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
, self
._Platform
]
623 for Record
in RecordList
:
625 Value
= _PpiValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
627 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
628 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
629 "Value of PPI [%s] is not found under [Ppis] section in " % CName
,
630 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
631 RetVal
[CName
] = Value
632 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
633 self
._PpiComments
[CName
] = [a
[0] for a
in CommentRecords
]
637 def GuidComments(self
):
639 return self
._GuidComments
641 ## Retrieve GUIDs consumed/produced by this module
644 RetVal
= OrderedDict()
645 self
._GuidComments
= OrderedDict()
646 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
, self
._Platform
]
647 for Record
in RecordList
:
649 Value
= GuidValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
651 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
652 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
653 "Value of Guid [%s] is not found under [Guids] section in" % CName
,
654 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
655 RetVal
[CName
] = Value
656 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
657 self
._GuidComments
[CName
] = [a
[0] for a
in CommentRecords
]
660 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
664 Macros
= self
._Macros
665 Macros
['PROCESSOR'] = GlobalData
.gEdkGlobal
.get('PROCESSOR', self
._Arch
)
666 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
, self
._Platform
]
667 for Record
in RecordList
:
668 File
= NormPath(Record
[0], Macros
)
670 File
= os
.path
.join(self
._ModuleDir
, File
)
672 File
= mws
.join(GlobalData
.gWorkspace
, File
)
673 File
= RealPath(os
.path
.normpath(File
))
678 ## Retrieve packages this module depends on
682 RecordList
= self
._RawData
[MODEL_META_DATA_PACKAGE
, self
._Arch
, self
._Platform
]
683 Macros
= self
._Macros
684 for Record
in RecordList
:
685 File
= PathClass(NormPath(Record
[0], Macros
), GlobalData
.gWorkspace
, Arch
=self
._Arch
)
686 # check the file validation
687 ErrorCode
, ErrorInfo
= File
.Validate('.dec')
690 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
691 # parse this package now. we need it to get protocol/ppi/guid value
692 RetVal
.append(self
._Bdb
[File
, self
._Arch
, self
._Target
, self
._Toolchain
])
695 ## Retrieve PCD comments
697 def PcdComments(self
):
699 return self
._PcdComments
701 ## Retrieve PCDs used in this module
704 self
._PcdComments
= OrderedDict()
705 RetVal
= OrderedDict()
706 RetVal
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
707 RetVal
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
708 RetVal
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
709 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
710 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
716 for Type
in (MODEL_PCD_FIXED_AT_BUILD
,MODEL_PCD_PATCHABLE_IN_MODULE
,MODEL_PCD_FEATURE_FLAG
,MODEL_PCD_DYNAMIC
,MODEL_PCD_DYNAMIC_EX
):
717 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
718 for TokenSpaceGuid
, PcdCName
, _
, _
, _
, _
, _
in RecordList
:
719 PcdsName
.add((PcdCName
, TokenSpaceGuid
))
722 ## Retrieve build options specific to this module
724 def BuildOptions(self
):
725 if self
._BuildOptions
is None:
726 self
._BuildOptions
= OrderedDict()
727 RecordList
= self
._RawData
[MODEL_META_DATA_BUILD_OPTION
, self
._Arch
, self
._Platform
]
728 for Record
in RecordList
:
729 ToolChainFamily
= Record
[0]
730 ToolChain
= Record
[1]
732 if (ToolChainFamily
, ToolChain
) not in self
._BuildOptions
or Option
.startswith('='):
733 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = Option
735 # concatenate the option string if they're for the same tool
736 OptionString
= self
._BuildOptions
[ToolChainFamily
, ToolChain
]
737 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = OptionString
+ " " + Option
738 return self
._BuildOptions
740 ## Retrieve dependency expression
743 RetVal
= tdict(False, 2)
745 # If the module has only Binaries and no Sources, then ignore [Depex]
746 if not self
.Sources
and self
.Binaries
:
749 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
750 # PEIM and DXE drivers must have a valid [Depex] section
751 if len(self
.LibraryClass
) == 0 and len(RecordList
) == 0:
752 if self
.ModuleType
== SUP_MODULE_DXE_DRIVER
or self
.ModuleType
== SUP_MODULE_PEIM
or self
.ModuleType
== SUP_MODULE_DXE_SMM_DRIVER
or \
753 self
.ModuleType
== SUP_MODULE_DXE_SAL_DRIVER
or self
.ModuleType
== SUP_MODULE_DXE_RUNTIME_DRIVER
:
754 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
755 % self
.ModuleType
, File
=self
.MetaFile
)
757 if len(RecordList
) != 0 and self
.ModuleType
== SUP_MODULE_USER_DEFINED
:
758 for Record
in RecordList
:
759 if Record
[4] not in [SUP_MODULE_PEIM
, SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_SMM_DRIVER
]:
760 EdkLogger
.error('build', FORMAT_INVALID
,
761 "'%s' module must specify the type of [Depex] section" % self
.ModuleType
,
764 TemporaryDictionary
= OrderedDict()
765 for Record
in RecordList
:
766 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
768 ModuleType
= Record
[4]
769 TokenList
= DepexStr
.split()
770 if (Arch
, ModuleType
) not in TemporaryDictionary
:
771 TemporaryDictionary
[Arch
, ModuleType
] = []
772 DepexList
= TemporaryDictionary
[Arch
, ModuleType
]
773 for Token
in TokenList
:
774 if Token
in DEPEX_SUPPORTED_OPCODE_SET
:
775 DepexList
.append(Token
)
776 elif Token
.endswith(".inf"): # module file name
777 ModuleFile
= os
.path
.normpath(Token
)
778 Module
= self
.BuildDatabase
[ModuleFile
]
780 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "Module is not found in active platform",
781 ExtraData
=Token
, File
=self
.MetaFile
, Line
=Record
[-1])
782 DepexList
.append(Module
.Guid
)
784 # it use the Fixed PCD format
786 if tuple(Token
.split('.')[::-1]) not in self
.Pcds
:
787 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])
789 if self
.Pcds
[tuple(Token
.split('.')[::-1])].DatumType
!= TAB_VOID
:
790 EdkLogger
.error('build', FORMAT_INVALID
, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token
), File
=self
.MetaFile
, Line
=Record
[-1])
793 # get the GUID value now
794 Value
= _ProtocolValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
796 Value
= _PpiValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
798 Value
= GuidValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
801 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
802 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
803 "Value of [%s] is not found in" % Token
,
804 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
805 DepexList
.append(Value
)
806 for Arch
, ModuleType
in TemporaryDictionary
:
807 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
810 ## Retrieve dependency expression
812 def DepexExpression(self
):
813 RetVal
= tdict(False, 2)
814 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
815 TemporaryDictionary
= OrderedDict()
816 for Record
in RecordList
:
817 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
819 ModuleType
= Record
[4]
820 TokenList
= DepexStr
.split()
821 if (Arch
, ModuleType
) not in TemporaryDictionary
:
822 TemporaryDictionary
[Arch
, ModuleType
] = ''
823 for Token
in TokenList
:
824 TemporaryDictionary
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
] + Token
.strip() + ' '
825 for Arch
, ModuleType
in TemporaryDictionary
:
826 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
829 @cached_class_function
830 def GetGuidsUsedByPcd(self
):
832 return self
._GuidsUsedByPcd
834 ## Retrieve PCD for given type
835 def _GetPcd(self
, Type
):
837 PcdDict
= tdict(True, 4)
839 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
840 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, Platform
, Id
, LineNo
in RecordList
:
841 PcdDict
[Arch
, Platform
, PcdCName
, TokenSpaceGuid
] = (Setting
, LineNo
)
842 PcdList
.append((PcdCName
, TokenSpaceGuid
))
844 if TokenSpaceGuid
not in self
.Guids
:
845 Value
= GuidValue(TokenSpaceGuid
, self
.Packages
, self
.MetaFile
.Path
)
847 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
848 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
849 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid
,
850 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=LineNo
)
851 self
.Guids
[TokenSpaceGuid
] = Value
852 self
._GuidsUsedByPcd
[TokenSpaceGuid
] = Value
853 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Id
]
855 for CmtRec
in CommentRecords
:
856 Comments
.append(CmtRec
[0])
857 self
._PcdComments
[TokenSpaceGuid
, PcdCName
] = Comments
859 # resolve PCD type, value, datum info, etc. by getting its definition from package
860 _GuidDict
= self
.Guids
.copy()
861 for PcdCName
, TokenSpaceGuid
in PcdList
:
862 PcdRealName
= PcdCName
863 Setting
, LineNo
= PcdDict
[self
._Arch
, self
.Platform
, PcdCName
, TokenSpaceGuid
]
866 ValueList
= AnalyzePcdData(Setting
)
867 DefaultValue
= ValueList
[0]
868 Pcd
= PcdClassObject(
878 self
.Guids
[TokenSpaceGuid
]
880 if Type
== MODEL_PCD_PATCHABLE_IN_MODULE
and ValueList
[1]:
881 # Patch PCD: TokenSpace.PcdCName|Value|Offset
882 Pcd
.Offset
= ValueList
[1]
884 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
885 for Package
in self
.Packages
:
886 for key
in Package
.Pcds
:
887 if (Package
.Pcds
[key
].TokenCName
, Package
.Pcds
[key
].TokenSpaceGuidCName
) == (PcdRealName
, TokenSpaceGuid
):
888 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
889 Pcd_Type
= item
[0].split('_')[-1]
890 if Pcd_Type
== Package
.Pcds
[key
].Type
:
891 Value
= Package
.Pcds
[key
]
892 Value
.TokenCName
= Package
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
894 newkey
= (Value
.TokenCName
, key
[1])
896 newkey
= (Value
.TokenCName
, key
[1], key
[2])
897 del Package
.Pcds
[key
]
898 Package
.Pcds
[newkey
] = Value
905 # get necessary info from package declaring this PCD
906 for Package
in self
.Packages
:
908 # 'dynamic' in INF means its type is determined by platform;
909 # if platform doesn't give its type, use 'lowest' one in the
910 # following order, if any
912 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
914 _GuidDict
.update(Package
.Guids
)
915 PcdType
= self
._PCD
_TYPE
_STRING
_[Type
]
916 if Type
== MODEL_PCD_DYNAMIC
:
918 for T
in PCD_TYPE_LIST
:
919 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
920 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
921 if str(item
[0]).endswith(T
) and (item
[0], item
[1], T
) in Package
.Pcds
:
929 if (PcdRealName
, TokenSpaceGuid
, T
) in Package
.Pcds
:
935 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
936 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
937 Pcd_Type
= item
[0].split('_')[-1]
938 if Pcd_Type
== PcdType
:
946 if (PcdCName
, TokenSpaceGuid
, PcdType
) in Package
.Pcds
:
947 PcdInPackage
= Package
.Pcds
[PcdCName
, TokenSpaceGuid
, PcdType
]
949 Pcd
.TokenValue
= PcdInPackage
.TokenValue
952 # Check whether the token value exist or not.
954 if Pcd
.TokenValue
is None or Pcd
.TokenValue
== "":
958 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid
, PcdRealName
, str(Package
)),
959 File
=self
.MetaFile
, Line
=LineNo
,
963 # Check hexadecimal token value length and format.
965 ReIsValidPcdTokenValue
= re
.compile(r
"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re
.DOTALL
)
966 if Pcd
.TokenValue
.startswith("0x") or Pcd
.TokenValue
.startswith("0X"):
967 if ReIsValidPcdTokenValue
.match(Pcd
.TokenValue
) is None:
971 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd
.TokenValue
, TokenSpaceGuid
, PcdRealName
, str(Package
)),
972 File
=self
.MetaFile
, Line
=LineNo
,
977 # Check decimal token value length and format.
981 TokenValueInt
= int (Pcd
.TokenValue
, 10)
982 if (TokenValueInt
< 0 or TokenValueInt
> 4294967295):
986 "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
)),
987 File
=self
.MetaFile
, Line
=LineNo
,
994 "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
)),
995 File
=self
.MetaFile
, Line
=LineNo
,
999 Pcd
.DatumType
= PcdInPackage
.DatumType
1000 Pcd
.MaxDatumSize
= PcdInPackage
.MaxDatumSize
1001 Pcd
.InfDefaultValue
= Pcd
.DefaultValue
1002 if not Pcd
.DefaultValue
:
1003 Pcd
.DefaultValue
= PcdInPackage
.DefaultValue
1006 Pcd
.DefaultValue
= ValueExpressionEx(Pcd
.DefaultValue
, Pcd
.DatumType
, _GuidDict
)(True)
1007 except BadExpression
as Value
:
1008 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid
, PcdRealName
, Pcd
.DefaultValue
, Value
),
1009 File
=self
.MetaFile
, Line
=LineNo
)
1015 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid
, PcdRealName
, self
.MetaFile
),
1016 File
=self
.MetaFile
, Line
=LineNo
,
1017 ExtraData
="\t%s" % '\n\t'.join(str(P
) for P
in self
.Packages
)
1019 Pcds
[PcdCName
, TokenSpaceGuid
] = Pcd
1023 ## check whether current module is binary module
1025 def IsBinaryModule(self
):
1026 if (self
.Binaries
and not self
.Sources
) or GlobalData
.gIgnoreSource
: