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