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