]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/InfBuildData.py
BaseTools: Decouple AutoGen Objects
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / InfBuildData.py
1 ## @file
2 # This file is used to create a database used by build tool
3 #
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
7 #
8
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
13 from types import *
14 from .MetaFileParser import *
15 from collections import OrderedDict
16 from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject
17
18 ## Get Protocol value from given packages
19 #
20 # @param CName The CName of the GUID
21 # @param PackageList List of packages looking-up in
22 # @param Inffile The driver file
23 #
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
26 #
27 def _ProtocolValue(CName, PackageList, Inffile = None):
28 for P in PackageList:
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]
35 return None
36
37 ## Get PPI value from given packages
38 #
39 # @param CName The CName of the GUID
40 # @param PackageList List of packages looking-up in
41 # @param Inffile The driver file
42 #
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
45 #
46 def _PpiValue(CName, PackageList, Inffile = None):
47 for P in PackageList:
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]
52 if CName in PpiKeys:
53 return P.Ppis[CName]
54 return None
55
56 ## Module build information from INF file
57 #
58 # This class is used to retrieve information stored in database and convert them
59 # into ModuleBuildClassObject form for easier use for AutoGen.
60 #
61 class InfBuildData(ModuleBuildClassObject):
62 # dict used to convert PCD type in database to string used by build tool
63 _PCD_TYPE_STRING_ = {
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,
75 }
76
77 # dict used to convert part of [Defines] to members of InfBuildData directly
78 _PROPERTY_ = {
79 #
80 # Required Fields
81 #
82 TAB_INF_DEFINES_BASE_NAME : "_BaseName",
83 TAB_INF_DEFINES_FILE_GUID : "_Guid",
84 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
85 #
86 # Optional Fields
87 #
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"
98 }
99
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
103 _TOOL_CODE_ = {
104 "C" : "CC",
105 BINARY_FILE_TYPE_LIB : "SLINK",
106 "LINK" : "DLINK",
107 }
108
109
110 ## Constructor of InfBuildData
111 #
112 # Initialize object of InfBuildData
113 #
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
120 #
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
126 self._Arch = Arch
127 self._Target = Target
128 self._Toolchain = Toolchain
129 self._Platform = TAB_COMMON
130 self._TailComments = None
131 self._BaseName = None
132 self._DxsFile = None
133 self._ModuleType = None
134 self._ComponentType = None
135 self._BuildType = None
136 self._Guid = None
137 self._Version = None
138 self._PcdIsDriver = None
139 self._BinaryModule = None
140 self._Shadow = 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()
159 self.Guids
160 self.Pcds
161 def SetReferenceModule(self,Module):
162 self.ReferenceModules.add(Module)
163 return self
164
165 ## XXX[key] = value
166 def __setitem__(self, key, value):
167 self.__dict__[self._PROPERTY_[key]] = value
168
169 ## value = XXX[key]
170 def __getitem__(self, key):
171 return self.__dict__[self._PROPERTY_[key]]
172
173 ## "in" test support
174 def __contains__(self, key):
175 return key in self._PROPERTY_
176
177 ## Get current effective macros
178 @cached_property
179 def _Macros(self):
180 RetVal = {}
181 return RetVal
182
183 ## Get architecture
184 @cached_property
185 def Arch(self):
186 return self._Arch
187
188 ## Return the name of platform employing this module
189 @cached_property
190 def Platform(self):
191 return self._Platform
192
193 @cached_property
194 def HeaderComments(self):
195 return [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
196
197 @cached_property
198 def TailComments(self):
199 return [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
200
201 ## Retrieve all information in [Defines] section
202 #
203 # (Retrieving all [Defines] information in one-shot is just to save time.)
204 #
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
211 if Name in self:
212 self[Name] = Value
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], ' ')
233 else:
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 = []
243 if not Value:
244 continue
245 self._ModuleUnloadImageList.append(Value)
246 elif Name == 'CONSTRUCTOR':
247 if self._ConstructorList is None:
248 self._ConstructorList = []
249 if not Value:
250 continue
251 self._ConstructorList.append(Value)
252 elif Name == 'DESTRUCTOR':
253 if self._DestructorList is None:
254 self._DestructorList = []
255 if not Value:
256 continue
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]
265 else:
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]
271 else:
272 self._Defs[Name] = Value
273 self._Macros[Name] = Value
274
275 #
276 # Retrieve information in sections specific to Edk.x modules
277 #
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:
284 Name = Record[1]
285 if Name == "MODULE_TYPE":
286 LineNo = Record[6]
287 break
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)
305
306 elif 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
307 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
308 self._BuildType = 'UEFI_HII'
309 else:
310 self._BuildType = self._ModuleType.upper()
311
312 if self._DxsFile:
313 File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch)
314 # check the file validation
315 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
316 if ErrorCode != 0:
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)
322
323 ## Retrieve file version
324 @cached_property
325 def AutoGenVersion(self):
326 RetVal = 0x00010000
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:
330 if '.' in Record[2]:
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)
335 else:
336 RetVal = int(Record[2], 0)
337 break
338 return RetVal
339
340 ## Retrieve BASE_NAME
341 @cached_property
342 def BaseName(self):
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
348
349 ## Retrieve DxsFile
350 @cached_property
351 def DxsFile(self):
352 if self._DxsFile is None:
353 self._GetHeaderInfo()
354 if self._DxsFile is None:
355 self._DxsFile = ''
356 return self._DxsFile
357
358 ## Retrieve MODULE_TYPE
359 @cached_property
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
368
369 ## Retrieve COMPONENT_TYPE
370 @cached_property
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
377
378 ## Retrieve "BUILD_TYPE"
379 @cached_property
380 def BuildType(self):
381 if self._BuildType is None:
382 self._GetHeaderInfo()
383 if not self._BuildType:
384 self._BuildType = SUP_MODULE_BASE
385 return self._BuildType
386
387 ## Retrieve file guid
388 @cached_property
389 def Guid(self):
390 if self._Guid is None:
391 self._GetHeaderInfo()
392 if self._Guid is None:
393 self._Guid = '00000000-0000-0000-0000-000000000000'
394 return self._Guid
395
396 ## Retrieve module version
397 @cached_property
398 def Version(self):
399 if self._Version is None:
400 self._GetHeaderInfo()
401 if self._Version is None:
402 self._Version = '0.0'
403 return self._Version
404
405 ## Retrieve PCD_IS_DRIVER
406 @cached_property
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
413
414 ## Retrieve SHADOW
415 @cached_property
416 def Shadow(self):
417 if self._Shadow is None:
418 self._GetHeaderInfo()
419 if self._Shadow and self._Shadow.upper() == 'TRUE':
420 self._Shadow = True
421 else:
422 self._Shadow = False
423 return self._Shadow
424
425 ## Retrieve CUSTOM_MAKEFILE
426 @cached_property
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
433
434 ## Retrieve EFI_SPECIFICATION_VERSION
435 @cached_property
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
442
443 ## Retrieve LIBRARY_CLASS
444 @cached_property
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
451
452 ## Retrieve ENTRY_POINT
453 @cached_property
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
460
461 ## Retrieve UNLOAD_IMAGE
462 @cached_property
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
469
470 ## Retrieve CONSTRUCTOR
471 @cached_property
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
478
479 ## Retrieve DESTRUCTOR
480 @cached_property
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
487
488 ## Retrieve definies other than above ones
489 @cached_property
490 def Defines(self):
491 self._GetHeaderInfo()
492 return self._Defs
493
494 ## Retrieve binary files
495 @cached_class_function
496 def _GetBinaries(self):
497 RetVal = []
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:
502 FileType = Record[0]
503 LineNo = Record[-1]
504 Target = TAB_COMMON
505 FeatureFlag = []
506 if Record[2]:
507 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
508 if TokenList:
509 Target = TokenList[0]
510 if len(TokenList) > 1:
511 FeatureFlag = Record[1:]
512
513 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
514 # check the file validation
515 ErrorCode, ErrorInfo = File.Validate()
516 if ErrorCode != 0:
517 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
518 RetVal.append(File)
519 return RetVal
520
521 ## Retrieve binary files with error check.
522 @cached_property
523 def Binaries(self):
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)
528
529 return RetVal
530
531 ## Retrieve source files
532 @cached_property
533 def Sources(self):
534 self._GetHeaderInfo()
535 # Ignore all source files in a binary build mode
536 if GlobalData.gIgnoreSource:
537 return []
538
539 RetVal = []
540 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
541 Macros = self._Macros
542 for Record in RecordList:
543 LineNo = Record[-1]
544 ToolChainFamily = Record[1]
545 TagName = Record[2]
546 ToolCode = Record[3]
547
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()
552 if ErrorCode != 0:
553 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
554
555 RetVal.append(File)
556 # add any previously found dependency files to the source list
557 if self._DependencyFileList:
558 RetVal.extend(self._DependencyFileList)
559 return RetVal
560
561 ## Retrieve library classes employed by this module
562 @cached_property
563 def LibraryClasses(self):
564 RetVal = OrderedDict()
565 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
566 for Record in RecordList:
567 Lib = Record[0]
568 Instance = Record[1]
569 if Instance:
570 Instance = NormPath(Instance, self._Macros)
571 RetVal[Lib] = Instance
572 else:
573 RetVal[Lib] = None
574 return RetVal
575
576 ## Retrieve library names (for Edk.x style of modules)
577 @cached_property
578 def Libraries(self):
579 RetVal = []
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)
587 return RetVal
588
589 @cached_property
590 def ProtocolComments(self):
591 self.Protocols
592 return self._ProtocolComments
593
594 ## Retrieve protocols consumed/produced by this module
595 @cached_property
596 def Protocols(self):
597 RetVal = OrderedDict()
598 self._ProtocolComments = OrderedDict()
599 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
600 for Record in RecordList:
601 CName = Record[0]
602 Value = _ProtocolValue(CName, self.Packages, self.MetaFile.Path)
603 if Value is None:
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]
611 return RetVal
612
613 @cached_property
614 def PpiComments(self):
615 self.Ppis
616 return self._PpiComments
617
618 ## Retrieve PPIs consumed/produced by this module
619 @cached_property
620 def Ppis(self):
621 RetVal = OrderedDict()
622 self._PpiComments = OrderedDict()
623 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
624 for Record in RecordList:
625 CName = Record[0]
626 Value = _PpiValue(CName, self.Packages, self.MetaFile.Path)
627 if Value is None:
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]
635 return RetVal
636
637 @cached_property
638 def GuidComments(self):
639 self.Guids
640 return self._GuidComments
641
642 ## Retrieve GUIDs consumed/produced by this module
643 @cached_property
644 def Guids(self):
645 RetVal = OrderedDict()
646 self._GuidComments = OrderedDict()
647 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
648 for Record in RecordList:
649 CName = Record[0]
650 Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
651 if Value is None:
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]
659 return RetVal
660
661 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
662 @cached_property
663 def Includes(self):
664 RetVal = []
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)
670 if File[0] == '.':
671 File = os.path.join(self._ModuleDir, File)
672 else:
673 File = mws.join(GlobalData.gWorkspace, File)
674 File = RealPath(os.path.normpath(File))
675 if File:
676 RetVal.append(File)
677 return RetVal
678
679 ## Retrieve packages this module depends on
680 @cached_property
681 def Packages(self):
682 RetVal = []
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')
689 if ErrorCode != 0:
690 LineNo = Record[-1]
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])
694 return RetVal
695
696 ## Retrieve PCD comments
697 @cached_property
698 def PcdComments(self):
699 self.Pcds
700 return self._PcdComments
701
702 ## Retrieve PCDs used in this module
703 @cached_property
704 def Pcds(self):
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))
712 return RetVal
713
714 @cached_property
715 def ModulePcdList(self):
716 RetVal = self.Pcds
717 return RetVal
718 @cached_property
719 def LibraryPcdList(self):
720 if bool(self.LibraryClass):
721 return []
722 RetVal = {}
723 Pcds = set()
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:
728 continue
729 Pcds.add(Key)
730 PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
731 RetVal[Library] = PcdsInLibrary
732 return RetVal
733 @cached_property
734 def PcdsName(self):
735 PcdsName = set()
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))
740 return PcdsName
741
742 ## Retrieve build options specific to this module
743 @cached_property
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]
751 Option = Record[2]
752 if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='):
753 self._BuildOptions[ToolChainFamily, ToolChain] = Option
754 else:
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
759
760 ## Retrieve dependency expression
761 @cached_property
762 def Depex(self):
763 RetVal = tdict(False, 2)
764
765 # If the module has only Binaries and no Sources, then ignore [Depex]
766 if not self.Sources and self.Binaries:
767 return RetVal
768
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)
776
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,
782 File=self.MetaFile)
783
784 TemporaryDictionary = OrderedDict()
785 for Record in RecordList:
786 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
787 Arch = Record[3]
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]
799 if Module is None:
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)
803 else:
804 # it use the Fixed PCD format
805 if '.' in Token:
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])
808 else:
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])
811 Value = Token
812 else:
813 # get the GUID value now
814 Value = _ProtocolValue(Token, self.Packages, self.MetaFile.Path)
815 if Value is None:
816 Value = _PpiValue(Token, self.Packages, self.MetaFile.Path)
817 if Value is None:
818 Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
819
820 if Value is None:
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]
828 return RetVal
829
830 ## Retrieve dependency expression
831 @cached_property
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)
838 Arch = Record[3]
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]
847 return RetVal
848 def LocalPkg(self):
849 module_path = self.MetaFile.File
850 subdir = os.path.split(module_path)[0]
851 TopDir = ""
852 while subdir:
853 subdir,TopDir = os.path.split(subdir)
854
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)
858 return pkg
859 @cached_class_function
860 def GetGuidsUsedByPcd(self):
861 self.Pcds
862 return self._GuidsUsedByPcd
863
864 ## Retrieve PCD for given type
865 def _GetPcd(self, Type):
866 Pcds = OrderedDict()
867 PcdDict = tdict(True, 4)
868 PcdList = []
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))
873 # get the guid value
874 if TokenSpaceGuid not in self.Guids:
875 Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path)
876 if Value is None:
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]
884 Comments = []
885 for CmtRec in CommentRecords:
886 Comments.append(CmtRec[0])
887 self._PcdComments[TokenSpaceGuid, PcdCName] = Comments
888
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]
894 if Setting is None:
895 continue
896 ValueList = AnalyzePcdData(Setting)
897 DefaultValue = ValueList[0]
898 Pcd = PcdClassObject(
899 PcdCName,
900 TokenSpaceGuid,
901 '',
902 '',
903 DefaultValue,
904 '',
905 '',
906 {},
907 False,
908 self.Guids[TokenSpaceGuid]
909 )
910 if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]:
911 # Patch PCD: TokenSpace.PcdCName|Value|Offset
912 Pcd.Offset = ValueList[1]
913
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
923 if len(key) == 2:
924 newkey = (Value.TokenCName, key[1])
925 elif len(key) == 3:
926 newkey = (Value.TokenCName, key[1], key[2])
927 del Package.Pcds[key]
928 Package.Pcds[newkey] = Value
929 break
930 else:
931 pass
932 else:
933 pass
934
935 # get necessary info from package declaring this PCD
936 for Package in self.Packages:
937 #
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
941 #
942 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
943 #
944 _GuidDict.update(Package.Guids)
945 PcdType = self._PCD_TYPE_STRING_[Type]
946 if Type == MODEL_PCD_DYNAMIC:
947 Pcd.Pending = True
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:
952 PcdType = T
953 PcdCName = item[0]
954 break
955 else:
956 pass
957 break
958 else:
959 if (PcdRealName, TokenSpaceGuid, T) in Package.Pcds:
960 PcdType = T
961 break
962
963 else:
964 Pcd.Pending = False
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:
969 PcdCName = item[0]
970 break
971 else:
972 pass
973 else:
974 pass
975
976 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
977 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
978 Pcd.Type = PcdType
979 Pcd.TokenValue = PcdInPackage.TokenValue
980
981 #
982 # Check whether the token value exist or not.
983 #
984 if Pcd.TokenValue is None or Pcd.TokenValue == "":
985 EdkLogger.error(
986 'build',
987 FORMAT_INVALID,
988 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdRealName, str(Package)),
989 File=self.MetaFile, Line=LineNo,
990 ExtraData=None
991 )
992 #
993 # Check hexadecimal token value length and format.
994 #
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:
998 EdkLogger.error(
999 'build',
1000 FORMAT_INVALID,
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,
1003 ExtraData=None
1004 )
1005
1006 #
1007 # Check decimal token value length and format.
1008 #
1009 else:
1010 try:
1011 TokenValueInt = int (Pcd.TokenValue, 10)
1012 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
1013 EdkLogger.error(
1014 'build',
1015 FORMAT_INVALID,
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,
1018 ExtraData=None
1019 )
1020 except:
1021 EdkLogger.error(
1022 'build',
1023 FORMAT_INVALID,
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,
1026 ExtraData=None
1027 )
1028
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
1034 else:
1035 try:
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)
1040 break
1041 else:
1042 EdkLogger.error(
1043 'build',
1044 FORMAT_INVALID,
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)
1048 )
1049 Pcds[PcdCName, TokenSpaceGuid] = Pcd
1050
1051 return Pcds
1052
1053 ## check whether current module is binary module
1054 @property
1055 def IsBinaryModule(self):
1056 if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
1057 return True
1058 return False
1059 def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
1060 for Key in CopyFromDict:
1061 CopyToDict[Key].extend(CopyFromDict[Key])