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        elif IsValidDecVersionVal(InfVersion):
344            if (InfVersion < 65541):
345                ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF,
346                           ErrorCode=ToolError.EDK1_INF_ERROR,
347                           LineInfo=self.CurrentLine)
348        else:
349            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(InfVersion),
350                       LineInfo=self.CurrentLine)
351            return False
352
353        self.InfVersion = InfDefMember()
354        self.InfVersion.SetValue(InfVersion)
355        self.InfVersion.Comments = Comments
356        return True
357
358    ## GetInfVersion
359    #
360    def GetInfVersion(self):
361        return self.InfVersion
362
363    ## SetEdkReleaseVersion
364    #
365    # @param EdkReleaseVersion: EdkReleaseVersion
366    #
367    def SetEdkReleaseVersion(self, EdkReleaseVersion, Comments):
368        #
369        # Value has been set before.
370        #
371        if self.EdkReleaseVersion != None:
372            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
373                       %(DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION),
374                       LineInfo=self.CurrentLine)
375            return False
376        #
377        # The EdkReleaseVersion should be 4 bytes hex string.
378        #
379        if IsValidHexVersion(EdkReleaseVersion) or \
380           IsValidDecVersionVal(EdkReleaseVersion):
381            self.EdkReleaseVersion = InfDefMember()
382            self.EdkReleaseVersion.SetValue(EdkReleaseVersion)
383            self.EdkReleaseVersion.Comments = Comments
384            return True
385        else:
386            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
387                       %(EdkReleaseVersion),
388                       LineInfo=self.CurrentLine)
389            return False
390
391    ## GetEdkReleaseVersion
392    #
393    def GetEdkReleaseVersion(self):
394        return self.EdkReleaseVersion
395
396    ## SetUefiSpecificationVersion
397    #
398    # @param UefiSpecificationVersion: UefiSpecificationVersion
399    #
400    def SetUefiSpecificationVersion(self, UefiSpecificationVersion, Comments):
401        #
402        # Value has been set before.
403        #
404        if self.UefiSpecificationVersion != None:
405            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
406                       %(DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION),
407                       LineInfo=self.CurrentLine)
408            return False
409        #
410        # The EdkReleaseVersion should be 4 bytes hex string.
411        #
412        if IsValidHexVersion(UefiSpecificationVersion) or \
413           IsValidDecVersionVal(UefiSpecificationVersion):
414            self.UefiSpecificationVersion = InfDefMember()
415            self.UefiSpecificationVersion.SetValue(UefiSpecificationVersion)
416            self.UefiSpecificationVersion.Comments = Comments
417            return True
418        else:
419            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
420                       %(UefiSpecificationVersion),
421                       LineInfo=self.CurrentLine)
422            return False
423
424    ## GetUefiSpecificationVersion
425    #
426    def GetUefiSpecificationVersion(self):
427        return self.UefiSpecificationVersion
428
429    ## SetPiSpecificationVersion
430    #
431    # @param PiSpecificationVersion: PiSpecificationVersion
432    #
433    def SetPiSpecificationVersion(self, PiSpecificationVersion, Comments):
434        #
435        # Value has been set before.
436        #
437        if self.PiSpecificationVersion != None:
438            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
439                       %(DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION),
440                       LineInfo=self.CurrentLine)
441            return False
442        #
443        # The EdkReleaseVersion should be 4 bytes hex string.
444        #
445        if IsValidHexVersion(PiSpecificationVersion) or \
446           IsValidDecVersionVal(PiSpecificationVersion):
447            self.PiSpecificationVersion = InfDefMember()
448            self.PiSpecificationVersion.SetValue(PiSpecificationVersion)
449            self.PiSpecificationVersion.Comments = Comments
450            return True
451        else:
452            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
453                       %(PiSpecificationVersion),
454                       LineInfo=self.CurrentLine)
455            return False
456
457    ## GetPiSpecificationVersion
458    #
459    def GetPiSpecificationVersion(self):
460        return self.PiSpecificationVersion
461
462    ## SetLibraryClass
463    #
464    # @param LibraryClass: LibraryClass
465    #
466    def SetLibraryClass(self, LibraryClass, Comments):
467        ValueList = GetSplitValueList(LibraryClass)
468        Name = ValueList[0]
469        if IsValidWord(Name):
470            InfDefineLibraryItemObj = InfDefineLibraryItem()
471            InfDefineLibraryItemObj.SetLibraryName(Name)
472            InfDefineLibraryItemObj.Comments = Comments
473            if len(ValueList) == 2:
474                Type = ValueList[1]
475                TypeList = GetSplitValueList(Type, ' ')
476                TypeList = [Type for Type in TypeList if Type != '']
477                for Item in TypeList:
478                    if Item not in DT.MODULE_LIST:
479                        ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Item),
480                                   LineInfo=self.CurrentLine)
481                        return False
482                InfDefineLibraryItemObj.SetTypes(TypeList)
483            self.LibraryClass.append(InfDefineLibraryItemObj)
484        else:
485            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Name),
486                       LineInfo=self.CurrentLine)
487            return False
488
489        return True
490
491    def GetLibraryClass(self):
492        return self.LibraryClass
493
494    def SetVersionString(self, VersionString, Comments):
495        #
496        # Value has been set before.
497        #
498        if self.VersionString != None:
499            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
500                       %(DT.TAB_INF_DEFINES_VERSION_STRING),
501                       LineInfo=self.CurrentLine)
502            return False
503        if not IsValidDecVersion(VersionString):
504            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID\
505                       %(VersionString),
506                       LineInfo=self.CurrentLine)
507        self.VersionString = InfDefMember()
508        self.VersionString.SetValue(VersionString)
509        self.VersionString.Comments = Comments
510        return True
511
512
513    def GetVersionString(self):
514        return self.VersionString
515
516    def SetPcdIsDriver(self, PcdIsDriver, Comments):
517        #
518        # Value has been set before.
519        #
520        if self.PcdIsDriver != None:
521            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND\
522                       %(DT.TAB_INF_DEFINES_PCD_IS_DRIVER),
523                       LineInfo=self.CurrentLine)
524            return False
525        if PcdIsDriver == 'PEI_PCD_DRIVER' or PcdIsDriver == 'DXE_PCD_DRIVER':
526            self.PcdIsDriver = InfDefMember()
527            self.PcdIsDriver.SetValue(PcdIsDriver)
528            self.PcdIsDriver.Comments = Comments
529            return True
530        else:
531            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(PcdIsDriver),
532                       LineInfo=self.CurrentLine)
533            return False
534
535    def GetPcdIsDriver(self):
536        return self.PcdIsDriver
537
538    #
539    # SetEntryPoint
540    #
541    def SetEntryPoint(self, EntryPoint, Comments):
542        #
543        # It can be a list
544        #
545        ValueList = []
546        TokenList = GetSplitValueList(EntryPoint, DT.TAB_VALUE_SPLIT)
547        ValueList[0:len(TokenList)] = TokenList
548        InfDefineEntryPointItemObj = InfDefineEntryPointItem()
549        if not IsValidCVariableName(ValueList[0]):
550            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\
551                       (ValueList[0]),
552                       LineInfo=self.CurrentLine)
553        InfDefineEntryPointItemObj.SetCName(ValueList[0])
554        if len(ValueList) == 2:
555            if ValueList[1].strip() == '':
556                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%\
557                           (ValueList[1]),
558                           LineInfo=self.CurrentLine)
559            #
560            # Validate FFE
561            #
562            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[1].strip())
563            if not FeatureFlagRtv[0]:
564                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%\
565                           (FeatureFlagRtv[1]),
566                           LineInfo=self.CurrentLine)
567            InfDefineEntryPointItemObj.SetFeatureFlagExp(ValueList[1])
568        if len(ValueList) > 2:
569            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(EntryPoint),
570                       LineInfo=self.CurrentLine)
571        InfDefineEntryPointItemObj.Comments = Comments
572        self.EntryPoint.append(InfDefineEntryPointItemObj)
573
574    def GetEntryPoint(self):
575        return self.EntryPoint
576
577    #
578    # SetUnloadImages
579    #
580    def SetUnloadImages(self, UnloadImages, Comments):
581        #
582        # It can be a list
583        #
584        ValueList = []
585        TokenList = GetSplitValueList(UnloadImages, DT.TAB_VALUE_SPLIT)
586        ValueList[0:len(TokenList)] = TokenList
587        InfDefineUnloadImageItemObj = InfDefineUnloadImageItem()
588        if not IsValidCVariableName(ValueList[0]):
589            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]),
590                       LineInfo=self.CurrentLine)
591        InfDefineUnloadImageItemObj.SetCName(ValueList[0])
592        if len(ValueList) == 2:
593            if ValueList[1].strip() == '':
594                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]),
595                           LineInfo=self.CurrentLine)
596            #
597            # Validate FFE
598            #
599            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[1].strip())
600            if not FeatureFlagRtv[0]:
601                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]),
602                           LineInfo=self.CurrentLine)
603            InfDefineUnloadImageItemObj.SetFeatureFlagExp(ValueList[1])
604
605        if len(ValueList) > 2:
606            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(UnloadImages),
607                       LineInfo=self.CurrentLine)
608        InfDefineUnloadImageItemObj.Comments = Comments
609        self.UnloadImages.append(InfDefineUnloadImageItemObj)
610
611    def GetUnloadImages(self):
612        return self.UnloadImages
613
614    #
615    # SetConstructor
616    #
617    def SetConstructor(self, Constructor, Comments):
618        #
619        # It can be a list
620        #
621        ValueList = []
622        TokenList = GetSplitValueList(Constructor, DT.TAB_VALUE_SPLIT)
623        ValueList[0:len(TokenList)] = TokenList
624        InfDefineConstructorItemObj = InfDefineConstructorItem()
625        if not IsValidCVariableName(ValueList[0]):
626            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]),
627                       LineInfo=self.CurrentLine)
628        InfDefineConstructorItemObj.SetCName(ValueList[0])
629        if len(ValueList) >= 2:
630            ModList = GetSplitValueList(ValueList[1], ' ')
631            if ValueList[1].strip() == '':
632                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]),
633                           LineInfo=self.CurrentLine)
634            for ModItem in ModList:
635                if ModItem not in DT.MODULE_LIST:
636                    ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%(ModItem),
637                               LineInfo=self.CurrentLine)
638            InfDefineConstructorItemObj.SetSupModList(ModList)
639        if len(ValueList) == 3:
640            if ValueList[2].strip() == '':
641                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[2]),
642                           LineInfo=self.CurrentLine)
643            #
644            # Validate FFE
645            #
646            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[2].strip())
647            if not FeatureFlagRtv[0]:
648                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[2]),
649                           LineInfo=self.CurrentLine)
650            InfDefineConstructorItemObj.SetFeatureFlagExp(ValueList[2])
651
652        if len(ValueList) > 3:
653            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Constructor),
654                       LineInfo=self.CurrentLine)
655        InfDefineConstructorItemObj.Comments = Comments
656        self.Constructor.append(InfDefineConstructorItemObj)
657
658    def GetConstructor(self):
659        return self.Constructor
660
661    #
662    # SetDestructor
663    #
664    def SetDestructor(self, Destructor, Comments):
665        #
666        # It can be a list and only 1 set to TRUE
667        #
668        ValueList = []
669        TokenList = GetSplitValueList(Destructor, DT.TAB_VALUE_SPLIT)
670        ValueList[0:len(TokenList)] = TokenList
671        InfDefineDestructorItemObj = InfDefineDestructorItem()
672        if not IsValidCVariableName(ValueList[0]):
673            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[0]),
674                       LineInfo=self.CurrentLine)
675        InfDefineDestructorItemObj.SetCName(ValueList[0])
676        if len(ValueList) >= 2:
677            ModList = GetSplitValueList(ValueList[1].strip(), ' ')
678            if ValueList[1].strip() == '':
679                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[1]),
680                           LineInfo=self.CurrentLine)
681            for ModItem in ModList:
682                if ModItem not in DT.MODULE_LIST:
683                    ErrorInInf(ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID%(ModItem),
684                               LineInfo=self.CurrentLine)
685            InfDefineDestructorItemObj.SetSupModList(ModList)
686        if len(ValueList) == 3:
687            if ValueList[2].strip() == '':
688                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(ValueList[2]),
689                           LineInfo=self.CurrentLine)
690            #
691            # Validate FFE
692            #
693            FeatureFlagRtv = IsValidFeatureFlagExp(ValueList[2].strip())
694            if not FeatureFlagRtv[0]:
695                ErrorInInf(ST.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID%(FeatureFlagRtv[1]),
696                           LineInfo=self.CurrentLine)
697            InfDefineDestructorItemObj.SetFeatureFlagExp(ValueList[2])
698
699        if len(ValueList) > 3:
700            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Destructor),
701                       LineInfo=self.CurrentLine)
702
703        InfDefineDestructorItemObj.Comments = Comments
704        self.Destructor.append(InfDefineDestructorItemObj)
705
706    def GetDestructor(self):
707        return self.Destructor
708
709    def SetShadow(self, Shadow, Comments):
710        #
711        # Value has been set before.
712        #
713        if self.Shadow != None:
714            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND%(DT.TAB_INF_DEFINES_SHADOW),
715                       LineInfo=self.CurrentLine)
716            return False
717        if (IsValidBoolType(Shadow)):
718            self.Shadow = InfDefMember()
719            self.Shadow.SetValue(Shadow)
720            self.Shadow.Comments = Comments
721            return True
722        else:
723            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Shadow),
724                       LineInfo=self.CurrentLine)
725            return False
726    def GetShadow(self):
727        return self.Shadow
728
729    #
730    # <Family>               ::=  {"MSFT"} {"GCC"}
731    # <CustomMake>           ::=  [<Family> "|"] <Filename>
732    #
733    def SetCustomMakefile(self, CustomMakefile, Comments):
734        if not (CustomMakefile == '' or CustomMakefile == None):
735            ValueList = GetSplitValueList(CustomMakefile)
736            if len(ValueList) == 1:
737                FileName = ValueList[0]
738                Family = ''
739            else:
740                Family = ValueList[0]
741                FileName = ValueList[1]
742            Family = Family.strip()
743            if Family != '':
744                if not IsValidFamily(Family):
745                    ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Family),
746                               LineInfo=self.CurrentLine)
747                    return False
748            #
749            # The MakefileName specified file should exist
750            #
751            IsValidFileFlag = False
752            ModulePath = os.path.split(self.CurrentLine[0])[0]
753            if IsValidPath(FileName, ModulePath):
754                IsValidFileFlag = True
755            else:
756                ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(FileName),
757                           LineInfo=self.CurrentLine)
758                return False
759            if IsValidFileFlag:
760                FileName = ConvPathFromAbsToRel(FileName, GlobalData.gINF_MODULE_DIR)
761                self.CustomMakefile.append((Family, FileName, Comments))
762                IsValidFileFlag = False
763            return True
764        else:
765            return False
766
767    def GetCustomMakefile(self):
768        return self.CustomMakefile
769
770    #
771    # ["SPEC" <Spec> <EOL>]*{0,}
772    # <Spec>                 ::=  <Word> "=" <VersionVal>
773    # <VersionVal>           ::=  {<HexVersion>] {<DecVersion>}
774    # <HexNumber>            ::=  "0x" [<HexDigit>]{1,}
775    # <DecVersion>           ::=  (0-9){1,} ["." (0-9){1,2}]
776    #
777    def SetSpecification(self, Specification, Comments):
778        #
779        # Valid the value of Specification
780        #
781        __ValueList = []
782        TokenList = GetSplitValueList(Specification, DT.TAB_EQUAL_SPLIT, 1)
783        __ValueList[0:len(TokenList)] = TokenList
784        if len(__ValueList) != 2:
785            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME + ' Or ' + ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
786                       LineInfo=self.CurrentLine)
787        Name = __ValueList[0].strip()
788        Version = __ValueList[1].strip()
789        if IsValidIdentifier(Name):
790            if IsValidDecVersion(Version):
791                self.Specification.append((Name, Version, Comments))
792                return True
793            else:
794                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Version),
795                           LineInfo=self.CurrentLine)
796                return False
797        else:
798            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(Name),
799                       LineInfo=self.CurrentLine)
800            return False
801        return True
802
803    def GetSpecification(self):
804        return self.Specification
805
806    #
807    # [<UefiHiiResource> <EOL>]{0,1}
808    # <UefiHiiResource>      ::=  "UEFI_HII_RESOURCE_SECTION" "=" <BoolType>
809    #
810    def SetUefiHiiResourceSection(self, UefiHiiResourceSection, Comments):
811        #
812        # Value has been set before.
813        #
814        if self.UefiHiiResourceSection != None:
815            ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_MORE_THAN_ONE_FOUND
816                       %(DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION),
817                       LineInfo=self.CurrentLine)
818            return False
819        if not (UefiHiiResourceSection == '' or UefiHiiResourceSection == None):
820            if (IsValidBoolType(UefiHiiResourceSection)):
821                self.UefiHiiResourceSection = InfDefMember()
822                self.UefiHiiResourceSection.SetValue(UefiHiiResourceSection)
823                self.UefiHiiResourceSection.Comments = Comments
824                return True
825            else:
826                ErrorInInf(ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(UefiHiiResourceSection),
827                           LineInfo=self.CurrentLine)
828                return False
829        else:
830            return False
831
832    def GetUefiHiiResourceSection(self):
833        return self.UefiHiiResourceSection
834
835    def SetDpxSource(self, DpxSource, Comments):
836        #
837        # The MakefileName specified file should exist
838        #
839        IsValidFileFlag = False
840        ModulePath = os.path.split(self.CurrentLine[0])[0]
841        if IsValidPath(DpxSource, ModulePath):
842            IsValidFileFlag = True
843        else:
844            ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(DpxSource),
845                       LineInfo=self.CurrentLine)
846            return False
847        if IsValidFileFlag:
848            DpxSource = ConvPathFromAbsToRel(DpxSource,
849                            GlobalData.gINF_MODULE_DIR)
850            self.DpxSource.append((DpxSource, Comments))
851            IsValidFileFlag = False
852        return True
853
854    def GetDpxSource(self):
855        return self.DpxSource
856
857gFUNCTION_MAPPING_FOR_DEFINE_SECTION = {
858    #
859    # Required Fields
860    #
861    DT.TAB_INF_DEFINES_BASE_NAME                   : InfDefSection.SetBaseName,
862    DT.TAB_INF_DEFINES_FILE_GUID                   : InfDefSection.SetFileGuid,
863    DT.TAB_INF_DEFINES_MODULE_TYPE                 : InfDefSection.SetModuleType,
864    #
865    # Required by EDKII style INF file
866    #
867    DT.TAB_INF_DEFINES_INF_VERSION                 : InfDefSection.SetInfVersion,
868    #
869    # Optional Fields
870    #
871    DT.TAB_INF_DEFINES_MODULE_UNI_FILE             : InfDefSection.SetModuleUniFileName,
872    DT.TAB_INF_DEFINES_EDK_RELEASE_VERSION         : InfDefSection.SetEdkReleaseVersion,
873    DT.TAB_INF_DEFINES_UEFI_SPECIFICATION_VERSION  : InfDefSection.SetUefiSpecificationVersion,
874    DT.TAB_INF_DEFINES_PI_SPECIFICATION_VERSION    : InfDefSection.SetPiSpecificationVersion,
875    DT.TAB_INF_DEFINES_LIBRARY_CLASS               : InfDefSection.SetLibraryClass,
876    DT.TAB_INF_DEFINES_VERSION_STRING              : InfDefSection.SetVersionString,
877    DT.TAB_INF_DEFINES_PCD_IS_DRIVER               : InfDefSection.SetPcdIsDriver,
878    DT.TAB_INF_DEFINES_ENTRY_POINT                 : InfDefSection.SetEntryPoint,
879    DT.TAB_INF_DEFINES_UNLOAD_IMAGE                : InfDefSection.SetUnloadImages,
880    DT.TAB_INF_DEFINES_CONSTRUCTOR                 : InfDefSection.SetConstructor,
881    DT.TAB_INF_DEFINES_DESTRUCTOR                  : InfDefSection.SetDestructor,
882    DT.TAB_INF_DEFINES_SHADOW                      : InfDefSection.SetShadow,
883    DT.TAB_INF_DEFINES_PCI_VENDOR_ID               : InfDefSection.SetPciVendorId,
884    DT.TAB_INF_DEFINES_PCI_DEVICE_ID               : InfDefSection.SetPciDeviceId,
885    DT.TAB_INF_DEFINES_PCI_CLASS_CODE              : InfDefSection.SetPciClassCode,
886    DT.TAB_INF_DEFINES_PCI_REVISION                : InfDefSection.SetPciRevision,
887    DT.TAB_INF_DEFINES_PCI_COMPRESS                : InfDefSection.SetPciCompress,
888    DT.TAB_INF_DEFINES_CUSTOM_MAKEFILE             : InfDefSection.SetCustomMakefile,
889    DT.TAB_INF_DEFINES_SPEC                        : InfDefSection.SetSpecification,
890    DT.TAB_INF_DEFINES_UEFI_HII_RESOURCE_SECTION   : InfDefSection.SetUefiHiiResourceSection,
891    DT.TAB_INF_DEFINES_DPX_SOURCE                  : InfDefSection.SetDpxSource
892}
893
894## InfDefMember
895#
896#
897class InfDefMember():
898    def __init__(self, Name='', Value=''):
899        self.Comments = InfLineCommentObject()
900        self.Name  = Name
901        self.Value = Value
902        self.CurrentLine = CurrentLine()
903    def GetName(self):
904        return self.Name
905    def SetName(self, Name):
906        self.Name = Name
907    def GetValue(self):
908        return self.Value
909    def SetValue(self, Value):
910        self.Value = Value
911
912## InfDefObject
913#
914#
915class InfDefObject(InfSectionCommonDef):
916    def __init__(self):
917        self.Defines = Sdict()
918        InfSectionCommonDef.__init__(self)
919    def SetDefines(self, DefineContent, Arch = None):
920        #
921        # Validate Arch
922        #
923        HasFoundInfVersionFalg = False
924        LineInfo = ['', -1, '']
925        ArchListString = ' '.join(Arch)
926        #
927        # Parse Define items.
928        #
929        for InfDefMemberObj in DefineContent:
930            ProcessFunc = None
931            Name = InfDefMemberObj.GetName()
932            Value = InfDefMemberObj.GetValue()
933            if Name == DT.TAB_INF_DEFINES_MODULE_UNI_FILE:
934                ValidateUNIFilePath(Value)
935                Value = os.path.join(os.path.dirname(InfDefMemberObj.CurrentLine.FileName), Value)
936                if not os.path.isfile(Value) or not os.path.exists(Value):
937                    LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName()
938                    LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo()
939                    LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString()
940                    ErrorInInf(ST.ERR_INF_PARSER_FILE_NOT_EXIST_OR_NAME_INVALID%(Name),
941                                   LineInfo=LineInfo)
942            InfLineCommentObj = InfLineCommentObject()
943            InfLineCommentObj.SetHeaderComments(InfDefMemberObj.Comments.GetHeaderComments())
944            InfLineCommentObj.SetTailComments(InfDefMemberObj.Comments.GetTailComments())
945            if Name == 'COMPONENT_TYPE':
946                ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF,
947                           ErrorCode=ToolError.EDK1_INF_ERROR,
948                           RaiseError=True)
949            if Name == DT.TAB_INF_DEFINES_INF_VERSION:
950                HasFoundInfVersionFalg = True
951            if not (Name == '' or Name == None):
952                #
953                # Process "SPEC" Keyword definition.
954                #
955                ReName = re.compile(r"SPEC ", re.DOTALL)
956                if ReName.match(Name):
957                    SpecValue = Name[Name.find("SPEC") + len("SPEC"):].strip()
958                    Name = "SPEC"
959                    Value = SpecValue + " = " + Value
960                if self.Defines.has_key(ArchListString):
961                    DefineList = self.Defines[ArchListString]
962                    LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName()
963                    LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo()
964                    LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString()
965                    DefineList.CurrentLine = LineInfo
966                    #
967                    # Found the process function from mapping table.
968                    #
969                    if Name not in gFUNCTION_MAPPING_FOR_DEFINE_SECTION.keys():
970                        ErrorInInf(ST.ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID%(Name),
971                                   LineInfo=LineInfo)
972                    else:
973                        ProcessFunc = gFUNCTION_MAPPING_FOR_DEFINE_SECTION[Name]
974                    if (ProcessFunc != None):
975                        ProcessFunc(DefineList, Value, InfLineCommentObj)
976                    self.Defines[ArchListString] = DefineList
977                else:
978                    DefineList = InfDefSection()
979                    LineInfo[0] = InfDefMemberObj.CurrentLine.GetFileName()
980                    LineInfo[1] = InfDefMemberObj.CurrentLine.GetLineNo()
981                    LineInfo[2] = InfDefMemberObj.CurrentLine.GetLineString()
982                    DefineList.CurrentLine = LineInfo
983                    #
984                    # Found the process function from mapping table.
985                    #
986                    if Name not in gFUNCTION_MAPPING_FOR_DEFINE_SECTION.keys():
987                        ErrorInInf(ST.ERR_INF_PARSER_DEFINE_SECTION_KEYWORD_INVALID%(Name),
988                                   LineInfo=LineInfo)
989                    #
990                    # Found the process function from mapping table.
991                    #
992                    else:
993                        ProcessFunc = gFUNCTION_MAPPING_FOR_DEFINE_SECTION[Name]
994                    if (ProcessFunc != None):
995                        ProcessFunc(DefineList, Value, InfLineCommentObj)
996                    self.Defines[ArchListString] = DefineList
997        #
998        # After set, check whether INF_VERSION defined.
999        #
1000        if not HasFoundInfVersionFalg:
1001            ErrorInInf(ST.ERR_INF_PARSER_NOT_SUPPORT_EDKI_INF,
1002                       ErrorCode=ToolError.EDK1_INF_ERROR,
1003                       RaiseError=True)
1004        return True
1005
1006    def GetDefines(self):
1007        return self.Defines
1008
1009