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