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