]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
4bfa7d8ffd53cc7a2199e06a0c010df8867d21e7
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / WorkspaceDatabase.py
1 ## @file
2 # This file is used to create a database used by build tool
3 #
4 # Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ##
15 # Import Modules
16 #
17 import sqlite3
18 import os
19 import os.path
20 import pickle
21 import uuid
22
23 import Common.EdkLogger as EdkLogger
24 import Common.GlobalData as GlobalData
25
26 from Common.String import *
27 from Common.DataType import *
28 from Common.Misc import *
29 from types import *
30
31 from CommonDataClass.CommonClass import SkuInfoClass
32
33 from MetaDataTable import *
34 from MetaFileTable import *
35 from MetaFileParser import *
36 from BuildClassObject import *
37
38 ## Platform build information from DSC file
39 #
40 # This class is used to retrieve information stored in database and convert them
41 # into PlatformBuildClassObject form for easier use for AutoGen.
42 #
43 class DscBuildData(PlatformBuildClassObject):
44 # dict used to convert PCD type in database to string used by build tool
45 _PCD_TYPE_STRING_ = {
46 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
47 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
48 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
49 MODEL_PCD_DYNAMIC : "Dynamic",
50 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
51 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
52 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
53 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
54 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
55 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
56 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
57 }
58
59 # dict used to convert part of [Defines] to members of DscBuildData directly
60 _PROPERTY_ = {
61 #
62 # Required Fields
63 #
64 TAB_DSC_DEFINES_PLATFORM_NAME : "_PlatformName",
65 TAB_DSC_DEFINES_PLATFORM_GUID : "_Guid",
66 TAB_DSC_DEFINES_PLATFORM_VERSION : "_Version",
67 TAB_DSC_DEFINES_DSC_SPECIFICATION : "_DscSpecification",
68 #TAB_DSC_DEFINES_OUTPUT_DIRECTORY : "_OutputDirectory",
69 #TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES : "_SupArchList",
70 #TAB_DSC_DEFINES_BUILD_TARGETS : "_BuildTargets",
71 #TAB_DSC_DEFINES_SKUID_IDENTIFIER : "_SkuName",
72 #TAB_DSC_DEFINES_FLASH_DEFINITION : "_FlashDefinition",
73 TAB_DSC_DEFINES_BUILD_NUMBER : "_BuildNumber",
74 TAB_DSC_DEFINES_MAKEFILE_NAME : "_MakefileName",
75 TAB_DSC_DEFINES_BS_BASE_ADDRESS : "_BsBaseAddress",
76 TAB_DSC_DEFINES_RT_BASE_ADDRESS : "_RtBaseAddress",
77 #TAB_DSC_DEFINES_RFC_LANGUAGES : "_RFCLanguages",
78 #TAB_DSC_DEFINES_ISO_LANGUAGES : "_ISOLanguages",
79 }
80
81 # used to compose dummy library class name for those forced library instances
82 _NullLibraryNumber = 0
83
84 ## Constructor of DscBuildData
85 #
86 # Initialize object of DscBuildData
87 #
88 # @param FilePath The path of platform description file
89 # @param RawData The raw data of DSC file
90 # @param BuildDataBase Database used to retrieve module/package information
91 # @param Arch The target architecture
92 # @param Platform (not used for DscBuildData)
93 # @param Macros Macros used for replacement in DSC file
94 #
95 def __init__(self, FilePath, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}):
96 self.MetaFile = FilePath
97 self._RawData = RawData
98 self._Bdb = BuildDataBase
99 self._Arch = Arch
100 self._Macros = Macros
101 self._Clear()
102 RecordList = self._RawData[MODEL_META_DATA_DEFINE, self._Arch]
103 for Record in RecordList:
104 GlobalData.gEdkGlobal[Record[0]] = Record[1]
105
106 RecordList = self._RawData[MODEL_META_DATA_GLOBAL_DEFINE, self._Arch]
107 for Record in RecordList:
108 GlobalData.gGlobalDefines[Record[0]] = Record[1]
109
110 ## XXX[key] = value
111 def __setitem__(self, key, value):
112 self.__dict__[self._PROPERTY_[key]] = value
113
114 ## value = XXX[key]
115 def __getitem__(self, key):
116 return self.__dict__[self._PROPERTY_[key]]
117
118 ## "in" test support
119 def __contains__(self, key):
120 return key in self._PROPERTY_
121
122 ## Set all internal used members of DscBuildData to None
123 def _Clear(self):
124 self._Header = None
125 self._PlatformName = None
126 self._Guid = None
127 self._Version = None
128 self._DscSpecification = None
129 self._OutputDirectory = None
130 self._SupArchList = None
131 self._BuildTargets = None
132 self._SkuName = None
133 self._FlashDefinition = None
134 self._BuildNumber = None
135 self._MakefileName = None
136 self._BsBaseAddress = None
137 self._RtBaseAddress = None
138 self._SkuIds = None
139 self._Modules = None
140 self._LibraryInstances = None
141 self._LibraryClasses = None
142 self._Pcds = None
143 self._BuildOptions = None
144 self._LoadFixAddress = None
145 self._RFCLanguages = None
146 self._ISOLanguages = None
147 self._VpdToolGuid = None
148
149 ## Get architecture
150 def _GetArch(self):
151 return self._Arch
152
153 ## Set architecture
154 #
155 # Changing the default ARCH to another may affect all other information
156 # because all information in a platform may be ARCH-related. That's
157 # why we need to clear all internal used members, in order to cause all
158 # information to be re-retrieved.
159 #
160 # @param Value The value of ARCH
161 #
162 def _SetArch(self, Value):
163 if self._Arch == Value:
164 return
165 self._Arch = Value
166 self._Clear()
167
168 ## Retrieve all information in [Defines] section
169 #
170 # (Retriving all [Defines] information in one-shot is just to save time.)
171 #
172 def _GetHeaderInfo(self):
173 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
174 for Record in RecordList:
175 Name = Record[0]
176 # items defined _PROPERTY_ don't need additional processing
177 if Name in self:
178 self[Name] = Record[1]
179 # some special items in [Defines] section need special treatment
180 elif Name == TAB_DSC_DEFINES_OUTPUT_DIRECTORY:
181 self._OutputDirectory = NormPath(Record[1], self._Macros)
182 if ' ' in self._OutputDirectory:
183 EdkLogger.error("build", FORMAT_NOT_SUPPORTED, "No space is allowed in OUTPUT_DIRECTORY",
184 File=self.MetaFile, Line=Record[-1],
185 ExtraData=self._OutputDirectory)
186 elif Name == TAB_DSC_DEFINES_FLASH_DEFINITION:
187 self._FlashDefinition = PathClass(NormPath(Record[1], self._Macros), GlobalData.gWorkspace)
188 ErrorCode, ErrorInfo = self._FlashDefinition.Validate('.fdf')
189 if ErrorCode != 0:
190 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=Record[-1],
191 ExtraData=ErrorInfo)
192 elif Name == TAB_DSC_DEFINES_SUPPORTED_ARCHITECTURES:
193 self._SupArchList = GetSplitValueList(Record[1], TAB_VALUE_SPLIT)
194 elif Name == TAB_DSC_DEFINES_BUILD_TARGETS:
195 self._BuildTargets = GetSplitValueList(Record[1])
196 elif Name == TAB_DSC_DEFINES_SKUID_IDENTIFIER:
197 if self._SkuName == None:
198 self._SkuName = Record[1]
199 elif Name == TAB_FIX_LOAD_TOP_MEMORY_ADDRESS:
200 self._LoadFixAddress = Record[1]
201 elif Name == TAB_DSC_DEFINES_RFC_LANGUAGES:
202 if not Record[1] or Record[1][0] != '"' or Record[1][-1] != '"' or len(Record[1]) == 1:
203 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for RFC_LANGUAGES must have double quotes around it, for example: RFC_LANGUAGES = "en-us;zh-hans"',
204 File=self.MetaFile, Line=Record[-1])
205 LanguageCodes = Record[1][1:-1]
206 if not LanguageCodes:
207 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more RFC4646 format language code must be provided for RFC_LANGUAGES statement',
208 File=self.MetaFile, Line=Record[-1])
209 LanguageList = GetSplitValueList(LanguageCodes, TAB_SEMI_COLON_SPLIT)
210 # check whether there is empty entries in the list
211 if None in LanguageList:
212 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more empty language code is in RFC_LANGUAGES statement',
213 File=self.MetaFile, Line=Record[-1])
214 self._RFCLanguages = LanguageList
215 elif Name == TAB_DSC_DEFINES_ISO_LANGUAGES:
216 if not Record[1] or Record[1][0] != '"' or Record[1][-1] != '"' or len(Record[1]) == 1:
217 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'language code for ISO_LANGUAGES must have double quotes around it, for example: ISO_LANGUAGES = "engchn"',
218 File=self.MetaFile, Line=Record[-1])
219 LanguageCodes = Record[1][1:-1]
220 if not LanguageCodes:
221 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'one or more ISO639-2 format language code must be provided for ISO_LANGUAGES statement',
222 File=self.MetaFile, Line=Record[-1])
223 if len(LanguageCodes)%3:
224 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, 'bad ISO639-2 format for ISO_LANGUAGES',
225 File=self.MetaFile, Line=Record[-1])
226 LanguageList = []
227 for i in range(0, len(LanguageCodes), 3):
228 LanguageList.append(LanguageCodes[i:i+3])
229 self._ISOLanguages = LanguageList
230 elif Name == TAB_DSC_DEFINES_VPD_TOOL_GUID:
231 #
232 # try to convert GUID to a real UUID value to see whether the GUID is format
233 # for VPD_TOOL_GUID is correct.
234 #
235 try:
236 uuid.UUID(Record[1])
237 except:
238 EdkLogger.error("build", FORMAT_INVALID, "Invalid GUID format for VPD_TOOL_GUID", File=self.MetaFile)
239 self._VpdToolGuid = Record[1]
240 # set _Header to non-None in order to avoid database re-querying
241 self._Header = 'DUMMY'
242
243 ## Retrieve platform name
244 def _GetPlatformName(self):
245 if self._PlatformName == None:
246 if self._Header == None:
247 self._GetHeaderInfo()
248 if self._PlatformName == None:
249 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No PLATFORM_NAME", File=self.MetaFile)
250 return self._PlatformName
251
252 ## Retrieve file guid
253 def _GetFileGuid(self):
254 if self._Guid == None:
255 if self._Header == None:
256 self._GetHeaderInfo()
257 if self._Guid == None:
258 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No FILE_GUID", File=self.MetaFile)
259 return self._Guid
260
261 ## Retrieve platform version
262 def _GetVersion(self):
263 if self._Version == None:
264 if self._Header == None:
265 self._GetHeaderInfo()
266 if self._Version == None:
267 self._Version = ''
268 return self._Version
269
270 ## Retrieve platform description file version
271 def _GetDscSpec(self):
272 if self._DscSpecification == None:
273 if self._Header == None:
274 self._GetHeaderInfo()
275 if self._DscSpecification == None:
276 self._DscSpecification = ''
277 return self._DscSpecification
278
279 ## Retrieve OUTPUT_DIRECTORY
280 def _GetOutpuDir(self):
281 if self._OutputDirectory == None:
282 if self._Header == None:
283 self._GetHeaderInfo()
284 if self._OutputDirectory == None:
285 self._OutputDirectory = os.path.join("Build", self._PlatformName)
286 return self._OutputDirectory
287
288 ## Retrieve SUPPORTED_ARCHITECTURES
289 def _GetSupArch(self):
290 if self._SupArchList == None:
291 if self._Header == None:
292 self._GetHeaderInfo()
293 if self._SupArchList == None:
294 self._SupArchList = ARCH_LIST
295 return self._SupArchList
296
297 ## Retrieve BUILD_TARGETS
298 def _GetBuildTarget(self):
299 if self._BuildTargets == None:
300 if self._Header == None:
301 self._GetHeaderInfo()
302 if self._BuildTargets == None:
303 self._BuildTargets = ['DEBUG', 'RELEASE', 'NOOPT']
304 return self._BuildTargets
305
306 ## Retrieve SKUID_IDENTIFIER
307 def _GetSkuName(self):
308 if self._SkuName == None:
309 if self._Header == None:
310 self._GetHeaderInfo()
311 if self._SkuName == None or self._SkuName not in self.SkuIds:
312 self._SkuName = 'DEFAULT'
313 return self._SkuName
314
315 ## Override SKUID_IDENTIFIER
316 def _SetSkuName(self, Value):
317 if Value in self.SkuIds:
318 self._SkuName = Value
319 # Needs to re-retrieve the PCD information
320 self._Pcds = None
321
322 def _GetFdfFile(self):
323 if self._FlashDefinition == None:
324 if self._Header == None:
325 self._GetHeaderInfo()
326 if self._FlashDefinition == None:
327 self._FlashDefinition = ''
328 return self._FlashDefinition
329
330 ## Retrieve FLASH_DEFINITION
331 def _GetBuildNumber(self):
332 if self._BuildNumber == None:
333 if self._Header == None:
334 self._GetHeaderInfo()
335 if self._BuildNumber == None:
336 self._BuildNumber = ''
337 return self._BuildNumber
338
339 ## Retrieve MAKEFILE_NAME
340 def _GetMakefileName(self):
341 if self._MakefileName == None:
342 if self._Header == None:
343 self._GetHeaderInfo()
344 if self._MakefileName == None:
345 self._MakefileName = ''
346 return self._MakefileName
347
348 ## Retrieve BsBaseAddress
349 def _GetBsBaseAddress(self):
350 if self._BsBaseAddress == None:
351 if self._Header == None:
352 self._GetHeaderInfo()
353 if self._BsBaseAddress == None:
354 self._BsBaseAddress = ''
355 return self._BsBaseAddress
356
357 ## Retrieve RtBaseAddress
358 def _GetRtBaseAddress(self):
359 if self._RtBaseAddress == None:
360 if self._Header == None:
361 self._GetHeaderInfo()
362 if self._RtBaseAddress == None:
363 self._RtBaseAddress = ''
364 return self._RtBaseAddress
365
366 ## Retrieve the top address for the load fix address
367 def _GetLoadFixAddress(self):
368 if self._LoadFixAddress == None:
369 if self._Header == None:
370 self._GetHeaderInfo()
371 if self._LoadFixAddress == None:
372 self._LoadFixAddress = ''
373 return self._LoadFixAddress
374
375 ## Retrieve RFCLanguage filter
376 def _GetRFCLanguages(self):
377 if self._RFCLanguages == None:
378 if self._Header == None:
379 self._GetHeaderInfo()
380 if self._RFCLanguages == None:
381 self._RFCLanguages = []
382 return self._RFCLanguages
383
384 ## Retrieve ISOLanguage filter
385 def _GetISOLanguages(self):
386 if self._ISOLanguages == None:
387 if self._Header == None:
388 self._GetHeaderInfo()
389 if self._ISOLanguages == None:
390 self._ISOLanguages = []
391 return self._ISOLanguages
392
393 ## Retrieve the GUID string for VPD tool
394 def _GetVpdToolGuid(self):
395 if self._VpdToolGuid == None:
396 if self._Header == None:
397 self._GetHeaderInfo()
398 if self._VpdToolGuid == None:
399 self._VpdToolGuid = ''
400 return self._VpdToolGuid
401
402 ## Retrieve [SkuIds] section information
403 def _GetSkuIds(self):
404 if self._SkuIds == None:
405 self._SkuIds = {}
406 RecordList = self._RawData[MODEL_EFI_SKU_ID]
407 for Record in RecordList:
408 if Record[0] in [None, '']:
409 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID number',
410 File=self.MetaFile, Line=Record[-1])
411 if Record[1] in [None, '']:
412 EdkLogger.error('build', FORMAT_INVALID, 'No Sku ID name',
413 File=self.MetaFile, Line=Record[-1])
414 self._SkuIds[Record[1]] = Record[0]
415 if 'DEFAULT' not in self._SkuIds:
416 self._SkuIds['DEFAULT'] = 0
417 return self._SkuIds
418
419 ## Retrieve [Components] section information
420 def _GetModules(self):
421 if self._Modules != None:
422 return self._Modules
423
424 self._Modules = sdict()
425 RecordList = self._RawData[MODEL_META_DATA_COMPONENT, self._Arch]
426 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
427 Macros.update(self._Macros)
428 for Record in RecordList:
429 ModuleFile = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
430 ModuleId = Record[5]
431 LineNo = Record[6]
432
433 # check the file validation
434 ErrorCode, ErrorInfo = ModuleFile.Validate('.inf')
435 if ErrorCode != 0:
436 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
437 ExtraData=ErrorInfo)
438 # Check duplication
439 if ModuleFile in self._Modules:
440 EdkLogger.error('build', FILE_DUPLICATED, File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
441
442 Module = ModuleBuildClassObject()
443 Module.MetaFile = ModuleFile
444
445 # get module override path
446 RecordList = self._RawData[MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH, self._Arch, None, ModuleId]
447 if RecordList != []:
448 Module.SourceOverridePath = os.path.join(GlobalData.gWorkspace, NormPath(RecordList[0][0], Macros))
449
450 # Check if the source override path exists
451 if not os.path.isdir(Module.SourceOverridePath):
452 EdkLogger.error('build', FILE_NOT_FOUND, Message = 'Source override path does not exist:', File=self.MetaFile, ExtraData=Module.SourceOverridePath, Line=LineNo)
453
454 #Add to GlobalData Variables
455 GlobalData.gOverrideDir[ModuleFile.Key] = Module.SourceOverridePath
456
457 # get module private library instance
458 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
459 for Record in RecordList:
460 LibraryClass = Record[0]
461 LibraryPath = PathClass(NormPath(Record[1], Macros), GlobalData.gWorkspace, Arch=self._Arch)
462 LineNo = Record[-1]
463
464 # check the file validation
465 ErrorCode, ErrorInfo = LibraryPath.Validate('.inf')
466 if ErrorCode != 0:
467 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
468 ExtraData=ErrorInfo)
469
470 if LibraryClass == '' or LibraryClass == 'NULL':
471 self._NullLibraryNumber += 1
472 LibraryClass = 'NULL%d' % self._NullLibraryNumber
473 EdkLogger.verbose("Found forced library for %s\n\t%s [%s]" % (ModuleFile, LibraryPath, LibraryClass))
474 Module.LibraryClasses[LibraryClass] = LibraryPath
475 if LibraryPath not in self.LibraryInstances:
476 self.LibraryInstances.append(LibraryPath)
477
478 # get module private PCD setting
479 for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
480 MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
481 RecordList = self._RawData[Type, self._Arch, None, ModuleId]
482 for TokenSpaceGuid, PcdCName, Setting, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
483 TokenList = GetSplitValueList(Setting)
484 DefaultValue = TokenList[0]
485 if len(TokenList) > 1:
486 MaxDatumSize = TokenList[1]
487 else:
488 MaxDatumSize = ''
489 TypeString = self._PCD_TYPE_STRING_[Type]
490 Pcd = PcdClassObject(
491 PcdCName,
492 TokenSpaceGuid,
493 TypeString,
494 '',
495 DefaultValue,
496 '',
497 MaxDatumSize,
498 {},
499 False,
500 None
501 )
502 Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd
503
504 # get module private build options
505 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
506 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
507 if (ToolChainFamily, ToolChain) not in Module.BuildOptions:
508 Module.BuildOptions[ToolChainFamily, ToolChain] = Option
509 else:
510 OptionString = Module.BuildOptions[ToolChainFamily, ToolChain]
511 Module.BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
512
513 self._Modules[ModuleFile] = Module
514 return self._Modules
515
516 ## Retrieve all possible library instances used in this platform
517 def _GetLibraryInstances(self):
518 if self._LibraryInstances == None:
519 self._GetLibraryClasses()
520 return self._LibraryInstances
521
522 ## Retrieve [LibraryClasses] information
523 def _GetLibraryClasses(self):
524 if self._LibraryClasses == None:
525 self._LibraryInstances = []
526 #
527 # tdict is a special dict kind of type, used for selecting correct
528 # library instance for given library class and module type
529 #
530 LibraryClassDict = tdict(True, 3)
531 # track all library class names
532 LibraryClassSet = set()
533 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
534 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
535 Macros.update(self._Macros)
536 for Record in RecordList:
537 LibraryClass, LibraryInstance, Dummy, Arch, ModuleType, Dummy, LineNo = Record
538 if LibraryClass == '' or LibraryClass == 'NULL':
539 self._NullLibraryNumber += 1
540 LibraryClass = 'NULL%d' % self._NullLibraryNumber
541 EdkLogger.verbose("Found forced library for arch=%s\n\t%s [%s]" % (Arch, LibraryInstance, LibraryClass))
542 LibraryClassSet.add(LibraryClass)
543 LibraryInstance = PathClass(NormPath(LibraryInstance, Macros), GlobalData.gWorkspace, Arch=self._Arch)
544 # check the file validation
545 ErrorCode, ErrorInfo = LibraryInstance.Validate('.inf')
546 if ErrorCode != 0:
547 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
548 ExtraData=ErrorInfo)
549
550 if ModuleType != 'COMMON' and ModuleType not in SUP_MODULE_LIST:
551 EdkLogger.error('build', OPTION_UNKNOWN, "Unknown module type [%s]" % ModuleType,
552 File=self.MetaFile, ExtraData=LibraryInstance, Line=LineNo)
553 LibraryClassDict[Arch, ModuleType, LibraryClass] = LibraryInstance
554 if LibraryInstance not in self._LibraryInstances:
555 self._LibraryInstances.append(LibraryInstance)
556
557 # resolve the specific library instance for each class and each module type
558 self._LibraryClasses = tdict(True)
559 for LibraryClass in LibraryClassSet:
560 # try all possible module types
561 for ModuleType in SUP_MODULE_LIST:
562 LibraryInstance = LibraryClassDict[self._Arch, ModuleType, LibraryClass]
563 if LibraryInstance == None:
564 continue
565 self._LibraryClasses[LibraryClass, ModuleType] = LibraryInstance
566
567 # for EDK style library instances, which are listed in different section
568 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch]
569 for Record in RecordList:
570 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
571 LineNo = Record[-1]
572 # check the file validation
573 ErrorCode, ErrorInfo = File.Validate('.inf')
574 if ErrorCode != 0:
575 EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
576 ExtraData=ErrorInfo)
577 if File not in self._LibraryInstances:
578 self._LibraryInstances.append(File)
579 #
580 # we need the module name as the library class name, so we have
581 # to parse it here. (self._Bdb[] will trigger a file parse if it
582 # hasn't been parsed)
583 #
584 Library = self._Bdb[File, self._Arch]
585 self._LibraryClasses[Library.BaseName, ':dummy:'] = Library
586 return self._LibraryClasses
587
588 ## Retrieve all PCD settings in platform
589 def _GetPcds(self):
590 if self._Pcds == None:
591 self._Pcds = {}
592 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
593 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
594 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
595 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_DEFAULT))
596 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_HII))
597 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_VPD))
598 self._Pcds.update(self._GetDynamicPcd(MODEL_PCD_DYNAMIC_EX_DEFAULT))
599 self._Pcds.update(self._GetDynamicHiiPcd(MODEL_PCD_DYNAMIC_EX_HII))
600 self._Pcds.update(self._GetDynamicVpdPcd(MODEL_PCD_DYNAMIC_EX_VPD))
601 return self._Pcds
602
603 ## Retrieve [BuildOptions]
604 def _GetBuildOptions(self):
605 if self._BuildOptions == None:
606 self._BuildOptions = {}
607 #
608 # Retrieve build option for EDKII style module
609 #
610 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, 'COMMON', EDKII_NAME]
611 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
612 self._BuildOptions[ToolChainFamily, ToolChain, EDKII_NAME] = Option
613 #
614 # Retrieve build option for EDK style module
615 #
616 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, 'COMMON', EDK_NAME]
617 for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4 in RecordList:
618 self._BuildOptions[ToolChainFamily, ToolChain, EDK_NAME] = Option
619 return self._BuildOptions
620
621 ## Retrieve non-dynamic PCD settings
622 #
623 # @param Type PCD type
624 #
625 # @retval a dict object contains settings of given PCD type
626 #
627 def _GetPcd(self, Type):
628 Pcds = {}
629 #
630 # tdict is a special dict kind of type, used for selecting correct
631 # PCD settings for certain ARCH
632 #
633 PcdDict = tdict(True, 3)
634 PcdSet = set()
635 # Find out all possible PCD candidates for self._Arch
636 RecordList = self._RawData[Type, self._Arch]
637 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
638 PcdSet.add((PcdCName, TokenSpaceGuid))
639 PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting
640 # Remove redundant PCD candidates
641 for PcdCName, TokenSpaceGuid in PcdSet:
642 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
643 if Setting == None:
644 continue
645 PcdValue, DatumType, MaxDatumSize = AnalyzePcdData(Setting)
646 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
647 PcdCName,
648 TokenSpaceGuid,
649 self._PCD_TYPE_STRING_[Type],
650 DatumType,
651 PcdValue,
652 '',
653 MaxDatumSize,
654 {},
655 False,
656 None
657 )
658 return Pcds
659
660 ## Retrieve dynamic PCD settings
661 #
662 # @param Type PCD type
663 #
664 # @retval a dict object contains settings of given PCD type
665 #
666 def _GetDynamicPcd(self, Type):
667 Pcds = {}
668 #
669 # tdict is a special dict kind of type, used for selecting correct
670 # PCD settings for certain ARCH and SKU
671 #
672 PcdDict = tdict(True, 4)
673 PcdList = []
674 # Find out all possible PCD candidates for self._Arch
675 RecordList = self._RawData[Type, self._Arch]
676 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
677 PcdList.append((PcdCName, TokenSpaceGuid))
678 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
679 # Remove redundant PCD candidates, per the ARCH and SKU
680 for PcdCName, TokenSpaceGuid in PcdList:
681 Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]
682 if Setting == None:
683 continue
684
685 PcdValue, DatumType, MaxDatumSize = AnalyzePcdData(Setting)
686
687 SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', '', PcdValue)
688 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
689 PcdCName,
690 TokenSpaceGuid,
691 self._PCD_TYPE_STRING_[Type],
692 DatumType,
693 PcdValue,
694 '',
695 MaxDatumSize,
696 {self.SkuName : SkuInfo},
697 False,
698 None
699 )
700 return Pcds
701
702 ## Retrieve dynamic HII PCD settings
703 #
704 # @param Type PCD type
705 #
706 # @retval a dict object contains settings of given PCD type
707 #
708 def _GetDynamicHiiPcd(self, Type):
709 Pcds = {}
710 #
711 # tdict is a special dict kind of type, used for selecting correct
712 # PCD settings for certain ARCH and SKU
713 #
714 PcdDict = tdict(True, 4)
715 PcdSet = set()
716 RecordList = self._RawData[Type, self._Arch]
717 # Find out all possible PCD candidates for self._Arch
718 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
719 PcdSet.add((PcdCName, TokenSpaceGuid))
720 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
721 # Remove redundant PCD candidates, per the ARCH and SKU
722 for PcdCName, TokenSpaceGuid in PcdSet:
723 Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]
724 if Setting == None:
725 continue
726 VariableName, VariableGuid, VariableOffset, DefaultValue = AnalyzeHiiPcdData(Setting)
727 SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue)
728 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
729 PcdCName,
730 TokenSpaceGuid,
731 self._PCD_TYPE_STRING_[Type],
732 '',
733 DefaultValue,
734 '',
735 '',
736 {self.SkuName : SkuInfo},
737 False,
738 None
739 )
740 return Pcds
741
742 ## Retrieve dynamic VPD PCD settings
743 #
744 # @param Type PCD type
745 #
746 # @retval a dict object contains settings of given PCD type
747 #
748 def _GetDynamicVpdPcd(self, Type):
749 Pcds = {}
750 #
751 # tdict is a special dict kind of type, used for selecting correct
752 # PCD settings for certain ARCH and SKU
753 #
754 PcdDict = tdict(True, 4)
755 PcdList = []
756 # Find out all possible PCD candidates for self._Arch
757 RecordList = self._RawData[Type, self._Arch]
758 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
759 PcdList.append((PcdCName, TokenSpaceGuid))
760 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
761 # Remove redundant PCD candidates, per the ARCH and SKU
762 for PcdCName, TokenSpaceGuid in PcdList:
763 Setting = PcdDict[self._Arch, self.SkuName, PcdCName, TokenSpaceGuid]
764 if Setting == None:
765 continue
766 #
767 # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
768 # For the Integer & Boolean type, the optional data can only be InitialValue.
769 # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
770 # until the DEC parser has been called.
771 #
772 VpdOffset, MaxDatumSize, InitialValue = AnalyzeVpdPcdData(Setting)
773
774 SkuInfo = SkuInfoClass(self.SkuName, self.SkuIds[self.SkuName], '', '', '', '', VpdOffset, InitialValue)
775 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
776 PcdCName,
777 TokenSpaceGuid,
778 self._PCD_TYPE_STRING_[Type],
779 '',
780 '',
781 '',
782 MaxDatumSize,
783 {self.SkuName : SkuInfo},
784 False,
785 None
786 )
787 return Pcds
788
789 ## Add external modules
790 #
791 # The external modules are mostly those listed in FDF file, which don't
792 # need "build".
793 #
794 # @param FilePath The path of module description file
795 #
796 def AddModule(self, FilePath):
797 FilePath = NormPath(FilePath)
798 if FilePath not in self.Modules:
799 Module = ModuleBuildClassObject()
800 Module.MetaFile = FilePath
801 self.Modules.append(Module)
802
803 ## Add external PCDs
804 #
805 # The external PCDs are mostly those listed in FDF file to specify address
806 # or offset information.
807 #
808 # @param Name Name of the PCD
809 # @param Guid Token space guid of the PCD
810 # @param Value Value of the PCD
811 #
812 def AddPcd(self, Name, Guid, Value):
813 if (Name, Guid) not in self.Pcds:
814 self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
815 self.Pcds[Name, Guid].DefaultValue = Value
816
817 Arch = property(_GetArch, _SetArch)
818 Platform = property(_GetPlatformName)
819 PlatformName = property(_GetPlatformName)
820 Guid = property(_GetFileGuid)
821 Version = property(_GetVersion)
822 DscSpecification = property(_GetDscSpec)
823 OutputDirectory = property(_GetOutpuDir)
824 SupArchList = property(_GetSupArch)
825 BuildTargets = property(_GetBuildTarget)
826 SkuName = property(_GetSkuName, _SetSkuName)
827 FlashDefinition = property(_GetFdfFile)
828 BuildNumber = property(_GetBuildNumber)
829 MakefileName = property(_GetMakefileName)
830 BsBaseAddress = property(_GetBsBaseAddress)
831 RtBaseAddress = property(_GetRtBaseAddress)
832 LoadFixAddress = property(_GetLoadFixAddress)
833 RFCLanguages = property(_GetRFCLanguages)
834 ISOLanguages = property(_GetISOLanguages)
835 VpdToolGuid = property(_GetVpdToolGuid)
836 SkuIds = property(_GetSkuIds)
837 Modules = property(_GetModules)
838 LibraryInstances = property(_GetLibraryInstances)
839 LibraryClasses = property(_GetLibraryClasses)
840 Pcds = property(_GetPcds)
841 BuildOptions = property(_GetBuildOptions)
842
843 ## Platform build information from DEC file
844 #
845 # This class is used to retrieve information stored in database and convert them
846 # into PackageBuildClassObject form for easier use for AutoGen.
847 #
848 class DecBuildData(PackageBuildClassObject):
849 # dict used to convert PCD type in database to string used by build tool
850 _PCD_TYPE_STRING_ = {
851 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
852 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
853 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
854 MODEL_PCD_DYNAMIC : "Dynamic",
855 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
856 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
857 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
858 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
859 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
860 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
861 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
862 }
863
864 # dict used to convert part of [Defines] to members of DecBuildData directly
865 _PROPERTY_ = {
866 #
867 # Required Fields
868 #
869 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",
870 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",
871 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",
872 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",
873 }
874
875
876 ## Constructor of DecBuildData
877 #
878 # Initialize object of DecBuildData
879 #
880 # @param FilePath The path of package description file
881 # @param RawData The raw data of DEC file
882 # @param BuildDataBase Database used to retrieve module information
883 # @param Arch The target architecture
884 # @param Platform (not used for DecBuildData)
885 # @param Macros Macros used for replacement in DSC file
886 #
887 def __init__(self, File, RawData, BuildDataBase, Arch='COMMON', Platform='DUMMY', Macros={}):
888 self.MetaFile = File
889 self._PackageDir = File.Dir
890 self._RawData = RawData
891 self._Bdb = BuildDataBase
892 self._Arch = Arch
893 self._Macros = Macros
894 self._Clear()
895
896 ## XXX[key] = value
897 def __setitem__(self, key, value):
898 self.__dict__[self._PROPERTY_[key]] = value
899
900 ## value = XXX[key]
901 def __getitem__(self, key):
902 return self.__dict__[self._PROPERTY_[key]]
903
904 ## "in" test support
905 def __contains__(self, key):
906 return key in self._PROPERTY_
907
908 ## Set all internal used members of DecBuildData to None
909 def _Clear(self):
910 self._Header = None
911 self._PackageName = None
912 self._Guid = None
913 self._Version = None
914 self._PkgUniFile = None
915 self._Protocols = None
916 self._Ppis = None
917 self._Guids = None
918 self._Includes = None
919 self._LibraryClasses = None
920 self._Pcds = None
921
922 ## Get architecture
923 def _GetArch(self):
924 return self._Arch
925
926 ## Set architecture
927 #
928 # Changing the default ARCH to another may affect all other information
929 # because all information in a platform may be ARCH-related. That's
930 # why we need to clear all internal used members, in order to cause all
931 # information to be re-retrieved.
932 #
933 # @param Value The value of ARCH
934 #
935 def _SetArch(self, Value):
936 if self._Arch == Value:
937 return
938 self._Arch = Value
939 self._Clear()
940
941 ## Retrieve all information in [Defines] section
942 #
943 # (Retriving all [Defines] information in one-shot is just to save time.)
944 #
945 def _GetHeaderInfo(self):
946 RecordList = self._RawData[MODEL_META_DATA_HEADER]
947 for Record in RecordList:
948 Name = Record[0]
949 if Name in self:
950 self[Name] = Record[1]
951 self._Header = 'DUMMY'
952
953 ## Retrieve package name
954 def _GetPackageName(self):
955 if self._PackageName == None:
956 if self._Header == None:
957 self._GetHeaderInfo()
958 if self._PackageName == None:
959 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
960 return self._PackageName
961
962 ## Retrieve file guid
963 def _GetFileGuid(self):
964 if self._Guid == None:
965 if self._Header == None:
966 self._GetHeaderInfo()
967 if self._Guid == None:
968 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
969 return self._Guid
970
971 ## Retrieve package version
972 def _GetVersion(self):
973 if self._Version == None:
974 if self._Header == None:
975 self._GetHeaderInfo()
976 if self._Version == None:
977 self._Version = ''
978 return self._Version
979
980 ## Retrieve protocol definitions (name/value pairs)
981 def _GetProtocol(self):
982 if self._Protocols == None:
983 #
984 # tdict is a special kind of dict, used for selecting correct
985 # protocol defition for given ARCH
986 #
987 ProtocolDict = tdict(True)
988 NameList = []
989 # find out all protocol definitions for specific and 'common' arch
990 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
991 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
992 if Name not in NameList:
993 NameList.append(Name)
994 ProtocolDict[Arch, Name] = Guid
995 # use sdict to keep the order
996 self._Protocols = sdict()
997 for Name in NameList:
998 #
999 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1000 # will automatically turn to 'common' ARCH for trying
1001 #
1002 self._Protocols[Name] = ProtocolDict[self._Arch, Name]
1003 return self._Protocols
1004
1005 ## Retrieve PPI definitions (name/value pairs)
1006 def _GetPpi(self):
1007 if self._Ppis == None:
1008 #
1009 # tdict is a special kind of dict, used for selecting correct
1010 # PPI defition for given ARCH
1011 #
1012 PpiDict = tdict(True)
1013 NameList = []
1014 # find out all PPI definitions for specific arch and 'common' arch
1015 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
1016 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
1017 if Name not in NameList:
1018 NameList.append(Name)
1019 PpiDict[Arch, Name] = Guid
1020 # use sdict to keep the order
1021 self._Ppis = sdict()
1022 for Name in NameList:
1023 #
1024 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1025 # will automatically turn to 'common' ARCH for trying
1026 #
1027 self._Ppis[Name] = PpiDict[self._Arch, Name]
1028 return self._Ppis
1029
1030 ## Retrieve GUID definitions (name/value pairs)
1031 def _GetGuid(self):
1032 if self._Guids == None:
1033 #
1034 # tdict is a special kind of dict, used for selecting correct
1035 # GUID defition for given ARCH
1036 #
1037 GuidDict = tdict(True)
1038 NameList = []
1039 # find out all protocol definitions for specific and 'common' arch
1040 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
1041 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
1042 if Name not in NameList:
1043 NameList.append(Name)
1044 GuidDict[Arch, Name] = Guid
1045 # use sdict to keep the order
1046 self._Guids = sdict()
1047 for Name in NameList:
1048 #
1049 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1050 # will automatically turn to 'common' ARCH for trying
1051 #
1052 self._Guids[Name] = GuidDict[self._Arch, Name]
1053 return self._Guids
1054
1055 ## Retrieve public include paths declared in this package
1056 def _GetInclude(self):
1057 if self._Includes == None:
1058 self._Includes = []
1059 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
1060 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1061 Macros.update(self._Macros)
1062 for Record in RecordList:
1063 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
1064 LineNo = Record[-1]
1065 # validate the path
1066 ErrorCode, ErrorInfo = File.Validate()
1067 if ErrorCode != 0:
1068 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1069
1070 # avoid duplicate include path
1071 if File not in self._Includes:
1072 self._Includes.append(File)
1073 return self._Includes
1074
1075 ## Retrieve library class declarations (not used in build at present)
1076 def _GetLibraryClass(self):
1077 if self._LibraryClasses == None:
1078 #
1079 # tdict is a special kind of dict, used for selecting correct
1080 # library class declaration for given ARCH
1081 #
1082 LibraryClassDict = tdict(True)
1083 LibraryClassSet = set()
1084 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
1085 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1086 Macros.update(self._Macros)
1087 for LibraryClass, File, Dummy, Arch, ID, LineNo in RecordList:
1088 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
1089 # check the file validation
1090 ErrorCode, ErrorInfo = File.Validate()
1091 if ErrorCode != 0:
1092 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1093 LibraryClassSet.add(LibraryClass)
1094 LibraryClassDict[Arch, LibraryClass] = File
1095 self._LibraryClasses = sdict()
1096 for LibraryClass in LibraryClassSet:
1097 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
1098 return self._LibraryClasses
1099
1100 ## Retrieve PCD declarations
1101 def _GetPcds(self):
1102 if self._Pcds == None:
1103 self._Pcds = {}
1104 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1105 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1106 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1107 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
1108 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
1109 return self._Pcds
1110
1111 ## Retrieve PCD declarations for given type
1112 def _GetPcd(self, Type):
1113 Pcds = {}
1114 #
1115 # tdict is a special kind of dict, used for selecting correct
1116 # PCD declaration for given ARCH
1117 #
1118 PcdDict = tdict(True, 3)
1119 # for summarizing PCD
1120 PcdSet = set()
1121 # find out all PCDs of the 'type'
1122 RecordList = self._RawData[Type, self._Arch]
1123 for TokenSpaceGuid, PcdCName, Setting, Arch, Dummy1, Dummy2 in RecordList:
1124 PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting
1125 PcdSet.add((PcdCName, TokenSpaceGuid))
1126
1127 for PcdCName, TokenSpaceGuid in PcdSet:
1128 #
1129 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1130 # will automatically turn to 'common' ARCH and try again
1131 #
1132 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
1133 if Setting == None:
1134 continue
1135
1136 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
1137
1138 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject(
1139 PcdCName,
1140 TokenSpaceGuid,
1141 self._PCD_TYPE_STRING_[Type],
1142 DatumType,
1143 DefaultValue,
1144 TokenNumber,
1145 '',
1146 {},
1147 False,
1148 None
1149 )
1150 return Pcds
1151
1152
1153 Arch = property(_GetArch, _SetArch)
1154 PackageName = property(_GetPackageName)
1155 Guid = property(_GetFileGuid)
1156 Version = property(_GetVersion)
1157
1158 Protocols = property(_GetProtocol)
1159 Ppis = property(_GetPpi)
1160 Guids = property(_GetGuid)
1161 Includes = property(_GetInclude)
1162 LibraryClasses = property(_GetLibraryClass)
1163 Pcds = property(_GetPcds)
1164
1165 ## Module build information from INF file
1166 #
1167 # This class is used to retrieve information stored in database and convert them
1168 # into ModuleBuildClassObject form for easier use for AutoGen.
1169 #
1170 class InfBuildData(ModuleBuildClassObject):
1171 # dict used to convert PCD type in database to string used by build tool
1172 _PCD_TYPE_STRING_ = {
1173 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
1174 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
1175 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
1176 MODEL_PCD_DYNAMIC : "Dynamic",
1177 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
1178 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
1179 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
1180 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
1181 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
1182 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
1183 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
1184 }
1185
1186 # dict used to convert part of [Defines] to members of InfBuildData directly
1187 _PROPERTY_ = {
1188 #
1189 # Required Fields
1190 #
1191 TAB_INF_DEFINES_BASE_NAME : "_BaseName",
1192 TAB_INF_DEFINES_FILE_GUID : "_Guid",
1193 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
1194 #
1195 # Optional Fields
1196 #
1197 TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
1198 TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType",
1199 TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName",
1200 #TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
1201 TAB_INF_DEFINES_DPX_SOURCE :"_DxsFile",
1202 TAB_INF_DEFINES_VERSION_NUMBER : "_Version",
1203 TAB_INF_DEFINES_VERSION_STRING : "_Version",
1204 TAB_INF_DEFINES_VERSION : "_Version",
1205 TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver",
1206 TAB_INF_DEFINES_SHADOW : "_Shadow",
1207
1208 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH : "_SourceOverridePath",
1209 }
1210
1211 # dict used to convert Component type to Module type
1212 _MODULE_TYPE_ = {
1213 "LIBRARY" : "BASE",
1214 "SECURITY_CORE" : "SEC",
1215 "PEI_CORE" : "PEI_CORE",
1216 "COMBINED_PEIM_DRIVER" : "PEIM",
1217 "PIC_PEIM" : "PEIM",
1218 "RELOCATABLE_PEIM" : "PEIM",
1219 "PE32_PEIM" : "PEIM",
1220 "BS_DRIVER" : "DXE_DRIVER",
1221 "RT_DRIVER" : "DXE_RUNTIME_DRIVER",
1222 "SAL_RT_DRIVER" : "DXE_SAL_DRIVER",
1223 "DXE_SMM_DRIVER" : "DXE_SMM_DRIVER",
1224 # "SMM_DRIVER" : "DXE_SMM_DRIVER",
1225 # "BS_DRIVER" : "DXE_SMM_DRIVER",
1226 # "BS_DRIVER" : "UEFI_DRIVER",
1227 "APPLICATION" : "UEFI_APPLICATION",
1228 "LOGO" : "BASE",
1229 }
1230
1231 # regular expression for converting XXX_FLAGS in [nmake] section to new type
1232 _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE)
1233 # dict used to convert old tool name used in [nmake] section to new ones
1234 _TOOL_CODE_ = {
1235 "C" : "CC",
1236 "LIB" : "SLINK",
1237 "LINK" : "DLINK",
1238 }
1239
1240
1241 ## Constructor of DscBuildData
1242 #
1243 # Initialize object of DscBuildData
1244 #
1245 # @param FilePath The path of platform description file
1246 # @param RawData The raw data of DSC file
1247 # @param BuildDataBase Database used to retrieve module/package information
1248 # @param Arch The target architecture
1249 # @param Platform The name of platform employing this module
1250 # @param Macros Macros used for replacement in DSC file
1251 #
1252 def __init__(self, FilePath, RawData, BuildDatabase, Arch='COMMON', Platform='COMMON', Macros={}):
1253 self.MetaFile = FilePath
1254 self._ModuleDir = FilePath.Dir
1255 self._RawData = RawData
1256 self._Bdb = BuildDatabase
1257 self._Arch = Arch
1258 self._Platform = 'COMMON'
1259 self._Macros = Macros
1260 self._SourceOverridePath = None
1261 if FilePath.Key in GlobalData.gOverrideDir:
1262 self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key]
1263 self._Clear()
1264
1265 ## XXX[key] = value
1266 def __setitem__(self, key, value):
1267 self.__dict__[self._PROPERTY_[key]] = value
1268
1269 ## value = XXX[key]
1270 def __getitem__(self, key):
1271 return self.__dict__[self._PROPERTY_[key]]
1272
1273 ## "in" test support
1274 def __contains__(self, key):
1275 return key in self._PROPERTY_
1276
1277 ## Set all internal used members of InfBuildData to None
1278 def _Clear(self):
1279 self._Header_ = None
1280 self._AutoGenVersion = None
1281 self._BaseName = None
1282 self._DxsFile = None
1283 self._ModuleType = None
1284 self._ComponentType = None
1285 self._BuildType = None
1286 self._Guid = None
1287 self._Version = None
1288 self._PcdIsDriver = None
1289 self._BinaryModule = None
1290 self._Shadow = None
1291 self._MakefileName = None
1292 self._CustomMakefile = None
1293 self._Specification = None
1294 self._LibraryClass = None
1295 self._ModuleEntryPointList = None
1296 self._ModuleUnloadImageList = None
1297 self._ConstructorList = None
1298 self._DestructorList = None
1299 self._Defs = None
1300 self._Binaries = None
1301 self._Sources = None
1302 self._LibraryClasses = None
1303 self._Libraries = None
1304 self._Protocols = None
1305 self._Ppis = None
1306 self._Guids = None
1307 self._Includes = None
1308 self._Packages = None
1309 self._Pcds = None
1310 self._BuildOptions = None
1311 self._Depex = None
1312 self._DepexExpression = None
1313 #self._SourceOverridePath = None
1314
1315 ## Get architecture
1316 def _GetArch(self):
1317 return self._Arch
1318
1319 ## Set architecture
1320 #
1321 # Changing the default ARCH to another may affect all other information
1322 # because all information in a platform may be ARCH-related. That's
1323 # why we need to clear all internal used members, in order to cause all
1324 # information to be re-retrieved.
1325 #
1326 # @param Value The value of ARCH
1327 #
1328 def _SetArch(self, Value):
1329 if self._Arch == Value:
1330 return
1331 self._Arch = Value
1332 self._Clear()
1333
1334 ## Return the name of platform employing this module
1335 def _GetPlatform(self):
1336 return self._Platform
1337
1338 ## Change the name of platform employing this module
1339 #
1340 # Changing the default name of platform to another may affect some information
1341 # because they may be PLATFORM-related. That's why we need to clear all internal
1342 # used members, in order to cause all information to be re-retrieved.
1343 #
1344 def _SetPlatform(self, Value):
1345 if self._Platform == Value:
1346 return
1347 self._Platform = Value
1348 self._Clear()
1349
1350 ## Retrieve all information in [Defines] section
1351 #
1352 # (Retriving all [Defines] information in one-shot is just to save time.)
1353 #
1354 def _GetHeaderInfo(self):
1355 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
1356 for Record in RecordList:
1357 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1358 Name = Record[0]
1359 # items defined _PROPERTY_ don't need additional processing
1360 if Name in self:
1361 self[Name] = Record[1]
1362 # some special items in [Defines] section need special treatment
1363 elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
1364 if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
1365 Name = 'UEFI_SPECIFICATION_VERSION'
1366 if self._Specification == None:
1367 self._Specification = sdict()
1368 self._Specification[Name] = GetHexVerValue(Record[1])
1369 if self._Specification[Name] == None:
1370 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1371 "'%s' format is not supported for %s" % (Record[1], Name),
1372 File=self.MetaFile, Line=Record[-1])
1373 elif Name == 'LIBRARY_CLASS':
1374 if self._LibraryClass == None:
1375 self._LibraryClass = []
1376 ValueList = GetSplitValueList(Record[1])
1377 LibraryClass = ValueList[0]
1378 if len(ValueList) > 1:
1379 SupModuleList = GetSplitValueList(ValueList[1], ' ')
1380 else:
1381 SupModuleList = SUP_MODULE_LIST
1382 self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList))
1383 elif Name == 'ENTRY_POINT':
1384 if self._ModuleEntryPointList == None:
1385 self._ModuleEntryPointList = []
1386 self._ModuleEntryPointList.append(Record[1])
1387 elif Name == 'UNLOAD_IMAGE':
1388 if self._ModuleUnloadImageList == None:
1389 self._ModuleUnloadImageList = []
1390 if Record[1] == '':
1391 continue
1392 self._ModuleUnloadImageList.append(Record[1])
1393 elif Name == 'CONSTRUCTOR':
1394 if self._ConstructorList == None:
1395 self._ConstructorList = []
1396 if Record[1] == '':
1397 continue
1398 self._ConstructorList.append(Record[1])
1399 elif Name == 'DESTRUCTOR':
1400 if self._DestructorList == None:
1401 self._DestructorList = []
1402 if Record[1] == '':
1403 continue
1404 self._DestructorList.append(Record[1])
1405 elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE:
1406 TokenList = GetSplitValueList(Record[1])
1407 if self._CustomMakefile == None:
1408 self._CustomMakefile = {}
1409 if len(TokenList) < 2:
1410 self._CustomMakefile['MSFT'] = TokenList[0]
1411 self._CustomMakefile['GCC'] = TokenList[0]
1412 else:
1413 if TokenList[0] not in ['MSFT', 'GCC']:
1414 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1415 "No supported family [%s]" % TokenList[0],
1416 File=self.MetaFile, Line=Record[-1])
1417 self._CustomMakefile[TokenList[0]] = TokenList[1]
1418 else:
1419 if self._Defs == None:
1420 self._Defs = sdict()
1421 self._Defs[Name] = Record[1]
1422
1423 #
1424 # Retrieve information in sections specific to EDK.x modules
1425 #
1426 if self._AutoGenVersion >= 0x00010005: # _AutoGenVersion may be None, which is less than anything
1427 if not self._ModuleType:
1428 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1429 "MODULE_TYPE is not given", File=self.MetaFile)
1430 if self._ModuleType not in SUP_MODULE_LIST:
1431 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
1432 for Record in RecordList:
1433 Name = Record[0]
1434 if Name == "MODULE_TYPE":
1435 LineNo = Record[6]
1436 break
1437 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1438 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self._ModuleType,' '.join(l for l in SUP_MODULE_LIST)),
1439 File=self.MetaFile, Line=LineNo)
1440 if (self._Specification == None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
1441 if self._ModuleType == SUP_MODULE_SMM_CORE:
1442 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)
1443 if self._Defs and 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \
1444 and 'PCI_CLASS_CODE' in self._Defs:
1445 self._BuildType = 'UEFI_OPTIONROM'
1446 elif self._Defs and 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
1447 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
1448 self._BuildType = 'UEFI_HII'
1449 else:
1450 self._BuildType = self._ModuleType.upper()
1451
1452 if self._DxsFile:
1453 File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch)
1454 # check the file validation
1455 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
1456 if ErrorCode != 0:
1457 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
1458 File=self.MetaFile, Line=LineNo)
1459 if self.Sources == None:
1460 self._Sources = []
1461 self._Sources.append(File)
1462 else:
1463 self._BuildType = self._ComponentType.upper()
1464 if not self._ComponentType:
1465 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1466 "COMPONENT_TYPE is not given", File=self.MetaFile)
1467 if self._ComponentType in self._MODULE_TYPE_:
1468 self._ModuleType = self._MODULE_TYPE_[self._ComponentType]
1469 if self._ComponentType == 'LIBRARY':
1470 self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)]
1471 # make use some [nmake] section macros
1472 RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform]
1473 for Name,Value,Dummy,Arch,Platform,ID,LineNo in RecordList:
1474 Value = Value.replace('$(PROCESSOR)', self._Arch)
1475 Name = Name.replace('$(PROCESSOR)', self._Arch)
1476 Name, Value = ReplaceMacros((Name, Value), GlobalData.gEdkGlobal, True)
1477 if Name == "IMAGE_ENTRY_POINT":
1478 if self._ModuleEntryPointList == None:
1479 self._ModuleEntryPointList = []
1480 self._ModuleEntryPointList.append(Value)
1481 elif Name == "DPX_SOURCE":
1482 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1483 Macros.update(self._Macros)
1484 File = PathClass(NormPath(Value, Macros), self._ModuleDir, Arch=self._Arch)
1485 # check the file validation
1486 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
1487 if ErrorCode != 0:
1488 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
1489 File=self.MetaFile, Line=LineNo)
1490 if self.Sources == None:
1491 self._Sources = []
1492 self._Sources.append(File)
1493 else:
1494 ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name)
1495 if len(ToolList) == 0 or len(ToolList) != 1:
1496 pass
1497 # EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name,
1498 # File=self.MetaFile, Line=LineNo)
1499 else:
1500 if self._BuildOptions == None:
1501 self._BuildOptions = sdict()
1502
1503 if ToolList[0] in self._TOOL_CODE_:
1504 Tool = self._TOOL_CODE_[ToolList[0]]
1505 else:
1506 Tool = ToolList[0]
1507 ToolChain = "*_*_*_%s_FLAGS" % Tool
1508 ToolChainFamily = 'MSFT' # EDK.x only support MSFT tool chain
1509 #ignore not replaced macros in value
1510 ValueList = GetSplitValueList(' ' + Value, '/D')
1511 Dummy = ValueList[0]
1512 for Index in range(1, len(ValueList)):
1513 if ValueList[Index][-1] == '=' or ValueList[Index] == '':
1514 continue
1515 Dummy = Dummy + ' /D ' + ValueList[Index]
1516 Value = Dummy.strip()
1517 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1518 self._BuildOptions[ToolChainFamily, ToolChain] = Value
1519 else:
1520 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1521 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value
1522 # set _Header to non-None in order to avoid database re-querying
1523 self._Header_ = 'DUMMY'
1524
1525 ## Retrieve file version
1526 def _GetInfVersion(self):
1527 if self._AutoGenVersion == None:
1528 if self._Header_ == None:
1529 self._GetHeaderInfo()
1530 if self._AutoGenVersion == None:
1531 self._AutoGenVersion = 0x00010000
1532 return self._AutoGenVersion
1533
1534 ## Retrieve BASE_NAME
1535 def _GetBaseName(self):
1536 if self._BaseName == None:
1537 if self._Header_ == None:
1538 self._GetHeaderInfo()
1539 if self._BaseName == None:
1540 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
1541 return self._BaseName
1542
1543 ## Retrieve DxsFile
1544 def _GetDxsFile(self):
1545 if self._DxsFile == None:
1546 if self._Header_ == None:
1547 self._GetHeaderInfo()
1548 if self._DxsFile == None:
1549 self._DxsFile = ''
1550 return self._DxsFile
1551
1552 ## Retrieve MODULE_TYPE
1553 def _GetModuleType(self):
1554 if self._ModuleType == None:
1555 if self._Header_ == None:
1556 self._GetHeaderInfo()
1557 if self._ModuleType == None:
1558 self._ModuleType = 'BASE'
1559 if self._ModuleType not in SUP_MODULE_LIST:
1560 self._ModuleType = "USER_DEFINED"
1561 return self._ModuleType
1562
1563 ## Retrieve COMPONENT_TYPE
1564 def _GetComponentType(self):
1565 if self._ComponentType == None:
1566 if self._Header_ == None:
1567 self._GetHeaderInfo()
1568 if self._ComponentType == None:
1569 self._ComponentType = 'USER_DEFINED'
1570 return self._ComponentType
1571
1572 ## Retrieve "BUILD_TYPE"
1573 def _GetBuildType(self):
1574 if self._BuildType == None:
1575 if self._Header_ == None:
1576 self._GetHeaderInfo()
1577 if not self._BuildType:
1578 self._BuildType = "BASE"
1579 return self._BuildType
1580
1581 ## Retrieve file guid
1582 def _GetFileGuid(self):
1583 if self._Guid == None:
1584 if self._Header_ == None:
1585 self._GetHeaderInfo()
1586 if self._Guid == None:
1587 self._Guid = '00000000-0000-0000-000000000000'
1588 return self._Guid
1589
1590 ## Retrieve module version
1591 def _GetVersion(self):
1592 if self._Version == None:
1593 if self._Header_ == None:
1594 self._GetHeaderInfo()
1595 if self._Version == None:
1596 self._Version = '0.0'
1597 return self._Version
1598
1599 ## Retrieve PCD_IS_DRIVER
1600 def _GetPcdIsDriver(self):
1601 if self._PcdIsDriver == None:
1602 if self._Header_ == None:
1603 self._GetHeaderInfo()
1604 if self._PcdIsDriver == None:
1605 self._PcdIsDriver = ''
1606 return self._PcdIsDriver
1607
1608 ## Retrieve SHADOW
1609 def _GetShadow(self):
1610 if self._Shadow == None:
1611 if self._Header_ == None:
1612 self._GetHeaderInfo()
1613 if self._Shadow != None and self._Shadow.upper() == 'TRUE':
1614 self._Shadow = True
1615 else:
1616 self._Shadow = False
1617 return self._Shadow
1618
1619 ## Retrieve CUSTOM_MAKEFILE
1620 def _GetMakefile(self):
1621 if self._CustomMakefile == None:
1622 if self._Header_ == None:
1623 self._GetHeaderInfo()
1624 if self._CustomMakefile == None:
1625 self._CustomMakefile = {}
1626 return self._CustomMakefile
1627
1628 ## Retrieve EFI_SPECIFICATION_VERSION
1629 def _GetSpec(self):
1630 if self._Specification == None:
1631 if self._Header_ == None:
1632 self._GetHeaderInfo()
1633 if self._Specification == None:
1634 self._Specification = {}
1635 return self._Specification
1636
1637 ## Retrieve LIBRARY_CLASS
1638 def _GetLibraryClass(self):
1639 if self._LibraryClass == None:
1640 if self._Header_ == None:
1641 self._GetHeaderInfo()
1642 if self._LibraryClass == None:
1643 self._LibraryClass = []
1644 return self._LibraryClass
1645
1646 ## Retrieve ENTRY_POINT
1647 def _GetEntryPoint(self):
1648 if self._ModuleEntryPointList == None:
1649 if self._Header_ == None:
1650 self._GetHeaderInfo()
1651 if self._ModuleEntryPointList == None:
1652 self._ModuleEntryPointList = []
1653 return self._ModuleEntryPointList
1654
1655 ## Retrieve UNLOAD_IMAGE
1656 def _GetUnloadImage(self):
1657 if self._ModuleUnloadImageList == None:
1658 if self._Header_ == None:
1659 self._GetHeaderInfo()
1660 if self._ModuleUnloadImageList == None:
1661 self._ModuleUnloadImageList = []
1662 return self._ModuleUnloadImageList
1663
1664 ## Retrieve CONSTRUCTOR
1665 def _GetConstructor(self):
1666 if self._ConstructorList == None:
1667 if self._Header_ == None:
1668 self._GetHeaderInfo()
1669 if self._ConstructorList == None:
1670 self._ConstructorList = []
1671 return self._ConstructorList
1672
1673 ## Retrieve DESTRUCTOR
1674 def _GetDestructor(self):
1675 if self._DestructorList == None:
1676 if self._Header_ == None:
1677 self._GetHeaderInfo()
1678 if self._DestructorList == None:
1679 self._DestructorList = []
1680 return self._DestructorList
1681
1682 ## Retrieve definies other than above ones
1683 def _GetDefines(self):
1684 if self._Defs == None:
1685 if self._Header_ == None:
1686 self._GetHeaderInfo()
1687 if self._Defs == None:
1688 self._Defs = sdict()
1689 return self._Defs
1690
1691 ## Retrieve binary files
1692 def _GetBinaryFiles(self):
1693 if self._Binaries == None:
1694 self._Binaries = []
1695 RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
1696 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch}
1697 Macros.update(self._Macros)
1698 for Record in RecordList:
1699 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1700 FileType = Record[0]
1701 LineNo = Record[-1]
1702 Target = 'COMMON'
1703 FeatureFlag = []
1704 if Record[2]:
1705 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
1706 if TokenList:
1707 Target = TokenList[0]
1708 if len(TokenList) > 1:
1709 FeatureFlag = Record[1:]
1710
1711 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
1712 # check the file validation
1713 ErrorCode, ErrorInfo = File.Validate()
1714 if ErrorCode != 0:
1715 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1716 self._Binaries.append(File)
1717 return self._Binaries
1718
1719 ## Retrieve source files
1720 def _GetSourceFiles(self):
1721 if self._Sources == None:
1722 self._Sources = []
1723 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
1724 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch}
1725 Macros.update(self._Macros)
1726 for Record in RecordList:
1727 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1728 LineNo = Record[-1]
1729 ToolChainFamily = Record[1]
1730 TagName = Record[2]
1731 ToolCode = Record[3]
1732 FeatureFlag = Record[4]
1733 if self._AutoGenVersion < 0x00010005:
1734 # old module source files (EDK)
1735 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, self._SourceOverridePath,
1736 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
1737 # check the file validation
1738 ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
1739 if ErrorCode != 0:
1740 if File.Ext.lower() == '.h':
1741 EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo,
1742 File=self.MetaFile, Line=LineNo)
1743 continue
1744 else:
1745 EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo)
1746 else:
1747 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
1748 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
1749 # check the file validation
1750 ErrorCode, ErrorInfo = File.Validate()
1751 if ErrorCode != 0:
1752 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1753
1754 self._Sources.append(File)
1755 return self._Sources
1756
1757 ## Retrieve library classes employed by this module
1758 def _GetLibraryClassUses(self):
1759 if self._LibraryClasses == None:
1760 self._LibraryClasses = sdict()
1761 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
1762 for Record in RecordList:
1763 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1764 Lib = Record[0]
1765 Instance = Record[1]
1766 if Instance != None and Instance != '':
1767 Instance = NormPath(Instance, self._Macros)
1768 self._LibraryClasses[Lib] = Instance
1769 return self._LibraryClasses
1770
1771 ## Retrieve library names (for EDK.x style of modules)
1772 def _GetLibraryNames(self):
1773 if self._Libraries == None:
1774 self._Libraries = []
1775 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
1776 for Record in RecordList:
1777 # in case of name with '.lib' extension, which is unusual in EDK.x inf
1778 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1779 LibraryName = os.path.splitext(Record[0])[0]
1780 if LibraryName not in self._Libraries:
1781 self._Libraries.append(LibraryName)
1782 return self._Libraries
1783
1784 ## Retrieve protocols consumed/produced by this module
1785 def _GetProtocols(self):
1786 if self._Protocols == None:
1787 self._Protocols = sdict()
1788 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
1789 for Record in RecordList:
1790 CName = Record[0]
1791 Value = ProtocolValue(CName, self.Packages)
1792 if Value == None:
1793 PackageList = "\n\t".join([str(P) for P in self.Packages])
1794 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1795 "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
1796 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1797 self._Protocols[CName] = Value
1798 return self._Protocols
1799
1800 ## Retrieve PPIs consumed/produced by this module
1801 def _GetPpis(self):
1802 if self._Ppis == None:
1803 self._Ppis = sdict()
1804 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
1805 for Record in RecordList:
1806 CName = Record[0]
1807 Value = PpiValue(CName, self.Packages)
1808 if Value == None:
1809 PackageList = "\n\t".join([str(P) for P in self.Packages])
1810 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1811 "Value of PPI [%s] is not found under [Ppis] section in " % CName,
1812 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1813 self._Ppis[CName] = Value
1814 return self._Ppis
1815
1816 ## Retrieve GUIDs consumed/produced by this module
1817 def _GetGuids(self):
1818 if self._Guids == None:
1819 self._Guids = sdict()
1820 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
1821 for Record in RecordList:
1822 CName = Record[0]
1823 Value = GuidValue(CName, self.Packages)
1824 if Value == None:
1825 PackageList = "\n\t".join([str(P) for P in self.Packages])
1826 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1827 "Value of Guid [%s] is not found under [Guids] section in" % CName,
1828 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1829 self._Guids[CName] = Value
1830 return self._Guids
1831
1832 ## Retrieve include paths necessary for this module (for EDK.x style of modules)
1833 def _GetIncludes(self):
1834 if self._Includes == None:
1835 self._Includes = []
1836 if self._SourceOverridePath:
1837 self._Includes.append(self._SourceOverridePath)
1838 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
1839 # [includes] section must be used only in old (EDK.x) inf file
1840 if self.AutoGenVersion >= 0x00010005 and len(RecordList) > 0:
1841 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, "No [include] section allowed",
1842 File=self.MetaFile, Line=RecordList[0][-1]-1)
1843 for Record in RecordList:
1844 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1845 Record[0] = Record[0].replace('$(PROCESSOR)', self._Arch)
1846 Record[0] = ReplaceMacro(Record[0], {'EFI_SOURCE' : GlobalData.gEfiSource}, False)
1847 if Record[0].find('EDK_SOURCE') > -1:
1848 File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEcpSource}, False), self._Macros)
1849 if File[0] == '.':
1850 File = os.path.join(self._ModuleDir, File)
1851 else:
1852 File = os.path.join(GlobalData.gWorkspace, File)
1853 File = RealPath(os.path.normpath(File))
1854 if File:
1855 self._Includes.append(File)
1856
1857 #TRICK: let compiler to choose correct header file
1858 File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEdkSource}, False), self._Macros)
1859 if File[0] == '.':
1860 File = os.path.join(self._ModuleDir, File)
1861 else:
1862 File = os.path.join(GlobalData.gWorkspace, File)
1863 File = RealPath(os.path.normpath(File))
1864 if File:
1865 self._Includes.append(File)
1866 else:
1867 File = NormPath(Record[0], self._Macros)
1868 if File[0] == '.':
1869 File = os.path.join(self._ModuleDir, File)
1870 else:
1871 File = os.path.join(GlobalData.gWorkspace, File)
1872 File = RealPath(os.path.normpath(File))
1873 if File:
1874 self._Includes.append(File)
1875 return self._Includes
1876
1877 ## Retrieve packages this module depends on
1878 def _GetPackages(self):
1879 if self._Packages == None:
1880 self._Packages = []
1881 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
1882 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1883 Macros.update(self._Macros)
1884 for Record in RecordList:
1885 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
1886 LineNo = Record[-1]
1887 # check the file validation
1888 ErrorCode, ErrorInfo = File.Validate('.dec')
1889 if ErrorCode != 0:
1890 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1891 # parse this package now. we need it to get protocol/ppi/guid value
1892 Package = self._Bdb[File, self._Arch]
1893 self._Packages.append(Package)
1894 return self._Packages
1895
1896 ## Retrieve PCDs used in this module
1897 def _GetPcds(self):
1898 if self._Pcds == None:
1899 self._Pcds = {}
1900 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1901 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1902 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1903 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
1904 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
1905 return self._Pcds
1906
1907 ## Retrieve build options specific to this module
1908 def _GetBuildOptions(self):
1909 if self._BuildOptions == None:
1910 self._BuildOptions = sdict()
1911 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
1912 for Record in RecordList:
1913 ToolChainFamily = Record[0]
1914 ToolChain = Record[1]
1915 Option = Record[2]
1916 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1917 self._BuildOptions[ToolChainFamily, ToolChain] = Option
1918 else:
1919 # concatenate the option string if they're for the same tool
1920 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1921 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
1922 return self._BuildOptions
1923
1924 ## Retrieve depedency expression
1925 def _GetDepex(self):
1926 if self._Depex == None:
1927 self._Depex = tdict(False, 2)
1928 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
1929
1930 # If the module has only Binaries and no Sources, then ignore [Depex]
1931 if self.Sources == None or self.Sources == []:
1932 if self.Binaries <> None and self.Binaries <> []:
1933 return self._Depex
1934
1935 # PEIM and DXE drivers must have a valid [Depex] section
1936 if len(self.LibraryClass) == 0 and len(RecordList) == 0:
1937 if self.ModuleType == 'DXE_DRIVER' or self.ModuleType == 'PEIM' or self.ModuleType == 'DXE_SMM_DRIVER' or \
1938 self.ModuleType == 'DXE_SAL_DRIVER' or self.ModuleType == 'DXE_RUNTIME_DRIVER':
1939 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
1940 % self.ModuleType, File=self.MetaFile)
1941
1942 Depex = {}
1943 for Record in RecordList:
1944 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1945 Arch = Record[3]
1946 ModuleType = Record[4]
1947 TokenList = Record[0].split()
1948 if (Arch, ModuleType) not in Depex:
1949 Depex[Arch, ModuleType] = []
1950 DepexList = Depex[Arch, ModuleType]
1951 for Token in TokenList:
1952 if Token in DEPEX_SUPPORTED_OPCODE:
1953 DepexList.append(Token)
1954 elif Token.endswith(".inf"): # module file name
1955 ModuleFile = os.path.normpath(Token)
1956 Module = self.BuildDatabase[ModuleFile]
1957 if Module == None:
1958 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
1959 ExtraData=Token, File=self.MetaFile, Line=Record[-1])
1960 DepexList.append(Module.Guid)
1961 else:
1962 # get the GUID value now
1963 Value = ProtocolValue(Token, self.Packages)
1964 if Value == None:
1965 Value = PpiValue(Token, self.Packages)
1966 if Value == None:
1967 Value = GuidValue(Token, self.Packages)
1968 if Value == None:
1969 PackageList = "\n\t".join([str(P) for P in self.Packages])
1970 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1971 "Value of [%s] is not found in" % Token,
1972 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1973 DepexList.append(Value)
1974 for Arch, ModuleType in Depex:
1975 self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType]
1976 return self._Depex
1977
1978 ## Retrieve depedency expression
1979 def _GetDepexExpression(self):
1980 if self._DepexExpression == None:
1981 self._DepexExpression = tdict(False, 2)
1982 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
1983 DepexExpression = {}
1984 for Record in RecordList:
1985 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1986 Arch = Record[3]
1987 ModuleType = Record[4]
1988 TokenList = Record[0].split()
1989 if (Arch, ModuleType) not in DepexExpression:
1990 DepexExpression[Arch, ModuleType] = ''
1991 for Token in TokenList:
1992 DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] + Token.strip() + ' '
1993 for Arch, ModuleType in DepexExpression:
1994 self._DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType]
1995 return self._DepexExpression
1996
1997 ## Retrieve PCD for given type
1998 def _GetPcd(self, Type):
1999 Pcds = {}
2000 PcdDict = tdict(True, 4)
2001 PcdList = []
2002 RecordList = self._RawData[Type, self._Arch, self._Platform]
2003 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Dummy1, LineNo in RecordList:
2004 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
2005 PcdList.append((PcdCName, TokenSpaceGuid))
2006 # get the guid value
2007 if TokenSpaceGuid not in self.Guids:
2008 Value = GuidValue(TokenSpaceGuid, self.Packages)
2009 if Value == None:
2010 PackageList = "\n\t".join([str(P) for P in self.Packages])
2011 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
2012 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
2013 ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
2014 self.Guids[TokenSpaceGuid] = Value
2015
2016 # resolve PCD type, value, datum info, etc. by getting its definition from package
2017 for PcdCName, TokenSpaceGuid in PcdList:
2018 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
2019 if Setting == None:
2020 continue
2021 ValueList = AnalyzePcdData(Setting)
2022 DefaultValue = ValueList[0]
2023 Pcd = PcdClassObject(
2024 PcdCName,
2025 TokenSpaceGuid,
2026 '',
2027 '',
2028 DefaultValue,
2029 '',
2030 '',
2031 {},
2032 False,
2033 self.Guids[TokenSpaceGuid]
2034 )
2035
2036 # get necessary info from package declaring this PCD
2037 for Package in self.Packages:
2038 #
2039 # 'dynamic' in INF means its type is determined by platform;
2040 # if platform doesn't give its type, use 'lowest' one in the
2041 # following order, if any
2042 #
2043 # "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"
2044 #
2045 PcdType = self._PCD_TYPE_STRING_[Type]
2046 if Type == MODEL_PCD_DYNAMIC:
2047 Pcd.Pending = True
2048 for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]:
2049 if (PcdCName, TokenSpaceGuid, T) in Package.Pcds:
2050 PcdType = T
2051 break
2052 else:
2053 Pcd.Pending = False
2054
2055 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
2056 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
2057 Pcd.Type = PcdType
2058 Pcd.TokenValue = PcdInPackage.TokenValue
2059
2060 #
2061 # Check whether the token value exist or not.
2062 #
2063 if Pcd.TokenValue == None or Pcd.TokenValue == "":
2064 EdkLogger.error(
2065 'build',
2066 FORMAT_INVALID,
2067 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdCName, str(Package)),
2068 File =self.MetaFile, Line=LineNo,
2069 ExtraData=None
2070 )
2071 #
2072 # Check hexadecimal token value length and format.
2073 #
2074 if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"):
2075 if len(Pcd.TokenValue) < 3 or len(Pcd.TokenValue) > 10:
2076 EdkLogger.error(
2077 'build',
2078 FORMAT_INVALID,
2079 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2080 File =self.MetaFile, Line=LineNo,
2081 ExtraData=None
2082 )
2083 try:
2084 int (Pcd.TokenValue, 16)
2085 except:
2086 EdkLogger.error(
2087 'build',
2088 FORMAT_INVALID,
2089 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2090 File =self.MetaFile, Line=LineNo,
2091 ExtraData=None
2092 )
2093
2094 #
2095 # Check decimal token value length and format.
2096 #
2097 else:
2098 try:
2099 TokenValueInt = int (Pcd.TokenValue, 10)
2100 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
2101 EdkLogger.error(
2102 'build',
2103 FORMAT_INVALID,
2104 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, as a decimal it should between: 0 - 4294967295!"% (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2105 File =self.MetaFile, Line=LineNo,
2106 ExtraData=None
2107 )
2108 except:
2109 EdkLogger.error(
2110 'build',
2111 FORMAT_INVALID,
2112 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid, it should be hexadecimal or decimal!"% (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2113 File =self.MetaFile, Line=LineNo,
2114 ExtraData=None
2115 )
2116
2117 Pcd.DatumType = PcdInPackage.DatumType
2118 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
2119 Pcd.InfDefaultValue = Pcd.DefaultValue
2120 if Pcd.DefaultValue in [None, '']:
2121 Pcd.DefaultValue = PcdInPackage.DefaultValue
2122 break
2123 else:
2124 EdkLogger.error(
2125 'build',
2126 FORMAT_INVALID,
2127 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdCName, self.MetaFile),
2128 File =self.MetaFile, Line=LineNo,
2129 ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages])
2130 )
2131 Pcds[PcdCName, TokenSpaceGuid] = Pcd
2132
2133 return Pcds
2134
2135 Arch = property(_GetArch, _SetArch)
2136 Platform = property(_GetPlatform, _SetPlatform)
2137
2138 AutoGenVersion = property(_GetInfVersion)
2139 BaseName = property(_GetBaseName)
2140 ModuleType = property(_GetModuleType)
2141 ComponentType = property(_GetComponentType)
2142 BuildType = property(_GetBuildType)
2143 Guid = property(_GetFileGuid)
2144 Version = property(_GetVersion)
2145 PcdIsDriver = property(_GetPcdIsDriver)
2146 Shadow = property(_GetShadow)
2147 CustomMakefile = property(_GetMakefile)
2148 Specification = property(_GetSpec)
2149 LibraryClass = property(_GetLibraryClass)
2150 ModuleEntryPointList = property(_GetEntryPoint)
2151 ModuleUnloadImageList = property(_GetUnloadImage)
2152 ConstructorList = property(_GetConstructor)
2153 DestructorList = property(_GetDestructor)
2154 Defines = property(_GetDefines)
2155 DxsFile = property(_GetDxsFile)
2156
2157 Binaries = property(_GetBinaryFiles)
2158 Sources = property(_GetSourceFiles)
2159 LibraryClasses = property(_GetLibraryClassUses)
2160 Libraries = property(_GetLibraryNames)
2161 Protocols = property(_GetProtocols)
2162 Ppis = property(_GetPpis)
2163 Guids = property(_GetGuids)
2164 Includes = property(_GetIncludes)
2165 Packages = property(_GetPackages)
2166 Pcds = property(_GetPcds)
2167 BuildOptions = property(_GetBuildOptions)
2168 Depex = property(_GetDepex)
2169 DepexExpression = property(_GetDepexExpression)
2170
2171 ## Database
2172 #
2173 # This class defined the build database for all modules, packages and platform.
2174 # It will call corresponding parser for the given file if it cannot find it in
2175 # the database.
2176 #
2177 # @param DbPath Path of database file
2178 # @param GlobalMacros Global macros used for replacement during file parsing
2179 # @prarm RenewDb=False Create new database file if it's already there
2180 #
2181 class WorkspaceDatabase(object):
2182 # file parser
2183 _FILE_PARSER_ = {
2184 MODEL_FILE_INF : InfParser,
2185 MODEL_FILE_DEC : DecParser,
2186 MODEL_FILE_DSC : DscParser,
2187 MODEL_FILE_FDF : None, #FdfParser,
2188 MODEL_FILE_CIF : None
2189 }
2190
2191 # file table
2192 _FILE_TABLE_ = {
2193 MODEL_FILE_INF : ModuleTable,
2194 MODEL_FILE_DEC : PackageTable,
2195 MODEL_FILE_DSC : PlatformTable,
2196 }
2197
2198 # default database file path
2199 _DB_PATH_ = "Conf/.cache/build.db"
2200
2201 #
2202 # internal class used for call corresponding file parser and caching the result
2203 # to avoid unnecessary re-parsing
2204 #
2205 class BuildObjectFactory(object):
2206 _FILE_TYPE_ = {
2207 ".inf" : MODEL_FILE_INF,
2208 ".dec" : MODEL_FILE_DEC,
2209 ".dsc" : MODEL_FILE_DSC,
2210 ".fdf" : MODEL_FILE_FDF,
2211 }
2212
2213 # convert to xxxBuildData object
2214 _GENERATOR_ = {
2215 MODEL_FILE_INF : InfBuildData,
2216 MODEL_FILE_DEC : DecBuildData,
2217 MODEL_FILE_DSC : DscBuildData,
2218 MODEL_FILE_FDF : None #FlashDefTable,
2219 }
2220
2221 _CACHE_ = {} # (FilePath, Arch) : <object>
2222
2223 # constructor
2224 def __init__(self, WorkspaceDb):
2225 self.WorkspaceDb = WorkspaceDb
2226
2227 # key = (FilePath, Arch='COMMON')
2228 def __contains__(self, Key):
2229 FilePath = Key[0]
2230 Arch = 'COMMON'
2231 if len(Key) > 1:
2232 Arch = Key[1]
2233 return (FilePath, Arch) in self._CACHE_
2234
2235 # key = (FilePath, Arch='COMMON')
2236 def __getitem__(self, Key):
2237 FilePath = Key[0]
2238 Arch = 'COMMON'
2239 Platform = 'COMMON'
2240 if len(Key) > 1:
2241 Arch = Key[1]
2242 if len(Key) > 2:
2243 Platform = Key[2]
2244
2245 # if it's generated before, just return the cached one
2246 Key = (FilePath, Arch)
2247 if Key in self._CACHE_:
2248 return self._CACHE_[Key]
2249
2250 # check file type
2251 Ext = FilePath.Ext.lower()
2252 if Ext not in self._FILE_TYPE_:
2253 return None
2254 FileType = self._FILE_TYPE_[Ext]
2255 if FileType not in self._GENERATOR_:
2256 return None
2257
2258 # get table for current file
2259 MetaFile = self.WorkspaceDb[FilePath, FileType, self.WorkspaceDb._GlobalMacros]
2260 BuildObject = self._GENERATOR_[FileType](
2261 FilePath,
2262 MetaFile,
2263 self,
2264 Arch,
2265 Platform,
2266 self.WorkspaceDb._GlobalMacros,
2267 )
2268 self._CACHE_[Key] = BuildObject
2269 return BuildObject
2270
2271 # placeholder for file format conversion
2272 class TransformObjectFactory:
2273 def __init__(self, WorkspaceDb):
2274 self.WorkspaceDb = WorkspaceDb
2275
2276 # key = FilePath, Arch
2277 def __getitem__(self, Key):
2278 pass
2279
2280 ## Constructor of WorkspaceDatabase
2281 #
2282 # @param DbPath Path of database file
2283 # @param GlobalMacros Global macros used for replacement during file parsing
2284 # @prarm RenewDb=False Create new database file if it's already there
2285 #
2286 def __init__(self, DbPath, GlobalMacros={}, RenewDb=False):
2287 self._DbClosedFlag = False
2288 self._GlobalMacros = GlobalMacros
2289
2290 if DbPath == None or DbPath == '':
2291 DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_))
2292
2293 # don't create necessary path for db in memory
2294 if DbPath != ':memory:':
2295 DbDir = os.path.split(DbPath)[0]
2296 if not os.path.exists(DbDir):
2297 os.makedirs(DbDir)
2298
2299 # remove db file in case inconsistency between db and file in file system
2300 if self._CheckWhetherDbNeedRenew(RenewDb, DbPath):
2301 os.remove(DbPath)
2302
2303 # create db with optimized parameters
2304 self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED')
2305 self.Conn.execute("PRAGMA synchronous=OFF")
2306 self.Conn.execute("PRAGMA temp_store=MEMORY")
2307 self.Conn.execute("PRAGMA count_changes=OFF")
2308 self.Conn.execute("PRAGMA cache_size=8192")
2309 #self.Conn.execute("PRAGMA page_size=8192")
2310
2311 # to avoid non-ascii character conversion issue
2312 self.Conn.text_factory = str
2313 self.Cur = self.Conn.cursor()
2314
2315 # create table for internal uses
2316 self.TblDataModel = TableDataModel(self.Cur)
2317 self.TblFile = TableFile(self.Cur)
2318
2319 # conversion object for build or file format conversion purpose
2320 self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
2321 self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
2322
2323 ## Check whether workspace database need to be renew.
2324 # The renew reason maybe:
2325 # 1) If user force to renew;
2326 # 2) If user do not force renew, and
2327 # a) If the time of last modified python source is newer than database file;
2328 # b) If the time of last modified frozen executable file is newer than database file;
2329 #
2330 # @param force User force renew database
2331 # @param DbPath The absolute path of workspace database file
2332 #
2333 # @return Bool value for whether need renew workspace databse
2334 #
2335 def _CheckWhetherDbNeedRenew (self, force, DbPath):
2336 DbDir = os.path.split(DbPath)[0]
2337 MacroFilePath = os.path.normpath(os.path.join(DbDir, "build.mac"))
2338 MacroMatch = False
2339 if os.path.exists(MacroFilePath) and os.path.isfile(MacroFilePath):
2340 LastMacros = None
2341 try:
2342 f = open(MacroFilePath,'r')
2343 LastMacros = pickle.load(f)
2344 f.close()
2345 except IOError:
2346 pass
2347 except:
2348 f.close()
2349
2350 if LastMacros != None and type(LastMacros) is DictType:
2351 if LastMacros == self._GlobalMacros:
2352 MacroMatch = True
2353 for Macro in LastMacros.keys():
2354 if not (Macro in self._GlobalMacros and LastMacros[Macro] == self._GlobalMacros[Macro]):
2355 MacroMatch = False;
2356 break;
2357
2358 if not MacroMatch:
2359 # save command line macros to file
2360 try:
2361 f = open(MacroFilePath,'w')
2362 pickle.dump(self._GlobalMacros, f, 2)
2363 f.close()
2364 except IOError:
2365 pass
2366 except:
2367 f.close()
2368
2369 force = True
2370
2371 # if database does not exist, we need do nothing
2372 if not os.path.exists(DbPath): return False
2373
2374 # if user force to renew database, then not check whether database is out of date
2375 if force: return True
2376
2377 #
2378 # Check the time of last modified source file or build.exe
2379 # if is newer than time of database, then database need to be re-created.
2380 #
2381 timeOfToolModified = 0
2382 if hasattr(sys, "frozen"):
2383 exePath = os.path.abspath(sys.executable)
2384 timeOfToolModified = os.stat(exePath).st_mtime
2385 else:
2386 curPath = os.path.dirname(__file__) # curPath is the path of WorkspaceDatabase.py
2387 rootPath = os.path.split(curPath)[0] # rootPath is root path of python source, such as /BaseTools/Source/Python
2388 if rootPath == "" or rootPath == None:
2389 EdkLogger.verbose("\nFail to find the root path of build.exe or python sources, so can not \
2390 determine whether database file is out of date!\n")
2391
2392 # walk the root path of source or build's binary to get the time last modified.
2393
2394 for root, dirs, files in os.walk (rootPath):
2395 for dir in dirs:
2396 # bypass source control folder
2397 if dir.lower() in [".svn", "_svn", "cvs"]:
2398 dirs.remove(dir)
2399
2400 for file in files:
2401 ext = os.path.splitext(file)[1]
2402 if ext.lower() == ".py": # only check .py files
2403 fd = os.stat(os.path.join(root, file))
2404 if timeOfToolModified < fd.st_mtime:
2405 timeOfToolModified = fd.st_mtime
2406 if timeOfToolModified > os.stat(DbPath).st_mtime:
2407 EdkLogger.verbose("\nWorkspace database is out of data!")
2408 return True
2409
2410 return False
2411
2412 ## Initialize build database
2413 def InitDatabase(self):
2414 EdkLogger.verbose("\nInitialize build database started ...")
2415
2416 #
2417 # Create new tables
2418 #
2419 self.TblDataModel.Create(False)
2420 self.TblFile.Create(False)
2421
2422 #
2423 # Initialize table DataModel
2424 #
2425 self.TblDataModel.InitTable()
2426 EdkLogger.verbose("Initialize build database ... DONE!")
2427
2428 ## Query a table
2429 #
2430 # @param Table: The instance of the table to be queried
2431 #
2432 def QueryTable(self, Table):
2433 Table.Query()
2434
2435 ## Close entire database
2436 #
2437 # Commit all first
2438 # Close the connection and cursor
2439 #
2440 def Close(self):
2441 if not self._DbClosedFlag:
2442 self.Conn.commit()
2443 self.Cur.close()
2444 self.Conn.close()
2445 self._DbClosedFlag = True
2446
2447 ## Get unique file ID for the gvien file
2448 def GetFileId(self, FilePath):
2449 return self.TblFile.GetFileId(FilePath)
2450
2451 ## Get file type value for the gvien file ID
2452 def GetFileType(self, FileId):
2453 return self.TblFile.GetFileType(FileId)
2454
2455 ## Get time stamp stored in file table
2456 def GetTimeStamp(self, FileId):
2457 return self.TblFile.GetFileTimeStamp(FileId)
2458
2459 ## Update time stamp in file table
2460 def SetTimeStamp(self, FileId, TimeStamp):
2461 return self.TblFile.SetFileTimeStamp(FileId, TimeStamp)
2462
2463 ## Check if a table integrity flag exists or not
2464 def CheckIntegrity(self, TableName):
2465 try:
2466 Result = self.Cur.execute("select min(ID) from %s" % (TableName)).fetchall()
2467 if Result[0][0] != -1:
2468 return False
2469 #
2470 # Check whether the meta data file has external dependency by comparing the time stamp
2471 #
2472 Sql = "select Value1, Value2 from %s where Model=%d" % (TableName, MODEL_EXTERNAL_DEPENDENCY)
2473 for Dependency in self.Cur.execute(Sql).fetchall():
2474 if str(os.stat(Dependency[0])[8]) != Dependency[1]:
2475 return False
2476 except:
2477 return False
2478 return True
2479
2480 ## Compose table name for given file type and file ID
2481 def GetTableName(self, FileType, FileId):
2482 return "_%s_%s" % (FileType, FileId)
2483
2484 ## Return a temp table containing all content of the given file
2485 #
2486 # @param FileInfo The tuple containing path and type of a file
2487 #
2488 def __getitem__(self, FileInfo):
2489 FilePath, FileType, Macros = FileInfo
2490 if FileType not in self._FILE_TABLE_:
2491 return None
2492
2493 # flag used to indicate if it's parsed or not
2494 FilePath = str(FilePath)
2495 Parsed = False
2496 FileId = self.GetFileId(FilePath)
2497 if FileId != None:
2498 TimeStamp = os.stat(FilePath)[8]
2499 TableName = self.GetTableName(FileType, FileId)
2500 if TimeStamp != self.GetTimeStamp(FileId):
2501 # update the timestamp in database
2502 self.SetTimeStamp(FileId, TimeStamp)
2503 else:
2504 # if the table exists and is integrity, don't parse it
2505 Parsed = self.CheckIntegrity(TableName)
2506 else:
2507 FileId = self.TblFile.InsertFile(FilePath, FileType)
2508 TableName = self.GetTableName(FileType, FileId)
2509
2510 FileTable = self._FILE_TABLE_[FileType](self.Cur, TableName, FileId)
2511 FileTable.Create(not Parsed)
2512 Parser = self._FILE_PARSER_[FileType](FilePath, FileType, FileTable, Macros)
2513 # set the "Finished" flag in parser in order to avoid re-parsing (if parsed)
2514 Parser.Finished = Parsed
2515 return Parser
2516
2517 ## Summarize all packages in the database
2518 def _GetPackageList(self):
2519 PackageList = []
2520 for Module in self.ModuleList:
2521 for Package in Module.Packages:
2522 if Package not in PackageList:
2523 PackageList.append(Package)
2524 return PackageList
2525
2526 ## Summarize all platforms in the database
2527 def _GetPlatformList(self):
2528 PlatformList = []
2529 for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC):
2530 try:
2531 Platform = self.BuildObject[PathClass(PlatformFile), 'COMMON']
2532 except:
2533 Platform = None
2534 if Platform != None:
2535 PlatformList.append(Platform)
2536 return PlatformList
2537
2538 ## Summarize all modules in the database
2539 def _GetModuleList(self):
2540 ModuleList = []
2541 for ModuleFile in self.TblFile.GetFileList(MODEL_FILE_INF):
2542 try:
2543 Module = self.BuildObject[PathClass(ModuleFile), 'COMMON']
2544 except:
2545 Module = None
2546 if Module != None:
2547 ModuleList.append(Module)
2548 return ModuleList
2549
2550 PlatformList = property(_GetPlatformList)
2551 PackageList = property(_GetPackageList)
2552 ModuleList = property(_GetModuleList)
2553
2554 ##
2555 #
2556 # This acts like the main() function for the script, unless it is 'import'ed into another
2557 # script.
2558 #
2559 if __name__ == '__main__':
2560 pass
2561