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