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