1## @file
2# This file is used to define class objects of [Defines] section for INF file.
3# It will consumed by InfParser
4#
5# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR>
6#
7# This program and the accompanying materials are licensed and made available
8# under the terms and conditions of the BSD License which accompanies this
9# distribution. The full text of the license may be found at
10# http://opensource.org/licenses/bsd-license.php
11#
12# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15'''
16InfDefineObject
17'''
18
19import os
20import re
21
22from Logger import StringTable as ST
23from Logger import ToolError
24from Library import GlobalData
25from Library import DataType as DT
26from Library.String import GetSplitValueList
27from Library.Misc import CheckGuidRegFormat
28from Library.Misc import Sdict
29from Library.Misc import ConvPathFromAbsToRel
30from Library.Misc import ValidateUNIFilePath
31from Library.ExpressionValidate import IsValidFeatureFlagExp
32from Library.ParserValidate import IsValidWord
33from Library.ParserValidate import IsValidInfMoudleType
34from Library.ParserValidate import IsValidHex
35from Library.ParserValidate import IsValidHexVersion
36from Library.ParserValidate import IsValidDecVersion
37from Library.ParserValidate import IsValidCVariableName
38from Library.ParserValidate import IsValidBoolType
39from Library.ParserValidate import IsValidPath
40from Library.ParserValidate import IsValidFamily
41from Library.ParserValidate import IsValidIdentifier
42from Library.ParserValidate import IsValidDecVersionVal
43from Object.Parser.InfCommonObject import InfLineCommentObject
44from Object.Parser.InfCommonObject import CurrentLine
45from Object.Parser.InfCommonObject import InfSectionCommonDef
46from Object.Parser.InfMisc import ErrorInInf
47from Object.Parser.InfDefineCommonObject import InfDefineLibraryItem
48from Object.Parser.InfDefineCommonObject import InfDefineEntryPointItem
49from Object.Parser.InfDefineCommonObject import InfDefineUnloadImageItem
50from Object.Parser.InfDefineCommonObject import InfDefineConstructorItem
51from Object.Parser.InfDefineCommonObject import InfDefineDestructorItem
52
53class InfDefSectionOptionRomInfo():
54    def __init__(self):
55        self.PciVendorId                = None
56        self.PciDeviceId                = None
57        self.PciClassCode               = None
58        self.PciRevision                = None
59        self.PciCompress                = None
60        self.CurrentLine                = ['', -1, '']
61    def SetPciVendorId(self, PciVendorId, Comments):
62        #
63        # Value has been set before.
64        #
65        if self.PciVendorId != None:
66            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_VENDOR_ID),
67                       LineInfo=self.CurrentLine)
68            return False
69        #
70        # The PciVendorId should be hex string.
71        #
72        if (IsValidHex(PciVendorId)):
73            self.PciVendorId = InfDefMember()
74            self.PciVendorId.SetValue(PciVendorId)
75            self.PciVendorId.Comments = Comments
76            return True
77        else:
78            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciVendorId),
79                       LineInfo=self.CurrentLine)
80            return False
81
82    def GetPciVendorId(self):
83        return self.PciVendorId
84
85    def SetPciDeviceId(self, PciDeviceId, Comments):
86        #
87        # Value has been set before.
88        #
89        if self.PciDeviceId != None:
90            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_DEVICE_ID),
91                       LineInfo=self.CurrentLine)
92            return False
93        #
94        # The PciDeviceId should be hex string.
95        #
96        if (IsValidHex(PciDeviceId)):
97            self.PciDeviceId = InfDefMember()
98            self.PciDeviceId.SetValue(PciDeviceId)
99            self.PciDeviceId.Comments = Comments
100            return True
101        else:
102            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciDeviceId),
103                       LineInfo=self.CurrentLine)
104            return False
105
106    def GetPciDeviceId(self):
107        return self.PciDeviceId
108
109    def SetPciClassCode(self, PciClassCode, Comments):
110        #
111        # Value has been set before.
112        #
113        if self.PciClassCode != None:
114            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_CLASS_CODE),
115                       LineInfo=self.CurrentLine)
116            return False
117        #
118        # The PciClassCode should be 4 bytes hex string.
119        #
120        if (IsValidHex(PciClassCode)):
121            self.PciClassCode = InfDefMember()
122            self.PciClassCode.SetValue(PciClassCode)
123            self.PciClassCode.Comments = Comments
124            return True
125        else:
126            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\
127                       (PciClassCode),
128                       LineInfo=self.CurrentLine)
129            return False
130
131    def GetPciClassCode(self):
132        return self.PciClassCode
133
134    def SetPciRevision(self, PciRevision, Comments):
135        #
136        # Value has been set before.
137        #
138        if self.PciRevision != None:
139            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_REVISION),
140                       LineInfo=self.CurrentLine)
141            return False
142        #
143        # The PciRevision should be 4 bytes hex string.
144        #
145        if (IsValidHex(PciRevision)):
146            self.PciRevision = InfDefMember()
147            self.PciRevision.SetValue(PciRevision)
148            self.PciRevision.Comments = Comments
149            return True
150        else:
151            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciRevision),
152                       LineInfo=self.CurrentLine)
153            return False
154
155    def GetPciRevision(self):
156        return self.PciRevision
157
158    def SetPciCompress(self, PciCompress, Comments):
159        #
160        # Value has been set before.
161        #
162        if self.PciCompress != None:
163            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_PCI_COMPRESS),
164                       LineInfo=self.CurrentLine)
165            return False
166
167        #
168        # The PciCompress should be 'TRUE' or 'FALSE'.
169        #
170        if (PciCompress == 'TRUE' or PciCompress == 'FALSE'):
171            self.PciCompress = InfDefMember()
172            self.PciCompress.SetValue(PciCompress)
173            self.PciCompress.Comments = Comments
174            return True
175        else:
176            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PciCompress),
177                       LineInfo=self.CurrentLine)
178            return False
179    def GetPciCompress(self):
180        return self.PciCompress
181##
182# INF [Define] section Object
183#
184class InfDefSection(InfDefSectionOptionRomInfo):
185    def __init__(self):
186        self.BaseName                   = None
187        self.FileGuid                   = None
188        self.ModuleType                 = None
189        self.ModuleUniFileName          = None
190        self.InfVersion                 = None
191        self.EdkReleaseVersion          = None
192        self.UefiSpecificationVersion   = None
193        self.PiSpecificationVersion     = None
194        self.LibraryClass               = []
195        self.Package                    = None
196        self.VersionString              = None
197        self.PcdIsDriver                = None
198        self.EntryPoint                 = []
199        self.UnloadImages               = []
200        self.Constructor                = []
201        self.Destructor                 = []
202        self.Shadow                     = None
203        self.CustomMakefile             = []
204        self.Specification              = []
205        self.UefiHiiResourceSection     = None
206        self.DpxSource                  = []
207        self.CurrentLine                = ['', -1, '']
208        InfDefSectionOptionRomInfo.__init__(self)
209
210    ## SetHeadComment
211    #
212    # @param BaseName: BaseName
213    #
214    def SetBaseName(self, BaseName, Comments):
215        #
216        # Value has been set before.
217        #
218        if self.BaseName != None:
219            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_BASE_NAME),
220                       LineInfo=self.CurrentLine)
221            return False
222        if not (BaseName == '' or BaseName == None):
223            if IsValidWord(BaseName) and not BaseName.startswith("_"):
224                self.BaseName = InfDefMember()
225                self.BaseName.SetValue(BaseName)
226                self.BaseName.Comments = Comments
227                return True
228            else:
229                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_NAME_INVALID%(BaseName),
230                           LineInfo=self.CurrentLine)
231                return False
232
233    ## GetBaseName
234    #
235    def GetBaseName(self):
236        return self.BaseName
237
238    ## SetFileGuid
239    #
240    # @param FileGuid: FileGuid
241    #
242    def SetFileGuid(self, FileGuid, Comments):
243        #
244        # Value has been set before.
245        #
246        if self.FileGuid != None:
247            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
248                       %(DT.TAB_INF_DEFINES_FILE_GUID),
249                       LineInfo=self.CurrentLine)
250            return False
251        #
252        # Do verification of GUID content/format
253        #
254        if (CheckGuidRegFormat(FileGuid)):
255            self.FileGuid = InfDefMember()
256            self.FileGuid.SetValue(FileGuid)
257            self.FileGuid.Comments = Comments
258            return True
259        else:
260            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_GUID_INVALID%(FileGuid),
261                       LineInfo=self.CurrentLine)
262            return False
263
264    ## GetFileGuid
265    #
266    def GetFileGuid(self):
267        return self.FileGuid
268
269    ## SetModuleType
270    #
271    # @param ModuleType: ModuleType
272    #
273    def SetModuleType(self, ModuleType, Comments):
274        #
275        # Value has been set before.
276        #
277        if self.ModuleType != None:
278            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
279                       %(DT.TAB_INF_DEFINES_MODULE_TYPE),
280                       LineInfo=self.CurrentLine)
281            return False
282        #
283        # Valid Module Type or not
284        #
285        if (IsValidInfMoudleType(ModuleType)):
286            self.ModuleType = InfDefMember()
287            self.ModuleType.SetValue(ModuleType)
288            self.ModuleType.CurrentLine = CurrentLine()
289            self.ModuleType.CurrentLine.SetLineNo(self.CurrentLine[1])
290            self.ModuleType.CurrentLine.SetLineString(self.CurrentLine[2])
291            self.ModuleType.CurrentLine.SetFileName(self.CurrentLine[0])
292            self.ModuleType.Comments = Comments
293            return True
294        else:
295            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%\
296                       (ModuleType),
297                       LineInfo=self.CurrentLine)
298            return False
299
300    ## GetModuleType
301    #
302    def GetModuleType(self):
303        return self.ModuleType
304
305    ## SetModuleUniFileName
306    #
307    # @param ModuleUniFileName: ModuleUniFileName
308    #
309    def SetModuleUniFileName(self, ModuleUniFileName, Comments):
310        if Comments:
311            pass
312        if self.ModuleUniFileName != None:
313            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_MODULE_UNI_FILE),
314                       LineInfo=self.CurrentLine)
315        self.ModuleUniFileName = ModuleUniFileName
316
317    ## GetModuleType
318    #
319    def GetModuleUniFileName(self):
320        return self.ModuleUniFileName
321
322    ## SetInfVersion
323    #
324    # @param InfVersion: InfVersion
325    #
326    def SetInfVersion(self, InfVersion, Comments):
327        #
328        # Value has been set before.
329        #
330        if self.InfVersion != None:
331            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
332                       %(DT.TAB_INF_DEFINES_INF_VERSION),
333                       LineInfo=self.CurrentLine)
334            return False
335        #
336        # The InfVersion should be 4 bytes hex string.
337        #
338        if (IsValidHex(InfVersion)):
339            if (InfVersion < '0x00010005'):
340                ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF,
341                           ErrorCode=ToolError.EDK1_INF_ERROR,
342                           LineInfo=self.CurrentLine)
343
344            self.InfVersion = InfDefMember()
345            self.InfVersion.SetValue(InfVersion)
346            self.InfVersion.Comments = Comments
347            return True
348        else:
349            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(InfVersion),
350                       LineInfo=self.CurrentLine)
351            return False
352
353    ## GetInfVersion
354    #
355    def GetInfVersion(self):
356        return self.InfVersion
357
358    ## SetEdkReleaseVersion
359    #
360    # @param EdkReleaseVersion: EdkReleaseVersion
361    #
362    def SetEdkReleaseVersion(self, EdkReleaseVersion, Comments):
363        #
364        # Value has been set before.
365        #
366        if self.EdkReleaseVersion != None:
367            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
368                       %(DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION),
369                       LineInfo=self.CurrentLine)
370            return False
371        #
372        # The EdkReleaseVersion should be 4 bytes hex string.
373        #
374        if IsValidHexVersion(EdkReleaseVersion) or \
375           IsValidDecVersionVal(EdkReleaseVersion):
376            self.EdkReleaseVersion = InfDefMember()
377            self.EdkReleaseVersion.SetValue(EdkReleaseVersion)
378            self.EdkReleaseVersion.Comments = Comments
379            return True
380        else:
381            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
382                       %(EdkReleaseVersion),
383                       LineInfo=self.CurrentLine)
384            return False
385
386    ## GetEdkReleaseVersion
387    #
388    def GetEdkReleaseVersion(self):
389        return self.EdkReleaseVersion
390
391    ## SetUefiSpecificationVersion
392    #
393    # @param UefiSpecificationVersion: UefiSpecificationVersion
394    #
395    def SetUefiSpecificationVersion(self, UefiSpecificationVersion, Comments):
396        #
397        # Value has been set before.
398        #
399        if self.UefiSpecificationVersion != None:
400            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
401                       %(DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION),
402                       LineInfo=self.CurrentLine)
403            return False
404        #
405        # The EdkReleaseVersion should be 4 bytes hex string.
406        #
407        if IsValidHexVersion(UefiSpecificationVersion) or \
408           IsValidDecVersionVal(UefiSpecificationVersion):
409            self.UefiSpecificationVersion = InfDefMember()
410            self.UefiSpecificationVersion.SetValue(UefiSpecificationVersion)
411            self.UefiSpecificationVersion.Comments = Comments
412            return True
413        else:
414            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
415                       %(UefiSpecificationVersion),
416                       LineInfo=self.CurrentLine)
417            return False
418
419    ## GetUefiSpecificationVersion
420    #
421    def GetUefiSpecificationVersion(self):
422        return self.UefiSpecificationVersion
423
424    ## SetPiSpecificationVersion
425    #
426    # @param PiSpecificationVersion: PiSpecificationVersion
427    #
428    def SetPiSpecificationVersion(self, PiSpecificationVersion, Comments):
429        #
430        # Value has been set before.
431        #
432        if self.PiSpecificationVersion != None:
433            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
434                       %(DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION),
435                       LineInfo=self.CurrentLine)
436            return False
437        #
438        # The EdkReleaseVersion should be 4 bytes hex string.
439        #
440        if IsValidHexVersion(PiSpecificationVersion) or \
441           IsValidDecVersionVal(PiSpecificationVersion):
442            self.PiSpecificationVersion = InfDefMember()
443            self.PiSpecificationVersion.SetValue(PiSpecificationVersion)
444            self.PiSpecificationVersion.Comments = Comments
445            return True
446        else:
447            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
448                       %(PiSpecificationVersion),
449                       LineInfo=self.CurrentLine)
450            return False
451
452    ## GetPiSpecificationVersion
453    #
454    def GetPiSpecificationVersion(self):
455        return self.PiSpecificationVersion
456
457    ## SetLibraryClass
458    #
459    # @param LibraryClass: LibraryClass
460    #
461    def SetLibraryClass(self, LibraryClass, Comments):
462        ValueList = GetSplitValueList(LibraryClass)
463        Name = ValueList[0]
464        if IsValidWord(Name):
465            InfDefineLibraryItemObj = InfDefineLibraryItem()
466            InfDefineLibraryItemObj.SetLibraryName(Name)
467            InfDefineLibraryItemObj.Comments = Comments
468            if len(ValueList) == 2:
469                Type = ValueList[1]
470                TypeList = GetSplitValueList(Type, ' ')
471                TypeList = [Type for Type in TypeList if Type != '']
472                for Item in TypeList:
473                    if Item not in DT.MODULE_LIST:
474                        ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Item),
475                                   LineInfo=self.CurrentLine)
476                        return False
477                InfDefineLibraryItemObj.SetTypes(TypeList)
478            self.LibraryClass.append(InfDefineLibraryItemObj)
479        else:
480            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Name),
481                       LineInfo=self.CurrentLine)
482            return False
483
484        return True
485
486    def GetLibraryClass(self):
487        return self.LibraryClass
488
489    def SetVersionString(self, VersionString, Comments):
490        #
491        # Value has been set before.
492        #
493        if self.VersionString != None:
494            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
495                       %(DT.TAB_INF_DEFINES_VERSION_STRING),
496                       LineInfo=self.CurrentLine)
497            return False
498        if not IsValidDecVersion(VersionString):
499            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
500                       %(VersionString),
501                       LineInfo=self.CurrentLine)
502        self.VersionString = InfDefMember()
503        self.VersionString.SetValue(VersionString)
504        self.VersionString.Comments = Comments
505        return True
506
507
508    def GetVersionString(self):
509        return self.VersionString
510
511    def SetPcdIsDriver(self, PcdIsDriver, Comments):
512        #
513        # Value has been set before.
514        #
515        if self.PcdIsDriver != None:
516            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
517                       %(DT.TAB_INF_DEFINES_PCD_IS_DRIVER),
518                       LineInfo=self.CurrentLine)
519            return False
520        if PcdIsDriver == 'PEI_PCD_DRIVER' or PcdIsDriver == 'DXE_PCD_DRIVER':
521            self.PcdIsDriver = InfDefMember()
522            self.PcdIsDriver.SetValue(PcdIsDriver)
523            self.PcdIsDriver.Comments = Comments
524            return True
525        else:
526            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PcdIsDriver),
527                       LineInfo=self.CurrentLine)
528            return False
529
530    def GetPcdIsDriver(self):
531        return self.PcdIsDriver
532
533    #
534    # SetEntryPoint
535    #
536    def SetEntryPoint(self, EntryPoint, Comments):
537        #
538        # It can be a list
539        #
540        ValueList = []
541        TokenList = GetSplitValueList(EntryPoint, DT.TAB_VALUE_SPLIT)
542        ValueList[0:len(TokenList)] = TokenList
543        InfDefineEntryPointItemObj = InfDefineEntryPointItem()
544        if not IsValidCVariableName(ValueList[0]):
545            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\
546                       (ValueList[0]),
547                       LineInfo=self.CurrentLine)
548        InfDefineEntryPointItemObj.SetCName(ValueList[0])
549        if len(ValueList) == 2:
550            if ValueList[1].strip() == '':
551                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\
552                           (ValueList[1]),
553                           LineInfo=self.CurrentLine)
554            #
555            # Validate FFE
556            #
557            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[1].strip())
558            if not FeatureFlagRtv[0]:
559                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%\
560                           (FeatureFlagRtv[1]),
561                           LineInfo=self.CurrentLine)
562            InfDefineEntryPointItemObj.SetFeatureFlagExp(ValueList[1])
563        if len(ValueList) > 2:
564            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(EntryPoint),
565                       LineInfo=self.CurrentLine)
566        InfDefineEntryPointItemObj.Comments = Comments
567        self.EntryPoint.append(InfDefineEntryPointItemObj)
568
569    def GetEntryPoint(self):
570        return self.EntryPoint
571
572    #
573    # SetUnloadImages
574    #
575    def SetUnloadImages(self, UnloadImages, Comments):
576        #
577        # It can be a list
578        #
579        ValueList = []
580        TokenList = GetSplitValueList(UnloadImages, DT.TAB_VALUE_SPLIT)
581        ValueList[0:len(TokenList)] = TokenList
582        InfDefineUnloadImageItemObj = InfDefineUnloadImageItem()
583        if not IsValidCVariableName(ValueList[0]):
584            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]),
585                       LineInfo=self.CurrentLine)
586        InfDefineUnloadImageItemObj.SetCName(ValueList[0])
587        if len(ValueList) == 2:
588            if ValueList[1].strip() == '':
589                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]),
590                           LineInfo=self.CurrentLine)
591            #
592            # Validate FFE
593            #
594            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[1].strip())
595            if not FeatureFlagRtv[0]:
596                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]),
597                           LineInfo=self.CurrentLine)
598            InfDefineUnloadImageItemObj.SetFeatureFlagExp(ValueList[1])
599
600        if len(ValueList) > 2:
601            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(UnloadImages),
602                       LineInfo=self.CurrentLine)
603        InfDefineUnloadImageItemObj.Comments = Comments
604        self.UnloadImages.append(InfDefineUnloadImageItemObj)
605
606    def GetUnloadImages(self):
607        return self.UnloadImages
608
609    #
610    # SetConstructor
611    #
612    def SetConstructor(self, Constructor, Comments):
613        #
614        # It can be a list
615        #
616        ValueList = []
617        TokenList = GetSplitValueList(Constructor, DT.TAB_VALUE_SPLIT)
618        ValueList[0:len(TokenList)] = TokenList
619        InfDefineConstructorItemObj = InfDefineConstructorItem()
620        if not IsValidCVariableName(ValueList[0]):
621            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]),
622                       LineInfo=self.CurrentLine)
623        InfDefineConstructorItemObj.SetCName(ValueList[0])
624        if len(ValueList) >= 2:
625            ModList = GetSplitValueList(ValueList[1], ' ')
626            if ValueList[1].strip() == '':
627                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]),
628                           LineInfo=self.CurrentLine)
629            for ModItem in ModList:
630                if ModItem not in DT.MODULE_LIST:
631                    ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%(ModItem),
632                               LineInfo=self.CurrentLine)
633            InfDefineConstructorItemObj.SetSupModList(ModList)
634        if len(ValueList) == 3:
635            if ValueList[2].strip() == '':
636                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[2]),
637                           LineInfo=self.CurrentLine)
638            #
639            # Validate FFE
640            #
641            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[2].strip())
642            if not FeatureFlagRtv[0]:
643                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[2]),
644                           LineInfo=self.CurrentLine)
645            InfDefineConstructorItemObj.SetFeatureFlagExp(ValueList[2])
646
647        if len(ValueList) > 3:
648            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Constructor),
649                       LineInfo=self.CurrentLine)
650        InfDefineConstructorItemObj.Comments = Comments
651        self.Constructor.append(InfDefineConstructorItemObj)
652
653    def GetConstructor(self):
654        return self.Constructor
655
656    #
657    # SetDestructor
658    #
659    def SetDestructor(self, Destructor, Comments):
660        #
661        # It can be a list and only 1 set to TRUE
662        #
663        ValueList = []
664        TokenList = GetSplitValueList(Destructor, DT.TAB_VALUE_SPLIT)
665        ValueList[0:len(TokenList)] = TokenList
666        InfDefineDestructorItemObj = InfDefineDestructorItem()
667        if not IsValidCVariableName(ValueList[0]):
668            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]),
669                       LineInfo=self.CurrentLine)
670        InfDefineDestructorItemObj.SetCName(ValueList[0])
671        if len(ValueList) >= 2:
672            ModList = GetSplitValueList(ValueList[1].strip(), ' ')
673            if ValueList[1].strip() == '':
674                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]),
675                           LineInfo=self.CurrentLine)
676            for ModItem in ModList:
677                if ModItem not in DT.MODULE_LIST:
678                    ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%(ModItem),
679                               LineInfo=self.CurrentLine)
680            InfDefineDestructorItemObj.SetSupModList(ModList)
681        if len(ValueList) == 3:
682            if ValueList[2].strip() == '':
683                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[2]),
684                           LineInfo=self.CurrentLine)
685            #
686            # Validate FFE
687            #
688            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[2].strip())
689            if not FeatureFlagRtv[0]:
690                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]),
691                           LineInfo=self.CurrentLine)
692            InfDefineDestructorItemObj.SetFeatureFlagExp(ValueList[2])
693
694        if len(ValueList) > 3:
695            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Destructor),
696                       LineInfo=self.CurrentLine)
697
698        InfDefineDestructorItemObj.Comments = Comments
699        self.Destructor.append(InfDefineDestructorItemObj)
700
701    def GetDestructor(self):
702        return self.Destructor
703
704    def SetShadow(self, Shadow, Comments):
705        #
706        # Value has been set before.
707        #
708        if self.Shadow != None:
709            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_SHADOW),
710                       LineInfo=self.CurrentLine)
711            return False
712        if (IsValidBoolType(Shadow)):
713            self.Shadow = InfDefMember()
714            self.Shadow.SetValue(Shadow)
715            self.Shadow.Comments = Comments
716            return True
717        else:
718            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Shadow),
719                       LineInfo=self.CurrentLine)
720            return False
721    def GetShadow(self):
722        return self.Shadow
723
724    #
725    # <Family>               ::=  {"MSFT"} {"GCC"}
726    # <CustomMake>           ::=  [<Family> "|"] <Filename>
727    #
728    def SetCustomMakefile(self, CustomMakefile, Comments):
729        if not (CustomMakefile == '' or CustomMakefile == None):
730            ValueList = GetSplitValueList(CustomMakefile)
731            if len(ValueList) == 1:
732                FileName = ValueList[0]
733                Family = ''
734            else:
735                Family = ValueList[0]
736                FileName = ValueList[1]
737            Family = Family.strip()
738            if Family != '':
739                if not IsValidFamily(Family):
740                    ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Family),
741                               LineInfo=self.CurrentLine)
742                    return False
743            #
744            # The MakefileName specified file should exist
745            #
746            IsValidFileFlag = False
747            ModulePath = os.path.split(self.CurrentLine[0])[0]
748            if IsValidPath(FileName, ModulePath):
749                IsValidFileFlag = True
750            else:
751                ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(FileName),
752                           LineInfo=self.CurrentLine)
753                return False
754            if IsValidFileFlag:
755                FileName = ConvPathFromAbsToRel(FileName, GlobalData.gINF_MODULE_DIR)
756                self.CustomMakefile.append((Family, FileName, Comments))
757                IsValidFileFlag = False
758            return True
759        else:
760            return False
761
762    def GetCustomMakefile(self):
763        return self.CustomMakefile
764
765    #
766    # ["SPEC" <Spec> <EOL>]*{0,}
767    # <Spec>                 ::=  <Word> "=" <VersionVal>
768    # <VersionVal>           ::=  {<HexVersion>] {<DecVersion>}
769    # <HexNumber>            ::=  "0x" [<HexDigit>]{1,}
770    # <DecVersion>           ::=  (0-9){1,} ["." (0-9){1,2}]
771    #
772    def SetSpecification(self, Specification, Comments):
773        #
774        # Valid the value of Specification
775        #
776        __ValueList = []
777        TokenList = GetSplitValueList(Specification, DT.TAB_EQUAL_SPLIT, 1)
778        __ValueList[0:len(TokenList)] = TokenList
779        if len(__ValueList) != 2:
780            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME + ' Or ' + ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
781                       LineInfo=self.CurrentLine)
782        Name = __ValueList[0].strip()
783        Version = __ValueList[1].strip()
784        if IsValidIdentifier(Name):
785            if IsValidDecVersion(Version):
786                self.Specification.append((Name, Version, Comments))
787                return True
788            else:
789                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Version),
790                           LineInfo=self.CurrentLine)
791                return False
792        else:
793            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Name),
794                       LineInfo=self.CurrentLine)
795            return False
796        return True
797
798    def GetSpecification(self):
799        return self.Specification
800
801    #
802    # [<UefiHiiResource> <EOL>]{0,1}
803    # <UefiHiiResource>      ::=  "UEFI_HII_RESOURCE_SECTION" "=" <BoolType>
804    #
805    def SetUefiHiiResourceSection(self, UefiHiiResourceSection, Comments):
806        #
807        # Value has been set before.
808        #
809        if self.UefiHiiResourceSection != None:
810            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND
811                       %(DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION),
812                       LineInfo=self.CurrentLine)
813            return False
814        if not (UefiHiiResourceSection == '' or UefiHiiResourceSection == None):
815            if (IsValidBoolType(UefiHiiResourceSection)):
816                self.UefiHiiResourceSection = InfDefMember()
817                self.UefiHiiResourceSection.SetValue(UefiHiiResourceSection)
818                self.UefiHiiResourceSection.Comments = Comments
819                return True
820            else:
821                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(UefiHiiResourceSection),
822                           LineInfo=self.CurrentLine)
823                return False
824        else:
825            return False
826
827    def GetUefiHiiResourceSection(self):
828        return self.UefiHiiResourceSection
829
830    def SetDpxSource(self, DpxSource, Comments):
831        #
832        # The MakefileName specified file should exist
833        #
834        IsValidFileFlag = False
835        ModulePath = os.path.split(self.CurrentLine[0])[0]
836        if IsValidPath(DpxSource, ModulePath):
837            IsValidFileFlag = True
838        else:
839            ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(DpxSource),
840                       LineInfo=self.CurrentLine)
841            return False
842        if IsValidFileFlag:
843            DpxSource = ConvPathFromAbsToRel(DpxSource,
844                            GlobalData.gINF_MODULE_DIR)
845            self.DpxSource.append((DpxSource, Comments))
846            IsValidFileFlag = False
847        return True
848
849    def GetDpxSource(self):
850        return self.DpxSource
851
852gFUNCTION_MAPPING_FOR_DEFINE_SECTION = {
853    #
854    # Required Fields
855    #
856    DT.TAB_INF_DEFINES_BASE_NAME                   : InfDefSection.SetBaseName,
857    DT.TAB_INF_DEFINES_FILE_GUID                   : InfDefSection.SetFileGuid,
858    DT.TAB_INF_DEFINES_MODULE_TYPE                 : InfDefSection.SetModuleType,
859    #
860    # Required by EDKII style INF file
861    #
862    DT.TAB_INF_DEFINES_INF_VERSION                 : InfDefSection.SetInfVersion,
863    #
864    # Optional Fields
865    #
866    DT.TAB_INF_DEFINES_MODULE_UNI_FILE             : InfDefSection.SetModuleUniFileName,
867    DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION         : InfDefSection.SetEdkReleaseVersion,
868    DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION  : InfDefSection.SetUefiSpecificationVersion,
869    DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION    : InfDefSection.SetPiSpecificationVersion,
870    DT.TAB_INF_DEFINES_LIBRARY_CLASS               : InfDefSection.SetLibraryClass,
871    DT.TAB_INF_DEFINES_VERSION_STRING              : InfDefSection.SetVersionString,
872    DT.TAB_INF_DEFINES_PCD_IS_DRIVER               : InfDefSection.SetPcdIsDriver,
873    DT.TAB_INF_DEFINES_ENTRY_POINT                 : InfDefSection.SetEntryPoint,
874    DT.TAB_INF_DEFINES_UNLOAD_IMAGE                : InfDefSection.SetUnloadImages,
875    DT.TAB_INF_DEFINES_CONSTRUCTOR                 : InfDefSection.SetConstructor,
876    DT.TAB_INF_DEFINES_DESTRUCTOR                  : InfDefSection.SetDestructor,
877    DT.TAB_INF_DEFINES_SHADOW                      : InfDefSection.SetShadow,
878    DT.TAB_INF_DEFINES_PCI_VENDOR_ID               : InfDefSection.SetPciVendorId,
879    DT.TAB_INF_DEFINES_PCI_DEVICE_ID               : InfDefSection.SetPciDeviceId,
880    DT.TAB_INF_DEFINES_PCI_CLASS_CODE              : InfDefSection.SetPciClassCode,
881    DT.TAB_INF_DEFINES_PCI_REVISION                : InfDefSection.SetPciRevision,
882    DT.TAB_INF_DEFINES_PCI_COMPRESS                : InfDefSection.SetPciCompress,
883    DT.TAB_INF_DEFINES_CUSTOM_MAKEFILE             : InfDefSection.SetCustomMakefile,
884    DT.TAB_INF_DEFINES_SPEC                        : InfDefSection.SetSpecification,
885    DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION   : InfDefSection.SetUefiHiiResourceSection,
886    DT.TAB_INF_DEFINES_DPX_SOURCE                  : InfDefSection.SetDpxSource
887}
888
889## InfDefMember
890#
891#
892class InfDefMember():
893    def __init__(self, Name='', Value=''):
894        self.Comments = InfLineCommentObject()
895        self.Name  = Name
896        self.Value = Value
897        self.CurrentLine = CurrentLine()
898    def GetName(self):
899        return self.Name
900    def SetName(self, Name):
901        self.Name = Name
902    def GetValue(self):
903        return self.Value
904    def SetValue(self, Value):
905        self.Value = Value
906
907## InfDefObject
908#
909#
910class InfDefObject(InfSectionCommonDef):
911    def __init__(self):
912        self.Defines = Sdict()
913        InfSectionCommonDef.__init__(self)
914    def SetDefines(self, DefineContent, Arch = None):
915        #
916        # Validate Arch
917        #
918        HasFoundInfVersionFalg = False
919        LineInfo = ['', -1, '']
920        ArchListString = ' '.join(Arch)
921        #
922        # Parse Define items.
923        #
924        for InfDefMemberObj in DefineContent:
925            ProcessFunc = None
926            Name = InfDefMemberObj.GetName()
927            Value = InfDefMemberObj.GetValue()
928            if Name == DT.TAB_INF_DEFINES_MODULE_UNI_FILE:
929                ValidateUNIFilePath(Value)
930                Value = os.path.join(os.path.dirname(InfDefMemberObj.CurrentLine.FileName), Value)
931                if not os.path.isfile(Value) or not os.path.exists(Value):
932                    LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName()
933                    LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo()
934                    LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString()
935                    ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Name),
936                                   LineInfo=LineInfo)
937            InfLineCommentObj = InfLineCommentObject()
938            InfLineCommentObj.SetHeaderComments(InfDefMemberObj.Comments.GetHeaderComments())
939            InfLineCommentObj.SetTailComments(InfDefMemberObj.Comments.GetTailComments())
940            if Name == 'COMPONENT_TYPE':
941                ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF,
942                           ErrorCode=ToolError.EDK1_INF_ERROR,
943                           RaiseError=True)
944            if Name == DT.TAB_INF_DEFINES_INF_VERSION:
945                HasFoundInfVersionFalg = True
946            if not (Name == '' or Name == None):
947                #
948                # Process "SPEC" Keyword definition.
949                #
950                ReName = re.compile(r"SPEC ", re.DOTALL)
951                if ReName.match(Name):
952                    SpecValue = Name[Name.find("SPEC") + len("SPEC"):].strip()
953                    Name = "SPEC"
954                    Value = SpecValue + " = " + Value
955                if self.Defines.has_key(ArchListString):
956                    DefineList = self.Defines[ArchListString]
957                    LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName()
958                    LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo()
959                    LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString()
960                    DefineList.CurrentLine = LineInfo
961                    #
962                    # Found the process function from mapping table.
963                    #
964                    if Name not in gFUNCTION_MAPPING_FOR_DEFINE_SECTION.keys():
965                        ErrorInInf(ST.ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID%(Name),
966                                   LineInfo=LineInfo)
967                    else:
968                        ProcessFunc = gFUNCTION_MAPPING_FOR_DEFINE_SECTION[Name]
969                    if (ProcessFunc != None):
970                        ProcessFunc(DefineList, Value, InfLineCommentObj)
971                    self.Defines[ArchListString] = DefineList
972                else:
973                    DefineList = InfDefSection()
974                    LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName()
975                    LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo()
976                    LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString()
977                    DefineList.CurrentLine = LineInfo
978                    #
979                    # Found the process function from mapping table.
980                    #
981                    if Name not in gFUNCTION_MAPPING_FOR_DEFINE_SECTION.keys():
982                        ErrorInInf(ST.ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID%(Name),
983                                   LineInfo=LineInfo)
984                    #
985                    # Found the process function from mapping table.
986                    #
987                    else:
988                        ProcessFunc = gFUNCTION_MAPPING_FOR_DEFINE_SECTION[Name]
989                    if (ProcessFunc != None):
990                        ProcessFunc(DefineList, Value, InfLineCommentObj)
991                    self.Defines[ArchListString] = DefineList
992        #
993        # After set, check whether INF_VERSION defined.
994        #
995        if not HasFoundInfVersionFalg:
996            ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF,
997                       ErrorCode=ToolError.EDK1_INF_ERROR,
998                       RaiseError=True)
999        return True
1000
1001    def GetDefines(self):
1002        return self.Defines
1003