]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
Sync EDKII BaseTools to BaseTools project r2093.
[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 #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._Specification == None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (self._Specification['PI_SPECIFICATION_VERSION'] < 0x0001000A):
1429 if self._ModuleType == SUP_MODULE_SMM_CORE:
1430 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)
1431 if self._Defs and 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \
1432 and 'PCI_CLASS_CODE' in self._Defs:
1433 self._BuildType = 'UEFI_OPTIONROM'
1434 elif self._Defs and 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
1435 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
1436 self._BuildType = 'UEFI_HII'
1437 else:
1438 self._BuildType = self._ModuleType.upper()
1439 else:
1440 self._BuildType = self._ComponentType.upper()
1441 if not self._ComponentType:
1442 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1443 "COMPONENT_TYPE is not given", File=self.MetaFile)
1444 if self._ComponentType in self._MODULE_TYPE_:
1445 self._ModuleType = self._MODULE_TYPE_[self._ComponentType]
1446 if self._ComponentType == 'LIBRARY':
1447 self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)]
1448 # make use some [nmake] section macros
1449 RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform]
1450 for Name,Value,Dummy,Arch,Platform,ID,LineNo in RecordList:
1451 Value = Value.replace('$(PROCESSOR)', self._Arch)
1452 Name = Name.replace('$(PROCESSOR)', self._Arch)
1453 Name, Value = ReplaceMacros((Name, Value), GlobalData.gEdkGlobal, True)
1454 if Name == "IMAGE_ENTRY_POINT":
1455 if self._ModuleEntryPointList == None:
1456 self._ModuleEntryPointList = []
1457 self._ModuleEntryPointList.append(Value)
1458 elif Name == "DPX_SOURCE":
1459 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1460 Macros.update(self._Macros)
1461 File = PathClass(NormPath(Value, Macros), self._ModuleDir, Arch=self._Arch)
1462 # check the file validation
1463 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
1464 if ErrorCode != 0:
1465 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
1466 File=self.MetaFile, Line=LineNo)
1467 if self.Sources == None:
1468 self._Sources = []
1469 self._Sources.append(File)
1470 else:
1471 ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name)
1472 if len(ToolList) == 0 or len(ToolList) != 1:
1473 pass
1474 # EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name,
1475 # File=self.MetaFile, Line=LineNo)
1476 else:
1477 if self._BuildOptions == None:
1478 self._BuildOptions = sdict()
1479
1480 if ToolList[0] in self._TOOL_CODE_:
1481 Tool = self._TOOL_CODE_[ToolList[0]]
1482 else:
1483 Tool = ToolList[0]
1484 ToolChain = "*_*_*_%s_FLAGS" % Tool
1485 ToolChainFamily = 'MSFT' # R8.x only support MSFT tool chain
1486 #ignore not replaced macros in value
1487 ValueList = GetSplitValueList(' ' + Value, '/D')
1488 Dummy = ValueList[0]
1489 for Index in range(1, len(ValueList)):
1490 if ValueList[Index][-1] == '=' or ValueList[Index] == '':
1491 continue
1492 Dummy = Dummy + ' /D ' + ValueList[Index]
1493 Value = Dummy.strip()
1494 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1495 self._BuildOptions[ToolChainFamily, ToolChain] = Value
1496 else:
1497 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1498 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value
1499 # set _Header to non-None in order to avoid database re-querying
1500 self._Header_ = 'DUMMY'
1501
1502 ## Retrieve file version
1503 def _GetInfVersion(self):
1504 if self._AutoGenVersion == None:
1505 if self._Header_ == None:
1506 self._GetHeaderInfo()
1507 if self._AutoGenVersion == None:
1508 self._AutoGenVersion = 0x00010000
1509 return self._AutoGenVersion
1510
1511 ## Retrieve BASE_NAME
1512 def _GetBaseName(self):
1513 if self._BaseName == None:
1514 if self._Header_ == None:
1515 self._GetHeaderInfo()
1516 if self._BaseName == None:
1517 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
1518 return self._BaseName
1519
1520 ## Retrieve MODULE_TYPE
1521 def _GetModuleType(self):
1522 if self._ModuleType == None:
1523 if self._Header_ == None:
1524 self._GetHeaderInfo()
1525 if self._ModuleType == None:
1526 self._ModuleType = 'BASE'
1527 if self._ModuleType not in SUP_MODULE_LIST:
1528 self._ModuleType = "USER_DEFINED"
1529 return self._ModuleType
1530
1531 ## Retrieve COMPONENT_TYPE
1532 def _GetComponentType(self):
1533 if self._ComponentType == None:
1534 if self._Header_ == None:
1535 self._GetHeaderInfo()
1536 if self._ComponentType == None:
1537 self._ComponentType = 'USER_DEFINED'
1538 return self._ComponentType
1539
1540 ## Retrieve "BUILD_TYPE"
1541 def _GetBuildType(self):
1542 if self._BuildType == None:
1543 if self._Header_ == None:
1544 self._GetHeaderInfo()
1545 if not self._BuildType:
1546 self._BuildType = "BASE"
1547 return self._BuildType
1548
1549 ## Retrieve file guid
1550 def _GetFileGuid(self):
1551 if self._Guid == None:
1552 if self._Header_ == None:
1553 self._GetHeaderInfo()
1554 if self._Guid == None:
1555 self._Guid = '00000000-0000-0000-000000000000'
1556 return self._Guid
1557
1558 ## Retrieve module version
1559 def _GetVersion(self):
1560 if self._Version == None:
1561 if self._Header_ == None:
1562 self._GetHeaderInfo()
1563 if self._Version == None:
1564 self._Version = '0.0'
1565 return self._Version
1566
1567 ## Retrieve PCD_IS_DRIVER
1568 def _GetPcdIsDriver(self):
1569 if self._PcdIsDriver == None:
1570 if self._Header_ == None:
1571 self._GetHeaderInfo()
1572 if self._PcdIsDriver == None:
1573 self._PcdIsDriver = ''
1574 return self._PcdIsDriver
1575
1576 ## Retrieve SHADOW
1577 def _GetShadow(self):
1578 if self._Shadow == None:
1579 if self._Header_ == None:
1580 self._GetHeaderInfo()
1581 if self._Shadow != None and self._Shadow.upper() == 'TRUE':
1582 self._Shadow = True
1583 else:
1584 self._Shadow = False
1585 return self._Shadow
1586
1587 ## Retrieve CUSTOM_MAKEFILE
1588 def _GetMakefile(self):
1589 if self._CustomMakefile == None:
1590 if self._Header_ == None:
1591 self._GetHeaderInfo()
1592 if self._CustomMakefile == None:
1593 self._CustomMakefile = {}
1594 return self._CustomMakefile
1595
1596 ## Retrieve EFI_SPECIFICATION_VERSION
1597 def _GetSpec(self):
1598 if self._Specification == None:
1599 if self._Header_ == None:
1600 self._GetHeaderInfo()
1601 if self._Specification == None:
1602 self._Specification = {}
1603 return self._Specification
1604
1605 ## Retrieve LIBRARY_CLASS
1606 def _GetLibraryClass(self):
1607 if self._LibraryClass == None:
1608 if self._Header_ == None:
1609 self._GetHeaderInfo()
1610 if self._LibraryClass == None:
1611 self._LibraryClass = []
1612 return self._LibraryClass
1613
1614 ## Retrieve ENTRY_POINT
1615 def _GetEntryPoint(self):
1616 if self._ModuleEntryPointList == None:
1617 if self._Header_ == None:
1618 self._GetHeaderInfo()
1619 if self._ModuleEntryPointList == None:
1620 self._ModuleEntryPointList = []
1621 return self._ModuleEntryPointList
1622
1623 ## Retrieve UNLOAD_IMAGE
1624 def _GetUnloadImage(self):
1625 if self._ModuleUnloadImageList == None:
1626 if self._Header_ == None:
1627 self._GetHeaderInfo()
1628 if self._ModuleUnloadImageList == None:
1629 self._ModuleUnloadImageList = []
1630 return self._ModuleUnloadImageList
1631
1632 ## Retrieve CONSTRUCTOR
1633 def _GetConstructor(self):
1634 if self._ConstructorList == None:
1635 if self._Header_ == None:
1636 self._GetHeaderInfo()
1637 if self._ConstructorList == None:
1638 self._ConstructorList = []
1639 return self._ConstructorList
1640
1641 ## Retrieve DESTRUCTOR
1642 def _GetDestructor(self):
1643 if self._DestructorList == None:
1644 if self._Header_ == None:
1645 self._GetHeaderInfo()
1646 if self._DestructorList == None:
1647 self._DestructorList = []
1648 return self._DestructorList
1649
1650 ## Retrieve definies other than above ones
1651 def _GetDefines(self):
1652 if self._Defs == None:
1653 if self._Header_ == None:
1654 self._GetHeaderInfo()
1655 if self._Defs == None:
1656 self._Defs = sdict()
1657 return self._Defs
1658
1659 ## Retrieve binary files
1660 def _GetBinaryFiles(self):
1661 if self._Binaries == None:
1662 self._Binaries = []
1663 RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
1664 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch}
1665 Macros.update(self._Macros)
1666 for Record in RecordList:
1667 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1668 FileType = Record[0]
1669 LineNo = Record[-1]
1670 Target = 'COMMON'
1671 FeatureFlag = []
1672 if Record[2]:
1673 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
1674 if TokenList:
1675 Target = TokenList[0]
1676 if len(TokenList) > 1:
1677 FeatureFlag = Record[1:]
1678
1679 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
1680 # check the file validation
1681 ErrorCode, ErrorInfo = File.Validate()
1682 if ErrorCode != 0:
1683 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1684 self._Binaries.append(File)
1685 return self._Binaries
1686
1687 ## Retrieve source files
1688 def _GetSourceFiles(self):
1689 if self._Sources == None:
1690 self._Sources = []
1691 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
1692 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource, 'PROCESSOR':self._Arch}
1693 Macros.update(self._Macros)
1694 for Record in RecordList:
1695 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1696 LineNo = Record[-1]
1697 ToolChainFamily = Record[1]
1698 TagName = Record[2]
1699 ToolCode = Record[3]
1700 FeatureFlag = Record[4]
1701 if self._AutoGenVersion < 0x00010005:
1702 # old module source files (R8)
1703 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, self._SourceOverridePath,
1704 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
1705 # check the file validation
1706 ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
1707 if ErrorCode != 0:
1708 if File.Ext.lower() == '.h':
1709 EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo,
1710 File=self.MetaFile, Line=LineNo)
1711 continue
1712 else:
1713 EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo)
1714 else:
1715 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
1716 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
1717 # check the file validation
1718 ErrorCode, ErrorInfo = File.Validate()
1719 if ErrorCode != 0:
1720 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1721
1722 self._Sources.append(File)
1723 return self._Sources
1724
1725 ## Retrieve library classes employed by this module
1726 def _GetLibraryClassUses(self):
1727 if self._LibraryClasses == None:
1728 self._LibraryClasses = sdict()
1729 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
1730 for Record in RecordList:
1731 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1732 Lib = Record[0]
1733 Instance = Record[1]
1734 if Instance != None and Instance != '':
1735 Instance = NormPath(Instance, self._Macros)
1736 self._LibraryClasses[Lib] = Instance
1737 return self._LibraryClasses
1738
1739 ## Retrieve library names (for R8.x style of modules)
1740 def _GetLibraryNames(self):
1741 if self._Libraries == None:
1742 self._Libraries = []
1743 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
1744 for Record in RecordList:
1745 # in case of name with '.lib' extension, which is unusual in R8.x inf
1746 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1747 LibraryName = os.path.splitext(Record[0])[0]
1748 if LibraryName not in self._Libraries:
1749 self._Libraries.append(LibraryName)
1750 return self._Libraries
1751
1752 ## Retrieve protocols consumed/produced by this module
1753 def _GetProtocols(self):
1754 if self._Protocols == None:
1755 self._Protocols = sdict()
1756 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
1757 for Record in RecordList:
1758 CName = Record[0]
1759 Value = ProtocolValue(CName, self.Packages)
1760 if Value == None:
1761 PackageList = "\n\t".join([str(P) for P in self.Packages])
1762 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1763 "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
1764 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1765 self._Protocols[CName] = Value
1766 return self._Protocols
1767
1768 ## Retrieve PPIs consumed/produced by this module
1769 def _GetPpis(self):
1770 if self._Ppis == None:
1771 self._Ppis = sdict()
1772 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
1773 for Record in RecordList:
1774 CName = Record[0]
1775 Value = PpiValue(CName, self.Packages)
1776 if Value == None:
1777 PackageList = "\n\t".join([str(P) for P in self.Packages])
1778 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1779 "Value of PPI [%s] is not found under [Ppis] section in " % CName,
1780 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1781 self._Ppis[CName] = Value
1782 return self._Ppis
1783
1784 ## Retrieve GUIDs consumed/produced by this module
1785 def _GetGuids(self):
1786 if self._Guids == None:
1787 self._Guids = sdict()
1788 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
1789 for Record in RecordList:
1790 CName = Record[0]
1791 Value = GuidValue(CName, self.Packages)
1792 if Value == None:
1793 PackageList = "\n\t".join([str(P) for P in self.Packages])
1794 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1795 "Value of Guid [%s] is not found under [Guids] section in" % CName,
1796 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1797 self._Guids[CName] = Value
1798 return self._Guids
1799
1800 ## Retrieve include paths necessary for this module (for R8.x style of modules)
1801 def _GetIncludes(self):
1802 if self._Includes == None:
1803 self._Includes = []
1804 if self._SourceOverridePath:
1805 self._Includes.append(self._SourceOverridePath)
1806 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
1807 # [includes] section must be used only in old (R8.x) inf file
1808 if self.AutoGenVersion >= 0x00010005 and len(RecordList) > 0:
1809 EdkLogger.error('build', FORMAT_NOT_SUPPORTED, "No [include] section allowed",
1810 File=self.MetaFile, Line=RecordList[0][-1]-1)
1811 for Record in RecordList:
1812 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1813 Record[0] = Record[0].replace('$(PROCESSOR)', self._Arch)
1814 Record[0] = ReplaceMacro(Record[0], {'EFI_SOURCE' : GlobalData.gEfiSource}, False)
1815 if Record[0].find('EDK_SOURCE') > -1:
1816 File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEcpSource}, False), self._Macros)
1817 if File[0] == '.':
1818 File = os.path.join(self._ModuleDir, File)
1819 else:
1820 File = os.path.join(GlobalData.gWorkspace, File)
1821 File = RealPath(os.path.normpath(File))
1822 if File:
1823 self._Includes.append(File)
1824
1825 #TRICK: let compiler to choose correct header file
1826 File = NormPath(ReplaceMacro(Record[0], {'EDK_SOURCE' : GlobalData.gEdkSource}, 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 else:
1835 File = NormPath(Record[0], self._Macros)
1836 if File[0] == '.':
1837 File = os.path.join(self._ModuleDir, File)
1838 else:
1839 File = os.path.join(GlobalData.gWorkspace, File)
1840 File = RealPath(os.path.normpath(File))
1841 if File:
1842 self._Includes.append(File)
1843 return self._Includes
1844
1845 ## Retrieve packages this module depends on
1846 def _GetPackages(self):
1847 if self._Packages == None:
1848 self._Packages = []
1849 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
1850 Macros = {"EDK_SOURCE":GlobalData.gEcpSource, "EFI_SOURCE":GlobalData.gEfiSource}
1851 Macros.update(self._Macros)
1852 for Record in RecordList:
1853 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
1854 LineNo = Record[-1]
1855 # check the file validation
1856 ErrorCode, ErrorInfo = File.Validate('.dec')
1857 if ErrorCode != 0:
1858 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1859 # parse this package now. we need it to get protocol/ppi/guid value
1860 Package = self._Bdb[File, self._Arch]
1861 self._Packages.append(Package)
1862 return self._Packages
1863
1864 ## Retrieve PCDs used in this module
1865 def _GetPcds(self):
1866 if self._Pcds == None:
1867 self._Pcds = {}
1868 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1869 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1870 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1871 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
1872 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
1873 return self._Pcds
1874
1875 ## Retrieve build options specific to this module
1876 def _GetBuildOptions(self):
1877 if self._BuildOptions == None:
1878 self._BuildOptions = sdict()
1879 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
1880 for Record in RecordList:
1881 ToolChainFamily = Record[0]
1882 ToolChain = Record[1]
1883 Option = Record[2]
1884 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1885 self._BuildOptions[ToolChainFamily, ToolChain] = Option
1886 else:
1887 # concatenate the option string if they're for the same tool
1888 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1889 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
1890 return self._BuildOptions
1891
1892 ## Retrieve depedency expression
1893 def _GetDepex(self):
1894 if self._Depex == None:
1895 self._Depex = tdict(False, 2)
1896 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
1897
1898 # PEIM and DXE drivers must have a valid [Depex] section
1899 if len(self.LibraryClass) == 0 and len(RecordList) == 0:
1900 if self.ModuleType == 'DXE_DRIVER' or self.ModuleType == 'PEIM' or self.ModuleType == 'DXE_SMM_DRIVER' or \
1901 self.ModuleType == 'DXE_SAL_DRIVER' or self.ModuleType == 'DXE_RUNTIME_DRIVER':
1902 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
1903 % self.ModuleType, File=self.MetaFile)
1904
1905 Depex = {}
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 Depex:
1912 Depex[Arch, ModuleType] = []
1913 DepexList = Depex[Arch, ModuleType]
1914 for Token in TokenList:
1915 if Token in DEPEX_SUPPORTED_OPCODE:
1916 DepexList.append(Token)
1917 elif Token.endswith(".inf"): # module file name
1918 ModuleFile = os.path.normpath(Token)
1919 Module = self.BuildDatabase[ModuleFile]
1920 if Module == None:
1921 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
1922 ExtraData=Token, File=self.MetaFile, Line=Record[-1])
1923 DepexList.append(Module.Guid)
1924 else:
1925 # get the GUID value now
1926 Value = ProtocolValue(Token, self.Packages)
1927 if Value == None:
1928 Value = PpiValue(Token, self.Packages)
1929 if Value == None:
1930 Value = GuidValue(Token, 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 [%s] is not found in" % Token,
1935 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
1936 DepexList.append(Value)
1937 for Arch, ModuleType in Depex:
1938 self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType]
1939 return self._Depex
1940
1941 ## Retrieve depedency expression
1942 def _GetDepexExpression(self):
1943 if self._DepexExpression == None:
1944 self._DepexExpression = tdict(False, 2)
1945 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
1946 DepexExpression = {}
1947 for Record in RecordList:
1948 Record = ReplaceMacros(Record, GlobalData.gEdkGlobal, False)
1949 Arch = Record[3]
1950 ModuleType = Record[4]
1951 TokenList = Record[0].split()
1952 if (Arch, ModuleType) not in DepexExpression:
1953 DepexExpression[Arch, ModuleType] = ''
1954 for Token in TokenList:
1955 DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] + Token.strip() + ' '
1956 for Arch, ModuleType in DepexExpression:
1957 self._DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType]
1958 return self._DepexExpression
1959
1960 ## Retrieve PCD for given type
1961 def _GetPcd(self, Type):
1962 Pcds = {}
1963 PcdDict = tdict(True, 4)
1964 PcdList = []
1965 RecordList = self._RawData[Type, self._Arch, self._Platform]
1966 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Dummy1, LineNo in RecordList:
1967 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
1968 PcdList.append((PcdCName, TokenSpaceGuid))
1969 # get the guid value
1970 if TokenSpaceGuid not in self.Guids:
1971 Value = GuidValue(TokenSpaceGuid, self.Packages)
1972 if Value == None:
1973 PackageList = "\n\t".join([str(P) for P in self.Packages])
1974 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
1975 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
1976 ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
1977 self.Guids[TokenSpaceGuid] = Value
1978
1979 # resolve PCD type, value, datum info, etc. by getting its definition from package
1980 for PcdCName, TokenSpaceGuid in PcdList:
1981 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
1982 if Setting == None:
1983 continue
1984 ValueList = AnalyzePcdData(Setting)
1985 DefaultValue = ValueList[0]
1986 Pcd = PcdClassObject(
1987 PcdCName,
1988 TokenSpaceGuid,
1989 '',
1990 '',
1991 DefaultValue,
1992 '',
1993 '',
1994 {},
1995 False,
1996 self.Guids[TokenSpaceGuid]
1997 )
1998
1999 # get necessary info from package declaring this PCD
2000 for Package in self.Packages:
2001 #
2002 # 'dynamic' in INF means its type is determined by platform;
2003 # if platform doesn't give its type, use 'lowest' one in the
2004 # following order, if any
2005 #
2006 # "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"
2007 #
2008 PcdType = self._PCD_TYPE_STRING_[Type]
2009 if Type == MODEL_PCD_DYNAMIC:
2010 Pcd.Pending = True
2011 for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]:
2012 if (PcdCName, TokenSpaceGuid, T) in Package.Pcds:
2013 PcdType = T
2014 break
2015 else:
2016 Pcd.Pending = False
2017
2018 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
2019 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
2020 Pcd.Type = PcdType
2021 Pcd.TokenValue = PcdInPackage.TokenValue
2022
2023 #
2024 # Check whether the token value exist or not.
2025 #
2026 if Pcd.TokenValue == None or Pcd.TokenValue == "":
2027 EdkLogger.error(
2028 'build',
2029 FORMAT_INVALID,
2030 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdCName, str(Package)),
2031 File =self.MetaFile, Line=LineNo,
2032 ExtraData=None
2033 )
2034 #
2035 # Check hexadecimal token value length and format.
2036 #
2037 if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"):
2038 if len(Pcd.TokenValue) < 3 or len(Pcd.TokenValue) > 10:
2039 EdkLogger.error(
2040 'build',
2041 FORMAT_INVALID,
2042 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2043 File =self.MetaFile, Line=LineNo,
2044 ExtraData=None
2045 )
2046 try:
2047 int (Pcd.TokenValue, 16)
2048 except:
2049 EdkLogger.error(
2050 'build',
2051 FORMAT_INVALID,
2052 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2053 File =self.MetaFile, Line=LineNo,
2054 ExtraData=None
2055 )
2056
2057 #
2058 # Check decimal token value length and format.
2059 #
2060 else:
2061 try:
2062 TokenValueInt = int (Pcd.TokenValue, 10)
2063 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
2064 EdkLogger.error(
2065 'build',
2066 FORMAT_INVALID,
2067 "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)),
2068 File =self.MetaFile, Line=LineNo,
2069 ExtraData=None
2070 )
2071 except:
2072 EdkLogger.error(
2073 'build',
2074 FORMAT_INVALID,
2075 "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)),
2076 File =self.MetaFile, Line=LineNo,
2077 ExtraData=None
2078 )
2079
2080 Pcd.DatumType = PcdInPackage.DatumType
2081 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
2082 Pcd.InfDefaultValue = Pcd.DefaultValue
2083 if Pcd.DefaultValue in [None, '']:
2084 Pcd.DefaultValue = PcdInPackage.DefaultValue
2085 break
2086 else:
2087 EdkLogger.error(
2088 'build',
2089 FORMAT_INVALID,
2090 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdCName, self.MetaFile),
2091 File =self.MetaFile, Line=LineNo,
2092 ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages])
2093 )
2094 Pcds[PcdCName, TokenSpaceGuid] = Pcd
2095
2096 return Pcds
2097
2098 Arch = property(_GetArch, _SetArch)
2099 Platform = property(_GetPlatform, _SetPlatform)
2100
2101 AutoGenVersion = property(_GetInfVersion)
2102 BaseName = property(_GetBaseName)
2103 ModuleType = property(_GetModuleType)
2104 ComponentType = property(_GetComponentType)
2105 BuildType = property(_GetBuildType)
2106 Guid = property(_GetFileGuid)
2107 Version = property(_GetVersion)
2108 PcdIsDriver = property(_GetPcdIsDriver)
2109 Shadow = property(_GetShadow)
2110 CustomMakefile = property(_GetMakefile)
2111 Specification = property(_GetSpec)
2112 LibraryClass = property(_GetLibraryClass)
2113 ModuleEntryPointList = property(_GetEntryPoint)
2114 ModuleUnloadImageList = property(_GetUnloadImage)
2115 ConstructorList = property(_GetConstructor)
2116 DestructorList = property(_GetDestructor)
2117 Defines = property(_GetDefines)
2118
2119 Binaries = property(_GetBinaryFiles)
2120 Sources = property(_GetSourceFiles)
2121 LibraryClasses = property(_GetLibraryClassUses)
2122 Libraries = property(_GetLibraryNames)
2123 Protocols = property(_GetProtocols)
2124 Ppis = property(_GetPpis)
2125 Guids = property(_GetGuids)
2126 Includes = property(_GetIncludes)
2127 Packages = property(_GetPackages)
2128 Pcds = property(_GetPcds)
2129 BuildOptions = property(_GetBuildOptions)
2130 Depex = property(_GetDepex)
2131 DepexExpression = property(_GetDepexExpression)
2132
2133 ## Database
2134 #
2135 # This class defined the build database for all modules, packages and platform.
2136 # It will call corresponding parser for the given file if it cannot find it in
2137 # the database.
2138 #
2139 # @param DbPath Path of database file
2140 # @param GlobalMacros Global macros used for replacement during file parsing
2141 # @prarm RenewDb=False Create new database file if it's already there
2142 #
2143 class WorkspaceDatabase(object):
2144 # file parser
2145 _FILE_PARSER_ = {
2146 MODEL_FILE_INF : InfParser,
2147 MODEL_FILE_DEC : DecParser,
2148 MODEL_FILE_DSC : DscParser,
2149 MODEL_FILE_FDF : None, #FdfParser,
2150 MODEL_FILE_CIF : None
2151 }
2152
2153 # file table
2154 _FILE_TABLE_ = {
2155 MODEL_FILE_INF : ModuleTable,
2156 MODEL_FILE_DEC : PackageTable,
2157 MODEL_FILE_DSC : PlatformTable,
2158 }
2159
2160 # default database file path
2161 _DB_PATH_ = "Conf/.cache/build.db"
2162
2163 #
2164 # internal class used for call corresponding file parser and caching the result
2165 # to avoid unnecessary re-parsing
2166 #
2167 class BuildObjectFactory(object):
2168 _FILE_TYPE_ = {
2169 ".inf" : MODEL_FILE_INF,
2170 ".dec" : MODEL_FILE_DEC,
2171 ".dsc" : MODEL_FILE_DSC,
2172 ".fdf" : MODEL_FILE_FDF,
2173 }
2174
2175 # convert to xxxBuildData object
2176 _GENERATOR_ = {
2177 MODEL_FILE_INF : InfBuildData,
2178 MODEL_FILE_DEC : DecBuildData,
2179 MODEL_FILE_DSC : DscBuildData,
2180 MODEL_FILE_FDF : None #FlashDefTable,
2181 }
2182
2183 _CACHE_ = {} # (FilePath, Arch) : <object>
2184
2185 # constructor
2186 def __init__(self, WorkspaceDb):
2187 self.WorkspaceDb = WorkspaceDb
2188
2189 # key = (FilePath, Arch='COMMON')
2190 def __contains__(self, Key):
2191 FilePath = Key[0]
2192 Arch = 'COMMON'
2193 if len(Key) > 1:
2194 Arch = Key[1]
2195 return (FilePath, Arch) in self._CACHE_
2196
2197 # key = (FilePath, Arch='COMMON')
2198 def __getitem__(self, Key):
2199 FilePath = Key[0]
2200 Arch = 'COMMON'
2201 Platform = 'COMMON'
2202 if len(Key) > 1:
2203 Arch = Key[1]
2204 if len(Key) > 2:
2205 Platform = Key[2]
2206
2207 # if it's generated before, just return the cached one
2208 Key = (FilePath, Arch)
2209 if Key in self._CACHE_:
2210 return self._CACHE_[Key]
2211
2212 # check file type
2213 Ext = FilePath.Ext.lower()
2214 if Ext not in self._FILE_TYPE_:
2215 return None
2216 FileType = self._FILE_TYPE_[Ext]
2217 if FileType not in self._GENERATOR_:
2218 return None
2219
2220 # get table for current file
2221 MetaFile = self.WorkspaceDb[FilePath, FileType, self.WorkspaceDb._GlobalMacros]
2222 BuildObject = self._GENERATOR_[FileType](
2223 FilePath,
2224 MetaFile,
2225 self,
2226 Arch,
2227 Platform,
2228 self.WorkspaceDb._GlobalMacros,
2229 )
2230 self._CACHE_[Key] = BuildObject
2231 return BuildObject
2232
2233 # placeholder for file format conversion
2234 class TransformObjectFactory:
2235 def __init__(self, WorkspaceDb):
2236 self.WorkspaceDb = WorkspaceDb
2237
2238 # key = FilePath, Arch
2239 def __getitem__(self, Key):
2240 pass
2241
2242 ## Constructor of WorkspaceDatabase
2243 #
2244 # @param DbPath Path of database file
2245 # @param GlobalMacros Global macros used for replacement during file parsing
2246 # @prarm RenewDb=False Create new database file if it's already there
2247 #
2248 def __init__(self, DbPath, GlobalMacros={}, RenewDb=False):
2249 self._GlobalMacros = GlobalMacros
2250
2251 if DbPath == None or DbPath == '':
2252 DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_))
2253
2254 # don't create necessary path for db in memory
2255 if DbPath != ':memory:':
2256 DbDir = os.path.split(DbPath)[0]
2257 if not os.path.exists(DbDir):
2258 os.makedirs(DbDir)
2259
2260 # remove db file in case inconsistency between db and file in file system
2261 if self._CheckWhetherDbNeedRenew(RenewDb, DbPath):
2262 os.remove(DbPath)
2263
2264 # create db with optimized parameters
2265 self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED')
2266 self.Conn.execute("PRAGMA synchronous=OFF")
2267 self.Conn.execute("PRAGMA temp_store=MEMORY")
2268 self.Conn.execute("PRAGMA count_changes=OFF")
2269 self.Conn.execute("PRAGMA cache_size=8192")
2270 #self.Conn.execute("PRAGMA page_size=8192")
2271
2272 # to avoid non-ascii character conversion issue
2273 self.Conn.text_factory = str
2274 self.Cur = self.Conn.cursor()
2275
2276 # create table for internal uses
2277 self.TblDataModel = TableDataModel(self.Cur)
2278 self.TblFile = TableFile(self.Cur)
2279
2280 # conversion object for build or file format conversion purpose
2281 self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
2282 self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
2283
2284 ## Check whether workspace database need to be renew.
2285 # The renew reason maybe:
2286 # 1) If user force to renew;
2287 # 2) If user do not force renew, and
2288 # a) If the time of last modified python source is newer than database file;
2289 # b) If the time of last modified frozen executable file is newer than database file;
2290 #
2291 # @param force User force renew database
2292 # @param DbPath The absolute path of workspace database file
2293 #
2294 # @return Bool value for whether need renew workspace databse
2295 #
2296 def _CheckWhetherDbNeedRenew (self, force, DbPath):
2297 DbDir = os.path.split(DbPath)[0]
2298 MacroFilePath = os.path.normpath(os.path.join(DbDir, "build.mac"))
2299 MacroMatch = False
2300 if os.path.exists(MacroFilePath) and os.path.isfile(MacroFilePath):
2301 LastMacros = None
2302 try:
2303 f = open(MacroFilePath,'r')
2304 LastMacros = pickle.load(f)
2305 f.close()
2306 except IOError:
2307 pass
2308 except:
2309 f.close()
2310
2311 if LastMacros != None and type(LastMacros) is DictType:
2312 if LastMacros == self._GlobalMacros:
2313 MacroMatch = True
2314 for Macro in LastMacros.keys():
2315 if not (Macro in self._GlobalMacros and LastMacros[Macro] == self._GlobalMacros[Macro]):
2316 MacroMatch = False;
2317 break;
2318
2319 if not MacroMatch:
2320 # save command line macros to file
2321 try:
2322 f = open(MacroFilePath,'w')
2323 pickle.dump(self._GlobalMacros, f, 2)
2324 f.close()
2325 except IOError:
2326 pass
2327 except:
2328 f.close()
2329
2330 force = True
2331
2332 # if database does not exist, we need do nothing
2333 if not os.path.exists(DbPath): return False
2334
2335 # if user force to renew database, then not check whether database is out of date
2336 if force: return True
2337
2338 #
2339 # Check the time of last modified source file or build.exe
2340 # if is newer than time of database, then database need to be re-created.
2341 #
2342 timeOfToolModified = 0
2343 if hasattr(sys, "frozen"):
2344 exePath = os.path.abspath(sys.executable)
2345 timeOfToolModified = os.stat(exePath).st_mtime
2346 else:
2347 curPath = os.path.dirname(__file__) # curPath is the path of WorkspaceDatabase.py
2348 rootPath = os.path.split(curPath)[0] # rootPath is root path of python source, such as /BaseTools/Source/Python
2349 if rootPath == "" or rootPath == None:
2350 EdkLogger.verbose("\nFail to find the root path of build.exe or python sources, so can not \
2351 determine whether database file is out of date!\n")
2352
2353 # walk the root path of source or build's binary to get the time last modified.
2354
2355 for root, dirs, files in os.walk (rootPath):
2356 for dir in dirs:
2357 # bypass source control folder
2358 if dir.lower() in [".svn", "_svn", "cvs"]:
2359 dirs.remove(dir)
2360
2361 for file in files:
2362 ext = os.path.splitext(file)[1]
2363 if ext.lower() == ".py": # only check .py files
2364 fd = os.stat(os.path.join(root, file))
2365 if timeOfToolModified < fd.st_mtime:
2366 timeOfToolModified = fd.st_mtime
2367 if timeOfToolModified > os.stat(DbPath).st_mtime:
2368 EdkLogger.verbose("\nWorkspace database is out of data!")
2369 return True
2370
2371 return False
2372
2373 ## Initialize build database
2374 def InitDatabase(self):
2375 EdkLogger.verbose("\nInitialize build database started ...")
2376
2377 #
2378 # Create new tables
2379 #
2380 self.TblDataModel.Create(False)
2381 self.TblFile.Create(False)
2382
2383 #
2384 # Initialize table DataModel
2385 #
2386 self.TblDataModel.InitTable()
2387 EdkLogger.verbose("Initialize build database ... DONE!")
2388
2389 ## Query a table
2390 #
2391 # @param Table: The instance of the table to be queried
2392 #
2393 def QueryTable(self, Table):
2394 Table.Query()
2395
2396 ## Close entire database
2397 #
2398 # Commit all first
2399 # Close the connection and cursor
2400 #
2401 def Close(self):
2402 self.Conn.commit()
2403 self.Cur.close()
2404 self.Conn.close()
2405
2406 ## Get unique file ID for the gvien file
2407 def GetFileId(self, FilePath):
2408 return self.TblFile.GetFileId(FilePath)
2409
2410 ## Get file type value for the gvien file ID
2411 def GetFileType(self, FileId):
2412 return self.TblFile.GetFileType(FileId)
2413
2414 ## Get time stamp stored in file table
2415 def GetTimeStamp(self, FileId):
2416 return self.TblFile.GetFileTimeStamp(FileId)
2417
2418 ## Update time stamp in file table
2419 def SetTimeStamp(self, FileId, TimeStamp):
2420 return self.TblFile.SetFileTimeStamp(FileId, TimeStamp)
2421
2422 ## Check if a table integrity flag exists or not
2423 def CheckIntegrity(self, TableName):
2424 try:
2425 Result = self.Cur.execute("select min(ID) from %s" % (TableName)).fetchall()
2426 if Result[0][0] != -1:
2427 return False
2428 #
2429 # Check whether the meta data file has external dependency by comparing the time stamp
2430 #
2431 Sql = "select Value1, Value2 from %s where Model=%d" % (TableName, MODEL_EXTERNAL_DEPENDENCY)
2432 for Dependency in self.Cur.execute(Sql).fetchall():
2433 if str(os.stat(Dependency[0])[8]) != Dependency[1]:
2434 return False
2435 except:
2436 return False
2437 return True
2438
2439 ## Compose table name for given file type and file ID
2440 def GetTableName(self, FileType, FileId):
2441 return "_%s_%s" % (FileType, FileId)
2442
2443 ## Return a temp table containing all content of the given file
2444 #
2445 # @param FileInfo The tuple containing path and type of a file
2446 #
2447 def __getitem__(self, FileInfo):
2448 FilePath, FileType, Macros = FileInfo
2449 if FileType not in self._FILE_TABLE_:
2450 return None
2451
2452 # flag used to indicate if it's parsed or not
2453 FilePath = str(FilePath)
2454 Parsed = False
2455 FileId = self.GetFileId(FilePath)
2456 if FileId != None:
2457 TimeStamp = os.stat(FilePath)[8]
2458 TableName = self.GetTableName(FileType, FileId)
2459 if TimeStamp != self.GetTimeStamp(FileId):
2460 # update the timestamp in database
2461 self.SetTimeStamp(FileId, TimeStamp)
2462 else:
2463 # if the table exists and is integrity, don't parse it
2464 Parsed = self.CheckIntegrity(TableName)
2465 else:
2466 FileId = self.TblFile.InsertFile(FilePath, FileType)
2467 TableName = self.GetTableName(FileType, FileId)
2468
2469 FileTable = self._FILE_TABLE_[FileType](self.Cur, TableName, FileId)
2470 FileTable.Create(not Parsed)
2471 Parser = self._FILE_PARSER_[FileType](FilePath, FileType, FileTable, Macros)
2472 # set the "Finished" flag in parser in order to avoid re-parsing (if parsed)
2473 Parser.Finished = Parsed
2474 return Parser
2475
2476 ## Summarize all packages in the database
2477 def _GetPackageList(self):
2478 PackageList = []
2479 for Module in self.ModuleList:
2480 for Package in Module.Packages:
2481 if Package not in PackageList:
2482 PackageList.append(Package)
2483 return PackageList
2484
2485 ## Summarize all platforms in the database
2486 def _GetPlatformList(self):
2487 PlatformList = []
2488 for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC):
2489 try:
2490 Platform = self.BuildObject[PathClass(PlatformFile), 'COMMON']
2491 except:
2492 Platform = None
2493 if Platform != None:
2494 PlatformList.append(Platform)
2495 return PlatformList
2496
2497 ## Summarize all modules in the database
2498 def _GetModuleList(self):
2499 ModuleList = []
2500 for ModuleFile in self.TblFile.GetFileList(MODEL_FILE_INF):
2501 try:
2502 Module = self.BuildObject[PathClass(ModuleFile), 'COMMON']
2503 except:
2504 Module = None
2505 if Module != None:
2506 ModuleList.append(Module)
2507 return ModuleList
2508
2509 PlatformList = property(_GetPlatformList)
2510 PackageList = property(_GetPackageList)
2511 ModuleList = property(_GetModuleList)
2512
2513 ##
2514 #
2515 # This acts like the main() function for the script, unless it is 'import'ed into another
2516 # script.
2517 #
2518 if __name__ == '__main__':
2519 pass
2520