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