]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/InfBuildData.py
BaseTools: Fixed regression issue for building !x86 builds
[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
160 def SetReferenceModule(self,Module):
161 self.ReferenceModules.add(Module)
162 return self
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
659 for Type in [MODEL_PCD_FIXED_AT_BUILD,MODEL_PCD_PATCHABLE_IN_MODULE,MODEL_PCD_FEATURE_FLAG,MODEL_PCD_DYNAMIC,MODEL_PCD_DYNAMIC_EX]:
660 RecordList = self._RawData[Type, self._Arch, self._Platform]
661 for TokenSpaceGuid, _, _, _, _, _, LineNo in RecordList:
662 # get the guid value
663 if TokenSpaceGuid not in RetVal:
664 Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path)
665 if Value is None:
666 PackageList = "\n\t".join(str(P) for P in self.Packages)
667 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
668 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
669 ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
670 RetVal[TokenSpaceGuid] = Value
671 self._GuidsUsedByPcd[TokenSpaceGuid] = Value
672 return RetVal
673
674 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
675 @cached_property
676 def Includes(self):
677 RetVal = []
678 Macros = self._Macros
679 Macros['PROCESSOR'] = GlobalData.gEdkGlobal.get('PROCESSOR', self._Arch)
680 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
681 for Record in RecordList:
682 File = NormPath(Record[0], Macros)
683 if File[0] == '.':
684 File = os.path.join(self._ModuleDir, File)
685 else:
686 File = mws.join(GlobalData.gWorkspace, File)
687 File = RealPath(os.path.normpath(File))
688 if File:
689 RetVal.append(File)
690 return RetVal
691
692 ## Retrieve packages this module depends on
693 @cached_property
694 def Packages(self):
695 RetVal = []
696 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
697 Macros = self._Macros
698 for Record in RecordList:
699 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
700 # check the file validation
701 ErrorCode, ErrorInfo = File.Validate('.dec')
702 if ErrorCode != 0:
703 LineNo = Record[-1]
704 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
705 # parse this package now. we need it to get protocol/ppi/guid value
706 RetVal.append(self._Bdb[File, self._Arch, self._Target, self._Toolchain])
707 return RetVal
708
709 ## Retrieve PCD comments
710 @cached_property
711 def PcdComments(self):
712 self.Pcds
713 return self._PcdComments
714
715 ## Retrieve PCDs used in this module
716 @cached_property
717 def Pcds(self):
718 self._PcdComments = OrderedDict()
719 RetVal = OrderedDict()
720 RetVal.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
721 RetVal.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
722 RetVal.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
723 RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC))
724 RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
725 return RetVal
726
727 @cached_property
728 def ModulePcdList(self):
729 RetVal = self.Pcds
730 return RetVal
731 @cached_property
732 def LibraryPcdList(self):
733 if bool(self.LibraryClass):
734 return []
735 RetVal = {}
736 Pcds = set()
737 for Library in self.LibInstances:
738 PcdsInLibrary = OrderedDict()
739 for Key in Library.Pcds:
740 if Key in self.Pcds or Key in Pcds:
741 continue
742 Pcds.add(Key)
743 PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
744 RetVal[Library] = PcdsInLibrary
745 return RetVal
746 @cached_property
747 def PcdsName(self):
748 PcdsName = set()
749 for Type in (MODEL_PCD_FIXED_AT_BUILD,MODEL_PCD_PATCHABLE_IN_MODULE,MODEL_PCD_FEATURE_FLAG,MODEL_PCD_DYNAMIC,MODEL_PCD_DYNAMIC_EX):
750 RecordList = self._RawData[Type, self._Arch, self._Platform]
751 for TokenSpaceGuid, PcdCName, _, _, _, _, _ in RecordList:
752 PcdsName.add((PcdCName, TokenSpaceGuid))
753 return PcdsName
754
755 ## Retrieve build options specific to this module
756 @cached_property
757 def BuildOptions(self):
758 if self._BuildOptions is None:
759 self._BuildOptions = OrderedDict()
760 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
761 for Record in RecordList:
762 ToolChainFamily = Record[0]
763 ToolChain = Record[1]
764 Option = Record[2]
765 if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='):
766 self._BuildOptions[ToolChainFamily, ToolChain] = Option
767 else:
768 # concatenate the option string if they're for the same tool
769 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
770 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
771 return self._BuildOptions
772
773 ## Retrieve dependency expression
774 @cached_property
775 def Depex(self):
776 RetVal = tdict(False, 2)
777
778 # If the module has only Binaries and no Sources, then ignore [Depex]
779 if not self.Sources and self.Binaries:
780 return RetVal
781
782 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
783 # PEIM and DXE drivers must have a valid [Depex] section
784 if len(self.LibraryClass) == 0 and len(RecordList) == 0:
785 if self.ModuleType == SUP_MODULE_DXE_DRIVER or self.ModuleType == SUP_MODULE_PEIM or self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER or \
786 self.ModuleType == SUP_MODULE_DXE_SAL_DRIVER or self.ModuleType == SUP_MODULE_DXE_RUNTIME_DRIVER:
787 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
788 % self.ModuleType, File=self.MetaFile)
789
790 if len(RecordList) != 0 and (self.ModuleType == SUP_MODULE_USER_DEFINED or self.ModuleType == SUP_MODULE_HOST_APPLICATION):
791 for Record in RecordList:
792 if Record[4] not in [SUP_MODULE_PEIM, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_SMM_DRIVER]:
793 EdkLogger.error('build', FORMAT_INVALID,
794 "'%s' module must specify the type of [Depex] section" % self.ModuleType,
795 File=self.MetaFile)
796
797 TemporaryDictionary = OrderedDict()
798 for Record in RecordList:
799 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
800 Arch = Record[3]
801 ModuleType = Record[4]
802 TokenList = DepexStr.split()
803 if (Arch, ModuleType) not in TemporaryDictionary:
804 TemporaryDictionary[Arch, ModuleType] = []
805 DepexList = TemporaryDictionary[Arch, ModuleType]
806 for Token in TokenList:
807 if Token in DEPEX_SUPPORTED_OPCODE_SET:
808 DepexList.append(Token)
809 elif Token.endswith(".inf"): # module file name
810 ModuleFile = os.path.normpath(Token)
811 Module = self.BuildDatabase[ModuleFile]
812 if Module is None:
813 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
814 ExtraData=Token, File=self.MetaFile, Line=Record[-1])
815 DepexList.append(Module.Guid)
816 else:
817 # it use the Fixed PCD format
818 if '.' in Token:
819 if tuple(Token.split('.')[::-1]) not in self.Pcds:
820 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])
821 else:
822 if self.Pcds[tuple(Token.split('.')[::-1])].DatumType != TAB_VOID:
823 EdkLogger.error('build', FORMAT_INVALID, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token), File=self.MetaFile, Line=Record[-1])
824 Value = Token
825 else:
826 # get the GUID value now
827 Value = _ProtocolValue(Token, self.Packages, self.MetaFile.Path)
828 if Value is None:
829 Value = _PpiValue(Token, self.Packages, self.MetaFile.Path)
830 if Value is None:
831 Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
832
833 if Value is None:
834 PackageList = "\n\t".join(str(P) for P in self.Packages)
835 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
836 "Value of [%s] is not found in" % Token,
837 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
838 DepexList.append(Value)
839 for Arch, ModuleType in TemporaryDictionary:
840 RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
841 return RetVal
842
843 ## Retrieve dependency expression
844 @cached_property
845 def DepexExpression(self):
846 RetVal = tdict(False, 2)
847 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
848 TemporaryDictionary = OrderedDict()
849 for Record in RecordList:
850 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
851 Arch = Record[3]
852 ModuleType = Record[4]
853 TokenList = DepexStr.split()
854 if (Arch, ModuleType) not in TemporaryDictionary:
855 TemporaryDictionary[Arch, ModuleType] = ''
856 for Token in TokenList:
857 TemporaryDictionary[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType] + Token.strip() + ' '
858 for Arch, ModuleType in TemporaryDictionary:
859 RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
860 return RetVal
861 def LocalPkg(self):
862 module_path = self.MetaFile.File
863 subdir = os.path.split(module_path)[0]
864 TopDir = ""
865 while subdir:
866 subdir,TopDir = os.path.split(subdir)
867
868 for file_name in os.listdir(os.path.join(self.MetaFile.Root,TopDir)):
869 if file_name.upper().endswith("DEC"):
870 pkg = os.path.join(TopDir,file_name)
871 return pkg
872 @cached_class_function
873 def GetGuidsUsedByPcd(self):
874 self.Guid
875 return self._GuidsUsedByPcd
876
877 ## Retrieve PCD for given type
878 def _GetPcd(self, Type):
879 Pcds = OrderedDict()
880 PcdDict = tdict(True, 4)
881 PcdList = []
882 RecordList = self._RawData[Type, self._Arch, self._Platform]
883 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Id, LineNo in RecordList:
884 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
885 PcdList.append((PcdCName, TokenSpaceGuid))
886 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Id]
887 Comments = []
888 for CmtRec in CommentRecords:
889 Comments.append(CmtRec[0])
890 self._PcdComments[TokenSpaceGuid, PcdCName] = Comments
891
892 # resolve PCD type, value, datum info, etc. by getting its definition from package
893 _GuidDict = self.Guids.copy()
894 for PcdCName, TokenSpaceGuid in PcdList:
895 PcdRealName = PcdCName
896 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
897 if Setting is None:
898 continue
899 ValueList = AnalyzePcdData(Setting)
900 DefaultValue = ValueList[0]
901 Pcd = PcdClassObject(
902 PcdCName,
903 TokenSpaceGuid,
904 '',
905 '',
906 DefaultValue,
907 '',
908 '',
909 {},
910 False,
911 self.Guids[TokenSpaceGuid]
912 )
913 if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]:
914 # Patch PCD: TokenSpace.PcdCName|Value|Offset
915 Pcd.Offset = ValueList[1]
916
917 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
918 for Package in self.Packages:
919 for key in Package.Pcds:
920 if (Package.Pcds[key].TokenCName, Package.Pcds[key].TokenSpaceGuidCName) == (PcdRealName, TokenSpaceGuid):
921 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
922 Pcd_Type = item[0].split('_')[-1]
923 if Pcd_Type == Package.Pcds[key].Type:
924 Value = Package.Pcds[key]
925 Value.TokenCName = Package.Pcds[key].TokenCName + '_' + Pcd_Type
926 if len(key) == 2:
927 newkey = (Value.TokenCName, key[1])
928 elif len(key) == 3:
929 newkey = (Value.TokenCName, key[1], key[2])
930 del Package.Pcds[key]
931 Package.Pcds[newkey] = Value
932 break
933 else:
934 pass
935 else:
936 pass
937
938 # get necessary info from package declaring this PCD
939 for Package in self.Packages:
940 #
941 # 'dynamic' in INF means its type is determined by platform;
942 # if platform doesn't give its type, use 'lowest' one in the
943 # following order, if any
944 #
945 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
946 #
947 _GuidDict.update(Package.Guids)
948 PcdType = self._PCD_TYPE_STRING_[Type]
949 if Type == MODEL_PCD_DYNAMIC:
950 Pcd.Pending = True
951 for T in PCD_TYPE_LIST:
952 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
953 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
954 if str(item[0]).endswith(T) and (item[0], item[1], T) in Package.Pcds:
955 PcdType = T
956 PcdCName = item[0]
957 break
958 else:
959 pass
960 break
961 else:
962 if (PcdRealName, TokenSpaceGuid, T) in Package.Pcds:
963 PcdType = T
964 break
965
966 else:
967 Pcd.Pending = False
968 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
969 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
970 Pcd_Type = item[0].split('_')[-1]
971 if Pcd_Type == PcdType:
972 PcdCName = item[0]
973 break
974 else:
975 pass
976 else:
977 pass
978
979 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
980 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
981 Pcd.Type = PcdType
982 Pcd.TokenValue = PcdInPackage.TokenValue
983
984 #
985 # Check whether the token value exist or not.
986 #
987 if Pcd.TokenValue is None or Pcd.TokenValue == "":
988 EdkLogger.error(
989 'build',
990 FORMAT_INVALID,
991 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdRealName, str(Package)),
992 File=self.MetaFile, Line=LineNo,
993 ExtraData=None
994 )
995 #
996 # Check hexadecimal token value length and format.
997 #
998 ReIsValidPcdTokenValue = re.compile(r"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re.DOTALL)
999 if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"):
1000 if ReIsValidPcdTokenValue.match(Pcd.TokenValue) is None:
1001 EdkLogger.error(
1002 'build',
1003 FORMAT_INVALID,
1004 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
1005 File=self.MetaFile, Line=LineNo,
1006 ExtraData=None
1007 )
1008
1009 #
1010 # Check decimal token value length and format.
1011 #
1012 else:
1013 try:
1014 TokenValueInt = int (Pcd.TokenValue, 10)
1015 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
1016 EdkLogger.error(
1017 'build',
1018 FORMAT_INVALID,
1019 "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)),
1020 File=self.MetaFile, Line=LineNo,
1021 ExtraData=None
1022 )
1023 except:
1024 EdkLogger.error(
1025 'build',
1026 FORMAT_INVALID,
1027 "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)),
1028 File=self.MetaFile, Line=LineNo,
1029 ExtraData=None
1030 )
1031
1032 Pcd.DatumType = PcdInPackage.DatumType
1033 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
1034 Pcd.InfDefaultValue = Pcd.DefaultValue
1035 if not Pcd.DefaultValue:
1036 Pcd.DefaultValue = PcdInPackage.DefaultValue
1037 else:
1038 try:
1039 Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, _GuidDict)(True)
1040 except BadExpression as Value:
1041 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid, PcdRealName, Pcd.DefaultValue, Value),
1042 File=self.MetaFile, Line=LineNo)
1043 break
1044 else:
1045 EdkLogger.error(
1046 'build',
1047 FORMAT_INVALID,
1048 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdRealName, self.MetaFile),
1049 File=self.MetaFile, Line=LineNo,
1050 ExtraData="\t%s" % '\n\t'.join(str(P) for P in self.Packages)
1051 )
1052 Pcds[PcdCName, TokenSpaceGuid] = Pcd
1053
1054 return Pcds
1055
1056 ## check whether current module is binary module
1057 @property
1058 def IsBinaryModule(self):
1059 if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
1060 return True
1061 return False
1062 def ExtendCopyDictionaryLists(CopyToDict, CopyFromDict):
1063 for Key in CopyFromDict:
1064 CopyToDict[Key].extend(CopyFromDict[Key])