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