]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/InfBuildData.py
9fed1198fd9b9213fffb6ada538c989649978dae
[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 # 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
10 #
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.
13 #
14
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
19 from types import *
20 from .MetaFileParser import *
21 from collections import OrderedDict
22 from Workspace.BuildClassObject import ModuleBuildClassObject, LibraryClassObject, PcdClassObject
23
24 ## Get Protocol value from given packages
25 #
26 # @param CName The CName of the GUID
27 # @param PackageList List of packages looking-up in
28 # @param Inffile The driver file
29 #
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
32 #
33 def _ProtocolValue(CName, PackageList, Inffile = None):
34 for P in PackageList:
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]
41 return None
42
43 ## Get PPI value from given packages
44 #
45 # @param CName The CName of the GUID
46 # @param PackageList List of packages looking-up in
47 # @param Inffile The driver file
48 #
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
51 #
52 def _PpiValue(CName, PackageList, Inffile = None):
53 for P in PackageList:
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]
58 if CName in PpiKeys:
59 return P.Ppis[CName]
60 return None
61
62 ## Module build information from INF file
63 #
64 # This class is used to retrieve information stored in database and convert them
65 # into ModuleBuildClassObject form for easier use for AutoGen.
66 #
67 class InfBuildData(ModuleBuildClassObject):
68 # dict used to convert PCD type in database to string used by build tool
69 _PCD_TYPE_STRING_ = {
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,
81 }
82
83 # dict used to convert part of [Defines] to members of InfBuildData directly
84 _PROPERTY_ = {
85 #
86 # Required Fields
87 #
88 TAB_INF_DEFINES_BASE_NAME : "_BaseName",
89 TAB_INF_DEFINES_FILE_GUID : "_Guid",
90 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
91 #
92 # Optional Fields
93 #
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"
104 }
105
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
109 _TOOL_CODE_ = {
110 "C" : "CC",
111 BINARY_FILE_TYPE_LIB : "SLINK",
112 "LINK" : "DLINK",
113 }
114
115
116 ## Constructor of InfBuildData
117 #
118 # Initialize object of InfBuildData
119 #
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
126 #
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
132 self._Arch = Arch
133 self._Target = Target
134 self._Toolchain = Toolchain
135 self._Platform = TAB_COMMON
136 self._TailComments = None
137 self._BaseName = None
138 self._DxsFile = None
139 self._ModuleType = None
140 self._ComponentType = None
141 self._BuildType = None
142 self._Guid = None
143 self._Version = None
144 self._PcdIsDriver = None
145 self._BinaryModule = None
146 self._Shadow = 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
163
164 ## XXX[key] = value
165 def __setitem__(self, key, value):
166 self.__dict__[self._PROPERTY_[key]] = value
167
168 ## value = XXX[key]
169 def __getitem__(self, key):
170 return self.__dict__[self._PROPERTY_[key]]
171
172 ## "in" test support
173 def __contains__(self, key):
174 return key in self._PROPERTY_
175
176 ## Get current effective macros
177 @cached_property
178 def _Macros(self):
179 RetVal = {}
180 return RetVal
181
182 ## Get architecture
183 @cached_property
184 def Arch(self):
185 return self._Arch
186
187 ## Return the name of platform employing this module
188 @cached_property
189 def Platform(self):
190 return self._Platform
191
192 @cached_property
193 def HeaderComments(self):
194 return [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
195
196 @cached_property
197 def TailComments(self):
198 return [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
199
200 ## Retrieve all information in [Defines] section
201 #
202 # (Retrieving all [Defines] information in one-shot is just to save time.)
203 #
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
210 if Name in self:
211 self[Name] = Value
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], ' ')
232 else:
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 = []
242 if not Value:
243 continue
244 self._ModuleUnloadImageList.append(Value)
245 elif Name == 'CONSTRUCTOR':
246 if self._ConstructorList is None:
247 self._ConstructorList = []
248 if not Value:
249 continue
250 self._ConstructorList.append(Value)
251 elif Name == 'DESTRUCTOR':
252 if self._DestructorList is None:
253 self._DestructorList = []
254 if not Value:
255 continue
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]
264 else:
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]
270 else:
271 self._Defs[Name] = Value
272 self._Macros[Name] = Value
273
274 #
275 # Retrieve information in sections specific to Edk.x modules
276 #
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:
283 Name = Record[1]
284 if Name == "MODULE_TYPE":
285 LineNo = Record[6]
286 break
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)
304
305 elif 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
306 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
307 self._BuildType = 'UEFI_HII'
308 else:
309 self._BuildType = self._ModuleType.upper()
310
311 if self._DxsFile:
312 File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch)
313 # check the file validation
314 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
315 if ErrorCode != 0:
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)
321
322 ## Retrieve file version
323 @cached_property
324 def AutoGenVersion(self):
325 RetVal = 0x00010000
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:
329 if '.' in Record[2]:
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)
334 else:
335 RetVal = int(Record[2], 0)
336 break
337 return RetVal
338
339 ## Retrieve BASE_NAME
340 @cached_property
341 def BaseName(self):
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
347
348 ## Retrieve DxsFile
349 @cached_property
350 def DxsFile(self):
351 if self._DxsFile is None:
352 self._GetHeaderInfo()
353 if self._DxsFile is None:
354 self._DxsFile = ''
355 return self._DxsFile
356
357 ## Retrieve MODULE_TYPE
358 @cached_property
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
367
368 ## Retrieve COMPONENT_TYPE
369 @cached_property
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
376
377 ## Retrieve "BUILD_TYPE"
378 @cached_property
379 def BuildType(self):
380 if self._BuildType is None:
381 self._GetHeaderInfo()
382 if not self._BuildType:
383 self._BuildType = SUP_MODULE_BASE
384 return self._BuildType
385
386 ## Retrieve file guid
387 @cached_property
388 def Guid(self):
389 if self._Guid is None:
390 self._GetHeaderInfo()
391 if self._Guid is None:
392 self._Guid = '00000000-0000-0000-0000-000000000000'
393 return self._Guid
394
395 ## Retrieve module version
396 @cached_property
397 def Version(self):
398 if self._Version is None:
399 self._GetHeaderInfo()
400 if self._Version is None:
401 self._Version = '0.0'
402 return self._Version
403
404 ## Retrieve PCD_IS_DRIVER
405 @cached_property
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
412
413 ## Retrieve SHADOW
414 @cached_property
415 def Shadow(self):
416 if self._Shadow is None:
417 self._GetHeaderInfo()
418 if self._Shadow and self._Shadow.upper() == 'TRUE':
419 self._Shadow = True
420 else:
421 self._Shadow = False
422 return self._Shadow
423
424 ## Retrieve CUSTOM_MAKEFILE
425 @cached_property
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
432
433 ## Retrieve EFI_SPECIFICATION_VERSION
434 @cached_property
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
441
442 ## Retrieve LIBRARY_CLASS
443 @cached_property
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
450
451 ## Retrieve ENTRY_POINT
452 @cached_property
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
459
460 ## Retrieve UNLOAD_IMAGE
461 @cached_property
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
468
469 ## Retrieve CONSTRUCTOR
470 @cached_property
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
477
478 ## Retrieve DESTRUCTOR
479 @cached_property
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
486
487 ## Retrieve definies other than above ones
488 @cached_property
489 def Defines(self):
490 self._GetHeaderInfo()
491 return self._Defs
492
493 ## Retrieve binary files
494 @cached_class_function
495 def _GetBinaries(self):
496 RetVal = []
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:
501 FileType = Record[0]
502 LineNo = Record[-1]
503 Target = TAB_COMMON
504 FeatureFlag = []
505 if Record[2]:
506 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
507 if TokenList:
508 Target = TokenList[0]
509 if len(TokenList) > 1:
510 FeatureFlag = Record[1:]
511
512 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
513 # check the file validation
514 ErrorCode, ErrorInfo = File.Validate()
515 if ErrorCode != 0:
516 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
517 RetVal.append(File)
518 return RetVal
519
520 ## Retrieve binary files with error check.
521 @cached_property
522 def Binaries(self):
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)
527
528 return RetVal
529
530 ## Retrieve source files
531 @cached_property
532 def Sources(self):
533 self._GetHeaderInfo()
534 # Ignore all source files in a binary build mode
535 if GlobalData.gIgnoreSource:
536 return []
537
538 RetVal = []
539 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
540 Macros = self._Macros
541 for Record in RecordList:
542 LineNo = Record[-1]
543 ToolChainFamily = Record[1]
544 TagName = Record[2]
545 ToolCode = Record[3]
546
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()
551 if ErrorCode != 0:
552 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
553
554 RetVal.append(File)
555 # add any previously found dependency files to the source list
556 if self._DependencyFileList:
557 RetVal.extend(self._DependencyFileList)
558 return RetVal
559
560 ## Retrieve library classes employed by this module
561 @cached_property
562 def LibraryClasses(self):
563 RetVal = OrderedDict()
564 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
565 for Record in RecordList:
566 Lib = Record[0]
567 Instance = Record[1]
568 if Instance:
569 Instance = NormPath(Instance, self._Macros)
570 RetVal[Lib] = Instance
571 else:
572 RetVal[Lib] = None
573 return RetVal
574
575 ## Retrieve library names (for Edk.x style of modules)
576 @cached_property
577 def Libraries(self):
578 RetVal = []
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)
586 return RetVal
587
588 @cached_property
589 def ProtocolComments(self):
590 self.Protocols
591 return self._ProtocolComments
592
593 ## Retrieve protocols consumed/produced by this module
594 @cached_property
595 def Protocols(self):
596 RetVal = OrderedDict()
597 self._ProtocolComments = OrderedDict()
598 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
599 for Record in RecordList:
600 CName = Record[0]
601 Value = _ProtocolValue(CName, self.Packages, self.MetaFile.Path)
602 if Value is None:
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]
610 return RetVal
611
612 @cached_property
613 def PpiComments(self):
614 self.Ppis
615 return self._PpiComments
616
617 ## Retrieve PPIs consumed/produced by this module
618 @cached_property
619 def Ppis(self):
620 RetVal = OrderedDict()
621 self._PpiComments = OrderedDict()
622 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
623 for Record in RecordList:
624 CName = Record[0]
625 Value = _PpiValue(CName, self.Packages, self.MetaFile.Path)
626 if Value is None:
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]
634 return RetVal
635
636 @cached_property
637 def GuidComments(self):
638 self.Guids
639 return self._GuidComments
640
641 ## Retrieve GUIDs consumed/produced by this module
642 @cached_property
643 def Guids(self):
644 RetVal = OrderedDict()
645 self._GuidComments = OrderedDict()
646 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
647 for Record in RecordList:
648 CName = Record[0]
649 Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
650 if Value is None:
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]
658 return RetVal
659
660 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
661 @cached_property
662 def Includes(self):
663 RetVal = []
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)
669 if File[0] == '.':
670 File = os.path.join(self._ModuleDir, File)
671 else:
672 File = mws.join(GlobalData.gWorkspace, File)
673 File = RealPath(os.path.normpath(File))
674 if File:
675 RetVal.append(File)
676 return RetVal
677
678 ## Retrieve packages this module depends on
679 @cached_property
680 def Packages(self):
681 RetVal = []
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')
688 if ErrorCode != 0:
689 LineNo = Record[-1]
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])
693 return RetVal
694
695 ## Retrieve PCD comments
696 @cached_property
697 def PcdComments(self):
698 self.Pcds
699 return self._PcdComments
700
701 ## Retrieve PCDs used in this module
702 @cached_property
703 def Pcds(self):
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))
711 return RetVal
712
713 @cached_property
714 def PcdsName(self):
715 PcdsName = set()
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))
720 return PcdsName
721
722 ## Retrieve build options specific to this module
723 @cached_property
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]
731 Option = Record[2]
732 if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='):
733 self._BuildOptions[ToolChainFamily, ToolChain] = Option
734 else:
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
739
740 ## Retrieve dependency expression
741 @cached_property
742 def Depex(self):
743 RetVal = tdict(False, 2)
744
745 # If the module has only Binaries and no Sources, then ignore [Depex]
746 if not self.Sources and self.Binaries:
747 return RetVal
748
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)
756
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,
762 File=self.MetaFile)
763
764 TemporaryDictionary = OrderedDict()
765 for Record in RecordList:
766 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
767 Arch = Record[3]
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]
779 if Module is None:
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)
783 else:
784 # it use the Fixed PCD format
785 if '.' in Token:
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])
788 else:
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])
791 Value = Token
792 else:
793 # get the GUID value now
794 Value = _ProtocolValue(Token, self.Packages, self.MetaFile.Path)
795 if Value is None:
796 Value = _PpiValue(Token, self.Packages, self.MetaFile.Path)
797 if Value is None:
798 Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
799
800 if Value is None:
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]
808 return RetVal
809
810 ## Retrieve dependency expression
811 @cached_property
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)
818 Arch = Record[3]
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]
827 return RetVal
828
829 @cached_class_function
830 def GetGuidsUsedByPcd(self):
831 self.Pcds
832 return self._GuidsUsedByPcd
833
834 ## Retrieve PCD for given type
835 def _GetPcd(self, Type):
836 Pcds = OrderedDict()
837 PcdDict = tdict(True, 4)
838 PcdList = []
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))
843 # get the guid value
844 if TokenSpaceGuid not in self.Guids:
845 Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path)
846 if Value is None:
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]
854 Comments = []
855 for CmtRec in CommentRecords:
856 Comments.append(CmtRec[0])
857 self._PcdComments[TokenSpaceGuid, PcdCName] = Comments
858
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]
864 if Setting is None:
865 continue
866 ValueList = AnalyzePcdData(Setting)
867 DefaultValue = ValueList[0]
868 Pcd = PcdClassObject(
869 PcdCName,
870 TokenSpaceGuid,
871 '',
872 '',
873 DefaultValue,
874 '',
875 '',
876 {},
877 False,
878 self.Guids[TokenSpaceGuid]
879 )
880 if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]:
881 # Patch PCD: TokenSpace.PcdCName|Value|Offset
882 Pcd.Offset = ValueList[1]
883
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
893 if len(key) == 2:
894 newkey = (Value.TokenCName, key[1])
895 elif len(key) == 3:
896 newkey = (Value.TokenCName, key[1], key[2])
897 del Package.Pcds[key]
898 Package.Pcds[newkey] = Value
899 break
900 else:
901 pass
902 else:
903 pass
904
905 # get necessary info from package declaring this PCD
906 for Package in self.Packages:
907 #
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
911 #
912 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
913 #
914 _GuidDict.update(Package.Guids)
915 PcdType = self._PCD_TYPE_STRING_[Type]
916 if Type == MODEL_PCD_DYNAMIC:
917 Pcd.Pending = True
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:
922 PcdType = T
923 PcdCName = item[0]
924 break
925 else:
926 pass
927 break
928 else:
929 if (PcdRealName, TokenSpaceGuid, T) in Package.Pcds:
930 PcdType = T
931 break
932
933 else:
934 Pcd.Pending = False
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:
939 PcdCName = item[0]
940 break
941 else:
942 pass
943 else:
944 pass
945
946 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
947 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
948 Pcd.Type = PcdType
949 Pcd.TokenValue = PcdInPackage.TokenValue
950
951 #
952 # Check whether the token value exist or not.
953 #
954 if Pcd.TokenValue is None or Pcd.TokenValue == "":
955 EdkLogger.error(
956 'build',
957 FORMAT_INVALID,
958 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdRealName, str(Package)),
959 File=self.MetaFile, Line=LineNo,
960 ExtraData=None
961 )
962 #
963 # Check hexadecimal token value length and format.
964 #
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:
968 EdkLogger.error(
969 'build',
970 FORMAT_INVALID,
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,
973 ExtraData=None
974 )
975
976 #
977 # Check decimal token value length and format.
978 #
979 else:
980 try:
981 TokenValueInt = int (Pcd.TokenValue, 10)
982 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
983 EdkLogger.error(
984 'build',
985 FORMAT_INVALID,
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,
988 ExtraData=None
989 )
990 except:
991 EdkLogger.error(
992 'build',
993 FORMAT_INVALID,
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,
996 ExtraData=None
997 )
998
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
1004 else:
1005 try:
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)
1010 break
1011 else:
1012 EdkLogger.error(
1013 'build',
1014 FORMAT_INVALID,
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)
1018 )
1019 Pcds[PcdCName, TokenSpaceGuid] = Pcd
1020
1021 return Pcds
1022
1023 ## check whether current module is binary module
1024 @property
1025 def IsBinaryModule(self):
1026 if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
1027 return True
1028 return False