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