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