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 ## Module build information from INF file
26 # This class is used to retrieve information stored in database and convert them
27 # into ModuleBuildClassObject form for easier use for AutoGen.
29 class InfBuildData(ModuleBuildClassObject
):
30 # dict used to convert PCD type in database to string used by build tool
32 MODEL_PCD_FIXED_AT_BUILD
: TAB_PCDS_FIXED_AT_BUILD
,
33 MODEL_PCD_PATCHABLE_IN_MODULE
: TAB_PCDS_PATCHABLE_IN_MODULE
,
34 MODEL_PCD_FEATURE_FLAG
: TAB_PCDS_FEATURE_FLAG
,
35 MODEL_PCD_DYNAMIC
: TAB_PCDS_DYNAMIC
,
36 MODEL_PCD_DYNAMIC_DEFAULT
: TAB_PCDS_DYNAMIC
,
37 MODEL_PCD_DYNAMIC_HII
: TAB_PCDS_DYNAMIC_HII
,
38 MODEL_PCD_DYNAMIC_VPD
: TAB_PCDS_DYNAMIC_VPD
,
39 MODEL_PCD_DYNAMIC_EX
: TAB_PCDS_DYNAMIC_EX
,
40 MODEL_PCD_DYNAMIC_EX_DEFAULT
: TAB_PCDS_DYNAMIC_EX
,
41 MODEL_PCD_DYNAMIC_EX_HII
: TAB_PCDS_DYNAMIC_EX_HII
,
42 MODEL_PCD_DYNAMIC_EX_VPD
: TAB_PCDS_DYNAMIC_EX_VPD
,
45 # dict used to convert part of [Defines] to members of InfBuildData directly
50 TAB_INF_DEFINES_BASE_NAME
: "_BaseName",
51 TAB_INF_DEFINES_FILE_GUID
: "_Guid",
52 TAB_INF_DEFINES_MODULE_TYPE
: "_ModuleType",
56 # TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
57 TAB_INF_DEFINES_COMPONENT_TYPE
: "_ComponentType",
58 TAB_INF_DEFINES_MAKEFILE_NAME
: "_MakefileName",
59 # TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
60 TAB_INF_DEFINES_DPX_SOURCE
:"_DxsFile",
61 TAB_INF_DEFINES_VERSION_NUMBER
: "_Version",
62 TAB_INF_DEFINES_VERSION_STRING
: "_Version",
63 TAB_INF_DEFINES_VERSION
: "_Version",
64 TAB_INF_DEFINES_PCD_IS_DRIVER
: "_PcdIsDriver",
65 TAB_INF_DEFINES_SHADOW
: "_Shadow",
67 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
: "_SourceOverridePath",
70 # regular expression for converting XXX_FLAGS in [nmake] section to new type
71 _NMAKE_FLAG_PATTERN_
= re
.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re
.UNICODE
)
72 # dict used to convert old tool name used in [nmake] section to new ones
75 BINARY_FILE_TYPE_LIB
: "SLINK",
80 ## Constructor of InfBuildData
82 # Initialize object of InfBuildData
84 # @param FilePath The path of platform description file
85 # @param RawData The raw data of DSC file
86 # @param BuildDataBase Database used to retrieve module/package information
87 # @param Arch The target architecture
88 # @param Platform The name of platform employing this module
89 # @param Macros Macros used for replacement in DSC file
91 def __init__(self
, FilePath
, RawData
, BuildDatabase
, Arch
=TAB_ARCH_COMMON
, Target
=None, Toolchain
=None):
92 self
.MetaFile
= FilePath
93 self
._ModuleDir
= FilePath
.Dir
94 self
._RawData
= RawData
95 self
._Bdb
= BuildDatabase
98 self
._Toolchain
= Toolchain
99 self
._Platform
= TAB_COMMON
100 if FilePath
.Key
in GlobalData
.gOverrideDir
:
101 self
._SourceOverridePath
= GlobalData
.gOverrideDir
[FilePath
.Key
]
103 self
._SourceOverridePath
= None
104 self
._TailComments
= None
105 self
._BaseName
= None
107 self
._ModuleType
= None
108 self
._ComponentType
= None
109 self
._BuildType
= None
112 self
._PcdIsDriver
= None
113 self
._BinaryModule
= None
115 self
._MakefileName
= None
116 self
._CustomMakefile
= None
117 self
._Specification
= None
118 self
._LibraryClass
= None
119 self
._ModuleEntryPointList
= None
120 self
._ModuleUnloadImageList
= None
121 self
._ConstructorList
= None
122 self
._DestructorList
= None
123 self
._Defs
= OrderedDict()
124 self
._ProtocolComments
= None
125 self
._PpiComments
= None
126 self
._GuidsUsedByPcd
= OrderedDict()
127 self
._GuidComments
= None
128 self
._PcdComments
= None
129 self
._BuildOptions
= None
130 self
._DependencyFileList
= None
133 def __setitem__(self
, key
, value
):
134 self
.__dict
__[self
._PROPERTY
_[key
]] = value
137 def __getitem__(self
, key
):
138 return self
.__dict
__[self
._PROPERTY
_[key
]]
141 def __contains__(self
, key
):
142 return key
in self
._PROPERTY
_
144 ## Get current effective macros
155 ## Return the name of platform employing this module
158 return self
._Platform
161 def HeaderComments(self
):
162 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_HEADER_COMMENT
]]
165 def TailComments(self
):
166 return [a
[0] for a
in self
._RawData
[MODEL_META_DATA_TAIL_COMMENT
]]
168 ## Retrieve all information in [Defines] section
170 # (Retriving all [Defines] information in one-shot is just to save time.)
172 @cached_class_function
173 def _GetHeaderInfo(self
):
174 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
175 for Record
in RecordList
:
176 Name
, Value
= Record
[1], ReplaceMacro(Record
[2], self
._Macros
, False)
177 # items defined _PROPERTY_ don't need additional processing
180 self
._Defs
[Name
] = Value
181 self
._Macros
[Name
] = Value
182 # some special items in [Defines] section need special treatment
183 elif Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
184 if Name
in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
185 Name
= 'UEFI_SPECIFICATION_VERSION'
186 if self
._Specification
is None:
187 self
._Specification
= OrderedDict()
188 self
._Specification
[Name
] = GetHexVerValue(Value
)
189 if self
._Specification
[Name
] is None:
190 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
191 "'%s' format is not supported for %s" % (Value
, Name
),
192 File
=self
.MetaFile
, Line
=Record
[-1])
193 elif Name
== 'LIBRARY_CLASS':
194 if self
._LibraryClass
is None:
195 self
._LibraryClass
= []
196 ValueList
= GetSplitValueList(Value
)
197 LibraryClass
= ValueList
[0]
198 if len(ValueList
) > 1:
199 SupModuleList
= GetSplitValueList(ValueList
[1], ' ')
201 SupModuleList
= SUP_MODULE_LIST
202 self
._LibraryClass
.append(LibraryClassObject(LibraryClass
, SupModuleList
))
203 elif Name
== 'ENTRY_POINT':
204 if self
._ModuleEntryPointList
is None:
205 self
._ModuleEntryPointList
= []
206 self
._ModuleEntryPointList
.append(Value
)
207 elif Name
== 'UNLOAD_IMAGE':
208 if self
._ModuleUnloadImageList
is None:
209 self
._ModuleUnloadImageList
= []
212 self
._ModuleUnloadImageList
.append(Value
)
213 elif Name
== 'CONSTRUCTOR':
214 if self
._ConstructorList
is None:
215 self
._ConstructorList
= []
218 self
._ConstructorList
.append(Value
)
219 elif Name
== 'DESTRUCTOR':
220 if self
._DestructorList
is None:
221 self
._DestructorList
= []
224 self
._DestructorList
.append(Value
)
225 elif Name
== TAB_INF_DEFINES_CUSTOM_MAKEFILE
:
226 TokenList
= GetSplitValueList(Value
)
227 if self
._CustomMakefile
is None:
228 self
._CustomMakefile
= {}
229 if len(TokenList
) < 2:
230 self
._CustomMakefile
[TAB_COMPILER_MSFT
] = TokenList
[0]
231 self
._CustomMakefile
['GCC'] = TokenList
[0]
233 if TokenList
[0] not in [TAB_COMPILER_MSFT
, 'GCC']:
234 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
235 "No supported family [%s]" % TokenList
[0],
236 File
=self
.MetaFile
, Line
=Record
[-1])
237 self
._CustomMakefile
[TokenList
[0]] = TokenList
[1]
239 self
._Defs
[Name
] = Value
240 self
._Macros
[Name
] = Value
243 # Retrieve information in sections specific to Edk.x modules
245 if not self
._ModuleType
:
246 EdkLogger
.error("build", ATTRIBUTE_NOT_AVAILABLE
,
247 "MODULE_TYPE is not given", File
=self
.MetaFile
)
248 if self
._ModuleType
not in SUP_MODULE_LIST
:
249 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
250 for Record
in RecordList
:
252 if Name
== "MODULE_TYPE":
255 EdkLogger
.error("build", FORMAT_NOT_SUPPORTED
,
256 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self
._ModuleType
, ' '.join(l
for l
in SUP_MODULE_LIST
)),
257 File
=self
.MetaFile
, Line
=LineNo
)
258 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
259 if self
._ModuleType
== SUP_MODULE_SMM_CORE
:
260 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
)
261 if (self
._Specification
is None) or (not 'PI_SPECIFICATION_VERSION' in self
._Specification
) or (int(self
._Specification
['PI_SPECIFICATION_VERSION'], 16) < 0x00010032):
262 if self
._ModuleType
== SUP_MODULE_MM_CORE_STANDALONE
:
263 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
)
264 if self
._ModuleType
== SUP_MODULE_MM_STANDALONE
:
265 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
)
266 if 'PCI_DEVICE_ID' in self
._Defs
and 'PCI_VENDOR_ID' in self
._Defs \
267 and 'PCI_CLASS_CODE' in self
._Defs
and 'PCI_REVISION' in self
._Defs
:
268 self
._BuildType
= 'UEFI_OPTIONROM'
269 if 'PCI_COMPRESS' in self
._Defs
:
270 if self
._Defs
['PCI_COMPRESS'] not in ('TRUE', 'FALSE'):
271 EdkLogger
.error("build", FORMAT_INVALID
, "Expected TRUE/FALSE for PCI_COMPRESS: %s" % self
.MetaFile
)
273 elif 'UEFI_HII_RESOURCE_SECTION' in self
._Defs \
274 and self
._Defs
['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
275 self
._BuildType
= 'UEFI_HII'
277 self
._BuildType
= self
._ModuleType
.upper()
280 File
= PathClass(NormPath(self
._DxsFile
), self
._ModuleDir
, Arch
=self
._Arch
)
281 # check the file validation
282 ErrorCode
, ErrorInfo
= File
.Validate(".dxs", CaseSensitive
=False)
284 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
,
285 File
=self
.MetaFile
, Line
=LineNo
)
286 if not self
._DependencyFileList
:
287 self
._DependencyFileList
= []
288 self
._DependencyFileList
.append(File
)
290 ## Retrieve file version
292 def AutoGenVersion(self
):
294 RecordList
= self
._RawData
[MODEL_META_DATA_HEADER
, self
._Arch
, self
._Platform
]
295 for Record
in RecordList
:
296 if Record
[1] == TAB_INF_DEFINES_INF_VERSION
:
298 ValueList
= Record
[2].split('.')
299 Major
= '%04o' % int(ValueList
[0], 0)
300 Minor
= '%04o' % int(ValueList
[1], 0)
301 RetVal
= int('0x' + Major
+ Minor
, 0)
303 RetVal
= int(Record
[2], 0)
307 ## Retrieve BASE_NAME
310 if self
._BaseName
is None:
311 self
._GetHeaderInfo
()
312 if self
._BaseName
is None:
313 EdkLogger
.error('build', ATTRIBUTE_NOT_AVAILABLE
, "No BASE_NAME name", File
=self
.MetaFile
)
314 return self
._BaseName
319 if self
._DxsFile
is None:
320 self
._GetHeaderInfo
()
321 if self
._DxsFile
is None:
325 ## Retrieve MODULE_TYPE
327 def ModuleType(self
):
328 if self
._ModuleType
is None:
329 self
._GetHeaderInfo
()
330 if self
._ModuleType
is None:
331 self
._ModuleType
= SUP_MODULE_BASE
332 if self
._ModuleType
not in SUP_MODULE_LIST
:
333 self
._ModuleType
= SUP_MODULE_USER_DEFINED
334 return self
._ModuleType
336 ## Retrieve COMPONENT_TYPE
338 def ComponentType(self
):
339 if self
._ComponentType
is None:
340 self
._GetHeaderInfo
()
341 if self
._ComponentType
is None:
342 self
._ComponentType
= SUP_MODULE_USER_DEFINED
343 return self
._ComponentType
345 ## Retrieve "BUILD_TYPE"
348 if self
._BuildType
is None:
349 self
._GetHeaderInfo
()
350 if not self
._BuildType
:
351 self
._BuildType
= SUP_MODULE_BASE
352 return self
._BuildType
354 ## Retrieve file guid
357 if self
._Guid
is None:
358 self
._GetHeaderInfo
()
359 if self
._Guid
is None:
360 self
._Guid
= '00000000-0000-0000-0000-000000000000'
363 ## Retrieve module version
366 if self
._Version
is None:
367 self
._GetHeaderInfo
()
368 if self
._Version
is None:
369 self
._Version
= '0.0'
372 ## Retrieve PCD_IS_DRIVER
374 def PcdIsDriver(self
):
375 if self
._PcdIsDriver
is None:
376 self
._GetHeaderInfo
()
377 if self
._PcdIsDriver
is None:
378 self
._PcdIsDriver
= ''
379 return self
._PcdIsDriver
384 if self
._Shadow
is None:
385 self
._GetHeaderInfo
()
386 if self
._Shadow
and self
._Shadow
.upper() == 'TRUE':
392 ## Retrieve CUSTOM_MAKEFILE
394 def CustomMakefile(self
):
395 if self
._CustomMakefile
is None:
396 self
._GetHeaderInfo
()
397 if self
._CustomMakefile
is None:
398 self
._CustomMakefile
= {}
399 return self
._CustomMakefile
401 ## Retrieve EFI_SPECIFICATION_VERSION
403 def Specification(self
):
404 if self
._Specification
is None:
405 self
._GetHeaderInfo
()
406 if self
._Specification
is None:
407 self
._Specification
= {}
408 return self
._Specification
410 ## Retrieve LIBRARY_CLASS
412 def LibraryClass(self
):
413 if self
._LibraryClass
is None:
414 self
._GetHeaderInfo
()
415 if self
._LibraryClass
is None:
416 self
._LibraryClass
= []
417 return self
._LibraryClass
419 ## Retrieve ENTRY_POINT
421 def ModuleEntryPointList(self
):
422 if self
._ModuleEntryPointList
is None:
423 self
._GetHeaderInfo
()
424 if self
._ModuleEntryPointList
is None:
425 self
._ModuleEntryPointList
= []
426 return self
._ModuleEntryPointList
428 ## Retrieve UNLOAD_IMAGE
430 def ModuleUnloadImageList(self
):
431 if self
._ModuleUnloadImageList
is None:
432 self
._GetHeaderInfo
()
433 if self
._ModuleUnloadImageList
is None:
434 self
._ModuleUnloadImageList
= []
435 return self
._ModuleUnloadImageList
437 ## Retrieve CONSTRUCTOR
439 def ConstructorList(self
):
440 if self
._ConstructorList
is None:
441 self
._GetHeaderInfo
()
442 if self
._ConstructorList
is None:
443 self
._ConstructorList
= []
444 return self
._ConstructorList
446 ## Retrieve DESTRUCTOR
448 def DestructorList(self
):
449 if self
._DestructorList
is None:
450 self
._GetHeaderInfo
()
451 if self
._DestructorList
is None:
452 self
._DestructorList
= []
453 return self
._DestructorList
455 ## Retrieve definies other than above ones
458 self
._GetHeaderInfo
()
461 ## Retrieve binary files
462 @cached_class_function
463 def _GetBinaries(self
):
465 RecordList
= self
._RawData
[MODEL_EFI_BINARY_FILE
, self
._Arch
, self
._Platform
]
466 Macros
= self
._Macros
467 Macros
['PROCESSOR'] = self
._Arch
468 for Record
in RecordList
:
474 TokenList
= GetSplitValueList(Record
[2], TAB_VALUE_SPLIT
)
476 Target
= TokenList
[0]
477 if len(TokenList
) > 1:
478 FeatureFlag
= Record
[1:]
480 File
= PathClass(NormPath(Record
[1], Macros
), self
._ModuleDir
, '', FileType
, True, self
._Arch
, '', Target
)
481 # check the file validation
482 ErrorCode
, ErrorInfo
= File
.Validate()
484 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
488 ## Retrieve binary files with error check.
491 RetVal
= self
._GetBinaries
()
492 if GlobalData
.gIgnoreSource
and not RetVal
:
493 ErrorInfo
= "The INF file does not contain any RetVal to use in creating the image\n"
494 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
)
498 ## Retrieve source files
501 self
._GetHeaderInfo
()
502 # Ignore all source files in a binary build mode
503 if GlobalData
.gIgnoreSource
:
507 RecordList
= self
._RawData
[MODEL_EFI_SOURCE_FILE
, self
._Arch
, self
._Platform
]
508 Macros
= self
._Macros
509 for Record
in RecordList
:
511 ToolChainFamily
= Record
[1]
515 File
= PathClass(NormPath(Record
[0], Macros
), self
._ModuleDir
, '',
516 '', False, self
._Arch
, ToolChainFamily
, '', TagName
, ToolCode
)
517 # check the file validation
518 ErrorCode
, ErrorInfo
= File
.Validate()
520 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
523 # add any previously found dependency files to the source list
524 if self
._DependencyFileList
:
525 RetVal
.extend(self
._DependencyFileList
)
528 ## Retrieve library classes employed by this module
530 def LibraryClasses(self
):
531 RetVal
= OrderedDict()
532 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_CLASS
, self
._Arch
, self
._Platform
]
533 for Record
in RecordList
:
537 Instance
= NormPath(Instance
, self
._Macros
)
538 RetVal
[Lib
] = Instance
543 ## Retrieve library names (for Edk.x style of modules)
547 RecordList
= self
._RawData
[MODEL_EFI_LIBRARY_INSTANCE
, self
._Arch
, self
._Platform
]
548 for Record
in RecordList
:
549 LibraryName
= ReplaceMacro(Record
[0], self
._Macros
, False)
550 # in case of name with '.lib' extension, which is unusual in Edk.x inf
551 LibraryName
= os
.path
.splitext(LibraryName
)[0]
552 if LibraryName
not in RetVal
:
553 RetVal
.append(LibraryName
)
557 def ProtocolComments(self
):
559 return self
._ProtocolComments
561 ## Retrieve protocols consumed/produced by this module
564 RetVal
= OrderedDict()
565 self
._ProtocolComments
= OrderedDict()
566 RecordList
= self
._RawData
[MODEL_EFI_PROTOCOL
, self
._Arch
, self
._Platform
]
567 for Record
in RecordList
:
569 Value
= ProtocolValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
571 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
572 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
573 "Value of Protocol [%s] is not found under [Protocols] section in" % CName
,
574 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
575 RetVal
[CName
] = Value
576 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
577 self
._ProtocolComments
[CName
] = [a
[0] for a
in CommentRecords
]
581 def PpiComments(self
):
583 return self
._PpiComments
585 ## Retrieve PPIs consumed/produced by this module
588 RetVal
= OrderedDict()
589 self
._PpiComments
= OrderedDict()
590 RecordList
= self
._RawData
[MODEL_EFI_PPI
, self
._Arch
, self
._Platform
]
591 for Record
in RecordList
:
593 Value
= PpiValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
595 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
596 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
597 "Value of PPI [%s] is not found under [Ppis] section in " % CName
,
598 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
599 RetVal
[CName
] = Value
600 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
601 self
._PpiComments
[CName
] = [a
[0] for a
in CommentRecords
]
605 def GuidComments(self
):
607 return self
._GuidComments
609 ## Retrieve GUIDs consumed/produced by this module
612 RetVal
= OrderedDict()
613 self
._GuidComments
= OrderedDict()
614 RecordList
= self
._RawData
[MODEL_EFI_GUID
, self
._Arch
, self
._Platform
]
615 for Record
in RecordList
:
617 Value
= GuidValue(CName
, self
.Packages
, self
.MetaFile
.Path
)
619 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
620 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
621 "Value of Guid [%s] is not found under [Guids] section in" % CName
,
622 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
623 RetVal
[CName
] = Value
624 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Record
[5]]
625 self
._GuidComments
[CName
] = [a
[0] for a
in CommentRecords
]
628 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
632 if self
._SourceOverridePath
:
633 RetVal
.append(self
._SourceOverridePath
)
635 Macros
= self
._Macros
636 Macros
['PROCESSOR'] = GlobalData
.gEdkGlobal
.get('PROCESSOR', self
._Arch
)
637 RecordList
= self
._RawData
[MODEL_EFI_INCLUDE
, self
._Arch
, self
._Platform
]
638 for Record
in RecordList
:
639 if Record
[0].find('EDK_SOURCE') > -1:
640 File
= NormPath(Record
[0], self
._Macros
)
642 File
= os
.path
.join(self
._ModuleDir
, File
)
644 File
= os
.path
.join(GlobalData
.gWorkspace
, File
)
645 File
= RealPath(os
.path
.normpath(File
))
649 # TRICK: let compiler to choose correct header file
650 File
= NormPath(Record
[0], self
._Macros
)
652 File
= os
.path
.join(self
._ModuleDir
, File
)
654 File
= os
.path
.join(GlobalData
.gWorkspace
, File
)
655 File
= RealPath(os
.path
.normpath(File
))
659 File
= NormPath(Record
[0], Macros
)
661 File
= os
.path
.join(self
._ModuleDir
, File
)
663 File
= mws
.join(GlobalData
.gWorkspace
, File
)
664 File
= RealPath(os
.path
.normpath(File
))
669 ## Retrieve packages this module depends on
673 RecordList
= self
._RawData
[MODEL_META_DATA_PACKAGE
, self
._Arch
, self
._Platform
]
674 Macros
= self
._Macros
675 for Record
in RecordList
:
676 File
= PathClass(NormPath(Record
[0], Macros
), GlobalData
.gWorkspace
, Arch
=self
._Arch
)
677 # check the file validation
678 ErrorCode
, ErrorInfo
= File
.Validate('.dec')
681 EdkLogger
.error('build', ErrorCode
, ExtraData
=ErrorInfo
, File
=self
.MetaFile
, Line
=LineNo
)
682 # parse this package now. we need it to get protocol/ppi/guid value
683 RetVal
.append(self
._Bdb
[File
, self
._Arch
, self
._Target
, self
._Toolchain
])
686 ## Retrieve PCD comments
688 def PcdComments(self
):
690 return self
._PcdComments
692 ## Retrieve PCDs used in this module
695 self
._PcdComments
= OrderedDict()
696 RetVal
= OrderedDict()
697 RetVal
.update(self
._GetPcd
(MODEL_PCD_FIXED_AT_BUILD
))
698 RetVal
.update(self
._GetPcd
(MODEL_PCD_PATCHABLE_IN_MODULE
))
699 RetVal
.update(self
._GetPcd
(MODEL_PCD_FEATURE_FLAG
))
700 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC
))
701 RetVal
.update(self
._GetPcd
(MODEL_PCD_DYNAMIC_EX
))
707 for Type
in (MODEL_PCD_FIXED_AT_BUILD
,MODEL_PCD_PATCHABLE_IN_MODULE
,MODEL_PCD_FEATURE_FLAG
,MODEL_PCD_DYNAMIC
,MODEL_PCD_DYNAMIC_EX
):
708 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
709 for TokenSpaceGuid
, PcdCName
, _
, _
, _
, _
, _
in RecordList
:
710 PcdsName
.add((PcdCName
, TokenSpaceGuid
))
713 ## Retrieve build options specific to this module
715 def BuildOptions(self
):
716 if self
._BuildOptions
is None:
717 self
._BuildOptions
= OrderedDict()
718 RecordList
= self
._RawData
[MODEL_META_DATA_BUILD_OPTION
, self
._Arch
, self
._Platform
]
719 for Record
in RecordList
:
720 ToolChainFamily
= Record
[0]
721 ToolChain
= Record
[1]
723 if (ToolChainFamily
, ToolChain
) not in self
._BuildOptions
or Option
.startswith('='):
724 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = Option
726 # concatenate the option string if they're for the same tool
727 OptionString
= self
._BuildOptions
[ToolChainFamily
, ToolChain
]
728 self
._BuildOptions
[ToolChainFamily
, ToolChain
] = OptionString
+ " " + Option
729 return self
._BuildOptions
731 ## Retrieve dependency expression
734 RetVal
= tdict(False, 2)
736 # If the module has only Binaries and no Sources, then ignore [Depex]
737 if not self
.Sources
and self
.Binaries
:
740 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
741 # PEIM and DXE drivers must have a valid [Depex] section
742 if len(self
.LibraryClass
) == 0 and len(RecordList
) == 0:
743 if self
.ModuleType
== SUP_MODULE_DXE_DRIVER
or self
.ModuleType
== SUP_MODULE_PEIM
or self
.ModuleType
== SUP_MODULE_DXE_SMM_DRIVER
or \
744 self
.ModuleType
== SUP_MODULE_DXE_SAL_DRIVER
or self
.ModuleType
== SUP_MODULE_DXE_RUNTIME_DRIVER
:
745 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
746 % self
.ModuleType
, File
=self
.MetaFile
)
748 if len(RecordList
) != 0 and self
.ModuleType
== SUP_MODULE_USER_DEFINED
:
749 for Record
in RecordList
:
750 if Record
[4] not in [SUP_MODULE_PEIM
, SUP_MODULE_DXE_DRIVER
, SUP_MODULE_DXE_SMM_DRIVER
]:
751 EdkLogger
.error('build', FORMAT_INVALID
,
752 "'%s' module must specify the type of [Depex] section" % self
.ModuleType
,
755 TemporaryDictionary
= OrderedDict()
756 for Record
in RecordList
:
757 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
759 ModuleType
= Record
[4]
760 TokenList
= DepexStr
.split()
761 if (Arch
, ModuleType
) not in TemporaryDictionary
:
762 TemporaryDictionary
[Arch
, ModuleType
] = []
763 DepexList
= TemporaryDictionary
[Arch
, ModuleType
]
764 for Token
in TokenList
:
765 if Token
in DEPEX_SUPPORTED_OPCODE_SET
:
766 DepexList
.append(Token
)
767 elif Token
.endswith(".inf"): # module file name
768 ModuleFile
= os
.path
.normpath(Token
)
769 Module
= self
.BuildDatabase
[ModuleFile
]
771 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
, "Module is not found in active platform",
772 ExtraData
=Token
, File
=self
.MetaFile
, Line
=Record
[-1])
773 DepexList
.append(Module
.Guid
)
775 # it use the Fixed PCD format
777 if tuple(Token
.split('.')[::-1]) not in self
.Pcds
:
778 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])
780 if self
.Pcds
[tuple(Token
.split('.')[::-1])].DatumType
!= TAB_VOID
:
781 EdkLogger
.error('build', FORMAT_INVALID
, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token
), File
=self
.MetaFile
, Line
=Record
[-1])
784 # get the GUID value now
785 Value
= ProtocolValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
787 Value
= PpiValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
789 Value
= GuidValue(Token
, self
.Packages
, self
.MetaFile
.Path
)
792 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
793 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
794 "Value of [%s] is not found in" % Token
,
795 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=Record
[-1])
796 DepexList
.append(Value
)
797 for Arch
, ModuleType
in TemporaryDictionary
:
798 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
801 ## Retrieve depedency expression
803 def DepexExpression(self
):
804 RetVal
= tdict(False, 2)
805 RecordList
= self
._RawData
[MODEL_EFI_DEPEX
, self
._Arch
]
806 TemporaryDictionary
= OrderedDict()
807 for Record
in RecordList
:
808 DepexStr
= ReplaceMacro(Record
[0], self
._Macros
, False)
810 ModuleType
= Record
[4]
811 TokenList
= DepexStr
.split()
812 if (Arch
, ModuleType
) not in TemporaryDictionary
:
813 TemporaryDictionary
[Arch
, ModuleType
] = ''
814 for Token
in TokenList
:
815 TemporaryDictionary
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
] + Token
.strip() + ' '
816 for Arch
, ModuleType
in TemporaryDictionary
:
817 RetVal
[Arch
, ModuleType
] = TemporaryDictionary
[Arch
, ModuleType
]
820 @cached_class_function
821 def GetGuidsUsedByPcd(self
):
823 return self
._GuidsUsedByPcd
825 ## Retrieve PCD for given type
826 def _GetPcd(self
, Type
):
828 PcdDict
= tdict(True, 4)
830 RecordList
= self
._RawData
[Type
, self
._Arch
, self
._Platform
]
831 for TokenSpaceGuid
, PcdCName
, Setting
, Arch
, Platform
, Id
, LineNo
in RecordList
:
832 PcdDict
[Arch
, Platform
, PcdCName
, TokenSpaceGuid
] = (Setting
, LineNo
)
833 PcdList
.append((PcdCName
, TokenSpaceGuid
))
835 if TokenSpaceGuid
not in self
.Guids
:
836 Value
= GuidValue(TokenSpaceGuid
, self
.Packages
, self
.MetaFile
.Path
)
838 PackageList
= "\n\t".join(str(P
) for P
in self
.Packages
)
839 EdkLogger
.error('build', RESOURCE_NOT_AVAILABLE
,
840 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid
,
841 ExtraData
=PackageList
, File
=self
.MetaFile
, Line
=LineNo
)
842 self
.Guids
[TokenSpaceGuid
] = Value
843 self
._GuidsUsedByPcd
[TokenSpaceGuid
] = Value
844 CommentRecords
= self
._RawData
[MODEL_META_DATA_COMMENT
, self
._Arch
, self
._Platform
, Id
]
846 for CmtRec
in CommentRecords
:
847 Comments
.append(CmtRec
[0])
848 self
._PcdComments
[TokenSpaceGuid
, PcdCName
] = Comments
850 # resolve PCD type, value, datum info, etc. by getting its definition from package
851 _GuidDict
= self
.Guids
.copy()
852 for PcdCName
, TokenSpaceGuid
in PcdList
:
853 PcdRealName
= PcdCName
854 Setting
, LineNo
= PcdDict
[self
._Arch
, self
.Platform
, PcdCName
, TokenSpaceGuid
]
857 ValueList
= AnalyzePcdData(Setting
)
858 DefaultValue
= ValueList
[0]
859 Pcd
= PcdClassObject(
869 self
.Guids
[TokenSpaceGuid
]
871 if Type
== MODEL_PCD_PATCHABLE_IN_MODULE
and ValueList
[1]:
872 # Patch PCD: TokenSpace.PcdCName|Value|Offset
873 Pcd
.Offset
= ValueList
[1]
875 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
876 for Package
in self
.Packages
:
877 for key
in Package
.Pcds
:
878 if (Package
.Pcds
[key
].TokenCName
, Package
.Pcds
[key
].TokenSpaceGuidCName
) == (PcdRealName
, TokenSpaceGuid
):
879 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
880 Pcd_Type
= item
[0].split('_')[-1]
881 if Pcd_Type
== Package
.Pcds
[key
].Type
:
882 Value
= Package
.Pcds
[key
]
883 Value
.TokenCName
= Package
.Pcds
[key
].TokenCName
+ '_' + Pcd_Type
885 newkey
= (Value
.TokenCName
, key
[1])
887 newkey
= (Value
.TokenCName
, key
[1], key
[2])
888 del Package
.Pcds
[key
]
889 Package
.Pcds
[newkey
] = Value
896 # get necessary info from package declaring this PCD
897 for Package
in self
.Packages
:
899 # 'dynamic' in INF means its type is determined by platform;
900 # if platform doesn't give its type, use 'lowest' one in the
901 # following order, if any
903 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
905 _GuidDict
.update(Package
.Guids
)
906 PcdType
= self
._PCD
_TYPE
_STRING
_[Type
]
907 if Type
== MODEL_PCD_DYNAMIC
:
909 for T
in PCD_TYPE_LIST
:
910 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
911 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
912 if str(item
[0]).endswith(T
) and (item
[0], item
[1], T
) in Package
.Pcds
:
920 if (PcdRealName
, TokenSpaceGuid
, T
) in Package
.Pcds
:
926 if (PcdRealName
, TokenSpaceGuid
) in GlobalData
.MixedPcd
:
927 for item
in GlobalData
.MixedPcd
[(PcdRealName
, TokenSpaceGuid
)]:
928 Pcd_Type
= item
[0].split('_')[-1]
929 if Pcd_Type
== PcdType
:
937 if (PcdCName
, TokenSpaceGuid
, PcdType
) in Package
.Pcds
:
938 PcdInPackage
= Package
.Pcds
[PcdCName
, TokenSpaceGuid
, PcdType
]
940 Pcd
.TokenValue
= PcdInPackage
.TokenValue
943 # Check whether the token value exist or not.
945 if Pcd
.TokenValue
is None or Pcd
.TokenValue
== "":
949 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid
, PcdRealName
, str(Package
)),
950 File
=self
.MetaFile
, Line
=LineNo
,
954 # Check hexadecimal token value length and format.
956 ReIsValidPcdTokenValue
= re
.compile(r
"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re
.DOTALL
)
957 if Pcd
.TokenValue
.startswith("0x") or Pcd
.TokenValue
.startswith("0X"):
958 if ReIsValidPcdTokenValue
.match(Pcd
.TokenValue
) is None:
962 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd
.TokenValue
, TokenSpaceGuid
, PcdRealName
, str(Package
)),
963 File
=self
.MetaFile
, Line
=LineNo
,
968 # Check decimal token value length and format.
972 TokenValueInt
= int (Pcd
.TokenValue
, 10)
973 if (TokenValueInt
< 0 or TokenValueInt
> 4294967295):
977 "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
)),
978 File
=self
.MetaFile
, Line
=LineNo
,
985 "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
)),
986 File
=self
.MetaFile
, Line
=LineNo
,
990 Pcd
.DatumType
= PcdInPackage
.DatumType
991 Pcd
.MaxDatumSize
= PcdInPackage
.MaxDatumSize
992 Pcd
.InfDefaultValue
= Pcd
.DefaultValue
993 if not Pcd
.DefaultValue
:
994 Pcd
.DefaultValue
= PcdInPackage
.DefaultValue
997 Pcd
.DefaultValue
= ValueExpressionEx(Pcd
.DefaultValue
, Pcd
.DatumType
, _GuidDict
)(True)
998 except BadExpression
as Value
:
999 EdkLogger
.error('Parser', FORMAT_INVALID
, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid
, PcdRealName
, Pcd
.DefaultValue
, Value
),
1000 File
=self
.MetaFile
, Line
=LineNo
)
1006 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid
, PcdRealName
, self
.MetaFile
),
1007 File
=self
.MetaFile
, Line
=LineNo
,
1008 ExtraData
="\t%s" % '\n\t'.join(str(P
) for P
in self
.Packages
)
1010 Pcds
[PcdCName
, TokenSpaceGuid
] = Pcd
1014 ## check whether current module is binary module
1016 def IsBinaryModule(self
):
1017 if (self
.Binaries
and not self
.Sources
) or GlobalData
.gIgnoreSource
: