]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
8252a3180d9512d494c445cbe0d222bd18131c86
[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 Common.LongFilePathOs as os
19 import pickle
20 import uuid
21
22 import Common.EdkLogger as EdkLogger
23 import Common.GlobalData as GlobalData
24
25 from Common.String import *
26 from Common.DataType import *
27 from Common.Misc import *
28 from types import *
29
30 from CommonDataClass.CommonClass import SkuInfoClass
31
32 from MetaDataTable import *
33 from MetaFileTable import *
34 from MetaFileParser import *
35 from BuildClassObject import *
36 from WorkspaceCommon import GetDeclaredPcd
37 from Common.Misc import AnalyzeDscPcd
38 import re
39 from Common.Parsing import IsValidWord
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 FormatCorrect = True
897 if VariableOffset.isdigit():
898 if int(VariableOffset,10) > 0xFFFF:
899 ExceedMax = True
900 elif re.match(r'[\t\s]*0[xX][a-fA-F0-9]+$',VariableOffset):
901 if int(VariableOffset,16) > 0xFFFF:
902 ExceedMax = True
903 # For Offset written in "A.B"
904 elif VariableOffset.find('.') > -1:
905 VariableOffsetList = VariableOffset.split(".")
906 if not (len(VariableOffsetList) == 2
907 and IsValidWord(VariableOffsetList[0])
908 and IsValidWord(VariableOffsetList[1])):
909 FormatCorrect = False
910 else:
911 FormatCorrect = False
912 if not FormatCorrect:
913 EdkLogger.error('Build', FORMAT_INVALID, "Invalid syntax or format of the variable offset value is incorrect for %s." % ".".join((TokenSpaceGuid,PcdCName)))
914
915 if ExceedMax:
916 EdkLogger.error('Build', OPTION_VALUE_INVALID, "The variable offset value must not exceed the maximum value of 0xFFFF (UINT16) for %s." % ".".join((TokenSpaceGuid,PcdCName)))
917
918 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], VariableName, VariableGuid, VariableOffset, DefaultValue)
919 if (PcdCName,TokenSpaceGuid) in Pcds.keys():
920 pcdObject = Pcds[PcdCName,TokenSpaceGuid]
921 pcdObject.SkuInfoList[SkuName] = SkuInfo
922 else:
923 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
924 PcdCName,
925 TokenSpaceGuid,
926 self._PCD_TYPE_STRING_[Type],
927 '',
928 DefaultValue,
929 '',
930 '',
931 {SkuName : SkuInfo},
932 False,
933 None
934 )
935
936
937 for pcd in Pcds.values():
938 SkuInfoObj = pcd.SkuInfoList.values()[0]
939 pcdDecObject = self._DecPcds[pcd.TokenCName,pcd.TokenSpaceGuidCName]
940 # Only fix the value while no value provided in DSC file.
941 for sku in pcd.SkuInfoList.values():
942 if (sku.HiiDefaultValue == "" or sku.HiiDefaultValue==None):
943 sku.HiiDefaultValue = pcdDecObject.DefaultValue
944 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
945 valuefromDec = pcdDecObject.DefaultValue
946 SkuInfo = SkuInfoClass('DEFAULT', '0', SkuInfoObj.VariableName, SkuInfoObj.VariableGuid, SkuInfoObj.VariableOffset, valuefromDec)
947 pcd.SkuInfoList['DEFAULT'] = SkuInfo
948 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
949 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
950 del(pcd.SkuInfoList['COMMON'])
951 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
952 del(pcd.SkuInfoList['COMMON'])
953
954 if SkuObj.SkuUsageType == SkuObj.SINGLE:
955 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys():
956 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT']
957 del(pcd.SkuInfoList['DEFAULT'])
958
959
960 if pcd.MaxDatumSize.strip():
961 MaxSize = int(pcd.MaxDatumSize,0)
962 else:
963 MaxSize = 0
964 if pcdDecObject.DatumType == 'VOID*':
965 for (skuname,skuobj) in pcd.SkuInfoList.items():
966 datalen = 0
967 if skuobj.HiiDefaultValue.startswith("L"):
968 datalen = (len(skuobj.HiiDefaultValue)- 3 + 1) * 2
969 elif skuobj.HiiDefaultValue.startswith("{"):
970 datalen = len(skuobj.HiiDefaultValue.split(","))
971 else:
972 datalen = len(skuobj.HiiDefaultValue) -2 + 1
973 if datalen>MaxSize:
974 MaxSize = datalen
975 pcd.MaxDatumSize = str(MaxSize)
976 return Pcds
977
978 ## Retrieve dynamic VPD PCD settings
979 #
980 # @param Type PCD type
981 #
982 # @retval a dict object contains settings of given PCD type
983 #
984 def _GetDynamicVpdPcd(self, Type):
985
986 SkuObj = SkuClass(self.SkuIdentifier,self.SkuIds)
987
988 Pcds = sdict()
989 #
990 # tdict is a special dict kind of type, used for selecting correct
991 # PCD settings for certain ARCH and SKU
992 #
993 PcdDict = tdict(True, 4)
994 PcdList = []
995 # Find out all possible PCD candidates for self._Arch
996 RecordList = self._RawData[Type, self._Arch]
997 AvailableSkuIdSet = SkuObj.AvailableSkuIdSet.copy()
998
999 AvailableSkuIdSet.update({'DEFAULT':0,'COMMON':0})
1000 for TokenSpaceGuid, PcdCName, Setting, Arch, SkuName, Dummy3, Dummy4 in RecordList:
1001 if SkuName not in AvailableSkuIdSet:
1002 continue
1003
1004 PcdList.append((PcdCName, TokenSpaceGuid,SkuName, Dummy4))
1005 PcdDict[Arch, SkuName, PcdCName, TokenSpaceGuid] = Setting
1006 # Remove redundant PCD candidates, per the ARCH and SKU
1007 for PcdCName, TokenSpaceGuid, SkuName,Dummy4 in PcdList:
1008 Setting = PcdDict[self._Arch, SkuName, PcdCName, TokenSpaceGuid]
1009 if Setting == None:
1010 continue
1011 #
1012 # For the VOID* type, it can have optional data of MaxDatumSize and InitialValue
1013 # For the Integer & Boolean type, the optional data can only be InitialValue.
1014 # At this point, we put all the data into the PcdClssObject for we don't know the PCD's datumtype
1015 # until the DEC parser has been called.
1016 #
1017 VpdOffset, MaxDatumSize, InitialValue = self._ValidatePcd(PcdCName, TokenSpaceGuid, Setting, Type, Dummy4)
1018 SkuInfo = SkuInfoClass(SkuName, self.SkuIds[SkuName], '', '', '', '', VpdOffset, InitialValue)
1019 if (PcdCName,TokenSpaceGuid) in Pcds.keys():
1020 pcdObject = Pcds[PcdCName,TokenSpaceGuid]
1021 pcdObject.SkuInfoList[SkuName] = SkuInfo
1022 if MaxDatumSize.strip():
1023 CurrentMaxSize = int(MaxDatumSize.strip(),0)
1024 else:
1025 CurrentMaxSize = 0
1026 if pcdObject.MaxDatumSize:
1027 PcdMaxSize = int(pcdObject.MaxDatumSize,0)
1028 else:
1029 PcdMaxSize = 0
1030 if CurrentMaxSize > PcdMaxSize:
1031 pcdObject.MaxDatumSize = str(CurrentMaxSize)
1032 else:
1033 Pcds[PcdCName, TokenSpaceGuid] = PcdClassObject(
1034 PcdCName,
1035 TokenSpaceGuid,
1036 self._PCD_TYPE_STRING_[Type],
1037 '',
1038 '',
1039 '',
1040 MaxDatumSize,
1041 {SkuName : SkuInfo},
1042 False,
1043 None
1044 )
1045 for pcd in Pcds.values():
1046 SkuInfoObj = pcd.SkuInfoList.values()[0]
1047 pcdDecObject = self._DecPcds[pcd.TokenCName,pcd.TokenSpaceGuidCName]
1048 if 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' not in pcd.SkuInfoList.keys():
1049 valuefromDec = pcdDecObject.DefaultValue
1050 SkuInfo = SkuInfoClass('DEFAULT', '0', '', '', '','',SkuInfoObj.VpdOffset, valuefromDec)
1051 pcd.SkuInfoList['DEFAULT'] = SkuInfo
1052 elif 'DEFAULT' not in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
1053 pcd.SkuInfoList['DEFAULT'] = pcd.SkuInfoList['COMMON']
1054 del(pcd.SkuInfoList['COMMON'])
1055 elif 'DEFAULT' in pcd.SkuInfoList.keys() and 'COMMON' in pcd.SkuInfoList.keys():
1056 del(pcd.SkuInfoList['COMMON'])
1057 if SkuObj.SkuUsageType == SkuObj.SINGLE:
1058 if 'DEFAULT' in pcd.SkuInfoList.keys() and SkuObj.SystemSkuId not in pcd.SkuInfoList.keys():
1059 pcd.SkuInfoList[SkuObj.SystemSkuId] = pcd.SkuInfoList['DEFAULT']
1060 del(pcd.SkuInfoList['DEFAULT'])
1061
1062 return Pcds
1063
1064 ## Add external modules
1065 #
1066 # The external modules are mostly those listed in FDF file, which don't
1067 # need "build".
1068 #
1069 # @param FilePath The path of module description file
1070 #
1071 def AddModule(self, FilePath):
1072 FilePath = NormPath(FilePath)
1073 if FilePath not in self.Modules:
1074 Module = ModuleBuildClassObject()
1075 Module.MetaFile = FilePath
1076 self.Modules.append(Module)
1077
1078 ## Add external PCDs
1079 #
1080 # The external PCDs are mostly those listed in FDF file to specify address
1081 # or offset information.
1082 #
1083 # @param Name Name of the PCD
1084 # @param Guid Token space guid of the PCD
1085 # @param Value Value of the PCD
1086 #
1087 def AddPcd(self, Name, Guid, Value):
1088 if (Name, Guid) not in self.Pcds:
1089 self.Pcds[Name, Guid] = PcdClassObject(Name, Guid, '', '', '', '', '', {}, False, None)
1090 self.Pcds[Name, Guid].DefaultValue = Value
1091
1092 _Macros = property(_GetMacros)
1093 Arch = property(_GetArch, _SetArch)
1094 Platform = property(_GetPlatformName)
1095 PlatformName = property(_GetPlatformName)
1096 Guid = property(_GetFileGuid)
1097 Version = property(_GetVersion)
1098 DscSpecification = property(_GetDscSpec)
1099 OutputDirectory = property(_GetOutpuDir)
1100 SupArchList = property(_GetSupArch)
1101 BuildTargets = property(_GetBuildTarget)
1102 SkuName = property(_GetSkuName, _SetSkuName)
1103 SkuIdentifier = property(_GetSkuIdentifier)
1104 PcdInfoFlag = property(_GetPcdInfoFlag)
1105 FlashDefinition = property(_GetFdfFile)
1106 BuildNumber = property(_GetBuildNumber)
1107 MakefileName = property(_GetMakefileName)
1108 BsBaseAddress = property(_GetBsBaseAddress)
1109 RtBaseAddress = property(_GetRtBaseAddress)
1110 LoadFixAddress = property(_GetLoadFixAddress)
1111 RFCLanguages = property(_GetRFCLanguages)
1112 ISOLanguages = property(_GetISOLanguages)
1113 VpdToolGuid = property(_GetVpdToolGuid)
1114 SkuIds = property(_GetSkuIds)
1115 Modules = property(_GetModules)
1116 LibraryInstances = property(_GetLibraryInstances)
1117 LibraryClasses = property(_GetLibraryClasses)
1118 Pcds = property(_GetPcds)
1119 BuildOptions = property(_GetBuildOptions)
1120
1121 ## Platform build information from DEC file
1122 #
1123 # This class is used to retrieve information stored in database and convert them
1124 # into PackageBuildClassObject form for easier use for AutoGen.
1125 #
1126 class DecBuildData(PackageBuildClassObject):
1127 # dict used to convert PCD type in database to string used by build tool
1128 _PCD_TYPE_STRING_ = {
1129 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
1130 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
1131 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
1132 MODEL_PCD_DYNAMIC : "Dynamic",
1133 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
1134 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
1135 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
1136 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
1137 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
1138 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
1139 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
1140 }
1141
1142 # dict used to convert part of [Defines] to members of DecBuildData directly
1143 _PROPERTY_ = {
1144 #
1145 # Required Fields
1146 #
1147 TAB_DEC_DEFINES_PACKAGE_NAME : "_PackageName",
1148 TAB_DEC_DEFINES_PACKAGE_GUID : "_Guid",
1149 TAB_DEC_DEFINES_PACKAGE_VERSION : "_Version",
1150 TAB_DEC_DEFINES_PKG_UNI_FILE : "_PkgUniFile",
1151 }
1152
1153
1154 ## Constructor of DecBuildData
1155 #
1156 # Initialize object of DecBuildData
1157 #
1158 # @param FilePath The path of package description file
1159 # @param RawData The raw data of DEC file
1160 # @param BuildDataBase Database used to retrieve module information
1161 # @param Arch The target architecture
1162 # @param Platform (not used for DecBuildData)
1163 # @param Macros Macros used for replacement in DSC file
1164 #
1165 def __init__(self, File, RawData, BuildDataBase, Arch='COMMON', Target=None, Toolchain=None):
1166 self.MetaFile = File
1167 self._PackageDir = File.Dir
1168 self._RawData = RawData
1169 self._Bdb = BuildDataBase
1170 self._Arch = Arch
1171 self._Target = Target
1172 self._Toolchain = Toolchain
1173 self._Clear()
1174
1175 ## XXX[key] = value
1176 def __setitem__(self, key, value):
1177 self.__dict__[self._PROPERTY_[key]] = value
1178
1179 ## value = XXX[key]
1180 def __getitem__(self, key):
1181 return self.__dict__[self._PROPERTY_[key]]
1182
1183 ## "in" test support
1184 def __contains__(self, key):
1185 return key in self._PROPERTY_
1186
1187 ## Set all internal used members of DecBuildData to None
1188 def _Clear(self):
1189 self._Header = None
1190 self._PackageName = None
1191 self._Guid = None
1192 self._Version = None
1193 self._PkgUniFile = None
1194 self._Protocols = None
1195 self._Ppis = None
1196 self._Guids = None
1197 self._Includes = None
1198 self._LibraryClasses = None
1199 self._Pcds = None
1200 self.__Macros = None
1201
1202 ## Get current effective macros
1203 def _GetMacros(self):
1204 if self.__Macros == None:
1205 self.__Macros = {}
1206 self.__Macros.update(GlobalData.gGlobalDefines)
1207 return self.__Macros
1208
1209 ## Get architecture
1210 def _GetArch(self):
1211 return self._Arch
1212
1213 ## Set architecture
1214 #
1215 # Changing the default ARCH to another may affect all other information
1216 # because all information in a platform may be ARCH-related. That's
1217 # why we need to clear all internal used members, in order to cause all
1218 # information to be re-retrieved.
1219 #
1220 # @param Value The value of ARCH
1221 #
1222 def _SetArch(self, Value):
1223 if self._Arch == Value:
1224 return
1225 self._Arch = Value
1226 self._Clear()
1227
1228 ## Retrieve all information in [Defines] section
1229 #
1230 # (Retriving all [Defines] information in one-shot is just to save time.)
1231 #
1232 def _GetHeaderInfo(self):
1233 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch]
1234 for Record in RecordList:
1235 Name = Record[1]
1236 if Name in self:
1237 self[Name] = Record[2]
1238 self._Header = 'DUMMY'
1239
1240 ## Retrieve package name
1241 def _GetPackageName(self):
1242 if self._PackageName == None:
1243 if self._Header == None:
1244 self._GetHeaderInfo()
1245 if self._PackageName == None:
1246 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_NAME", File=self.MetaFile)
1247 return self._PackageName
1248
1249 ## Retrieve file guid
1250 def _GetFileGuid(self):
1251 if self._Guid == None:
1252 if self._Header == None:
1253 self._GetHeaderInfo()
1254 if self._Guid == None:
1255 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE, "No PACKAGE_GUID", File=self.MetaFile)
1256 return self._Guid
1257
1258 ## Retrieve package version
1259 def _GetVersion(self):
1260 if self._Version == None:
1261 if self._Header == None:
1262 self._GetHeaderInfo()
1263 if self._Version == None:
1264 self._Version = ''
1265 return self._Version
1266
1267 ## Retrieve protocol definitions (name/value pairs)
1268 def _GetProtocol(self):
1269 if self._Protocols == None:
1270 #
1271 # tdict is a special kind of dict, used for selecting correct
1272 # protocol defition for given ARCH
1273 #
1274 ProtocolDict = tdict(True)
1275 NameList = []
1276 # find out all protocol definitions for specific and 'common' arch
1277 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch]
1278 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
1279 if Name not in NameList:
1280 NameList.append(Name)
1281 ProtocolDict[Arch, Name] = Guid
1282 # use sdict to keep the order
1283 self._Protocols = sdict()
1284 for Name in NameList:
1285 #
1286 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1287 # will automatically turn to 'common' ARCH for trying
1288 #
1289 self._Protocols[Name] = ProtocolDict[self._Arch, Name]
1290 return self._Protocols
1291
1292 ## Retrieve PPI definitions (name/value pairs)
1293 def _GetPpi(self):
1294 if self._Ppis == None:
1295 #
1296 # tdict is a special kind of dict, used for selecting correct
1297 # PPI defition for given ARCH
1298 #
1299 PpiDict = tdict(True)
1300 NameList = []
1301 # find out all PPI definitions for specific arch and 'common' arch
1302 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch]
1303 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
1304 if Name not in NameList:
1305 NameList.append(Name)
1306 PpiDict[Arch, Name] = Guid
1307 # use sdict to keep the order
1308 self._Ppis = sdict()
1309 for Name in NameList:
1310 #
1311 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1312 # will automatically turn to 'common' ARCH for trying
1313 #
1314 self._Ppis[Name] = PpiDict[self._Arch, Name]
1315 return self._Ppis
1316
1317 ## Retrieve GUID definitions (name/value pairs)
1318 def _GetGuid(self):
1319 if self._Guids == None:
1320 #
1321 # tdict is a special kind of dict, used for selecting correct
1322 # GUID defition for given ARCH
1323 #
1324 GuidDict = tdict(True)
1325 NameList = []
1326 # find out all protocol definitions for specific and 'common' arch
1327 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch]
1328 for Name, Guid, Dummy, Arch, ID, LineNo in RecordList:
1329 if Name not in NameList:
1330 NameList.append(Name)
1331 GuidDict[Arch, Name] = Guid
1332 # use sdict to keep the order
1333 self._Guids = sdict()
1334 for Name in NameList:
1335 #
1336 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1337 # will automatically turn to 'common' ARCH for trying
1338 #
1339 self._Guids[Name] = GuidDict[self._Arch, Name]
1340 return self._Guids
1341
1342 ## Retrieve public include paths declared in this package
1343 def _GetInclude(self):
1344 if self._Includes == None:
1345 self._Includes = []
1346 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch]
1347 Macros = self._Macros
1348 Macros["EDK_SOURCE"] = GlobalData.gEcpSource
1349 for Record in RecordList:
1350 File = PathClass(NormPath(Record[0], Macros), self._PackageDir, Arch=self._Arch)
1351 LineNo = Record[-1]
1352 # validate the path
1353 ErrorCode, ErrorInfo = File.Validate()
1354 if ErrorCode != 0:
1355 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1356
1357 # avoid duplicate include path
1358 if File not in self._Includes:
1359 self._Includes.append(File)
1360 return self._Includes
1361
1362 ## Retrieve library class declarations (not used in build at present)
1363 def _GetLibraryClass(self):
1364 if self._LibraryClasses == None:
1365 #
1366 # tdict is a special kind of dict, used for selecting correct
1367 # library class declaration for given ARCH
1368 #
1369 LibraryClassDict = tdict(True)
1370 LibraryClassSet = set()
1371 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch]
1372 Macros = self._Macros
1373 for LibraryClass, File, Dummy, Arch, ID, LineNo in RecordList:
1374 File = PathClass(NormPath(File, Macros), self._PackageDir, Arch=self._Arch)
1375 # check the file validation
1376 ErrorCode, ErrorInfo = File.Validate()
1377 if ErrorCode != 0:
1378 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
1379 LibraryClassSet.add(LibraryClass)
1380 LibraryClassDict[Arch, LibraryClass] = File
1381 self._LibraryClasses = sdict()
1382 for LibraryClass in LibraryClassSet:
1383 self._LibraryClasses[LibraryClass] = LibraryClassDict[self._Arch, LibraryClass]
1384 return self._LibraryClasses
1385
1386 ## Retrieve PCD declarations
1387 def _GetPcds(self):
1388 if self._Pcds == None:
1389 self._Pcds = sdict()
1390 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
1391 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
1392 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
1393 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
1394 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
1395 return self._Pcds
1396
1397 ## Retrieve PCD declarations for given type
1398 def _GetPcd(self, Type):
1399 Pcds = sdict()
1400 #
1401 # tdict is a special kind of dict, used for selecting correct
1402 # PCD declaration for given ARCH
1403 #
1404 PcdDict = tdict(True, 3)
1405 # for summarizing PCD
1406 PcdSet = set()
1407 # find out all PCDs of the 'type'
1408 RecordList = self._RawData[Type, self._Arch]
1409 for TokenSpaceGuid, PcdCName, Setting, Arch, Dummy1, Dummy2 in RecordList:
1410 PcdDict[Arch, PcdCName, TokenSpaceGuid] = Setting
1411 PcdSet.add((PcdCName, TokenSpaceGuid))
1412
1413 for PcdCName, TokenSpaceGuid in PcdSet:
1414 #
1415 # limit the ARCH to self._Arch, if no self._Arch found, tdict
1416 # will automatically turn to 'common' ARCH and try again
1417 #
1418 Setting = PcdDict[self._Arch, PcdCName, TokenSpaceGuid]
1419 if Setting == None:
1420 continue
1421
1422 DefaultValue, DatumType, TokenNumber = AnalyzePcdData(Setting)
1423
1424 Pcds[PcdCName, TokenSpaceGuid, self._PCD_TYPE_STRING_[Type]] = PcdClassObject(
1425 PcdCName,
1426 TokenSpaceGuid,
1427 self._PCD_TYPE_STRING_[Type],
1428 DatumType,
1429 DefaultValue,
1430 TokenNumber,
1431 '',
1432 {},
1433 False,
1434 None
1435 )
1436 return Pcds
1437
1438
1439 _Macros = property(_GetMacros)
1440 Arch = property(_GetArch, _SetArch)
1441 PackageName = property(_GetPackageName)
1442 Guid = property(_GetFileGuid)
1443 Version = property(_GetVersion)
1444
1445 Protocols = property(_GetProtocol)
1446 Ppis = property(_GetPpi)
1447 Guids = property(_GetGuid)
1448 Includes = property(_GetInclude)
1449 LibraryClasses = property(_GetLibraryClass)
1450 Pcds = property(_GetPcds)
1451
1452 ## Module build information from INF file
1453 #
1454 # This class is used to retrieve information stored in database and convert them
1455 # into ModuleBuildClassObject form for easier use for AutoGen.
1456 #
1457 class InfBuildData(ModuleBuildClassObject):
1458 # dict used to convert PCD type in database to string used by build tool
1459 _PCD_TYPE_STRING_ = {
1460 MODEL_PCD_FIXED_AT_BUILD : "FixedAtBuild",
1461 MODEL_PCD_PATCHABLE_IN_MODULE : "PatchableInModule",
1462 MODEL_PCD_FEATURE_FLAG : "FeatureFlag",
1463 MODEL_PCD_DYNAMIC : "Dynamic",
1464 MODEL_PCD_DYNAMIC_DEFAULT : "Dynamic",
1465 MODEL_PCD_DYNAMIC_HII : "DynamicHii",
1466 MODEL_PCD_DYNAMIC_VPD : "DynamicVpd",
1467 MODEL_PCD_DYNAMIC_EX : "DynamicEx",
1468 MODEL_PCD_DYNAMIC_EX_DEFAULT : "DynamicEx",
1469 MODEL_PCD_DYNAMIC_EX_HII : "DynamicExHii",
1470 MODEL_PCD_DYNAMIC_EX_VPD : "DynamicExVpd",
1471 }
1472
1473 # dict used to convert part of [Defines] to members of InfBuildData directly
1474 _PROPERTY_ = {
1475 #
1476 # Required Fields
1477 #
1478 TAB_INF_DEFINES_BASE_NAME : "_BaseName",
1479 TAB_INF_DEFINES_FILE_GUID : "_Guid",
1480 TAB_INF_DEFINES_MODULE_TYPE : "_ModuleType",
1481 #
1482 # Optional Fields
1483 #
1484 #TAB_INF_DEFINES_INF_VERSION : "_AutoGenVersion",
1485 TAB_INF_DEFINES_COMPONENT_TYPE : "_ComponentType",
1486 TAB_INF_DEFINES_MAKEFILE_NAME : "_MakefileName",
1487 #TAB_INF_DEFINES_CUSTOM_MAKEFILE : "_CustomMakefile",
1488 TAB_INF_DEFINES_DPX_SOURCE :"_DxsFile",
1489 TAB_INF_DEFINES_VERSION_NUMBER : "_Version",
1490 TAB_INF_DEFINES_VERSION_STRING : "_Version",
1491 TAB_INF_DEFINES_VERSION : "_Version",
1492 TAB_INF_DEFINES_PCD_IS_DRIVER : "_PcdIsDriver",
1493 TAB_INF_DEFINES_SHADOW : "_Shadow",
1494
1495 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH : "_SourceOverridePath",
1496 }
1497
1498 # dict used to convert Component type to Module type
1499 _MODULE_TYPE_ = {
1500 "LIBRARY" : "BASE",
1501 "SECURITY_CORE" : "SEC",
1502 "PEI_CORE" : "PEI_CORE",
1503 "COMBINED_PEIM_DRIVER" : "PEIM",
1504 "PIC_PEIM" : "PEIM",
1505 "RELOCATABLE_PEIM" : "PEIM",
1506 "PE32_PEIM" : "PEIM",
1507 "BS_DRIVER" : "DXE_DRIVER",
1508 "RT_DRIVER" : "DXE_RUNTIME_DRIVER",
1509 "SAL_RT_DRIVER" : "DXE_SAL_DRIVER",
1510 "DXE_SMM_DRIVER" : "DXE_SMM_DRIVER",
1511 # "SMM_DRIVER" : "DXE_SMM_DRIVER",
1512 # "BS_DRIVER" : "DXE_SMM_DRIVER",
1513 # "BS_DRIVER" : "UEFI_DRIVER",
1514 "APPLICATION" : "UEFI_APPLICATION",
1515 "LOGO" : "BASE",
1516 }
1517
1518 # regular expression for converting XXX_FLAGS in [nmake] section to new type
1519 _NMAKE_FLAG_PATTERN_ = re.compile("(?:EBC_)?([A-Z]+)_(?:STD_|PROJ_|ARCH_)?FLAGS(?:_DLL|_ASL|_EXE)?", re.UNICODE)
1520 # dict used to convert old tool name used in [nmake] section to new ones
1521 _TOOL_CODE_ = {
1522 "C" : "CC",
1523 "LIB" : "SLINK",
1524 "LINK" : "DLINK",
1525 }
1526
1527
1528 ## Constructor of DscBuildData
1529 #
1530 # Initialize object of DscBuildData
1531 #
1532 # @param FilePath The path of platform description file
1533 # @param RawData The raw data of DSC file
1534 # @param BuildDataBase Database used to retrieve module/package information
1535 # @param Arch The target architecture
1536 # @param Platform The name of platform employing this module
1537 # @param Macros Macros used for replacement in DSC file
1538 #
1539 def __init__(self, FilePath, RawData, BuildDatabase, Arch='COMMON', Target=None, Toolchain=None):
1540 self.MetaFile = FilePath
1541 self._ModuleDir = FilePath.Dir
1542 self._RawData = RawData
1543 self._Bdb = BuildDatabase
1544 self._Arch = Arch
1545 self._Target = Target
1546 self._Toolchain = Toolchain
1547 self._Platform = 'COMMON'
1548 self._SourceOverridePath = None
1549 if FilePath.Key in GlobalData.gOverrideDir:
1550 self._SourceOverridePath = GlobalData.gOverrideDir[FilePath.Key]
1551 self._Clear()
1552
1553 ## XXX[key] = value
1554 def __setitem__(self, key, value):
1555 self.__dict__[self._PROPERTY_[key]] = value
1556
1557 ## value = XXX[key]
1558 def __getitem__(self, key):
1559 return self.__dict__[self._PROPERTY_[key]]
1560
1561 ## "in" test support
1562 def __contains__(self, key):
1563 return key in self._PROPERTY_
1564
1565 ## Set all internal used members of InfBuildData to None
1566 def _Clear(self):
1567 self._HeaderComments = None
1568 self._TailComments = None
1569 self._Header_ = None
1570 self._AutoGenVersion = None
1571 self._BaseName = None
1572 self._DxsFile = None
1573 self._ModuleType = None
1574 self._ComponentType = None
1575 self._BuildType = None
1576 self._Guid = None
1577 self._Version = None
1578 self._PcdIsDriver = None
1579 self._BinaryModule = None
1580 self._Shadow = None
1581 self._MakefileName = None
1582 self._CustomMakefile = None
1583 self._Specification = None
1584 self._LibraryClass = None
1585 self._ModuleEntryPointList = None
1586 self._ModuleUnloadImageList = None
1587 self._ConstructorList = None
1588 self._DestructorList = None
1589 self._Defs = None
1590 self._Binaries = None
1591 self._Sources = None
1592 self._LibraryClasses = None
1593 self._Libraries = None
1594 self._Protocols = None
1595 self._ProtocolComments = None
1596 self._Ppis = None
1597 self._PpiComments = None
1598 self._Guids = None
1599 self._GuidsUsedByPcd = sdict()
1600 self._GuidComments = None
1601 self._Includes = None
1602 self._Packages = None
1603 self._Pcds = None
1604 self._PcdComments = None
1605 self._BuildOptions = None
1606 self._Depex = None
1607 self._DepexExpression = None
1608 self.__Macros = None
1609
1610 ## Get current effective macros
1611 def _GetMacros(self):
1612 if self.__Macros == None:
1613 self.__Macros = {}
1614 # EDK_GLOBAL defined macros can be applied to EDK module
1615 if self.AutoGenVersion < 0x00010005:
1616 self.__Macros.update(GlobalData.gEdkGlobal)
1617 self.__Macros.update(GlobalData.gGlobalDefines)
1618 return self.__Macros
1619
1620 ## Get architecture
1621 def _GetArch(self):
1622 return self._Arch
1623
1624 ## Set architecture
1625 #
1626 # Changing the default ARCH to another may affect all other information
1627 # because all information in a platform may be ARCH-related. That's
1628 # why we need to clear all internal used members, in order to cause all
1629 # information to be re-retrieved.
1630 #
1631 # @param Value The value of ARCH
1632 #
1633 def _SetArch(self, Value):
1634 if self._Arch == Value:
1635 return
1636 self._Arch = Value
1637 self._Clear()
1638
1639 ## Return the name of platform employing this module
1640 def _GetPlatform(self):
1641 return self._Platform
1642
1643 ## Change the name of platform employing this module
1644 #
1645 # Changing the default name of platform to another may affect some information
1646 # because they may be PLATFORM-related. That's why we need to clear all internal
1647 # used members, in order to cause all information to be re-retrieved.
1648 #
1649 def _SetPlatform(self, Value):
1650 if self._Platform == Value:
1651 return
1652 self._Platform = Value
1653 self._Clear()
1654 def _GetHeaderComments(self):
1655 if not self._HeaderComments:
1656 self._HeaderComments = []
1657 RecordList = self._RawData[MODEL_META_DATA_HEADER_COMMENT]
1658 for Record in RecordList:
1659 self._HeaderComments.append(Record[0])
1660 return self._HeaderComments
1661 def _GetTailComments(self):
1662 if not self._TailComments:
1663 self._TailComments = []
1664 RecordList = self._RawData[MODEL_META_DATA_TAIL_COMMENT]
1665 for Record in RecordList:
1666 self._TailComments.append(Record[0])
1667 return self._TailComments
1668 ## Retrieve all information in [Defines] section
1669 #
1670 # (Retriving all [Defines] information in one-shot is just to save time.)
1671 #
1672 def _GetHeaderInfo(self):
1673 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
1674 for Record in RecordList:
1675 Name, Value = Record[1], ReplaceMacro(Record[2], self._Macros, False)
1676 # items defined _PROPERTY_ don't need additional processing
1677 if Name in self:
1678 self[Name] = Value
1679 # some special items in [Defines] section need special treatment
1680 elif Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION', 'EDK_RELEASE_VERSION', 'PI_SPECIFICATION_VERSION'):
1681 if Name in ('EFI_SPECIFICATION_VERSION', 'UEFI_SPECIFICATION_VERSION'):
1682 Name = 'UEFI_SPECIFICATION_VERSION'
1683 if self._Specification == None:
1684 self._Specification = sdict()
1685 self._Specification[Name] = GetHexVerValue(Value)
1686 if self._Specification[Name] == None:
1687 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1688 "'%s' format is not supported for %s" % (Value, Name),
1689 File=self.MetaFile, Line=Record[-1])
1690 elif Name == 'LIBRARY_CLASS':
1691 if self._LibraryClass == None:
1692 self._LibraryClass = []
1693 ValueList = GetSplitValueList(Value)
1694 LibraryClass = ValueList[0]
1695 if len(ValueList) > 1:
1696 SupModuleList = GetSplitValueList(ValueList[1], ' ')
1697 else:
1698 SupModuleList = SUP_MODULE_LIST
1699 self._LibraryClass.append(LibraryClassObject(LibraryClass, SupModuleList))
1700 elif Name == 'ENTRY_POINT':
1701 if self._ModuleEntryPointList == None:
1702 self._ModuleEntryPointList = []
1703 self._ModuleEntryPointList.append(Value)
1704 elif Name == 'UNLOAD_IMAGE':
1705 if self._ModuleUnloadImageList == None:
1706 self._ModuleUnloadImageList = []
1707 if not Value:
1708 continue
1709 self._ModuleUnloadImageList.append(Value)
1710 elif Name == 'CONSTRUCTOR':
1711 if self._ConstructorList == None:
1712 self._ConstructorList = []
1713 if not Value:
1714 continue
1715 self._ConstructorList.append(Value)
1716 elif Name == 'DESTRUCTOR':
1717 if self._DestructorList == None:
1718 self._DestructorList = []
1719 if not Value:
1720 continue
1721 self._DestructorList.append(Value)
1722 elif Name == TAB_INF_DEFINES_CUSTOM_MAKEFILE:
1723 TokenList = GetSplitValueList(Value)
1724 if self._CustomMakefile == None:
1725 self._CustomMakefile = {}
1726 if len(TokenList) < 2:
1727 self._CustomMakefile['MSFT'] = TokenList[0]
1728 self._CustomMakefile['GCC'] = TokenList[0]
1729 else:
1730 if TokenList[0] not in ['MSFT', 'GCC']:
1731 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1732 "No supported family [%s]" % TokenList[0],
1733 File=self.MetaFile, Line=Record[-1])
1734 self._CustomMakefile[TokenList[0]] = TokenList[1]
1735 else:
1736 if self._Defs == None:
1737 self._Defs = sdict()
1738 self._Defs[Name] = Value
1739
1740 #
1741 # Retrieve information in sections specific to Edk.x modules
1742 #
1743 if self.AutoGenVersion >= 0x00010005:
1744 if not self._ModuleType:
1745 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1746 "MODULE_TYPE is not given", File=self.MetaFile)
1747 if self._ModuleType not in SUP_MODULE_LIST:
1748 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
1749 for Record in RecordList:
1750 Name = Record[1]
1751 if Name == "MODULE_TYPE":
1752 LineNo = Record[6]
1753 break
1754 EdkLogger.error("build", FORMAT_NOT_SUPPORTED,
1755 "MODULE_TYPE %s is not supported for EDK II, valid values are:\n %s" % (self._ModuleType,' '.join(l for l in SUP_MODULE_LIST)),
1756 File=self.MetaFile, Line=LineNo)
1757 if (self._Specification == None) or (not 'PI_SPECIFICATION_VERSION' in self._Specification) or (int(self._Specification['PI_SPECIFICATION_VERSION'], 16) < 0x0001000A):
1758 if self._ModuleType == SUP_MODULE_SMM_CORE:
1759 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)
1760 if self._Defs and 'PCI_DEVICE_ID' in self._Defs and 'PCI_VENDOR_ID' in self._Defs \
1761 and 'PCI_CLASS_CODE' in self._Defs:
1762 self._BuildType = 'UEFI_OPTIONROM'
1763 elif self._Defs and 'UEFI_HII_RESOURCE_SECTION' in self._Defs \
1764 and self._Defs['UEFI_HII_RESOURCE_SECTION'] == 'TRUE':
1765 self._BuildType = 'UEFI_HII'
1766 else:
1767 self._BuildType = self._ModuleType.upper()
1768
1769 if self._DxsFile:
1770 File = PathClass(NormPath(self._DxsFile), self._ModuleDir, Arch=self._Arch)
1771 # check the file validation
1772 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
1773 if ErrorCode != 0:
1774 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
1775 File=self.MetaFile, Line=LineNo)
1776 if self.Sources == None:
1777 self._Sources = []
1778 self._Sources.append(File)
1779 else:
1780 if not self._ComponentType:
1781 EdkLogger.error("build", ATTRIBUTE_NOT_AVAILABLE,
1782 "COMPONENT_TYPE is not given", File=self.MetaFile)
1783 self._BuildType = self._ComponentType.upper()
1784 if self._ComponentType in self._MODULE_TYPE_:
1785 self._ModuleType = self._MODULE_TYPE_[self._ComponentType]
1786 if self._ComponentType == 'LIBRARY':
1787 self._LibraryClass = [LibraryClassObject(self._BaseName, SUP_MODULE_LIST)]
1788 # make use some [nmake] section macros
1789 Macros = self._Macros
1790 Macros["EDK_SOURCE"] = GlobalData.gEcpSource
1791 Macros['PROCESSOR'] = self._Arch
1792 RecordList = self._RawData[MODEL_META_DATA_NMAKE, self._Arch, self._Platform]
1793 for Name,Value,Dummy,Arch,Platform,ID,LineNo in RecordList:
1794 Value = ReplaceMacro(Value, Macros, True)
1795 if Name == "IMAGE_ENTRY_POINT":
1796 if self._ModuleEntryPointList == None:
1797 self._ModuleEntryPointList = []
1798 self._ModuleEntryPointList.append(Value)
1799 elif Name == "DPX_SOURCE":
1800 File = PathClass(NormPath(Value), self._ModuleDir, Arch=self._Arch)
1801 # check the file validation
1802 ErrorCode, ErrorInfo = File.Validate(".dxs", CaseSensitive=False)
1803 if ErrorCode != 0:
1804 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo,
1805 File=self.MetaFile, Line=LineNo)
1806 if self.Sources == None:
1807 self._Sources = []
1808 self._Sources.append(File)
1809 else:
1810 ToolList = self._NMAKE_FLAG_PATTERN_.findall(Name)
1811 if len(ToolList) == 0 or len(ToolList) != 1:
1812 pass
1813 # EdkLogger.warn("build", "Don't know how to do with macro [%s]" % Name,
1814 # File=self.MetaFile, Line=LineNo)
1815 else:
1816 if self._BuildOptions == None:
1817 self._BuildOptions = sdict()
1818
1819 if ToolList[0] in self._TOOL_CODE_:
1820 Tool = self._TOOL_CODE_[ToolList[0]]
1821 else:
1822 Tool = ToolList[0]
1823 ToolChain = "*_*_*_%s_FLAGS" % Tool
1824 ToolChainFamily = 'MSFT' # Edk.x only support MSFT tool chain
1825 #ignore not replaced macros in value
1826 ValueList = GetSplitList(' ' + Value, '/D')
1827 Dummy = ValueList[0]
1828 for Index in range(1, len(ValueList)):
1829 if ValueList[Index][-1] == '=' or ValueList[Index] == '':
1830 continue
1831 Dummy = Dummy + ' /D ' + ValueList[Index]
1832 Value = Dummy.strip()
1833 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
1834 self._BuildOptions[ToolChainFamily, ToolChain] = Value
1835 else:
1836 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
1837 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Value
1838 # set _Header to non-None in order to avoid database re-querying
1839 self._Header_ = 'DUMMY'
1840
1841 ## Retrieve file version
1842 def _GetInfVersion(self):
1843 if self._AutoGenVersion == None:
1844 RecordList = self._RawData[MODEL_META_DATA_HEADER, self._Arch, self._Platform]
1845 for Record in RecordList:
1846 if Record[1] == TAB_INF_DEFINES_INF_VERSION:
1847 self._AutoGenVersion = int(Record[2], 0)
1848 break
1849 if self._AutoGenVersion == None:
1850 self._AutoGenVersion = 0x00010000
1851 return self._AutoGenVersion
1852
1853 ## Retrieve BASE_NAME
1854 def _GetBaseName(self):
1855 if self._BaseName == None:
1856 if self._Header_ == None:
1857 self._GetHeaderInfo()
1858 if self._BaseName == None:
1859 EdkLogger.error('build', ATTRIBUTE_NOT_AVAILABLE, "No BASE_NAME name", File=self.MetaFile)
1860 return self._BaseName
1861
1862 ## Retrieve DxsFile
1863 def _GetDxsFile(self):
1864 if self._DxsFile == None:
1865 if self._Header_ == None:
1866 self._GetHeaderInfo()
1867 if self._DxsFile == None:
1868 self._DxsFile = ''
1869 return self._DxsFile
1870
1871 ## Retrieve MODULE_TYPE
1872 def _GetModuleType(self):
1873 if self._ModuleType == None:
1874 if self._Header_ == None:
1875 self._GetHeaderInfo()
1876 if self._ModuleType == None:
1877 self._ModuleType = 'BASE'
1878 if self._ModuleType not in SUP_MODULE_LIST:
1879 self._ModuleType = "USER_DEFINED"
1880 return self._ModuleType
1881
1882 ## Retrieve COMPONENT_TYPE
1883 def _GetComponentType(self):
1884 if self._ComponentType == None:
1885 if self._Header_ == None:
1886 self._GetHeaderInfo()
1887 if self._ComponentType == None:
1888 self._ComponentType = 'USER_DEFINED'
1889 return self._ComponentType
1890
1891 ## Retrieve "BUILD_TYPE"
1892 def _GetBuildType(self):
1893 if self._BuildType == None:
1894 if self._Header_ == None:
1895 self._GetHeaderInfo()
1896 if not self._BuildType:
1897 self._BuildType = "BASE"
1898 return self._BuildType
1899
1900 ## Retrieve file guid
1901 def _GetFileGuid(self):
1902 if self._Guid == None:
1903 if self._Header_ == None:
1904 self._GetHeaderInfo()
1905 if self._Guid == None:
1906 self._Guid = '00000000-0000-0000-000000000000'
1907 return self._Guid
1908
1909 ## Retrieve module version
1910 def _GetVersion(self):
1911 if self._Version == None:
1912 if self._Header_ == None:
1913 self._GetHeaderInfo()
1914 if self._Version == None:
1915 self._Version = '0.0'
1916 return self._Version
1917
1918 ## Retrieve PCD_IS_DRIVER
1919 def _GetPcdIsDriver(self):
1920 if self._PcdIsDriver == None:
1921 if self._Header_ == None:
1922 self._GetHeaderInfo()
1923 if self._PcdIsDriver == None:
1924 self._PcdIsDriver = ''
1925 return self._PcdIsDriver
1926
1927 ## Retrieve SHADOW
1928 def _GetShadow(self):
1929 if self._Shadow == None:
1930 if self._Header_ == None:
1931 self._GetHeaderInfo()
1932 if self._Shadow != None and self._Shadow.upper() == 'TRUE':
1933 self._Shadow = True
1934 else:
1935 self._Shadow = False
1936 return self._Shadow
1937
1938 ## Retrieve CUSTOM_MAKEFILE
1939 def _GetMakefile(self):
1940 if self._CustomMakefile == None:
1941 if self._Header_ == None:
1942 self._GetHeaderInfo()
1943 if self._CustomMakefile == None:
1944 self._CustomMakefile = {}
1945 return self._CustomMakefile
1946
1947 ## Retrieve EFI_SPECIFICATION_VERSION
1948 def _GetSpec(self):
1949 if self._Specification == None:
1950 if self._Header_ == None:
1951 self._GetHeaderInfo()
1952 if self._Specification == None:
1953 self._Specification = {}
1954 return self._Specification
1955
1956 ## Retrieve LIBRARY_CLASS
1957 def _GetLibraryClass(self):
1958 if self._LibraryClass == None:
1959 if self._Header_ == None:
1960 self._GetHeaderInfo()
1961 if self._LibraryClass == None:
1962 self._LibraryClass = []
1963 return self._LibraryClass
1964
1965 ## Retrieve ENTRY_POINT
1966 def _GetEntryPoint(self):
1967 if self._ModuleEntryPointList == None:
1968 if self._Header_ == None:
1969 self._GetHeaderInfo()
1970 if self._ModuleEntryPointList == None:
1971 self._ModuleEntryPointList = []
1972 return self._ModuleEntryPointList
1973
1974 ## Retrieve UNLOAD_IMAGE
1975 def _GetUnloadImage(self):
1976 if self._ModuleUnloadImageList == None:
1977 if self._Header_ == None:
1978 self._GetHeaderInfo()
1979 if self._ModuleUnloadImageList == None:
1980 self._ModuleUnloadImageList = []
1981 return self._ModuleUnloadImageList
1982
1983 ## Retrieve CONSTRUCTOR
1984 def _GetConstructor(self):
1985 if self._ConstructorList == None:
1986 if self._Header_ == None:
1987 self._GetHeaderInfo()
1988 if self._ConstructorList == None:
1989 self._ConstructorList = []
1990 return self._ConstructorList
1991
1992 ## Retrieve DESTRUCTOR
1993 def _GetDestructor(self):
1994 if self._DestructorList == None:
1995 if self._Header_ == None:
1996 self._GetHeaderInfo()
1997 if self._DestructorList == None:
1998 self._DestructorList = []
1999 return self._DestructorList
2000
2001 ## Retrieve definies other than above ones
2002 def _GetDefines(self):
2003 if self._Defs == None:
2004 if self._Header_ == None:
2005 self._GetHeaderInfo()
2006 if self._Defs == None:
2007 self._Defs = sdict()
2008 return self._Defs
2009
2010 ## Retrieve binary files
2011 def _GetBinaries(self):
2012 if self._Binaries == None:
2013 self._Binaries = []
2014 RecordList = self._RawData[MODEL_EFI_BINARY_FILE, self._Arch, self._Platform]
2015 Macros = self._Macros
2016 Macros["EDK_SOURCE"] = GlobalData.gEcpSource
2017 Macros['PROCESSOR'] = self._Arch
2018 for Record in RecordList:
2019 FileType = Record[0]
2020 LineNo = Record[-1]
2021 Target = 'COMMON'
2022 FeatureFlag = []
2023 if Record[2]:
2024 TokenList = GetSplitValueList(Record[2], TAB_VALUE_SPLIT)
2025 if TokenList:
2026 Target = TokenList[0]
2027 if len(TokenList) > 1:
2028 FeatureFlag = Record[1:]
2029
2030 File = PathClass(NormPath(Record[1], Macros), self._ModuleDir, '', FileType, True, self._Arch, '', Target)
2031 # check the file validation
2032 ErrorCode, ErrorInfo = File.Validate()
2033 if ErrorCode != 0:
2034 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
2035 self._Binaries.append(File)
2036 return self._Binaries
2037
2038 ## Retrieve binary files with error check.
2039 def _GetBinaryFiles(self):
2040 Binaries = self._GetBinaries()
2041 if GlobalData.gIgnoreSource and Binaries == []:
2042 ErrorInfo = "The INF file does not contain any Binaries to use in creating the image\n"
2043 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, ExtraData=ErrorInfo, File=self.MetaFile)
2044
2045 return Binaries
2046 ## Check whether it exists the binaries with current ARCH in AsBuild INF
2047 def _IsSupportedArch(self):
2048 if self._GetBinaries() and not self._GetSourceFiles():
2049 return True
2050 else:
2051 return False
2052 ## Retrieve source files
2053 def _GetSourceFiles(self):
2054 if self._Sources == None:
2055 self._Sources = []
2056 RecordList = self._RawData[MODEL_EFI_SOURCE_FILE, self._Arch, self._Platform]
2057 Macros = self._Macros
2058 for Record in RecordList:
2059 LineNo = Record[-1]
2060 ToolChainFamily = Record[1]
2061 TagName = Record[2]
2062 ToolCode = Record[3]
2063 FeatureFlag = Record[4]
2064 if self.AutoGenVersion < 0x00010005:
2065 Macros["EDK_SOURCE"] = GlobalData.gEcpSource
2066 Macros['PROCESSOR'] = self._Arch
2067 # old module source files (Edk)
2068 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, self._SourceOverridePath,
2069 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
2070 # check the file validation
2071 ErrorCode, ErrorInfo = File.Validate(CaseSensitive=False)
2072 if ErrorCode != 0:
2073 if File.Ext.lower() == '.h':
2074 EdkLogger.warn('build', 'Include file not found', ExtraData=ErrorInfo,
2075 File=self.MetaFile, Line=LineNo)
2076 continue
2077 else:
2078 EdkLogger.error('build', ErrorCode, ExtraData=File, File=self.MetaFile, Line=LineNo)
2079 else:
2080 File = PathClass(NormPath(Record[0], Macros), self._ModuleDir, '',
2081 '', False, self._Arch, ToolChainFamily, '', TagName, ToolCode)
2082 # check the file validation
2083 ErrorCode, ErrorInfo = File.Validate()
2084 if ErrorCode != 0:
2085 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
2086
2087 self._Sources.append(File)
2088 return self._Sources
2089
2090 ## Retrieve library classes employed by this module
2091 def _GetLibraryClassUses(self):
2092 if self._LibraryClasses == None:
2093 self._LibraryClasses = sdict()
2094 RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, self._Platform]
2095 for Record in RecordList:
2096 Lib = Record[0]
2097 Instance = Record[1]
2098 if Instance:
2099 Instance = NormPath(Instance, self._Macros)
2100 self._LibraryClasses[Lib] = Instance
2101 return self._LibraryClasses
2102
2103 ## Retrieve library names (for Edk.x style of modules)
2104 def _GetLibraryNames(self):
2105 if self._Libraries == None:
2106 self._Libraries = []
2107 RecordList = self._RawData[MODEL_EFI_LIBRARY_INSTANCE, self._Arch, self._Platform]
2108 for Record in RecordList:
2109 LibraryName = ReplaceMacro(Record[0], self._Macros, False)
2110 # in case of name with '.lib' extension, which is unusual in Edk.x inf
2111 LibraryName = os.path.splitext(LibraryName)[0]
2112 if LibraryName not in self._Libraries:
2113 self._Libraries.append(LibraryName)
2114 return self._Libraries
2115
2116 def _GetProtocolComments(self):
2117 self._GetProtocols()
2118 return self._ProtocolComments
2119 ## Retrieve protocols consumed/produced by this module
2120 def _GetProtocols(self):
2121 if self._Protocols == None:
2122 self._Protocols = sdict()
2123 self._ProtocolComments = sdict()
2124 RecordList = self._RawData[MODEL_EFI_PROTOCOL, self._Arch, self._Platform]
2125 for Record in RecordList:
2126 CName = Record[0]
2127 Value = ProtocolValue(CName, self.Packages)
2128 if Value == None:
2129 PackageList = "\n\t".join([str(P) for P in self.Packages])
2130 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
2131 "Value of Protocol [%s] is not found under [Protocols] section in" % CName,
2132 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
2133 self._Protocols[CName] = Value
2134 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
2135 Comments = []
2136 for CmtRec in CommentRecords:
2137 Comments.append(CmtRec[0])
2138 self._ProtocolComments[CName] = Comments
2139 return self._Protocols
2140
2141 def _GetPpiComments(self):
2142 self._GetPpis()
2143 return self._PpiComments
2144 ## Retrieve PPIs consumed/produced by this module
2145 def _GetPpis(self):
2146 if self._Ppis == None:
2147 self._Ppis = sdict()
2148 self._PpiComments = sdict()
2149 RecordList = self._RawData[MODEL_EFI_PPI, self._Arch, self._Platform]
2150 for Record in RecordList:
2151 CName = Record[0]
2152 Value = PpiValue(CName, self.Packages)
2153 if Value == None:
2154 PackageList = "\n\t".join([str(P) for P in self.Packages])
2155 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
2156 "Value of PPI [%s] is not found under [Ppis] section in " % CName,
2157 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
2158 self._Ppis[CName] = Value
2159 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
2160 Comments = []
2161 for CmtRec in CommentRecords:
2162 Comments.append(CmtRec[0])
2163 self._PpiComments[CName] = Comments
2164 return self._Ppis
2165
2166 def _GetGuidComments(self):
2167 self._GetGuids()
2168 return self._GuidComments
2169 ## Retrieve GUIDs consumed/produced by this module
2170 def _GetGuids(self):
2171 if self._Guids == None:
2172 self._Guids = sdict()
2173 self._GuidComments = sdict()
2174 RecordList = self._RawData[MODEL_EFI_GUID, self._Arch, self._Platform]
2175 for Record in RecordList:
2176 CName = Record[0]
2177 Value = GuidValue(CName, self.Packages)
2178 if Value == None:
2179 PackageList = "\n\t".join([str(P) for P in self.Packages])
2180 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
2181 "Value of Guid [%s] is not found under [Guids] section in" % CName,
2182 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
2183 self._Guids[CName] = Value
2184 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Record[5]]
2185 Comments = []
2186 for CmtRec in CommentRecords:
2187 Comments.append(CmtRec[0])
2188 self._GuidComments[CName] = Comments
2189 return self._Guids
2190
2191 ## Retrieve include paths necessary for this module (for Edk.x style of modules)
2192 def _GetIncludes(self):
2193 if self._Includes == None:
2194 self._Includes = []
2195 if self._SourceOverridePath:
2196 self._Includes.append(self._SourceOverridePath)
2197
2198 Macros = self._Macros
2199 if 'PROCESSOR' in GlobalData.gEdkGlobal.keys():
2200 Macros['PROCESSOR'] = GlobalData.gEdkGlobal['PROCESSOR']
2201 else:
2202 Macros['PROCESSOR'] = self._Arch
2203 RecordList = self._RawData[MODEL_EFI_INCLUDE, self._Arch, self._Platform]
2204 for Record in RecordList:
2205 if Record[0].find('EDK_SOURCE') > -1:
2206 Macros['EDK_SOURCE'] = GlobalData.gEcpSource
2207 File = NormPath(Record[0], self._Macros)
2208 if File[0] == '.':
2209 File = os.path.join(self._ModuleDir, File)
2210 else:
2211 File = os.path.join(GlobalData.gWorkspace, File)
2212 File = RealPath(os.path.normpath(File))
2213 if File:
2214 self._Includes.append(File)
2215
2216 #TRICK: let compiler to choose correct header file
2217 Macros['EDK_SOURCE'] = GlobalData.gEdkSource
2218 File = NormPath(Record[0], self._Macros)
2219 if File[0] == '.':
2220 File = os.path.join(self._ModuleDir, File)
2221 else:
2222 File = os.path.join(GlobalData.gWorkspace, File)
2223 File = RealPath(os.path.normpath(File))
2224 if File:
2225 self._Includes.append(File)
2226 else:
2227 File = NormPath(Record[0], Macros)
2228 if File[0] == '.':
2229 File = os.path.join(self._ModuleDir, File)
2230 else:
2231 File = os.path.join(GlobalData.gWorkspace, File)
2232 File = RealPath(os.path.normpath(File))
2233 if File:
2234 self._Includes.append(File)
2235 return self._Includes
2236
2237 ## Retrieve packages this module depends on
2238 def _GetPackages(self):
2239 if self._Packages == None:
2240 self._Packages = []
2241 RecordList = self._RawData[MODEL_META_DATA_PACKAGE, self._Arch, self._Platform]
2242 Macros = self._Macros
2243 Macros['EDK_SOURCE'] = GlobalData.gEcpSource
2244 for Record in RecordList:
2245 File = PathClass(NormPath(Record[0], Macros), GlobalData.gWorkspace, Arch=self._Arch)
2246 LineNo = Record[-1]
2247 # check the file validation
2248 ErrorCode, ErrorInfo = File.Validate('.dec')
2249 if ErrorCode != 0:
2250 EdkLogger.error('build', ErrorCode, ExtraData=ErrorInfo, File=self.MetaFile, Line=LineNo)
2251 # parse this package now. we need it to get protocol/ppi/guid value
2252 Package = self._Bdb[File, self._Arch, self._Target, self._Toolchain]
2253 self._Packages.append(Package)
2254 return self._Packages
2255
2256 ## Retrieve PCD comments
2257 def _GetPcdComments(self):
2258 self._GetPcds()
2259 return self._PcdComments
2260 ## Retrieve PCDs used in this module
2261 def _GetPcds(self):
2262 if self._Pcds == None:
2263 self._Pcds = sdict()
2264 self._PcdComments = sdict()
2265 self._Pcds.update(self._GetPcd(MODEL_PCD_FIXED_AT_BUILD))
2266 self._Pcds.update(self._GetPcd(MODEL_PCD_PATCHABLE_IN_MODULE))
2267 self._Pcds.update(self._GetPcd(MODEL_PCD_FEATURE_FLAG))
2268 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC))
2269 self._Pcds.update(self._GetPcd(MODEL_PCD_DYNAMIC_EX))
2270 return self._Pcds
2271
2272 ## Retrieve build options specific to this module
2273 def _GetBuildOptions(self):
2274 if self._BuildOptions == None:
2275 self._BuildOptions = sdict()
2276 RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, self._Platform]
2277 for Record in RecordList:
2278 ToolChainFamily = Record[0]
2279 ToolChain = Record[1]
2280 Option = Record[2]
2281 if (ToolChainFamily, ToolChain) not in self._BuildOptions:
2282 self._BuildOptions[ToolChainFamily, ToolChain] = Option
2283 else:
2284 # concatenate the option string if they're for the same tool
2285 OptionString = self._BuildOptions[ToolChainFamily, ToolChain]
2286 self._BuildOptions[ToolChainFamily, ToolChain] = OptionString + " " + Option
2287 return self._BuildOptions
2288
2289 ## Retrieve dependency expression
2290 def _GetDepex(self):
2291 if self._Depex == None:
2292 self._Depex = tdict(False, 2)
2293 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
2294
2295 # If the module has only Binaries and no Sources, then ignore [Depex]
2296 if self.Sources == None or self.Sources == []:
2297 if self.Binaries != None and self.Binaries != []:
2298 return self._Depex
2299
2300 # PEIM and DXE drivers must have a valid [Depex] section
2301 if len(self.LibraryClass) == 0 and len(RecordList) == 0:
2302 if self.ModuleType == 'DXE_DRIVER' or self.ModuleType == 'PEIM' or self.ModuleType == 'DXE_SMM_DRIVER' or \
2303 self.ModuleType == 'DXE_SAL_DRIVER' or self.ModuleType == 'DXE_RUNTIME_DRIVER':
2304 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "No [Depex] section or no valid expression in [Depex] section for [%s] module" \
2305 % self.ModuleType, File=self.MetaFile)
2306
2307 Depex = sdict()
2308 for Record in RecordList:
2309 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
2310 Arch = Record[3]
2311 ModuleType = Record[4]
2312 TokenList = DepexStr.split()
2313 if (Arch, ModuleType) not in Depex:
2314 Depex[Arch, ModuleType] = []
2315 DepexList = Depex[Arch, ModuleType]
2316 for Token in TokenList:
2317 if Token in DEPEX_SUPPORTED_OPCODE:
2318 DepexList.append(Token)
2319 elif Token.endswith(".inf"): # module file name
2320 ModuleFile = os.path.normpath(Token)
2321 Module = self.BuildDatabase[ModuleFile]
2322 if Module == None:
2323 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE, "Module is not found in active platform",
2324 ExtraData=Token, File=self.MetaFile, Line=Record[-1])
2325 DepexList.append(Module.Guid)
2326 else:
2327 # get the GUID value now
2328 Value = ProtocolValue(Token, self.Packages)
2329 if Value == None:
2330 Value = PpiValue(Token, self.Packages)
2331 if Value == None:
2332 Value = GuidValue(Token, self.Packages)
2333 if Value == None:
2334 PackageList = "\n\t".join([str(P) for P in self.Packages])
2335 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
2336 "Value of [%s] is not found in" % Token,
2337 ExtraData=PackageList, File=self.MetaFile, Line=Record[-1])
2338 DepexList.append(Value)
2339 for Arch, ModuleType in Depex:
2340 self._Depex[Arch, ModuleType] = Depex[Arch, ModuleType]
2341 return self._Depex
2342
2343 ## Retrieve depedency expression
2344 def _GetDepexExpression(self):
2345 if self._DepexExpression == None:
2346 self._DepexExpression = tdict(False, 2)
2347 RecordList = self._RawData[MODEL_EFI_DEPEX, self._Arch]
2348 DepexExpression = sdict()
2349 for Record in RecordList:
2350 DepexStr = ReplaceMacro(Record[0], self._Macros, False)
2351 Arch = Record[3]
2352 ModuleType = Record[4]
2353 TokenList = DepexStr.split()
2354 if (Arch, ModuleType) not in DepexExpression:
2355 DepexExpression[Arch, ModuleType] = ''
2356 for Token in TokenList:
2357 DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType] + Token.strip() + ' '
2358 for Arch, ModuleType in DepexExpression:
2359 self._DepexExpression[Arch, ModuleType] = DepexExpression[Arch, ModuleType]
2360 return self._DepexExpression
2361
2362 def GetGuidsUsedByPcd(self):
2363 return self._GuidsUsedByPcd
2364 ## Retrieve PCD for given type
2365 def _GetPcd(self, Type):
2366 Pcds = sdict()
2367 PcdDict = tdict(True, 4)
2368 PcdList = []
2369 RecordList = self._RawData[Type, self._Arch, self._Platform]
2370 for TokenSpaceGuid, PcdCName, Setting, Arch, Platform, Id, LineNo in RecordList:
2371 PcdDict[Arch, Platform, PcdCName, TokenSpaceGuid] = (Setting, LineNo)
2372 PcdList.append((PcdCName, TokenSpaceGuid))
2373 # get the guid value
2374 if TokenSpaceGuid not in self.Guids:
2375 Value = GuidValue(TokenSpaceGuid, self.Packages)
2376 if Value == None:
2377 PackageList = "\n\t".join([str(P) for P in self.Packages])
2378 EdkLogger.error('build', RESOURCE_NOT_AVAILABLE,
2379 "Value of Guid [%s] is not found under [Guids] section in" % TokenSpaceGuid,
2380 ExtraData=PackageList, File=self.MetaFile, Line=LineNo)
2381 self.Guids[TokenSpaceGuid] = Value
2382 self._GuidsUsedByPcd[TokenSpaceGuid] = Value
2383 CommentRecords = self._RawData[MODEL_META_DATA_COMMENT, self._Arch, self._Platform, Id]
2384 Comments = []
2385 for CmtRec in CommentRecords:
2386 Comments.append(CmtRec[0])
2387 self._PcdComments[TokenSpaceGuid, PcdCName] = Comments
2388
2389 # resolve PCD type, value, datum info, etc. by getting its definition from package
2390 for PcdCName, TokenSpaceGuid in PcdList:
2391 Setting, LineNo = PcdDict[self._Arch, self.Platform, PcdCName, TokenSpaceGuid]
2392 if Setting == None:
2393 continue
2394 ValueList = AnalyzePcdData(Setting)
2395 DefaultValue = ValueList[0]
2396 Pcd = PcdClassObject(
2397 PcdCName,
2398 TokenSpaceGuid,
2399 '',
2400 '',
2401 DefaultValue,
2402 '',
2403 '',
2404 {},
2405 False,
2406 self.Guids[TokenSpaceGuid]
2407 )
2408 if Type == MODEL_PCD_PATCHABLE_IN_MODULE and ValueList[1]:
2409 # Patch PCD: TokenSpace.PcdCName|Value|Offset
2410 Pcd.Offset = ValueList[1]
2411
2412 # get necessary info from package declaring this PCD
2413 for Package in self.Packages:
2414 #
2415 # 'dynamic' in INF means its type is determined by platform;
2416 # if platform doesn't give its type, use 'lowest' one in the
2417 # following order, if any
2418 #
2419 # "FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"
2420 #
2421 PcdType = self._PCD_TYPE_STRING_[Type]
2422 if Type == MODEL_PCD_DYNAMIC:
2423 Pcd.Pending = True
2424 for T in ["FixedAtBuild", "PatchableInModule", "FeatureFlag", "Dynamic", "DynamicEx"]:
2425 if (PcdCName, TokenSpaceGuid, T) in Package.Pcds:
2426 PcdType = T
2427 break
2428 else:
2429 Pcd.Pending = False
2430
2431 if (PcdCName, TokenSpaceGuid, PcdType) in Package.Pcds:
2432 PcdInPackage = Package.Pcds[PcdCName, TokenSpaceGuid, PcdType]
2433 Pcd.Type = PcdType
2434 Pcd.TokenValue = PcdInPackage.TokenValue
2435
2436 #
2437 # Check whether the token value exist or not.
2438 #
2439 if Pcd.TokenValue == None or Pcd.TokenValue == "":
2440 EdkLogger.error(
2441 'build',
2442 FORMAT_INVALID,
2443 "No TokenValue for PCD [%s.%s] in [%s]!" % (TokenSpaceGuid, PcdCName, str(Package)),
2444 File =self.MetaFile, Line=LineNo,
2445 ExtraData=None
2446 )
2447 #
2448 # Check hexadecimal token value length and format.
2449 #
2450 ReIsValidPcdTokenValue = re.compile(r"^[0][x|X][0]*[0-9a-fA-F]{1,8}$", re.DOTALL)
2451 if Pcd.TokenValue.startswith("0x") or Pcd.TokenValue.startswith("0X"):
2452 if ReIsValidPcdTokenValue.match(Pcd.TokenValue) == None:
2453 EdkLogger.error(
2454 'build',
2455 FORMAT_INVALID,
2456 "The format of TokenValue [%s] of PCD [%s.%s] in [%s] is invalid:" % (Pcd.TokenValue, TokenSpaceGuid, PcdCName, str(Package)),
2457 File =self.MetaFile, Line=LineNo,
2458 ExtraData=None
2459 )
2460
2461 #
2462 # Check decimal token value length and format.
2463 #
2464 else:
2465 try:
2466 TokenValueInt = int (Pcd.TokenValue, 10)
2467 if (TokenValueInt < 0 or TokenValueInt > 4294967295):
2468 EdkLogger.error(
2469 'build',
2470 FORMAT_INVALID,
2471 "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)),
2472 File =self.MetaFile, Line=LineNo,
2473 ExtraData=None
2474 )
2475 except:
2476 EdkLogger.error(
2477 'build',
2478 FORMAT_INVALID,
2479 "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)),
2480 File =self.MetaFile, Line=LineNo,
2481 ExtraData=None
2482 )
2483
2484 Pcd.DatumType = PcdInPackage.DatumType
2485 Pcd.MaxDatumSize = PcdInPackage.MaxDatumSize
2486 Pcd.InfDefaultValue = Pcd.DefaultValue
2487 if Pcd.DefaultValue in [None, '']:
2488 Pcd.DefaultValue = PcdInPackage.DefaultValue
2489 break
2490 else:
2491 EdkLogger.error(
2492 'build',
2493 FORMAT_INVALID,
2494 "PCD [%s.%s] in [%s] is not found in dependent packages:" % (TokenSpaceGuid, PcdCName, self.MetaFile),
2495 File =self.MetaFile, Line=LineNo,
2496 ExtraData="\t%s" % '\n\t'.join([str(P) for P in self.Packages])
2497 )
2498 Pcds[PcdCName, TokenSpaceGuid] = Pcd
2499
2500 return Pcds
2501
2502 ## check whether current module is binary module
2503 def _IsBinaryModule(self):
2504 if self.Binaries and not self.Sources:
2505 return True
2506 elif GlobalData.gIgnoreSource:
2507 return True
2508 else:
2509 return False
2510
2511 _Macros = property(_GetMacros)
2512 Arch = property(_GetArch, _SetArch)
2513 Platform = property(_GetPlatform, _SetPlatform)
2514
2515 HeaderComments = property(_GetHeaderComments)
2516 TailComments = property(_GetTailComments)
2517 AutoGenVersion = property(_GetInfVersion)
2518 BaseName = property(_GetBaseName)
2519 ModuleType = property(_GetModuleType)
2520 ComponentType = property(_GetComponentType)
2521 BuildType = property(_GetBuildType)
2522 Guid = property(_GetFileGuid)
2523 Version = property(_GetVersion)
2524 PcdIsDriver = property(_GetPcdIsDriver)
2525 Shadow = property(_GetShadow)
2526 CustomMakefile = property(_GetMakefile)
2527 Specification = property(_GetSpec)
2528 LibraryClass = property(_GetLibraryClass)
2529 ModuleEntryPointList = property(_GetEntryPoint)
2530 ModuleUnloadImageList = property(_GetUnloadImage)
2531 ConstructorList = property(_GetConstructor)
2532 DestructorList = property(_GetDestructor)
2533 Defines = property(_GetDefines)
2534 DxsFile = property(_GetDxsFile)
2535
2536 Binaries = property(_GetBinaryFiles)
2537 Sources = property(_GetSourceFiles)
2538 LibraryClasses = property(_GetLibraryClassUses)
2539 Libraries = property(_GetLibraryNames)
2540 Protocols = property(_GetProtocols)
2541 ProtocolComments = property(_GetProtocolComments)
2542 Ppis = property(_GetPpis)
2543 PpiComments = property(_GetPpiComments)
2544 Guids = property(_GetGuids)
2545 GuidComments = property(_GetGuidComments)
2546 Includes = property(_GetIncludes)
2547 Packages = property(_GetPackages)
2548 Pcds = property(_GetPcds)
2549 PcdComments = property(_GetPcdComments)
2550 BuildOptions = property(_GetBuildOptions)
2551 Depex = property(_GetDepex)
2552 DepexExpression = property(_GetDepexExpression)
2553 IsBinaryModule = property(_IsBinaryModule)
2554 IsSupportedArch = property(_IsSupportedArch)
2555
2556 ## Database
2557 #
2558 # This class defined the build database for all modules, packages and platform.
2559 # It will call corresponding parser for the given file if it cannot find it in
2560 # the database.
2561 #
2562 # @param DbPath Path of database file
2563 # @param GlobalMacros Global macros used for replacement during file parsing
2564 # @prarm RenewDb=False Create new database file if it's already there
2565 #
2566 class WorkspaceDatabase(object):
2567
2568 # default database file path
2569 _DB_PATH_ = "Conf/.cache/build.db"
2570
2571 #
2572 # internal class used for call corresponding file parser and caching the result
2573 # to avoid unnecessary re-parsing
2574 #
2575 class BuildObjectFactory(object):
2576
2577 _FILE_TYPE_ = {
2578 ".inf" : MODEL_FILE_INF,
2579 ".dec" : MODEL_FILE_DEC,
2580 ".dsc" : MODEL_FILE_DSC,
2581 }
2582
2583 # file parser
2584 _FILE_PARSER_ = {
2585 MODEL_FILE_INF : InfParser,
2586 MODEL_FILE_DEC : DecParser,
2587 MODEL_FILE_DSC : DscParser,
2588 }
2589
2590 # convert to xxxBuildData object
2591 _GENERATOR_ = {
2592 MODEL_FILE_INF : InfBuildData,
2593 MODEL_FILE_DEC : DecBuildData,
2594 MODEL_FILE_DSC : DscBuildData,
2595 }
2596
2597 _CACHE_ = {} # (FilePath, Arch) : <object>
2598
2599 # constructor
2600 def __init__(self, WorkspaceDb):
2601 self.WorkspaceDb = WorkspaceDb
2602
2603 # key = (FilePath, Arch=None)
2604 def __contains__(self, Key):
2605 FilePath = Key[0]
2606 if len(Key) > 1:
2607 Arch = Key[1]
2608 else:
2609 Arch = None
2610 return (FilePath, Arch) in self._CACHE_
2611
2612 # key = (FilePath, Arch=None, Target=None, Toochain=None)
2613 def __getitem__(self, Key):
2614 FilePath = Key[0]
2615 KeyLength = len(Key)
2616 if KeyLength > 1:
2617 Arch = Key[1]
2618 else:
2619 Arch = None
2620 if KeyLength > 2:
2621 Target = Key[2]
2622 else:
2623 Target = None
2624 if KeyLength > 3:
2625 Toolchain = Key[3]
2626 else:
2627 Toolchain = None
2628
2629 # if it's generated before, just return the cached one
2630 Key = (FilePath, Arch, Target, Toolchain)
2631 if Key in self._CACHE_:
2632 return self._CACHE_[Key]
2633
2634 # check file type
2635 Ext = FilePath.Type
2636 if Ext not in self._FILE_TYPE_:
2637 return None
2638 FileType = self._FILE_TYPE_[Ext]
2639 if FileType not in self._GENERATOR_:
2640 return None
2641
2642 # get the parser ready for this file
2643 MetaFile = self._FILE_PARSER_[FileType](
2644 FilePath,
2645 FileType,
2646 MetaFileStorage(self.WorkspaceDb.Cur, FilePath, FileType)
2647 )
2648 # alwasy do post-process, in case of macros change
2649 MetaFile.DoPostProcess()
2650 # object the build is based on
2651 BuildObject = self._GENERATOR_[FileType](
2652 FilePath,
2653 MetaFile,
2654 self,
2655 Arch,
2656 Target,
2657 Toolchain
2658 )
2659 self._CACHE_[Key] = BuildObject
2660 return BuildObject
2661
2662 # placeholder for file format conversion
2663 class TransformObjectFactory:
2664 def __init__(self, WorkspaceDb):
2665 self.WorkspaceDb = WorkspaceDb
2666
2667 # key = FilePath, Arch
2668 def __getitem__(self, Key):
2669 pass
2670
2671 ## Constructor of WorkspaceDatabase
2672 #
2673 # @param DbPath Path of database file
2674 # @param GlobalMacros Global macros used for replacement during file parsing
2675 # @prarm RenewDb=False Create new database file if it's already there
2676 #
2677 def __init__(self, DbPath, RenewDb=False):
2678 self._DbClosedFlag = False
2679 if not DbPath:
2680 DbPath = os.path.normpath(os.path.join(GlobalData.gWorkspace, self._DB_PATH_))
2681
2682 # don't create necessary path for db in memory
2683 if DbPath != ':memory:':
2684 DbDir = os.path.split(DbPath)[0]
2685 if not os.path.exists(DbDir):
2686 os.makedirs(DbDir)
2687
2688 # remove db file in case inconsistency between db and file in file system
2689 if self._CheckWhetherDbNeedRenew(RenewDb, DbPath):
2690 os.remove(DbPath)
2691
2692 # create db with optimized parameters
2693 self.Conn = sqlite3.connect(DbPath, isolation_level='DEFERRED')
2694 self.Conn.execute("PRAGMA synchronous=OFF")
2695 self.Conn.execute("PRAGMA temp_store=MEMORY")
2696 self.Conn.execute("PRAGMA count_changes=OFF")
2697 self.Conn.execute("PRAGMA cache_size=8192")
2698 #self.Conn.execute("PRAGMA page_size=8192")
2699
2700 # to avoid non-ascii character conversion issue
2701 self.Conn.text_factory = str
2702 self.Cur = self.Conn.cursor()
2703
2704 # create table for internal uses
2705 self.TblDataModel = TableDataModel(self.Cur)
2706 self.TblFile = TableFile(self.Cur)
2707 self.Platform = None
2708
2709 # conversion object for build or file format conversion purpose
2710 self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
2711 self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
2712
2713 ## Check whether workspace database need to be renew.
2714 # The renew reason maybe:
2715 # 1) If user force to renew;
2716 # 2) If user do not force renew, and
2717 # a) If the time of last modified python source is newer than database file;
2718 # b) If the time of last modified frozen executable file is newer than database file;
2719 #
2720 # @param force User force renew database
2721 # @param DbPath The absolute path of workspace database file
2722 #
2723 # @return Bool value for whether need renew workspace databse
2724 #
2725 def _CheckWhetherDbNeedRenew (self, force, DbPath):
2726 # if database does not exist, we need do nothing
2727 if not os.path.exists(DbPath): return False
2728
2729 # if user force to renew database, then not check whether database is out of date
2730 if force: return True
2731
2732 #
2733 # Check the time of last modified source file or build.exe
2734 # if is newer than time of database, then database need to be re-created.
2735 #
2736 timeOfToolModified = 0
2737 if hasattr(sys, "frozen"):
2738 exePath = os.path.abspath(sys.executable)
2739 timeOfToolModified = os.stat(exePath).st_mtime
2740 else:
2741 curPath = os.path.dirname(__file__) # curPath is the path of WorkspaceDatabase.py
2742 rootPath = os.path.split(curPath)[0] # rootPath is root path of python source, such as /BaseTools/Source/Python
2743 if rootPath == "" or rootPath == None:
2744 EdkLogger.verbose("\nFail to find the root path of build.exe or python sources, so can not \
2745 determine whether database file is out of date!\n")
2746
2747 # walk the root path of source or build's binary to get the time last modified.
2748
2749 for root, dirs, files in os.walk (rootPath):
2750 for dir in dirs:
2751 # bypass source control folder
2752 if dir.lower() in [".svn", "_svn", "cvs"]:
2753 dirs.remove(dir)
2754
2755 for file in files:
2756 ext = os.path.splitext(file)[1]
2757 if ext.lower() == ".py": # only check .py files
2758 fd = os.stat(os.path.join(root, file))
2759 if timeOfToolModified < fd.st_mtime:
2760 timeOfToolModified = fd.st_mtime
2761 if timeOfToolModified > os.stat(DbPath).st_mtime:
2762 EdkLogger.verbose("\nWorkspace database is out of data!")
2763 return True
2764
2765 return False
2766
2767 ## Initialize build database
2768 def InitDatabase(self):
2769 EdkLogger.verbose("\nInitialize build database started ...")
2770
2771 #
2772 # Create new tables
2773 #
2774 self.TblDataModel.Create(False)
2775 self.TblFile.Create(False)
2776
2777 #
2778 # Initialize table DataModel
2779 #
2780 self.TblDataModel.InitTable()
2781 EdkLogger.verbose("Initialize build database ... DONE!")
2782
2783 ## Query a table
2784 #
2785 # @param Table: The instance of the table to be queried
2786 #
2787 def QueryTable(self, Table):
2788 Table.Query()
2789
2790 def __del__(self):
2791 self.Close()
2792
2793 ## Close entire database
2794 #
2795 # Commit all first
2796 # Close the connection and cursor
2797 #
2798 def Close(self):
2799 if not self._DbClosedFlag:
2800 self.Conn.commit()
2801 self.Cur.close()
2802 self.Conn.close()
2803 self._DbClosedFlag = True
2804
2805 ## Summarize all packages in the database
2806 def GetPackageList(self, Platform, Arch, TargetName, ToolChainTag):
2807 self.Platform = Platform
2808 PackageList =[]
2809 Pa = self.BuildObject[self.Platform, 'COMMON']
2810 #
2811 # Get Package related to Modules
2812 #
2813 for Module in Pa.Modules:
2814 ModuleObj = self.BuildObject[Module, Arch, TargetName, ToolChainTag]
2815 for Package in ModuleObj.Packages:
2816 if Package not in PackageList:
2817 PackageList.append(Package)
2818 #
2819 # Get Packages related to Libraries
2820 #
2821 for Lib in Pa.LibraryInstances:
2822 LibObj = self.BuildObject[Lib, Arch, TargetName, ToolChainTag]
2823 for Package in LibObj.Packages:
2824 if Package not in PackageList:
2825 PackageList.append(Package)
2826
2827 return PackageList
2828
2829 ## Summarize all platforms in the database
2830 def _GetPlatformList(self):
2831 PlatformList = []
2832 for PlatformFile in self.TblFile.GetFileList(MODEL_FILE_DSC):
2833 try:
2834 Platform = self.BuildObject[PathClass(PlatformFile), 'COMMON']
2835 except:
2836 Platform = None
2837 if Platform != None:
2838 PlatformList.append(Platform)
2839 return PlatformList
2840
2841 PlatformList = property(_GetPlatformList)
2842
2843 ##
2844 #
2845 # This acts like the main() function for the script, unless it is 'import'ed into another
2846 # script.
2847 #
2848 if __name__ == '__main__':
2849 pass
2850