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