]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/InfBuildData.py
BaseTools: Remove unused logic for EDKI
[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 ## Module build information from INF file
25 #
26 # This class is used to retrieve information stored in database and convert them
27 # into ModuleBuildClassObject form for easier use for AutoGen.
28 #
29 class InfBuildData(ModuleBuildClassObject):
30 # dict used to convert PCD type in database to string used by build tool
31 _PCD_TYPE_STRING_ = {
32 MODEL_PCD_FIXED_AT_BUILD : TAB_PCDS_FIXED_AT_BUILD,
33 MODEL_PCD_PATCHABLE_IN_MODULE : TAB_PCDS_PATCHABLE_IN_MODULE,
34 MODEL_PCD_FEATURE_FLAG : TAB_PCDS_FEATURE_FLAG,
35 MODEL_PCD_DYNAMIC : TAB_PCDS_DYNAMIC,
36 MODEL_PCD_DYNAMIC_DEFAULT : TAB_PCDS_DYNAMIC,
37 MODEL_PCD_DYNAMIC_HII : TAB_PCDS_DYNAMIC_HII,
38 MODEL_PCD_DYNAMIC_VPD : TAB_PCDS_DYNAMIC_VPD,
39 MODEL_PCD_DYNAMIC_EX : TAB_PCDS_DYNAMIC_EX,
40 MODEL_PCD_DYNAMIC_EX_DEFAULT : TAB_PCDS_DYNAMIC_EX,
41 MODEL_PCD_DYNAMIC_EX_HII : TAB_PCDS_DYNAMIC_EX_HII,
42 MODEL_PCD_DYNAMIC_EX_VPD : TAB_PCDS_DYNAMIC_EX_VPD,
43 }
44
45 # dict used to convert part of [Defines] to members of InfBuildData directly
46 _PROPERTY_ = {
47 #
48 # Required Fields
49 #
50 TAB_INF_DEFINES_BASE_NAME : "_BaseName",
51 TAB_INF_DEFINES_FILE_GUID : "_Guid",
52 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
53 #
54 # Optional Fields
55 #
56 # TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
57 TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType",
58 TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName",
59 # TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
60 TAB_INF_DEFINES_DPX_SOURCE :"_DxsFile",
61 TAB_INF_DEFINES_VERSION_NUMBER : "_Version",
62 TAB_INF_DEFINES_VERSION_STRING : "_Version",
63 TAB_INF_DEFINES_VERSION : "_Version",
64 TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver",
65 TAB_INF_DEFINES_SHADOW : "_Shadow",
66
67 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH : "_SourceOverridePath",
68 }
69
70 # regular expression for converting XXX_FLAGS in [nmake] section to new type
71 _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE)
72 # dict used to convert old tool name used in [nmake] section to new ones
73 _TOOL_CODE_ = {
74 "C" : "CC",
75 BINARY_FILE_TYPE_LIB : "SLINK",
76 "LINK" : "DLINK",
77 }
78
79
80 ## Constructor of InfBuildData
81 #
82 # Initialize object of InfBuildData
83 #
84 # @param FilePath The path of platform description file
85 # @param RawData The raw data of DSC file
86 # @param BuildDataBase Database used to retrieve module/package information
87 # @param Arch The target architecture
88 # @param Platform The name of platform employing this module
89 # @param Macros Macros used for replacement in DSC file
90 #
91 def __init__(self, FilePath, RawData, BuildDatabase, Arch=TAB_ARCH_COMMON, Target=None, Toolchain=None):
92 self.MetaFile = FilePath
93 self._ModuleDir = FilePath.Dir
94 self._RawData = RawData
95 self._Bdb = BuildDatabase
96 self._Arch = Arch
97 self._Target = Target
98 self._Toolchain = Toolchain
99 self._Platform = TAB_COMMON
100 if FilePath.Key in GlobalData.gOverrideDir:
101 self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key]
102 else:
103 self._SourceOverridePath = None
104 self._TailComments = None
105 self._BaseName = None
106 self._DxsFile = None
107 self._ModuleType = None
108 self._ComponentType = None
109 self._BuildType = None
110 self._Guid = None
111 self._Version = None
112 self._PcdIsDriver = None
113 self._BinaryModule = None
114 self._Shadow = None
115 self._MakefileName = None
116 self._CustomMakefile = None
117 self._Specification = None
118 self._LibraryClass = None
119 self._ModuleEntryPointList = None
120 self._ModuleUnloadImageList = None
121 self._ConstructorList = None
122 self._DestructorList = None
123 self._Defs = OrderedDict()
124 self._ProtocolComments = None
125 self._PpiComments = None
126 self._GuidsUsedByPcd = OrderedDict()
127 self._GuidComments = None
128 self._PcdComments = None
129 self._BuildOptions = None
130 self._DependencyFileList = None
131
132 ## XXX[key] = value
133 def __setitem__(self, key, value):
134 self.__dict__[self._PROPERTY_[key]] = value
135
136 ## value = XXX[key]
137 def __getitem__(self, key):
138 return self.__dict__[self._PROPERTY_[key]]
139
140 ## "in" test support
141 def __contains__(self, key):
142 return key in self._PROPERTY_
143
144 ## Get current effective macros
145 @cached_property
146 def _Macros(self):
147 RetVal = {}
148 return RetVal
149
150 ## Get architecture
151 @cached_property
152 def Arch(self):
153 return self._Arch
154
155 ## Return the name of platform employing this module
156 @cached_property
157 def Platform(self):
158 return self._Platform
159
160 @cached_property
161 def HeaderComments(self):
162 return [a[0] for a in self._RawData[MODEL_META_DATA_HEADER_COMMENT]]
163
164 @cached_property
165 def TailComments(self):
166 return [a[0] for a in self._RawData[MODEL_META_DATA_TAIL_COMMENT]]
167
168 ## Retrieve all information in [Defines] section
169 #
170 # (Retriving all [Defines] information in one-shot is just to save time.)
171 #
172 @cached_class_function
173 def _GetHeaderInfo(self):
174 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
175 for Record in RecordList:
176 Name, Value = Record[1], ReplaceMacro(Record[2], self._Macros, False)
177 # items defined _PROPERTY_ don't need additional processing
178 if Name in self:
179 self[Name] = Value
180 self._Defs[Name] = Value
181 self._Macros[Name] = Value
182 # some special items in [Defines] section need special treatment
183 elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
184 if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
185 Name = 'UEFI_SPECIFICATION_VERSION'
186 if self._Specification is None:
187 self._Specification = OrderedDict()
188 self._Specification[Name] = GetHexVerValue(Value)
189 if self._Specification[Name] is None:
190 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
191 "'%s' format is not supported for %s" % (Value, Name),
192 File=self.MetaFile, Line=Record[-1])
193 elif Name == 'LIBRARY_CLASS':
194 if self._LibraryClass is None:
195 self._LibraryClass = []
196 ValueList = GetSplitValueList(Value)
197 LibraryClass = ValueList[0]
198 if len(ValueList) > 1:
199 SupModuleList = GetSplitValueList(ValueList[1], ' ')
200 else:
201 SupModuleList = SUP_MODULE_LIST
202 self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList))
203 elif Name == 'ENTRY_POINT':
204 if self._ModuleEntryPointList is None:
205 self._ModuleEntryPointList = []
206 self._ModuleEntryPointList.append(Value)
207 elif Name == 'UNLOAD_IMAGE':
208 if self._ModuleUnloadImageList is None:
209 self._ModuleUnloadImageList = []
210 if not Value:
211 continue
212 self._ModuleUnloadImageList.append(Value)
213 elif Name == 'CONSTRUCTOR':
214 if self._ConstructorList is None:
215 self._ConstructorList = []
216 if not Value:
217 continue
218 self._ConstructorList.append(Value)
219 elif Name == 'DESTRUCTOR':
220 if self._DestructorList is None:
221 self._DestructorList = []
222 if not Value:
223 continue
224 self._DestructorList.append(Value)
225 elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE:
226 TokenList = GetSplitValueList(Value)
227 if self._CustomMakefile is None:
228 self._CustomMakefile = {}
229 if len(TokenList) < 2:
230 self._CustomMakefile[TAB_COMPILER_MSFT] = TokenList[0]
231 self._CustomMakefile['GCC'] = TokenList[0]
232 else:
233 if TokenList[0] not in [TAB_COMPILER_MSFT, 'GCC']:
234 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
235 "No supported family [%s]" % TokenList[0],
236 File=self.MetaFile, Line=Record[-1])
237 self._CustomMakefile[TokenList[0]] = TokenList[1]
238 else:
239 self._Defs[Name] = Value
240 self._Macros[Name] = Value
241
242 #
243 # Retrieve information in sections specific to Edk.x modules
244 #
245 if not self._ModuleType:
246 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
247 "MODULE_TYPE is not given", File=self.MetaFile)
248 if self._ModuleType not in SUP_MODULE_LIST:
249 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
250 for Record in RecordList:
251 Name = Record[1]
252 if Name == "MODULE_TYPE":
253 LineNo = Record[6]
254 break
255 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
256 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self._ModuleType, ' '.join(l for l in SUP_MODULE_LIST)),
257 File=self.MetaFile, Line=LineNo)
258 if (self._Specification is None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
259 if self._ModuleType == SUP_MODULE_SMM_CORE:
260 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "SMM_CORE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x0001000A", File=self.MetaFile)
261 if (self._Specification is None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x00010032):
262 if self._ModuleType == SUP_MODULE_MM_CORE_STANDALONE:
263 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "MM_CORE_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.MetaFile)
264 if self._ModuleType == SUP_MODULE_MM_STANDALONE:
265 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "MM_STANDALONE module type can't be used in the module with PI_SPECIFICATION_VERSION less than 0x00010032", File=self.MetaFile)
266 if 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \
267 and 'PCI_CLASS_CODE' in self._Defs and 'PCI_REVISION' in self._Defs:
268 self._BuildType = 'UEFI_OPTIONROM'
269 if 'PCI_COMPRESS' in self._Defs:
270 if self._Defs['PCI_COMPRESS'] not in ('TRUE', 'FALSE'):
271 EdkLogger.error("build", FORMAT_INVALID, "Expected TRUE/FALSE for PCI_COMPRESS: %s" % self.MetaFile)
272
273 elif 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
274 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
275 self._BuildType = 'UEFI_HII'
276 else:
277 self._BuildType = self._ModuleType.upper()
278
279 if self._DxsFile:
280 File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch)
281 # check the file validation
282 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
283 if ErrorCode != 0:
284 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
285 File=self.MetaFile, Line=LineNo)
286 if not self._DependencyFileList:
287 self._DependencyFileList = []
288 self._DependencyFileList.append(File)
289
290 ## Retrieve file version
291 @cached_property
292 def AutoGenVersion(self):
293 RetVal = 0x00010000
294 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
295 for Record in RecordList:
296 if Record[1] == TAB_INF_DEFINES_INF_VERSION:
297 if '.' in Record[2]:
298 ValueList = Record[2].split('.')
299 Major = '%04o' % int(ValueList[0], 0)
300 Minor = '%04o' % int(ValueList[1], 0)
301 RetVal = int('0x' + Major + Minor, 0)
302 else:
303 RetVal = int(Record[2], 0)
304 break
305 return RetVal
306
307 ## Retrieve BASE_NAME
308 @cached_property
309 def BaseName(self):
310 if self._BaseName is None:
311 self._GetHeaderInfo()
312 if self._BaseName is None:
313 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
314 return self._BaseName
315
316 ## Retrieve DxsFile
317 @cached_property
318 def DxsFile(self):
319 if self._DxsFile is None:
320 self._GetHeaderInfo()
321 if self._DxsFile is None:
322 self._DxsFile = ''
323 return self._DxsFile
324
325 ## Retrieve MODULE_TYPE
326 @cached_property
327 def ModuleType(self):
328 if self._ModuleType is None:
329 self._GetHeaderInfo()
330 if self._ModuleType is None:
331 self._ModuleType = SUP_MODULE_BASE
332 if self._ModuleType not in SUP_MODULE_LIST:
333 self._ModuleType = SUP_MODULE_USER_DEFINED
334 return self._ModuleType
335
336 ## Retrieve COMPONENT_TYPE
337 @cached_property
338 def ComponentType(self):
339 if self._ComponentType is None:
340 self._GetHeaderInfo()
341 if self._ComponentType is None:
342 self._ComponentType = SUP_MODULE_USER_DEFINED
343 return self._ComponentType
344
345 ## Retrieve "BUILD_TYPE"
346 @cached_property
347 def BuildType(self):
348 if self._BuildType is None:
349 self._GetHeaderInfo()
350 if not self._BuildType:
351 self._BuildType = SUP_MODULE_BASE
352 return self._BuildType
353
354 ## Retrieve file guid
355 @cached_property
356 def Guid(self):
357 if self._Guid is None:
358 self._GetHeaderInfo()
359 if self._Guid is None:
360 self._Guid = '00000000-0000-0000-0000-000000000000'
361 return self._Guid
362
363 ## Retrieve module version
364 @cached_property
365 def Version(self):
366 if self._Version is None:
367 self._GetHeaderInfo()
368 if self._Version is None:
369 self._Version = '0.0'
370 return self._Version
371
372 ## Retrieve PCD_IS_DRIVER
373 @cached_property
374 def PcdIsDriver(self):
375 if self._PcdIsDriver is None:
376 self._GetHeaderInfo()
377 if self._PcdIsDriver is None:
378 self._PcdIsDriver = ''
379 return self._PcdIsDriver
380
381 ## Retrieve SHADOW
382 @cached_property
383 def Shadow(self):
384 if self._Shadow is None:
385 self._GetHeaderInfo()
386 if self._Shadow and self._Shadow.upper() == 'TRUE':
387 self._Shadow = True
388 else:
389 self._Shadow = False
390 return self._Shadow
391
392 ## Retrieve CUSTOM_MAKEFILE
393 @cached_property
394 def CustomMakefile(self):
395 if self._CustomMakefile is None:
396 self._GetHeaderInfo()
397 if self._CustomMakefile is None:
398 self._CustomMakefile = {}
399 return self._CustomMakefile
400
401 ## Retrieve EFI_SPECIFICATION_VERSION
402 @cached_property
403 def Specification(self):
404 if self._Specification is None:
405 self._GetHeaderInfo()
406 if self._Specification is None:
407 self._Specification = {}
408 return self._Specification
409
410 ## Retrieve LIBRARY_CLASS
411 @cached_property
412 def LibraryClass(self):
413 if self._LibraryClass is None:
414 self._GetHeaderInfo()
415 if self._LibraryClass is None:
416 self._LibraryClass = []
417 return self._LibraryClass
418
419 ## Retrieve ENTRY_POINT
420 @cached_property
421 def ModuleEntryPointList(self):
422 if self._ModuleEntryPointList is None:
423 self._GetHeaderInfo()
424 if self._ModuleEntryPointList is None:
425 self._ModuleEntryPointList = []
426 return self._ModuleEntryPointList
427
428 ## Retrieve UNLOAD_IMAGE
429 @cached_property
430 def ModuleUnloadImageList(self):
431 if self._ModuleUnloadImageList is None:
432 self._GetHeaderInfo()
433 if self._ModuleUnloadImageList is None:
434 self._ModuleUnloadImageList = []
435 return self._ModuleUnloadImageList
436
437 ## Retrieve CONSTRUCTOR
438 @cached_property
439 def ConstructorList(self):
440 if self._ConstructorList is None:
441 self._GetHeaderInfo()
442 if self._ConstructorList is None:
443 self._ConstructorList = []
444 return self._ConstructorList
445
446 ## Retrieve DESTRUCTOR
447 @cached_property
448 def DestructorList(self):
449 if self._DestructorList is None:
450 self._GetHeaderInfo()
451 if self._DestructorList is None:
452 self._DestructorList = []
453 return self._DestructorList
454
455 ## Retrieve definies other than above ones
456 @cached_property
457 def Defines(self):
458 self._GetHeaderInfo()
459 return self._Defs
460
461 ## Retrieve binary files
462 @cached_class_function
463 def _GetBinaries(self):
464 RetVal = []
465 RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
466 Macros = self._Macros
467 Macros['PROCESSOR'] = self._Arch
468 for Record in RecordList:
469 FileType = Record[0]
470 LineNo = Record[-1]
471 Target = TAB_COMMON
472 FeatureFlag = []
473 if Record[2]:
474 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
475 if TokenList:
476 Target = TokenList[0]
477 if len(TokenList) > 1:
478 FeatureFlag = Record[1:]
479
480 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
481 # check the file validation
482 ErrorCode, ErrorInfo = File.Validate()
483 if ErrorCode != 0:
484 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
485 RetVal.append(File)
486 return RetVal
487
488 ## Retrieve binary files with error check.
489 @cached_property
490 def Binaries(self):
491 RetVal = self._GetBinaries()
492 if GlobalData.gIgnoreSource and not RetVal:
493 ErrorInfo = "The INF file does not contain any RetVal to use in creating the image\n"
494 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile)
495
496 return RetVal
497
498 ## Retrieve source files
499 @cached_property
500 def Sources(self):
501 self._GetHeaderInfo()
502 # Ignore all source files in a binary build mode
503 if GlobalData.gIgnoreSource:
504 return []
505
506 RetVal = []
507 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
508 Macros = self._Macros
509 for Record in RecordList:
510 LineNo = Record[-1]
511 ToolChainFamily = Record[1]
512 TagName = Record[2]
513 ToolCode = Record[3]
514
515 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
516 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
517 # check the file validation
518 ErrorCode, ErrorInfo = File.Validate()
519 if ErrorCode != 0:
520 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
521
522 RetVal.append(File)
523 # add any previously found dependency files to the source list
524 if self._DependencyFileList:
525 RetVal.extend(self._DependencyFileList)
526 return RetVal
527
528 ## Retrieve library classes employed by this module
529 @cached_property
530 def LibraryClasses(self):
531 RetVal = OrderedDict()
532 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
533 for Record in RecordList:
534 Lib = Record[0]
535 Instance = Record[1]
536 if Instance:
537 Instance = NormPath(Instance, self._Macros)
538 RetVal[Lib] = Instance
539 else:
540 RetVal[Lib] = None
541 return RetVal
542
543 ## Retrieve library names (for Edk.x style of modules)
544 @cached_property
545 def Libraries(self):
546 RetVal = []
547 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
548 for Record in RecordList:
549 LibraryName = ReplaceMacro(Record[0], self._Macros, False)
550 # in case of name with '.lib' extension, which is unusual in Edk.x inf
551 LibraryName = os.path.splitext(LibraryName)[0]
552 if LibraryName not in RetVal:
553 RetVal.append(LibraryName)
554 return RetVal
555
556 @cached_property
557 def ProtocolComments(self):
558 self.Protocols
559 return self._ProtocolComments
560
561 ## Retrieve protocols consumed/produced by this module
562 @cached_property
563 def Protocols(self):
564 RetVal = OrderedDict()
565 self._ProtocolComments = OrderedDict()
566 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
567 for Record in RecordList:
568 CName = Record[0]
569 Value = ProtocolValue(CName, self.Packages, self.MetaFile.Path)
570 if Value is None:
571 PackageList = "\n\t".join(str(P) for P in self.Packages)
572 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
573 "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
574 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
575 RetVal[CName] = Value
576 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
577 self._ProtocolComments[CName] = [a[0] for a in CommentRecords]
578 return RetVal
579
580 @cached_property
581 def PpiComments(self):
582 self.Ppis
583 return self._PpiComments
584
585 ## Retrieve PPIs consumed/produced by this module
586 @cached_property
587 def Ppis(self):
588 RetVal = OrderedDict()
589 self._PpiComments = OrderedDict()
590 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
591 for Record in RecordList:
592 CName = Record[0]
593 Value = PpiValue(CName, self.Packages, self.MetaFile.Path)
594 if Value is None:
595 PackageList = "\n\t".join(str(P) for P in self.Packages)
596 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
597 "Value of PPI [%s] is not found under [Ppis] section in " % CName,
598 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
599 RetVal[CName] = Value
600 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
601 self._PpiComments[CName] = [a[0] for a in CommentRecords]
602 return RetVal
603
604 @cached_property
605 def GuidComments(self):
606 self.Guids
607 return self._GuidComments
608
609 ## Retrieve GUIDs consumed/produced by this module
610 @cached_property
611 def Guids(self):
612 RetVal = OrderedDict()
613 self._GuidComments = OrderedDict()
614 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
615 for Record in RecordList:
616 CName = Record[0]
617 Value = GuidValue(CName, self.Packages, self.MetaFile.Path)
618 if Value is None:
619 PackageList = "\n\t".join(str(P) for P in self.Packages)
620 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
621 "Value of Guid [%s] is not found under [Guids] section in" % CName,
622 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
623 RetVal[CName] = Value
624 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
625 self._GuidComments[CName] = [a[0] for a in CommentRecords]
626 return RetVal
627
628 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
629 @cached_property
630 def Includes(self):
631 RetVal = []
632 if self._SourceOverridePath:
633 RetVal.append(self._SourceOverridePath)
634
635 Macros = self._Macros
636 Macros['PROCESSOR'] = GlobalData.gEdkGlobal.get('PROCESSOR', self._Arch)
637 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
638 for Record in RecordList:
639 if Record[0].find('EDK_SOURCE') > -1:
640 File = NormPath(Record[0], self._Macros)
641 if File[0] == '.':
642 File = os.path.join(self._ModuleDir, File)
643 else:
644 File = os.path.join(GlobalData.gWorkspace, File)
645 File = RealPath(os.path.normpath(File))
646 if File:
647 RetVal.append(File)
648
649 # TRICK: let compiler to choose correct header file
650 File = NormPath(Record[0], self._Macros)
651 if File[0] == '.':
652 File = os.path.join(self._ModuleDir, File)
653 else:
654 File = os.path.join(GlobalData.gWorkspace, File)
655 File = RealPath(os.path.normpath(File))
656 if File:
657 RetVal.append(File)
658 else:
659 File = NormPath(Record[0], Macros)
660 if File[0] == '.':
661 File = os.path.join(self._ModuleDir, File)
662 else:
663 File = mws.join(GlobalData.gWorkspace, File)
664 File = RealPath(os.path.normpath(File))
665 if File:
666 RetVal.append(File)
667 return RetVal
668
669 ## Retrieve packages this module depends on
670 @cached_property
671 def Packages(self):
672 RetVal = []
673 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
674 Macros = self._Macros
675 for Record in RecordList:
676 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
677 # check the file validation
678 ErrorCode, ErrorInfo = File.Validate('.dec')
679 if ErrorCode != 0:
680 LineNo = Record[-1]
681 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
682 # parse this package now. we need it to get protocol/ppi/guid value
683 RetVal.append(self._Bdb[File, self._Arch, self._Target, self._Toolchain])
684 return RetVal
685
686 ## Retrieve PCD comments
687 @cached_property
688 def PcdComments(self):
689 self.Pcds
690 return self._PcdComments
691
692 ## Retrieve PCDs used in this module
693 @cached_property
694 def Pcds(self):
695 self._PcdComments = OrderedDict()
696 RetVal = OrderedDict()
697 RetVal.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
698 RetVal.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
699 RetVal.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
700 RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC))
701 RetVal.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
702 return RetVal
703
704 @cached_property
705 def PcdsName(self):
706 PcdsName = set()
707 for Type in (MODEL_PCD_FIXED_AT_BUILD,MODEL_PCD_PATCHABLE_IN_MODULE,MODEL_PCD_FEATURE_FLAG,MODEL_PCD_DYNAMIC,MODEL_PCD_DYNAMIC_EX):
708 RecordList = self._RawData[Type, self._Arch, self._Platform]
709 for TokenSpaceGuid, PcdCName, _, _, _, _, _ in RecordList:
710 PcdsName.add((PcdCName, TokenSpaceGuid))
711 return PcdsName
712
713 ## Retrieve build options specific to this module
714 @cached_property
715 def BuildOptions(self):
716 if self._BuildOptions is None:
717 self._BuildOptions = OrderedDict()
718 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
719 for Record in RecordList:
720 ToolChainFamily = Record[0]
721 ToolChain = Record[1]
722 Option = Record[2]
723 if (ToolChainFamily, ToolChain) not in self._BuildOptions or Option.startswith('='):
724 self._BuildOptions[ToolChainFamily, ToolChain] = Option
725 else:
726 # concatenate the option string if they're for the same tool
727 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
728 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
729 return self._BuildOptions
730
731 ## Retrieve dependency expression
732 @cached_property
733 def Depex(self):
734 RetVal = tdict(False, 2)
735
736 # If the module has only Binaries and no Sources, then ignore [Depex]
737 if not self.Sources and self.Binaries:
738 return RetVal
739
740 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
741 # PEIM and DXE drivers must have a valid [Depex] section
742 if len(self.LibraryClass) == 0 and len(RecordList) == 0:
743 if self.ModuleType == SUP_MODULE_DXE_DRIVER or self.ModuleType == SUP_MODULE_PEIM or self.ModuleType == SUP_MODULE_DXE_SMM_DRIVER or \
744 self.ModuleType == SUP_MODULE_DXE_SAL_DRIVER or self.ModuleType == SUP_MODULE_DXE_RUNTIME_DRIVER:
745 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
746 % self.ModuleType, File=self.MetaFile)
747
748 if len(RecordList) != 0 and self.ModuleType == SUP_MODULE_USER_DEFINED:
749 for Record in RecordList:
750 if Record[4] not in [SUP_MODULE_PEIM, SUP_MODULE_DXE_DRIVER, SUP_MODULE_DXE_SMM_DRIVER]:
751 EdkLogger.error('build', FORMAT_INVALID,
752 "'%s' module must specify the type of [Depex] section" % self.ModuleType,
753 File=self.MetaFile)
754
755 TemporaryDictionary = OrderedDict()
756 for Record in RecordList:
757 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
758 Arch = Record[3]
759 ModuleType = Record[4]
760 TokenList = DepexStr.split()
761 if (Arch, ModuleType) not in TemporaryDictionary:
762 TemporaryDictionary[Arch, ModuleType] = []
763 DepexList = TemporaryDictionary[Arch, ModuleType]
764 for Token in TokenList:
765 if Token in DEPEX_SUPPORTED_OPCODE_SET:
766 DepexList.append(Token)
767 elif Token.endswith(".inf"): # module file name
768 ModuleFile = os.path.normpath(Token)
769 Module = self.BuildDatabase[ModuleFile]
770 if Module is None:
771 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
772 ExtraData=Token, File=self.MetaFile, Line=Record[-1])
773 DepexList.append(Module.Guid)
774 else:
775 # it use the Fixed PCD format
776 if '.' in Token:
777 if tuple(Token.split('.')[::-1]) not in self.Pcds:
778 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "PCD [{}] used in [Depex] section should be listed in module PCD section".format(Token), File=self.MetaFile, Line=Record[-1])
779 else:
780 if self.Pcds[tuple(Token.split('.')[::-1])].DatumType != TAB_VOID:
781 EdkLogger.error('build', FORMAT_INVALID, "PCD [{}] used in [Depex] section should be VOID* datum type".format(Token), File=self.MetaFile, Line=Record[-1])
782 Value = Token
783 else:
784 # get the GUID value now
785 Value = ProtocolValue(Token, self.Packages, self.MetaFile.Path)
786 if Value is None:
787 Value = PpiValue(Token, self.Packages, self.MetaFile.Path)
788 if Value is None:
789 Value = GuidValue(Token, self.Packages, self.MetaFile.Path)
790
791 if Value is None:
792 PackageList = "\n\t".join(str(P) for P in self.Packages)
793 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
794 "Value of [%s] is not found in" % Token,
795 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
796 DepexList.append(Value)
797 for Arch, ModuleType in TemporaryDictionary:
798 RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
799 return RetVal
800
801 ## Retrieve depedency expression
802 @cached_property
803 def DepexExpression(self):
804 RetVal = tdict(False, 2)
805 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
806 TemporaryDictionary = OrderedDict()
807 for Record in RecordList:
808 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
809 Arch = Record[3]
810 ModuleType = Record[4]
811 TokenList = DepexStr.split()
812 if (Arch, ModuleType) not in TemporaryDictionary:
813 TemporaryDictionary[Arch, ModuleType] = ''
814 for Token in TokenList:
815 TemporaryDictionary[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType] + Token.strip() + ' '
816 for Arch, ModuleType in TemporaryDictionary:
817 RetVal[Arch, ModuleType] = TemporaryDictionary[Arch, ModuleType]
818 return RetVal
819
820 @cached_class_function
821 def GetGuidsUsedByPcd(self):
822 self.Pcds
823 return self._GuidsUsedByPcd
824
825 ## Retrieve PCD for given type
826 def _GetPcd(self, Type):
827 Pcds = OrderedDict()
828 PcdDict = tdict(True, 4)
829 PcdList = []
830 RecordList = self._RawData[Type, self._Arch, self._Platform]
831 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Id, LineNo in RecordList:
832 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
833 PcdList.append((PcdCName, TokenSpaceGuid))
834 # get the guid value
835 if TokenSpaceGuid not in self.Guids:
836 Value = GuidValue(TokenSpaceGuid, self.Packages, self.MetaFile.Path)
837 if Value is None:
838 PackageList = "\n\t".join(str(P) for P in self.Packages)
839 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
840 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
841 ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
842 self.Guids[TokenSpaceGuid] = Value
843 self._GuidsUsedByPcd[TokenSpaceGuid] = Value
844 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Id]
845 Comments = []
846 for CmtRec in CommentRecords:
847 Comments.append(CmtRec[0])
848 self._PcdComments[TokenSpaceGuid, PcdCName] = Comments
849
850 # resolve PCD type, value, datum info, etc. by getting its definition from package
851 _GuidDict = self.Guids.copy()
852 for PcdCName, TokenSpaceGuid in PcdList:
853 PcdRealName = PcdCName
854 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
855 if Setting is None:
856 continue
857 ValueList = AnalyzePcdData(Setting)
858 DefaultValue = ValueList[0]
859 Pcd = PcdClassObject(
860 PcdCName,
861 TokenSpaceGuid,
862 '',
863 '',
864 DefaultValue,
865 '',
866 '',
867 {},
868 False,
869 self.Guids[TokenSpaceGuid]
870 )
871 if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]:
872 # Patch PCD: TokenSpace.PcdCName|Value|Offset
873 Pcd.Offset = ValueList[1]
874
875 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
876 for Package in self.Packages:
877 for key in Package.Pcds:
878 if (Package.Pcds[key].TokenCName, Package.Pcds[key].TokenSpaceGuidCName) == (PcdRealName, TokenSpaceGuid):
879 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
880 Pcd_Type = item[0].split('_')[-1]
881 if Pcd_Type == Package.Pcds[key].Type:
882 Value = Package.Pcds[key]
883 Value.TokenCName = Package.Pcds[key].TokenCName + '_' + Pcd_Type
884 if len(key) == 2:
885 newkey = (Value.TokenCName, key[1])
886 elif len(key) == 3:
887 newkey = (Value.TokenCName, key[1], key[2])
888 del Package.Pcds[key]
889 Package.Pcds[newkey] = Value
890 break
891 else:
892 pass
893 else:
894 pass
895
896 # get necessary info from package declaring this PCD
897 for Package in self.Packages:
898 #
899 # 'dynamic' in INF means its type is determined by platform;
900 # if platform doesn't give its type, use 'lowest' one in the
901 # following order, if any
902 #
903 # TAB_PCDS_FIXED_AT_BUILD, TAB_PCDS_PATCHABLE_IN_MODULE, TAB_PCDS_FEATURE_FLAG, TAB_PCDS_DYNAMIC, TAB_PCDS_DYNAMIC_EX
904 #
905 _GuidDict.update(Package.Guids)
906 PcdType = self._PCD_TYPE_STRING_[Type]
907 if Type == MODEL_PCD_DYNAMIC:
908 Pcd.Pending = True
909 for T in PCD_TYPE_LIST:
910 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
911 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
912 if str(item[0]).endswith(T) and (item[0], item[1], T) in Package.Pcds:
913 PcdType = T
914 PcdCName = item[0]
915 break
916 else:
917 pass
918 break
919 else:
920 if (PcdRealName, TokenSpaceGuid, T) in Package.Pcds:
921 PcdType = T
922 break
923
924 else:
925 Pcd.Pending = False
926 if (PcdRealName, TokenSpaceGuid) in GlobalData.MixedPcd:
927 for item in GlobalData.MixedPcd[(PcdRealName, TokenSpaceGuid)]:
928 Pcd_Type = item[0].split('_')[-1]
929 if Pcd_Type == PcdType:
930 PcdCName = item[0]
931 break
932 else:
933 pass
934 else:
935 pass
936
937 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
938 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
939 Pcd.Type = PcdType
940 Pcd.TokenValue = PcdInPackage.TokenValue
941
942 #
943 # Check whether the token value exist or not.
944 #
945 if Pcd.TokenValue is None or Pcd.TokenValue == "":
946 EdkLogger.error(
947 'build',
948 FORMAT_INVALID,
949 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdRealName, str(Package)),
950 File=self.MetaFile, Line=LineNo,
951 ExtraData=None
952 )
953 #
954 # Check hexadecimal token value length and format.
955 #
956 ReIsValidPcdTokenValue = re.compile(r"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re.DOTALL)
957 if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"):
958 if ReIsValidPcdTokenValue.match(Pcd.TokenValue) is None:
959 EdkLogger.error(
960 'build',
961 FORMAT_INVALID,
962 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
963 File=self.MetaFile, Line=LineNo,
964 ExtraData=None
965 )
966
967 #
968 # Check decimal token value length and format.
969 #
970 else:
971 try:
972 TokenValueInt = int (Pcd.TokenValue, 10)
973 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
974 EdkLogger.error(
975 'build',
976 FORMAT_INVALID,
977 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, as a decimal it should between: 0 - 4294967295!" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
978 File=self.MetaFile, Line=LineNo,
979 ExtraData=None
980 )
981 except:
982 EdkLogger.error(
983 'build',
984 FORMAT_INVALID,
985 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, it should be hexadecimal or decimal!" % (Pcd.TokenValue, TokenSpaceGuid, PcdRealName, str(Package)),
986 File=self.MetaFile, Line=LineNo,
987 ExtraData=None
988 )
989
990 Pcd.DatumType = PcdInPackage.DatumType
991 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
992 Pcd.InfDefaultValue = Pcd.DefaultValue
993 if not Pcd.DefaultValue:
994 Pcd.DefaultValue = PcdInPackage.DefaultValue
995 else:
996 try:
997 Pcd.DefaultValue = ValueExpressionEx(Pcd.DefaultValue, Pcd.DatumType, _GuidDict)(True)
998 except BadExpression as Value:
999 EdkLogger.error('Parser', FORMAT_INVALID, 'PCD [%s.%s] Value "%s", %s' %(TokenSpaceGuid, PcdRealName, Pcd.DefaultValue, Value),
1000 File=self.MetaFile, Line=LineNo)
1001 break
1002 else:
1003 EdkLogger.error(
1004 'build',
1005 FORMAT_INVALID,
1006 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdRealName, self.MetaFile),
1007 File=self.MetaFile, Line=LineNo,
1008 ExtraData="\t%s" % '\n\t'.join(str(P) for P in self.Packages)
1009 )
1010 Pcds[PcdCName, TokenSpaceGuid] = Pcd
1011
1012 return Pcds
1013
1014 ## check whether current module is binary module
1015 @property
1016 def IsBinaryModule(self):
1017 if (self.Binaries and not self.Sources) or GlobalData.gIgnoreSource:
1018 return True
1019 return False