• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1## @file
2# This file is used to define checkpoints used by ECC tool
3#
4# Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
5# This program and the accompanying materials
6# are licensed and made available under the terms and conditions of the BSD License
7# which accompanies this distribution.  The full text of the license may be found at
8# http://opensource.org/licenses/bsd-license.php
9#
10# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12#
13import Common.LongFilePathOs as os
14import re
15from CommonDataClass.DataClass import *
16import Common.DataType as DT
17from EccToolError import *
18from MetaDataParser import ParseHeaderCommentSection
19import EccGlobalData
20import c
21from Common.LongFilePathSupport import OpenLongFilePath as open
22from Common.MultipleWorkspace import MultipleWorkspace as mws
23
24## Check
25#
26# This class is to define checkpoints used by ECC tool
27#
28# @param object:          Inherited from object class
29#
30class Check(object):
31    def __init__(self):
32        pass
33
34    # Check all required checkpoints
35    def Check(self):
36        self.GeneralCheck()
37        self.MetaDataFileCheck()
38        self.DoxygenCheck()
39        self.IncludeFileCheck()
40        self.PredicateExpressionCheck()
41        self.DeclAndDataTypeCheck()
42        self.FunctionLayoutCheck()
43        self.NamingConventionCheck()
44
45    # Check UNI files
46    def UniCheck(self):
47        if EccGlobalData.gConfig.GeneralCheckUni == '1' or EccGlobalData.gConfig.GeneralCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
48            EdkLogger.quiet("Checking whether UNI file is UTF-16 ...")
49            SqlCommand = """select ID, FullPath, ExtName from File where ExtName like 'uni'"""
50            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
51            for Record in RecordSet:
52                File = Record[1]
53                FileIn = open(File, 'rb').read(2)
54                if FileIn != '\xff\xfe':
55                    OtherMsg = "File %s is not a valid UTF-16 UNI file" % Record[1]
56                    EccGlobalData.gDb.TblReport.Insert(ERROR_GENERAL_CHECK_UNI, OtherMsg=OtherMsg, BelongsToTable='File', BelongsToItem=Record[0])
57
58    # General Checking
59    def GeneralCheck(self):
60        self.GeneralCheckNonAcsii()
61        self.UniCheck()
62
63    # Check whether file has non ACSII char
64    def GeneralCheckNonAcsii(self):
65        if EccGlobalData.gConfig.GeneralCheckNonAcsii == '1' or EccGlobalData.gConfig.GeneralCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
66            EdkLogger.quiet("Checking Non-ACSII char in file ...")
67            SqlCommand = """select ID, FullPath, ExtName from File where ExtName in ('.dec', '.inf', '.dsc', 'c', 'h')"""
68            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
69            for Record in RecordSet:
70                if Record[2].upper() not in EccGlobalData.gConfig.BinaryExtList:
71                    op = open(Record[1]).readlines()
72                    IndexOfLine = 0
73                    for Line in op:
74                        IndexOfLine += 1
75                        IndexOfChar = 0
76                        for Char in Line:
77                            IndexOfChar += 1
78                            if ord(Char) > 126:
79                                OtherMsg = "File %s has Non-ASCII char at line %s column %s" % (Record[1], IndexOfLine, IndexOfChar)
80                                EccGlobalData.gDb.TblReport.Insert(ERROR_GENERAL_CHECK_NON_ACSII, OtherMsg=OtherMsg, BelongsToTable='File', BelongsToItem=Record[0])
81
82    # C Function Layout Checking
83    def FunctionLayoutCheck(self):
84        self.FunctionLayoutCheckReturnType()
85        self.FunctionLayoutCheckModifier()
86        self.FunctionLayoutCheckName()
87        self.FunctionLayoutCheckPrototype()
88        self.FunctionLayoutCheckBody()
89        self.FunctionLayoutCheckLocalVariable()
90
91    def WalkTree(self):
92        IgnoredPattern = c.GetIgnoredDirListPattern()
93        for Dirpath, Dirnames, Filenames in os.walk(EccGlobalData.gTarget):
94            for Dir in Dirnames:
95                Dirname = os.path.join(Dirpath, Dir)
96                if os.path.islink(Dirname):
97                    Dirname = os.path.realpath(Dirname)
98                    if os.path.isdir(Dirname):
99                        # symlinks to directories are treated as directories
100                        Dirnames.remove(Dir)
101                        Dirnames.append(Dirname)
102            if IgnoredPattern.match(Dirpath.upper()):
103                continue
104            for f in Filenames[:]:
105                if f.lower() in EccGlobalData.gConfig.SkipFileList:
106                    Filenames.remove(f)
107            yield (Dirpath, Dirnames, Filenames)
108
109    # Check whether return type exists and in the first line
110    def FunctionLayoutCheckReturnType(self):
111        if EccGlobalData.gConfig.CFunctionLayoutCheckReturnType == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
112            EdkLogger.quiet("Checking function layout return type ...")
113
114#            for Dirpath, Dirnames, Filenames in self.WalkTree():
115#                for F in Filenames:
116#                    if os.path.splitext(F)[1] in ('.c', '.h'):
117#                        FullName = os.path.join(Dirpath, F)
118#                        c.CheckFuncLayoutReturnType(FullName)
119            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
120                c.CheckFuncLayoutReturnType(FullName)
121
122    # Check whether any optional functional modifiers exist and next to the return type
123    def FunctionLayoutCheckModifier(self):
124        if EccGlobalData.gConfig.CFunctionLayoutCheckOptionalFunctionalModifier == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
125            EdkLogger.quiet("Checking function layout modifier ...")
126
127#            for Dirpath, Dirnames, Filenames in self.WalkTree():
128#                for F in Filenames:
129#                    if os.path.splitext(F)[1] in ('.c', '.h'):
130#                        FullName = os.path.join(Dirpath, F)
131#                        c.CheckFuncLayoutModifier(FullName)
132            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
133                c.CheckFuncLayoutModifier(FullName)
134
135    # Check whether the next line contains the function name, left justified, followed by the beginning of the parameter list
136    # Check whether the closing parenthesis is on its own line and also indented two spaces
137    def FunctionLayoutCheckName(self):
138        if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionName == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
139            EdkLogger.quiet("Checking function layout function name ...")
140
141#            for Dirpath, Dirnames, Filenames in self.WalkTree():
142#                for F in Filenames:
143#                    if os.path.splitext(F)[1] in ('.c', '.h'):
144#                        FullName = os.path.join(Dirpath, F)
145#                        c.CheckFuncLayoutName(FullName)
146            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
147                c.CheckFuncLayoutName(FullName)
148
149    # Check whether the function prototypes in include files have the same form as function definitions
150    def FunctionLayoutCheckPrototype(self):
151        if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionPrototype == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
152            EdkLogger.quiet("Checking function layout function prototype ...")
153
154#            for Dirpath, Dirnames, Filenames in self.WalkTree():
155#                for F in Filenames:
156#                    if os.path.splitext(F)[1] in ('.c'):
157#                        FullName = os.path.join(Dirpath, F)
158#                        EdkLogger.quiet("[PROTOTYPE]" + FullName)
159#                        c.CheckFuncLayoutPrototype(FullName)
160            for FullName in EccGlobalData.gCFileList:
161                EdkLogger.quiet("[PROTOTYPE]" + FullName)
162                c.CheckFuncLayoutPrototype(FullName)
163
164    # Check whether the body of a function is contained by open and close braces that must be in the first column
165    def FunctionLayoutCheckBody(self):
166        if EccGlobalData.gConfig.CFunctionLayoutCheckFunctionBody == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
167            EdkLogger.quiet("Checking function layout function body ...")
168
169#            for Dirpath, Dirnames, Filenames in self.WalkTree():
170#                for F in Filenames:
171#                    if os.path.splitext(F)[1] in ('.c'):
172#                        FullName = os.path.join(Dirpath, F)
173#                        c.CheckFuncLayoutBody(FullName)
174            for FullName in EccGlobalData.gCFileList:
175                c.CheckFuncLayoutBody(FullName)
176
177    # Check whether the data declarations is the first code in a module.
178    # self.CFunctionLayoutCheckDataDeclaration = 1
179    # Check whether no initialization of a variable as part of its declaration
180    def FunctionLayoutCheckLocalVariable(self):
181        if EccGlobalData.gConfig.CFunctionLayoutCheckNoInitOfVariable == '1' or EccGlobalData.gConfig.CFunctionLayoutCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
182            EdkLogger.quiet("Checking function layout local variables ...")
183
184#            for Dirpath, Dirnames, Filenames in self.WalkTree():
185#                for F in Filenames:
186#                    if os.path.splitext(F)[1] in ('.c'):
187#                        FullName = os.path.join(Dirpath, F)
188#                        c.CheckFuncLayoutLocalVariable(FullName)
189
190            for FullName in EccGlobalData.gCFileList:
191                c.CheckFuncLayoutLocalVariable(FullName)
192
193    # Check whether no use of STATIC for functions
194    # self.CFunctionLayoutCheckNoStatic = 1
195
196    # Declarations and Data Types Checking
197    def DeclAndDataTypeCheck(self):
198        self.DeclCheckNoUseCType()
199        self.DeclCheckInOutModifier()
200        self.DeclCheckEFIAPIModifier()
201        self.DeclCheckEnumeratedType()
202        self.DeclCheckStructureDeclaration()
203        self.DeclCheckSameStructure()
204        self.DeclCheckUnionType()
205
206
207    # Check whether no use of int, unsigned, char, void, static, long in any .c, .h or .asl files.
208    def DeclCheckNoUseCType(self):
209        if EccGlobalData.gConfig.DeclarationDataTypeCheckNoUseCType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
210            EdkLogger.quiet("Checking Declaration No use C type ...")
211
212#            for Dirpath, Dirnames, Filenames in self.WalkTree():
213#                for F in Filenames:
214#                    if os.path.splitext(F)[1] in ('.h', '.c'):
215#                        FullName = os.path.join(Dirpath, F)
216#                        c.CheckDeclNoUseCType(FullName)
217            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
218                c.CheckDeclNoUseCType(FullName)
219
220    # Check whether the modifiers IN, OUT, OPTIONAL, and UNALIGNED are used only to qualify arguments to a function and should not appear in a data type declaration
221    def DeclCheckInOutModifier(self):
222        if EccGlobalData.gConfig.DeclarationDataTypeCheckInOutModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
223            EdkLogger.quiet("Checking Declaration argument modifier ...")
224
225#            for Dirpath, Dirnames, Filenames in self.WalkTree():
226#                for F in Filenames:
227#                    if os.path.splitext(F)[1] in ('.h', '.c'):
228#                        FullName = os.path.join(Dirpath, F)
229#                        c.CheckDeclArgModifier(FullName)
230            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
231                c.CheckDeclArgModifier(FullName)
232
233    # Check whether the EFIAPI modifier should be used at the entry of drivers, events, and member functions of protocols
234    def DeclCheckEFIAPIModifier(self):
235        if EccGlobalData.gConfig.DeclarationDataTypeCheckEFIAPIModifier == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
236            pass
237
238    # Check whether Enumerated Type has a 'typedef' and the name is capital
239    def DeclCheckEnumeratedType(self):
240        if EccGlobalData.gConfig.DeclarationDataTypeCheckEnumeratedType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
241            EdkLogger.quiet("Checking Declaration enum typedef ...")
242
243#            for Dirpath, Dirnames, Filenames in self.WalkTree():
244#                for F in Filenames:
245#                    if os.path.splitext(F)[1] in ('.h', '.c'):
246#                        FullName = os.path.join(Dirpath, F)
247#                        EdkLogger.quiet("[ENUM]" + FullName)
248#                        c.CheckDeclEnumTypedef(FullName)
249            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
250                EdkLogger.quiet("[ENUM]" + FullName)
251                c.CheckDeclEnumTypedef(FullName)
252
253    # Check whether Structure Type has a 'typedef' and the name is capital
254    def DeclCheckStructureDeclaration(self):
255        if EccGlobalData.gConfig.DeclarationDataTypeCheckStructureDeclaration == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
256            EdkLogger.quiet("Checking Declaration struct typedef ...")
257
258#            for Dirpath, Dirnames, Filenames in self.WalkTree():
259#                for F in Filenames:
260#                    if os.path.splitext(F)[1] in ('.h', '.c'):
261#                        FullName = os.path.join(Dirpath, F)
262#                        EdkLogger.quiet("[STRUCT]" + FullName)
263#                        c.CheckDeclStructTypedef(FullName)
264            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
265                EdkLogger.quiet("[STRUCT]" + FullName)
266                c.CheckDeclStructTypedef(FullName)
267
268    # Check whether having same Structure
269    def DeclCheckSameStructure(self):
270        if EccGlobalData.gConfig.DeclarationDataTypeCheckSameStructure == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
271            EdkLogger.quiet("Checking same struct ...")
272            AllStructure = {}
273            for IdentifierTable in EccGlobalData.gIdentifierTableList:
274                SqlCommand = """select ID, Name, BelongsToFile from %s where Model = %s""" % (IdentifierTable, MODEL_IDENTIFIER_STRUCTURE)
275                RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
276                for Record in RecordSet:
277                    if Record[1] != '':
278                        if Record[1] not in AllStructure.keys():
279                            AllStructure[Record[1]] = Record[2]
280                        else:
281                            ID = AllStructure[Record[1]]
282                            SqlCommand = """select FullPath from File where ID = %s """ % ID
283                            NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
284                            OtherMsg = "The structure name '%s' is duplicate" % Record[1]
285                            if NewRecordSet != []:
286                                OtherMsg = "The structure name [%s] is duplicate with the one defined in %s, maybe struct NOT typedefed or the typedef new type NOT used to qualify variables" % (Record[1], NewRecordSet[0][0])
287                            if not EccGlobalData.gException.IsException(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, Record[1]):
288                                EccGlobalData.gDb.TblReport.Insert(ERROR_DECLARATION_DATA_TYPE_CHECK_SAME_STRUCTURE, OtherMsg=OtherMsg, BelongsToTable=IdentifierTable, BelongsToItem=Record[0])
289
290    # Check whether Union Type has a 'typedef' and the name is capital
291    def DeclCheckUnionType(self):
292        if EccGlobalData.gConfig.DeclarationDataTypeCheckUnionType == '1' or EccGlobalData.gConfig.DeclarationDataTypeCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
293            EdkLogger.quiet("Checking Declaration union typedef ...")
294
295#            for Dirpath, Dirnames, Filenames in self.WalkTree():
296#                for F in Filenames:
297#                    if os.path.splitext(F)[1] in ('.h', '.c'):
298#                        FullName = os.path.join(Dirpath, F)
299#                        EdkLogger.quiet("[UNION]" + FullName)
300#                        c.CheckDeclUnionTypedef(FullName)
301            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
302                EdkLogger.quiet("[UNION]" + FullName)
303                c.CheckDeclUnionTypedef(FullName)
304
305    # Predicate Expression Checking
306    def PredicateExpressionCheck(self):
307        self.PredicateExpressionCheckBooleanValue()
308        self.PredicateExpressionCheckNonBooleanOperator()
309        self.PredicateExpressionCheckComparisonNullType()
310
311    # Check whether Boolean values, variable type BOOLEAN not use explicit comparisons to TRUE or FALSE
312    def PredicateExpressionCheckBooleanValue(self):
313        if EccGlobalData.gConfig.PredicateExpressionCheckBooleanValue == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
314            EdkLogger.quiet("Checking predicate expression Boolean value ...")
315
316#            for Dirpath, Dirnames, Filenames in self.WalkTree():
317#                for F in Filenames:
318#                    if os.path.splitext(F)[1] in ('.c'):
319#                        FullName = os.path.join(Dirpath, F)
320#                        EdkLogger.quiet("[BOOLEAN]" + FullName)
321#                        c.CheckBooleanValueComparison(FullName)
322            for FullName in EccGlobalData.gCFileList:
323                EdkLogger.quiet("[BOOLEAN]" + FullName)
324                c.CheckBooleanValueComparison(FullName)
325
326    # Check whether Non-Boolean comparisons use a compare operator (==, !=, >, < >=, <=).
327    def PredicateExpressionCheckNonBooleanOperator(self):
328        if EccGlobalData.gConfig.PredicateExpressionCheckNonBooleanOperator == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
329            EdkLogger.quiet("Checking predicate expression Non-Boolean variable...")
330
331#            for Dirpath, Dirnames, Filenames in self.WalkTree():
332#                for F in Filenames:
333#                    if os.path.splitext(F)[1] in ('.c'):
334#                        FullName = os.path.join(Dirpath, F)
335#                        EdkLogger.quiet("[NON-BOOLEAN]" + FullName)
336#                        c.CheckNonBooleanValueComparison(FullName)
337            for FullName in EccGlobalData.gCFileList:
338                EdkLogger.quiet("[NON-BOOLEAN]" + FullName)
339                c.CheckNonBooleanValueComparison(FullName)
340
341    # Check whether a comparison of any pointer to zero must be done via the NULL type
342    def PredicateExpressionCheckComparisonNullType(self):
343        if EccGlobalData.gConfig.PredicateExpressionCheckComparisonNullType == '1' or EccGlobalData.gConfig.PredicateExpressionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
344            EdkLogger.quiet("Checking predicate expression NULL pointer ...")
345
346#            for Dirpath, Dirnames, Filenames in self.WalkTree():
347#                for F in Filenames:
348#                    if os.path.splitext(F)[1] in ('.c'):
349#                        FullName = os.path.join(Dirpath, F)
350#                        EdkLogger.quiet("[POINTER]" + FullName)
351#                        c.CheckPointerNullComparison(FullName)
352            for FullName in EccGlobalData.gCFileList:
353                EdkLogger.quiet("[POINTER]" + FullName)
354                c.CheckPointerNullComparison(FullName)
355
356    # Include file checking
357    def IncludeFileCheck(self):
358        self.IncludeFileCheckIfndef()
359        self.IncludeFileCheckData()
360        self.IncludeFileCheckSameName()
361
362    # Check whether having include files with same name
363    def IncludeFileCheckSameName(self):
364        if EccGlobalData.gConfig.IncludeFileCheckSameName == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
365            EdkLogger.quiet("Checking same header file name ...")
366            SqlCommand = """select ID, FullPath from File
367                            where Model = 1002 order by Name """
368            RecordDict = {}
369            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
370            for Record in RecordSet:
371                List = Record[1].replace('/', '\\').split('\\')
372                if len(List) >= 2:
373                    Key = List[-2] + '\\' + List[-1]
374                else:
375                    Key = List[0]
376                if Key not in RecordDict:
377                    RecordDict[Key] = [Record]
378                else:
379                    RecordDict[Key].append(Record)
380
381            for Key in RecordDict:
382                if len(RecordDict[Key]) > 1:
383                    for Item in RecordDict[Key]:
384                        Path = mws.relpath(Item[1], EccGlobalData.gWorkspace)
385                        if not EccGlobalData.gException.IsException(ERROR_INCLUDE_FILE_CHECK_NAME, Path):
386                            EccGlobalData.gDb.TblReport.Insert(ERROR_INCLUDE_FILE_CHECK_NAME, OtherMsg="The file name for [%s] is duplicate" % Path, BelongsToTable='File', BelongsToItem=Item[0])
387
388    # Check whether all include file contents is guarded by a #ifndef statement.
389    def IncludeFileCheckIfndef(self):
390        if EccGlobalData.gConfig.IncludeFileCheckIfndefStatement == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
391            EdkLogger.quiet("Checking header file ifndef ...")
392
393#            for Dirpath, Dirnames, Filenames in self.WalkTree():
394#                for F in Filenames:
395#                    if os.path.splitext(F)[1] in ('.h'):
396#                        FullName = os.path.join(Dirpath, F)
397#                        MsgList = c.CheckHeaderFileIfndef(FullName)
398            for FullName in EccGlobalData.gHFileList:
399                MsgList = c.CheckHeaderFileIfndef(FullName)
400
401    # Check whether include files NOT contain code or define data variables
402    def IncludeFileCheckData(self):
403        if EccGlobalData.gConfig.IncludeFileCheckData == '1' or EccGlobalData.gConfig.IncludeFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
404            EdkLogger.quiet("Checking header file data ...")
405
406#            for Dirpath, Dirnames, Filenames in self.WalkTree():
407#                for F in Filenames:
408#                    if os.path.splitext(F)[1] in ('.h'):
409#                        FullName = os.path.join(Dirpath, F)
410#                        MsgList = c.CheckHeaderFileData(FullName)
411            for FullName in EccGlobalData.gHFileList:
412                MsgList = c.CheckHeaderFileData(FullName)
413
414    # Doxygen document checking
415    def DoxygenCheck(self):
416        self.DoxygenCheckFileHeader()
417        self.DoxygenCheckFunctionHeader()
418        self.DoxygenCheckCommentDescription()
419        self.DoxygenCheckCommentFormat()
420        self.DoxygenCheckCommand()
421
422    # Check whether the file headers are followed Doxygen special documentation blocks in section 2.3.5
423    def DoxygenCheckFileHeader(self):
424        if EccGlobalData.gConfig.DoxygenCheckFileHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
425            EdkLogger.quiet("Checking Doxygen file header ...")
426
427            for Dirpath, Dirnames, Filenames in self.WalkTree():
428                for F in Filenames:
429                    Ext = os.path.splitext(F)[1]
430                    if Ext in ('.h', '.c'):
431                        FullName = os.path.join(Dirpath, F)
432                        MsgList = c.CheckFileHeaderDoxygenComments(FullName)
433                    elif Ext in ('.inf', '.dec', '.dsc', '.fdf'):
434                        FullName = os.path.join(Dirpath, F)
435                        op = open(FullName).readlines()
436                        FileLinesList = op
437                        LineNo             = 0
438                        CurrentSection     = MODEL_UNKNOWN
439                        HeaderSectionLines       = []
440                        HeaderCommentStart = False
441                        HeaderCommentEnd   = False
442
443                        for Line in FileLinesList:
444                            LineNo   = LineNo + 1
445                            Line     = Line.strip()
446                            if (LineNo < len(FileLinesList) - 1):
447                                NextLine = FileLinesList[LineNo].strip()
448
449                            #
450                            # blank line
451                            #
452                            if (Line == '' or not Line) and LineNo == len(FileLinesList):
453                                LastSectionFalg = True
454
455                            #
456                            # check whether file header comment section started
457                            #
458                            if Line.startswith('#') and \
459                                (Line.find('@file') > -1) and \
460                                not HeaderCommentStart:
461                                if CurrentSection != MODEL_UNKNOWN:
462                                    SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
463                                    ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
464                                    for Result in ResultSet:
465                                        Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file"" or ""# @file""at the very top file'
466                                        EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
467
468                                else:
469                                    CurrentSection = MODEL_IDENTIFIER_FILE_HEADER
470                                    #
471                                    # Append the first line to section lines.
472                                    #
473                                    HeaderSectionLines.append((Line, LineNo))
474                                    HeaderCommentStart = True
475                                    continue
476
477                            #
478                            # Collect Header content.
479                            #
480                            if (Line.startswith('#') and CurrentSection == MODEL_IDENTIFIER_FILE_HEADER) and\
481                                HeaderCommentStart and not Line.startswith('##') and not\
482                                HeaderCommentEnd and NextLine != '':
483                                HeaderSectionLines.append((Line, LineNo))
484                                continue
485                            #
486                            # Header content end
487                            #
488                            if (Line.startswith('##') or not Line.strip().startswith("#")) and HeaderCommentStart \
489                                and not HeaderCommentEnd:
490                                if Line.startswith('##'):
491                                    HeaderCommentEnd = True
492                                HeaderSectionLines.append((Line, LineNo))
493                                ParseHeaderCommentSection(HeaderSectionLines, FullName)
494                                break
495                        if HeaderCommentStart == False:
496                            SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
497                            ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
498                            for Result in ResultSet:
499                                Msg = 'INF/DEC/DSC/FDF file header comment should begin with ""## @file"" or ""# @file"" at the very top file'
500                                EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
501                        if HeaderCommentEnd == False:
502                            SqlStatement = """ select ID from File where FullPath like '%s'""" % FullName
503                            ResultSet = EccGlobalData.gDb.TblFile.Exec(SqlStatement)
504                            for Result in ResultSet:
505                                Msg = 'INF/DEC/DSC/FDF file header comment should end with ""##"" at the end of file header comment block'
506                                # Check whether File header Comment End with '##'
507                                if EccGlobalData.gConfig.HeaderCheckFileCommentEnd == '1' or EccGlobalData.gConfig.HeaderCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
508                                    EccGlobalData.gDb.TblReport.Insert(ERROR_DOXYGEN_CHECK_FILE_HEADER, Msg, "File", Result[0])
509
510
511
512    # Check whether the function headers are followed Doxygen special documentation blocks in section 2.3.5
513    def DoxygenCheckFunctionHeader(self):
514        if EccGlobalData.gConfig.DoxygenCheckFunctionHeader == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
515            EdkLogger.quiet("Checking Doxygen function header ...")
516
517#            for Dirpath, Dirnames, Filenames in self.WalkTree():
518#                for F in Filenames:
519#                    if os.path.splitext(F)[1] in ('.h', '.c'):
520#                        FullName = os.path.join(Dirpath, F)
521#                        MsgList = c.CheckFuncHeaderDoxygenComments(FullName)
522            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
523                MsgList = c.CheckFuncHeaderDoxygenComments(FullName)
524
525
526    # Check whether the first line of text in a comment block is a brief description of the element being documented.
527    # The brief description must end with a period.
528    def DoxygenCheckCommentDescription(self):
529        if EccGlobalData.gConfig.DoxygenCheckCommentDescription == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
530            pass
531
532    # Check whether comment lines with '///< ... text ...' format, if it is used, it should be after the code section.
533    def DoxygenCheckCommentFormat(self):
534        if EccGlobalData.gConfig.DoxygenCheckCommentFormat == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
535            EdkLogger.quiet("Checking Doxygen comment ///< ...")
536
537#            for Dirpath, Dirnames, Filenames in self.WalkTree():
538#                for F in Filenames:
539#                    if os.path.splitext(F)[1] in ('.h', '.c'):
540#                        FullName = os.path.join(Dirpath, F)
541#                        MsgList = c.CheckDoxygenTripleForwardSlash(FullName)
542            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
543                MsgList = c.CheckDoxygenTripleForwardSlash(FullName)
544
545    # Check whether only Doxygen commands allowed to mark the code are @bug and @todo.
546    def DoxygenCheckCommand(self):
547        if EccGlobalData.gConfig.DoxygenCheckCommand == '1' or EccGlobalData.gConfig.DoxygenCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
548            EdkLogger.quiet("Checking Doxygen command ...")
549
550#            for Dirpath, Dirnames, Filenames in self.WalkTree():
551#                for F in Filenames:
552#                    if os.path.splitext(F)[1] in ('.h', '.c'):
553#                        FullName = os.path.join(Dirpath, F)
554#                        MsgList = c.CheckDoxygenCommand(FullName)
555            for FullName in EccGlobalData.gCFileList + EccGlobalData.gHFileList:
556                MsgList = c.CheckDoxygenCommand(FullName)
557
558    # Meta-Data File Processing Checking
559    def MetaDataFileCheck(self):
560        self.MetaDataFileCheckPathName()
561        self.MetaDataFileCheckGenerateFileList()
562        self.MetaDataFileCheckLibraryInstance()
563        self.MetaDataFileCheckLibraryInstanceDependent()
564        self.MetaDataFileCheckLibraryInstanceOrder()
565        self.MetaDataFileCheckLibraryNoUse()
566        self.MetaDataFileCheckLibraryDefinedInDec()
567        self.MetaDataFileCheckBinaryInfInFdf()
568        self.MetaDataFileCheckPcdDuplicate()
569        self.MetaDataFileCheckPcdFlash()
570        self.MetaDataFileCheckPcdNoUse()
571        self.MetaDataFileCheckGuidDuplicate()
572        self.MetaDataFileCheckModuleFileNoUse()
573        self.MetaDataFileCheckPcdType()
574        self.MetaDataFileCheckModuleFileGuidDuplication()
575        self.MetaDataFileCheckModuleFileGuidFormat()
576        self.MetaDataFileCheckModuleFileProtocolFormat()
577        self.MetaDataFileCheckModuleFilePpiFormat()
578        self.MetaDataFileCheckModuleFilePcdFormat()
579
580    # Check whether each file defined in meta-data exists
581    def MetaDataFileCheckPathName(self):
582        if EccGlobalData.gConfig.MetaDataFileCheckPathName == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
583            # This item is covered when parsing Inf/Dec/Dsc files
584            pass
585
586    # Generate a list for all files defined in meta-data files
587    def MetaDataFileCheckGenerateFileList(self):
588        if EccGlobalData.gConfig.MetaDataFileCheckGenerateFileList == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
589            # This item is covered when parsing Inf/Dec/Dsc files
590            pass
591
592    # Check whether all Library Instances defined for a given module (or dependent library instance) match the module's type.
593    # Each Library Instance must specify the Supported Module Types in its Inf file,
594    # and any module specifying the library instance must be one of the supported types.
595    def MetaDataFileCheckLibraryInstance(self):
596        if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstance == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
597            EdkLogger.quiet("Checking for library instance type issue ...")
598            SqlCommand = """select A.ID, A.Value3, B.Value3 from Inf as A left join Inf as B
599                            where A.Value2 = 'LIBRARY_CLASS' and A.Model = %s
600                            and B.Value2 = 'MODULE_TYPE' and B.Model = %s and A.BelongsToFile = B.BelongsToFile
601                            group by A.BelongsToFile""" % (MODEL_META_DATA_HEADER, MODEL_META_DATA_HEADER)
602            RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
603            LibraryClasses = {}
604            for Record in RecordSet:
605                List = Record[1].split('|', 1)
606                SupModType = []
607                if len(List) == 1:
608                    SupModType = DT.SUP_MODULE_LIST_STRING.split(DT.TAB_VALUE_SPLIT)
609                elif len(List) == 2:
610                    SupModType = List[1].split()
611
612                if List[0] not in LibraryClasses:
613                    LibraryClasses[List[0]] = SupModType
614                else:
615                    for Item in SupModType:
616                        if Item not in LibraryClasses[List[0]]:
617                            LibraryClasses[List[0]].append(Item)
618
619                if Record[2] != 'BASE' and Record[2] not in SupModType:
620                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_2, OtherMsg="The Library Class '%s' does not specify its supported module types" % (List[0]), BelongsToTable='Inf', BelongsToItem=Record[0])
621
622            SqlCommand = """select A.ID, A.Value1, B.Value3 from Inf as A left join Inf as B
623                            where A.Model = %s and B.Value2 = '%s' and B.Model = %s
624                            and B.BelongsToFile = A.BelongsToFile""" \
625                            % (MODEL_EFI_LIBRARY_CLASS, 'MODULE_TYPE', MODEL_META_DATA_HEADER)
626            RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
627            # Merge all LibraryClasses' supmodlist
628            RecordDict = {}
629            for Record in RecordSet:
630                if Record[1] not in RecordDict:
631                    RecordDict[Record[1]] = [str(Record[2])]
632                else:
633                    if Record[2] not in RecordDict[Record[1]]:
634                        RecordDict[Record[1]].append(Record[2])
635
636            for Record in RecordSet:
637                if Record[1] in LibraryClasses:
638                    if Record[2] not in LibraryClasses[Record[1]] and 'BASE' not in RecordDict[Record[1]]:
639                        if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):
640                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, OtherMsg="The type of Library Class [%s] defined in Inf file does not match the type of the module" % (Record[1]), BelongsToTable='Inf', BelongsToItem=Record[0])
641                else:
642                    if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, Record[1]):
643                        EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_1, OtherMsg="The type of Library Class [%s] defined in Inf file does not match the type of the module" % (Record[1]), BelongsToTable='Inf', BelongsToItem=Record[0])
644
645    # Check whether a Library Instance has been defined for all dependent library classes
646    def MetaDataFileCheckLibraryInstanceDependent(self):
647        if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceDependent == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
648            EdkLogger.quiet("Checking for library instance dependent issue ...")
649            SqlCommand = """select ID, Value1, Value2 from Dsc where Model = %s""" % MODEL_EFI_LIBRARY_CLASS
650            LibraryClasses = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
651            for LibraryClass in LibraryClasses:
652                if LibraryClass[1].upper() == 'NULL' or LibraryClass[1].startswith('!ifdef') or LibraryClass[1].startswith('!ifndef') or LibraryClass[1].endswith('!endif'):
653                    continue
654                else:
655                    LibraryIns = os.path.normpath(mws.join(EccGlobalData.gWorkspace, LibraryClass[2]))
656                    SkipDirString = '|'.join(EccGlobalData.gConfig.SkipDirList)
657                    p = re.compile(r'.*[\\/](?:%s^\S)[\\/]?.*' % SkipDirString)
658                    if p.match(os.path.split(LibraryIns)[0].upper()):
659                        continue
660                    SqlCommand = """select Value3 from Inf where BelongsToFile =
661                                    (select ID from File where lower(FullPath) = lower('%s'))
662                                    and Value2 = '%s'""" % (LibraryIns, 'LIBRARY_CLASS')
663                    RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
664                    IsFound = False
665                    for Record in RecordSet:
666                        LibName = Record[0].split('|', 1)[0]
667                        if LibraryClass[1] == LibName:
668                            IsFound = True
669                    if not IsFound:
670                        if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, LibraryClass[1]):
671                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_INSTANCE_DEPENDENT, OtherMsg="The Library Class [%s] is not specified in '%s'" % (LibraryClass[1], LibraryClass[2]), BelongsToTable='Dsc', BelongsToItem=LibraryClass[0])
672
673    # Check whether the Library Instances specified by the LibraryClasses sections are listed in order of dependencies
674    def MetaDataFileCheckLibraryInstanceOrder(self):
675        if EccGlobalData.gConfig.MetaDataFileCheckLibraryInstanceOrder == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
676            # This checkpoint is not necessary for Ecc check
677            pass
678
679    # Check whether the unnecessary inclusion of library classes in the Inf file
680    # Check whether the unnecessary duplication of library classe names in the DSC file
681    def MetaDataFileCheckLibraryNoUse(self):
682        if EccGlobalData.gConfig.MetaDataFileCheckLibraryNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
683            EdkLogger.quiet("Checking for library instance not used ...")
684            SqlCommand = """select ID, Value1 from Inf as A where A.Model = %s and A.Value1 not in (select B.Value1 from Dsc as B where Model = %s)""" % (MODEL_EFI_LIBRARY_CLASS, MODEL_EFI_LIBRARY_CLASS)
685            RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
686            for Record in RecordSet:
687                if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, Record[1]):
688                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_NO_USE, OtherMsg="The Library Class [%s] is not used in any platform" % (Record[1]), BelongsToTable='Inf', BelongsToItem=Record[0])
689            SqlCommand = """
690                         select A.ID, A.Value1, A.BelongsToFile, A.StartLine, B.StartLine from Dsc as A left join Dsc as B
691                         where A.Model = %s and B.Model = %s and A.Scope1 = B.Scope1 and A.Scope2 = B.Scope2 and A.ID <> B.ID
692                         and A.Value1 = B.Value1 and A.Value2 <> B.Value2 and A.BelongsToItem = -1 and B.BelongsToItem = -1 and A.StartLine <> B.StartLine and B.BelongsToFile = A.BelongsToFile""" \
693                            % (MODEL_EFI_LIBRARY_CLASS, MODEL_EFI_LIBRARY_CLASS)
694            RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
695            for Record in RecordSet:
696                if Record[3] and Record[4] and Record[3] != Record[4] and Record[1] != 'NULL':
697                    SqlCommand = """select FullPath from File where ID = %s""" % (Record[2])
698                    FilePathList = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
699                    for FilePath in FilePathList:
700                        if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NAME_DUPLICATE, Record[1]):
701                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_NAME_DUPLICATE, OtherMsg="The Library Class [%s] is duplicated in '%s' line %s and line %s." % (Record[1], FilePath, Record[3], Record[4]), BelongsToTable='Dsc', BelongsToItem=Record[0])
702
703    # Check the header file in Include\Library directory whether be defined in the package DEC file.
704    def MetaDataFileCheckLibraryDefinedInDec(self):
705        if EccGlobalData.gConfig.MetaDataFileCheckLibraryDefinedInDec == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
706            EdkLogger.quiet("Checking for library instance whether be defined in the package dec file ...")
707            SqlCommand = """
708                    select A.Value1, A.StartLine, A.ID, B.Value1 from Inf as A left join Dec as B
709                    on A.Model = B.Model and A.Value1 = B.Value1 where A.Model=%s
710                    """ % MODEL_EFI_LIBRARY_CLASS
711            RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
712            for Record in RecordSet:
713                LibraryInInf, Line, ID, LibraryDec = Record
714                if not LibraryDec:
715                    if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_LIBRARY_NOT_DEFINED, LibraryInInf):
716                        EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_LIBRARY_NOT_DEFINED, \
717                                            OtherMsg="The Library Class [%s] in %s line is not defined in the associated package file." % (LibraryInInf, Line),
718                                            BelongsToTable='Inf', BelongsToItem=ID)
719
720    # Check whether an Inf file is specified in the FDF file, but not in the Dsc file, then the Inf file must be for a Binary module only
721    def MetaDataFileCheckBinaryInfInFdf(self):
722        if EccGlobalData.gConfig.MetaDataFileCheckBinaryInfInFdf == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
723            EdkLogger.quiet("Checking for non-binary modules defined in FDF files ...")
724            SqlCommand = """select A.ID, A.Value1 from Fdf as A
725                         where A.Model = %s
726                         and A.Enabled > -1
727                         and A.Value1 not in
728                         (select B.Value1 from Dsc as B
729                         where B.Model = %s
730                         and B.Enabled > -1)""" % (MODEL_META_DATA_COMPONENT, MODEL_META_DATA_COMPONENT)
731            RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)
732            for Record in RecordSet:
733                FdfID = Record[0]
734                FilePath = Record[1]
735                FilePath = os.path.normpath(mws.join(EccGlobalData.gWorkspace, FilePath))
736                SqlCommand = """select ID from Inf where Model = %s and BelongsToFile = (select ID from File where FullPath like '%s')
737                                """ % (MODEL_EFI_SOURCE_FILE, FilePath)
738                NewRecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
739                if NewRecordSet != []:
740                    if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, FilePath):
741                        EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_BINARY_INF_IN_FDF, OtherMsg="File [%s] defined in FDF file and not in DSC file must be a binary module" % (FilePath), BelongsToTable='Fdf', BelongsToItem=FdfID)
742
743    # Check whether a PCD is set in a Dsc file or the FDF file, but not in both.
744    def MetaDataFileCheckPcdDuplicate(self):
745        if EccGlobalData.gConfig.MetaDataFileCheckPcdDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
746            EdkLogger.quiet("Checking for duplicate PCDs defined in both DSC and FDF files ...")
747            SqlCommand = """
748                         select A.ID, A.Value1, A.Value2, A.BelongsToFile, B.ID, B.Value1, B.Value2, B.BelongsToFile from Dsc as A, Fdf as B
749                         where A.Model >= %s and A.Model < %s
750                         and B.Model >= %s and B.Model < %s
751                         and A.Value1 = B.Value1
752                         and A.Value2 = B.Value2
753                         and A.Enabled > -1
754                         and B.Enabled > -1
755                         group by A.ID
756                         """ % (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)
757            RecordSet = EccGlobalData.gDb.TblDsc.Exec(SqlCommand)
758            for Record in RecordSet:
759                SqlCommand1 = """select Name from File where ID = %s""" % Record[3]
760                SqlCommand2 = """select Name from File where ID = %s""" % Record[7]
761                DscFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand1)[0][0])[0]
762                FdfFileName = os.path.splitext(EccGlobalData.gDb.TblDsc.Exec(SqlCommand2)[0][0])[0]
763                if DscFileName != FdfFileName:
764                    continue
765                if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[1] + '.' + Record[2]):
766                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg="The PCD [%s] is defined in both FDF file and DSC file" % (Record[1] + '.' + Record[2]), BelongsToTable='Dsc', BelongsToItem=Record[0])
767                if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, Record[5] + '.' + Record[6]):
768                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg="The PCD [%s] is defined in both FDF file and DSC file" % (Record[5] + '.' + Record[6]), BelongsToTable='Fdf', BelongsToItem=Record[4])
769
770            EdkLogger.quiet("Checking for duplicate PCDs defined in DEC files ...")
771            SqlCommand = """
772                         select A.ID, A.Value1, A.Value2, A.Model, B.Model from Dec as A left join Dec as B
773                         where A.Model >= %s and A.Model < %s
774                         and B.Model >= %s and B.Model < %s
775                         and A.Value1 = B.Value1
776                         and A.Value2 = B.Value2
777                         and A.Scope1 = B.Scope1
778                         and A.ID <> B.ID
779                         and A.Model = B.Model
780                         and A.Enabled > -1
781                         and B.Enabled > -1
782                         and A.BelongsToFile = B.BelongsToFile
783                         group by A.ID
784                         """ % (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)
785            RecordSet = EccGlobalData.gDb.TblDec.Exec(SqlCommand)
786            for Record in RecordSet:
787                RecordCat = Record[1] + '.' + Record[2]
788                if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, RecordCat):
789                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_DUPLICATE, OtherMsg="The PCD [%s] is defined duplicated in DEC file" % RecordCat, BelongsToTable='Dec', BelongsToItem=Record[0])
790
791    # Check whether PCD settings in the FDF file can only be related to flash.
792    def MetaDataFileCheckPcdFlash(self):
793        if EccGlobalData.gConfig.MetaDataFileCheckPcdFlash == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
794            EdkLogger.quiet("Checking only Flash related PCDs are used in FDF ...")
795            SqlCommand = """
796                         select ID, Value1, Value2, BelongsToFile from Fdf as A
797                         where A.Model >= %s and Model < %s
798                         and A.Enabled > -1
799                         and A.Value2 not like '%%Flash%%'
800                         """ % (MODEL_PCD, MODEL_META_DATA_HEADER)
801            RecordSet = EccGlobalData.gDb.TblFdf.Exec(SqlCommand)
802            for Record in RecordSet:
803                if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, Record[1] + '.' + Record[2]):
804                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_FLASH, OtherMsg="The PCD [%s] defined in FDF file is not related to Flash" % (Record[1] + '.' + Record[2]), BelongsToTable='Fdf', BelongsToItem=Record[0])
805
806    # Check whether PCDs used in Inf files but not specified in Dsc or FDF files
807    def MetaDataFileCheckPcdNoUse(self):
808        if EccGlobalData.gConfig.MetaDataFileCheckPcdNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
809            EdkLogger.quiet("Checking for non-specified PCDs ...")
810            SqlCommand = """
811                         select ID, Value1, Value2, BelongsToFile from Inf as A
812                         where A.Model >= %s and Model < %s
813                         and A.Enabled > -1
814                         and (A.Value1, A.Value2) not in
815                             (select Value1, Value2 from Dsc as B
816                              where B.Model >= %s and B.Model < %s
817                              and B.Enabled > -1)
818                         and (A.Value1, A.Value2) not in
819                             (select Value1, Value2 from Fdf as C
820                              where C.Model >= %s and C.Model < %s
821                              and C.Enabled > -1)
822                         """ % (MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER, MODEL_PCD, MODEL_META_DATA_HEADER)
823            RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
824            for Record in RecordSet:
825                if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, Record[1] + '.' + Record[2]):
826                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_NO_USE, OtherMsg="The PCD [%s] defined in INF file is not specified in either DSC or FDF files" % (Record[1] + '.' + Record[2]), BelongsToTable='Inf', BelongsToItem=Record[0])
827
828    # Check whether having duplicate guids defined for Guid/Protocol/Ppi
829    def MetaDataFileCheckGuidDuplicate(self):
830        if EccGlobalData.gConfig.MetaDataFileCheckGuidDuplicate == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
831            EdkLogger.quiet("Checking for duplicate GUID/PPI/PROTOCOL ...")
832            # Check Guid
833            self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDec)
834            self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID, EccGlobalData.gDb.TblDsc)
835            self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_GUID, MODEL_EFI_GUID)
836            # Check protocol
837            self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDec)
838            self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL, EccGlobalData.gDb.TblDsc)
839            self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PROTOCOL, MODEL_EFI_PROTOCOL)
840            # Check ppi
841            self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDec)
842            self.CheckGuidProtocolPpi(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI, EccGlobalData.gDb.TblDsc)
843            self.CheckGuidProtocolPpiValue(ERROR_META_DATA_FILE_CHECK_DUPLICATE_PPI, MODEL_EFI_PPI)
844
845    # Check whether all files under module directory are described in INF files
846    def MetaDataFileCheckModuleFileNoUse(self):
847        if EccGlobalData.gConfig.MetaDataFileCheckModuleFileNoUse == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
848            EdkLogger.quiet("Checking for no used module files ...")
849            SqlCommand = """
850                         select upper(Path) from File where ID in (select BelongsToFile from Inf where BelongsToFile != -1)
851                         """
852            InfPathSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
853            InfPathList = []
854            for Item in InfPathSet:
855                if Item[0] not in InfPathList:
856                    InfPathList.append(Item[0])
857            SqlCommand = """
858                         select ID, Path, FullPath from File where upper(FullPath) not in
859                            (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B
860                            where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and
861                            B.BelongsToFile = A.ID and B.Model = %s)
862                            and (Model = %s or Model = %s)
863                        """ % (MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H)
864            RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
865            for Record in RecordSet:
866                Path = Record[1]
867                Path = Path.upper().replace('\X64', '').replace('\IA32', '').replace('\EBC', '').replace('\IPF', '').replace('\ARM', '')
868                if Path in InfPathList:
869                    if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, Record[2]):
870                        EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_NO_USE, OtherMsg="The source file [%s] is existing in module directory but it is not described in INF file." % (Record[2]), BelongsToTable='File', BelongsToItem=Record[0])
871
872    # Check whether the PCD is correctly used in C function via its type
873    def MetaDataFileCheckPcdType(self):
874        if EccGlobalData.gConfig.MetaDataFileCheckPcdType == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
875            EdkLogger.quiet("Checking for pcd type in c code function usage ...")
876            SqlCommand = """
877                         select ID, Model, Value1, Value2, BelongsToFile from INF where Model > %s and Model < %s
878                         """ % (MODEL_PCD, MODEL_META_DATA_HEADER)
879            PcdSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
880            for Pcd in PcdSet:
881                Model = Pcd[1]
882                PcdName = Pcd[2]
883                if Pcd[3]:
884                    PcdName = Pcd[3]
885                BelongsToFile = Pcd[4]
886                SqlCommand = """
887                             select ID from File where FullPath in
888                            (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s
889                             and B.ID = %s and (B.Model = %s or B.Model = %s))
890                             """ % (MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile, MODEL_FILE_C, MODEL_FILE_H)
891                TableSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
892                for Tbl in TableSet:
893                    TblName = 'Identifier' + str(Tbl[0])
894                    SqlCommand = """
895                                 select Name, ID from %s where value like '%s' and Model = %s
896                                 """ % (TblName, PcdName, MODEL_IDENTIFIER_FUNCTION_CALLING)
897                    RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
898                    TblNumber = TblName.replace('Identifier', '')
899                    for Record in RecordSet:
900                        FunName = Record[0]
901                        if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, FunName):
902                            if Model in [MODEL_PCD_FIXED_AT_BUILD] and not FunName.startswith('FixedPcdGet'):
903                                EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg="The pcd '%s' is defined as a FixPcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable=TblName, BelongsToItem=Record[1])
904                            if Model in [MODEL_PCD_FEATURE_FLAG] and (not FunName.startswith('FeaturePcdGet') and not FunName.startswith('FeaturePcdSet')):
905                                EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg="The pcd '%s' is defined as a FeaturePcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable=TblName, BelongsToItem=Record[1])
906                            if Model in [MODEL_PCD_PATCHABLE_IN_MODULE] and (not FunName.startswith('PatchablePcdGet') and not FunName.startswith('PatchablePcdSet')):
907                                EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_PCD_TYPE, OtherMsg="The pcd '%s' is defined as a PatchablePcd but now it is called by c function [%s]" % (PcdName, FunName), BelongsToTable=TblName, BelongsToItem=Record[1])
908
909            #ERROR_META_DATA_FILE_CHECK_PCD_TYPE
910        pass
911
912    # Internal worker function to get the INF workspace relative path from FileID
913    def GetInfFilePathFromID(self, FileID):
914        Table = EccGlobalData.gDb.TblFile
915        SqlCommand = """select A.FullPath from %s as A where A.ID = %s""" % (Table.Table, FileID)
916        RecordSet = Table.Exec(SqlCommand)
917        Path = ""
918        for Record in RecordSet:
919            Path = mws.relpath(Record[0], EccGlobalData.gWorkspace)
920        return Path
921
922    # Check whether two module INFs under one workspace has the same FILE_GUID value
923    def MetaDataFileCheckModuleFileGuidDuplication(self):
924        if EccGlobalData.gConfig.MetaDataFileCheckModuleFileGuidDuplication == '1' or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
925            EdkLogger.quiet("Checking for pcd type in c code function usage ...")
926            Table = EccGlobalData.gDb.TblInf
927            SqlCommand = """
928                         select A.ID, A.Value3, A.BelongsToFile, B.BelongsToFile from %s as A, %s as B
929                         where A.Value2 = 'FILE_GUID' and B.Value2 = 'FILE_GUID' and
930                         A.Value3 = B.Value3 and A.ID <> B.ID group by A.ID
931                         """ % (Table.Table, Table.Table)
932            RecordSet = Table.Exec(SqlCommand)
933            for Record in RecordSet:
934                InfPath1 = self.GetInfFilePathFromID(Record[2])
935                InfPath2 = self.GetInfFilePathFromID(Record[3])
936                if InfPath1 and InfPath2:
937                    if not EccGlobalData.gException.IsException(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION, InfPath1):
938                        Msg = "The FILE_GUID of INF file [%s] is duplicated with that of %s" % (InfPath1, InfPath2)
939                        EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_MODULE_FILE_GUID_DUPLICATION, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
940
941
942    # Check Guid Format in module INF
943    def MetaDataFileCheckModuleFileGuidFormat(self):
944        if EccGlobalData.gConfig.MetaDataFileCheckModuleFileGuidFormat or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
945            EdkLogger.quiet("Check Guid Format in module INF ...")
946            Table = EccGlobalData.gDb.TblInf
947            SqlCommand = """
948                         select ID, Value1, Usage, BelongsToFile from %s where Model = %s group by ID
949                         """ % (Table.Table, MODEL_EFI_GUID)
950            RecordSet = Table.Exec(SqlCommand)
951            for Record in RecordSet:
952                Value1 = Record[1]
953                Value2 = Record[2]
954                GuidCommentList = []
955                InfPath = self.GetInfFilePathFromID(Record[3])
956                Msg = "The GUID format of %s in INF file [%s] does not follow rules" % (Value1, InfPath)
957                if Value2.startswith(DT.TAB_SPECIAL_COMMENT):
958                    GuidCommentList = Value2[2:].split(DT.TAB_SPECIAL_COMMENT)
959                    if GuidCommentList[0].strip().startswith(DT.TAB_INF_USAGE_UNDEFINED):
960                        continue
961                    elif len(GuidCommentList) > 1:
962                        if not GuidCommentList[0].strip().startswith((DT.TAB_INF_USAGE_PRO,
963                                                                      DT.TAB_INF_USAGE_SOME_PRO,
964                                                                      DT.TAB_INF_USAGE_CON,
965                                                                      DT.TAB_INF_USAGE_SOME_CON)):
966                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_GUID, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
967                        if not (GuidCommentList[1].strip()).startswith(DT.TAB_INF_GUIDTYPE_VAR) and \
968                            not GuidCommentList[1].strip().startswith((DT.TAB_INF_GUIDTYPE_EVENT,
969                                                                       DT.TAB_INF_GUIDTYPE_HII,
970                                                                       DT.TAB_INF_GUIDTYPE_FILE,
971                                                                       DT.TAB_INF_GUIDTYPE_HOB,
972                                                                       DT.TAB_INF_GUIDTYPE_FV,
973                                                                       DT.TAB_INF_GUIDTYPE_ST,
974                                                                       DT.TAB_INF_GUIDTYPE_TSG,
975                                                                       DT.TAB_INF_GUIDTYPE_GUID,
976                                                                       DT.TAB_INF_GUIDTYPE_PROTOCOL,
977                                                                       DT.TAB_INF_GUIDTYPE_PPI,
978                                                                       DT.TAB_INF_USAGE_UNDEFINED)):
979                                EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_GUID, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
980                    else:
981                        EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_GUID, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
982                else:
983                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_GUID, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
984
985    # Check Protocol Format in module INF
986    def MetaDataFileCheckModuleFileProtocolFormat(self):
987        if EccGlobalData.gConfig.MetaDataFileCheckModuleFileProtocolFormat or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
988            EdkLogger.quiet("Check Protocol Format in module INF ...")
989            Table = EccGlobalData.gDb.TblInf
990            SqlCommand = """
991                         select ID, Value1, Usage, BelongsToFile from %s where Model = %s group by ID
992                         """ % (Table.Table, MODEL_EFI_PROTOCOL)
993            RecordSet = Table.Exec(SqlCommand)
994            for Record in RecordSet:
995                Value1 = Record[1]
996                Value2 = Record[2]
997                GuidCommentList = []
998                InfPath = self.GetInfFilePathFromID(Record[3])
999                Msg = "The Protocol format of %s in INF file [%s] does not follow rules" % (Value1, InfPath)
1000                if Value2.startswith(DT.TAB_SPECIAL_COMMENT):
1001                    GuidCommentList = Value2[2:].split(DT.TAB_SPECIAL_COMMENT)
1002                    if len(GuidCommentList) >= 1:
1003                        if not GuidCommentList[0].strip().startswith((DT.TAB_INF_USAGE_PRO,
1004                                                                      DT.TAB_INF_USAGE_SOME_PRO,
1005                                                                      DT.TAB_INF_USAGE_CON,
1006                                                                      DT.TAB_INF_USAGE_SOME_CON,
1007                                                                      DT.TAB_INF_USAGE_NOTIFY,
1008                                                                      DT.TAB_INF_USAGE_TO_START,
1009                                                                      DT.TAB_INF_USAGE_BY_START,
1010                                                                      DT.TAB_INF_USAGE_UNDEFINED)):
1011                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PROTOCOL, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1012                else:
1013                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PROTOCOL, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1014
1015
1016    # Check Ppi Format in module INF
1017    def MetaDataFileCheckModuleFilePpiFormat(self):
1018        if EccGlobalData.gConfig.MetaDataFileCheckModuleFilePpiFormat or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1019            EdkLogger.quiet("Check Ppi Format in module INF ...")
1020            Table = EccGlobalData.gDb.TblInf
1021            SqlCommand = """
1022                         select ID, Value1, Usage, BelongsToFile from %s where Model = %s group by ID
1023                         """ % (Table.Table, MODEL_EFI_PPI)
1024            RecordSet = Table.Exec(SqlCommand)
1025            for Record in RecordSet:
1026                Value1 = Record[1]
1027                Value2 = Record[2]
1028                GuidCommentList = []
1029                InfPath = self.GetInfFilePathFromID(Record[3])
1030                Msg = "The Ppi format of %s in INF file [%s] does not follow rules" % (Value1, InfPath)
1031                if Value2.startswith(DT.TAB_SPECIAL_COMMENT):
1032                    GuidCommentList = Value2[2:].split(DT.TAB_SPECIAL_COMMENT)
1033                    if len(GuidCommentList) >= 1:
1034                        if not GuidCommentList[0].strip().startswith((DT.TAB_INF_USAGE_PRO,
1035                                                                      DT.TAB_INF_USAGE_SOME_PRO,
1036                                                                      DT.TAB_INF_USAGE_CON,
1037                                                                      DT.TAB_INF_USAGE_SOME_CON,
1038                                                                      DT.TAB_INF_USAGE_NOTIFY,
1039                                                                      DT.TAB_INF_USAGE_UNDEFINED)):
1040                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PPI, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1041                else:
1042                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PPI, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1043
1044    # Check Pcd Format in module INF
1045    def MetaDataFileCheckModuleFilePcdFormat(self):
1046        if EccGlobalData.gConfig.MetaDataFileCheckModuleFilePcdFormat or EccGlobalData.gConfig.MetaDataFileCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1047            EdkLogger.quiet("Check Pcd Format in module INF ...")
1048            Table = EccGlobalData.gDb.TblInf
1049            SqlCommand = """
1050                         select ID, Model, Value1, Value2, Usage, BelongsToFile from %s where Model >= %s and Model < %s group by ID
1051                         """ % (Table.Table, MODEL_PCD, MODEL_META_DATA_HEADER)
1052            RecordSet = Table.Exec(SqlCommand)
1053            for Record in RecordSet:
1054                Model = Record[1]
1055                PcdName = Record[2] + '.' + Record[3]
1056                Usage = Record[4]
1057                PcdCommentList = []
1058                InfPath = self.GetInfFilePathFromID(Record[5])
1059                Msg = "The Pcd format of %s in INF file [%s] does not follow rules" % (PcdName, InfPath)
1060                if Usage.startswith(DT.TAB_SPECIAL_COMMENT):
1061                    PcdCommentList = Usage[2:].split(DT.TAB_SPECIAL_COMMENT)
1062                    if len(PcdCommentList) >= 1:
1063                        if Model in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_FEATURE_FLAG] \
1064                            and not PcdCommentList[0].strip().startswith((DT.TAB_INF_USAGE_SOME_PRO,
1065                                                                          DT.TAB_INF_USAGE_CON,
1066                                                                          DT.TAB_INF_USAGE_UNDEFINED)):
1067                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PCD, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1068                        if Model in [MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX] \
1069                            and not PcdCommentList[0].strip().startswith((DT.TAB_INF_USAGE_PRO,
1070                                                                          DT.TAB_INF_USAGE_SOME_PRO,
1071                                                                          DT.TAB_INF_USAGE_CON,
1072                                                                          DT.TAB_INF_USAGE_SOME_CON,
1073                                                                          DT.TAB_INF_USAGE_UNDEFINED)):
1074                            EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PCD, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1075                else:
1076                    EccGlobalData.gDb.TblReport.Insert(ERROR_META_DATA_FILE_CHECK_FORMAT_PCD, OtherMsg=Msg, BelongsToTable=Table.Table, BelongsToItem=Record[0])
1077
1078    # Check whether these is duplicate Guid/Ppi/Protocol name
1079    def CheckGuidProtocolPpi(self, ErrorID, Model, Table):
1080        Name = ''
1081        if Model == MODEL_EFI_GUID:
1082            Name = 'guid'
1083        if Model == MODEL_EFI_PROTOCOL:
1084            Name = 'protocol'
1085        if Model == MODEL_EFI_PPI:
1086            Name = 'ppi'
1087        SqlCommand = """
1088                     select A.ID, A.Value1 from %s as A, %s as B
1089                     where A.Model = %s and B.Model = %s
1090                     and A.Value1 like B.Value1 and A.ID <> B.ID
1091                     and A.Scope1 = B.Scope1
1092                     and A.Enabled > -1
1093                     and B.Enabled > -1
1094                     group by A.ID
1095                     """ % (Table.Table, Table.Table, Model, Model)
1096        RecordSet = Table.Exec(SqlCommand)
1097        for Record in RecordSet:
1098            if not EccGlobalData.gException.IsException(ErrorID, Record[1]):
1099                EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg="The %s name [%s] is defined more than one time" % (Name.upper(), Record[1]), BelongsToTable=Table.Table, BelongsToItem=Record[0])
1100
1101    # Check whether these is duplicate Guid/Ppi/Protocol value
1102    def CheckGuidProtocolPpiValue(self, ErrorID, Model):
1103        Name = ''
1104        Table = EccGlobalData.gDb.TblDec
1105        if Model == MODEL_EFI_GUID:
1106            Name = 'guid'
1107        if Model == MODEL_EFI_PROTOCOL:
1108            Name = 'protocol'
1109        if Model == MODEL_EFI_PPI:
1110            Name = 'ppi'
1111        SqlCommand = """
1112                     select A.ID, A.Value1, A.Value2 from %s as A, %s as B
1113                     where A.Model = %s and B.Model = %s
1114                     and A.Value2 like B.Value2 and A.ID <> B.ID
1115                     and A.Scope1 = B.Scope1 and A.Value1 <> B.Value1
1116                     group by A.ID
1117                     """ % (Table.Table, Table.Table, Model, Model)
1118        RecordSet = Table.Exec(SqlCommand)
1119        for Record in RecordSet:
1120            if not EccGlobalData.gException.IsException(ErrorID, Record[2]):
1121                EccGlobalData.gDb.TblReport.Insert(ErrorID, OtherMsg="The %s value [%s] is used more than one time" % (Name.upper(), Record[2]), BelongsToTable=Table.Table, BelongsToItem=Record[0])
1122
1123    # Naming Convention Check
1124    def NamingConventionCheck(self):
1125        if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' \
1126        or EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' \
1127        or EccGlobalData.gConfig.NamingConventionCheckIfndefStatement == '1' \
1128        or EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' \
1129        or EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' \
1130        or EccGlobalData.gConfig.NamingConventionCheckAll == '1'\
1131        or EccGlobalData.gConfig.CheckAll == '1':
1132            for Dirpath, Dirnames, Filenames in self.WalkTree():
1133                for F in Filenames:
1134                    if os.path.splitext(F)[1] in ('.h', '.c'):
1135                        FullName = os.path.join(Dirpath, F)
1136                        Id = c.GetTableID(FullName)
1137                        if Id < 0:
1138                            continue
1139                        FileTable = 'Identifier' + str(Id)
1140                        self.NamingConventionCheckDefineStatement(FileTable)
1141                        self.NamingConventionCheckTypedefStatement(FileTable)
1142                        self.NamingConventionCheckIfndefStatement(FileTable)
1143                        self.NamingConventionCheckVariableName(FileTable)
1144                        self.NamingConventionCheckSingleCharacterVariable(FileTable)
1145
1146        self.NamingConventionCheckPathName()
1147        self.NamingConventionCheckFunctionName()
1148
1149    # Check whether only capital letters are used for #define declarations
1150    def NamingConventionCheckDefineStatement(self, FileTable):
1151        if EccGlobalData.gConfig.NamingConventionCheckDefineStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1152            EdkLogger.quiet("Checking naming covention of #define statement ...")
1153
1154            SqlCommand = """select ID, Value from %s where Model = %s""" % (FileTable, MODEL_IDENTIFIER_MACRO_DEFINE)
1155            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1156            for Record in RecordSet:
1157                Name = Record[1].strip().split()[1]
1158                if Name.find('(') != -1:
1159                    Name = Name[0:Name.find('(')]
1160                if Name.upper() != Name:
1161                    if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, Name):
1162                        EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT, OtherMsg="The #define name [%s] does not follow the rules" % (Name), BelongsToTable=FileTable, BelongsToItem=Record[0])
1163
1164    # Check whether only capital letters are used for typedef declarations
1165    def NamingConventionCheckTypedefStatement(self, FileTable):
1166        if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1167            EdkLogger.quiet("Checking naming covention of #typedef statement ...")
1168
1169            SqlCommand = """select ID, Name from %s where Model = %s""" % (FileTable, MODEL_IDENTIFIER_TYPEDEF)
1170            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1171            for Record in RecordSet:
1172                Name = Record[1].strip()
1173                if Name != '' and Name != None:
1174                    if Name[0] == '(':
1175                        Name = Name[1:Name.find(')')]
1176                    if Name.find('(') > -1:
1177                        Name = Name[Name.find('(') + 1 : Name.find(')')]
1178                    Name = Name.replace('WINAPI', '')
1179                    Name = Name.replace('*', '').strip()
1180                    if Name.upper() != Name:
1181                        if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, Name):
1182                            EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT, OtherMsg="The #typedef name [%s] does not follow the rules" % (Name), BelongsToTable=FileTable, BelongsToItem=Record[0])
1183
1184    # Check whether the #ifndef at the start of an include file uses both prefix and postfix underscore characters, '_'.
1185    def NamingConventionCheckIfndefStatement(self, FileTable):
1186        if EccGlobalData.gConfig.NamingConventionCheckTypedefStatement == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1187            EdkLogger.quiet("Checking naming covention of #ifndef statement ...")
1188
1189            SqlCommand = """select ID, Value from %s where Model = %s""" % (FileTable, MODEL_IDENTIFIER_MACRO_IFNDEF)
1190            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1191            for Record in RecordSet:
1192                Name = Record[1].replace('#ifndef', '').strip()
1193                if Name[0] != '_' or Name[-1] != '_':
1194                    if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, Name):
1195                        EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, OtherMsg="The #ifndef name [%s] does not follow the rules" % (Name), BelongsToTable=FileTable, BelongsToItem=Record[0])
1196
1197    # Rule for path name, variable name and function name
1198    # 1. First character should be upper case
1199    # 2. Existing lower case in a word
1200    # 3. No space existence
1201    # Check whether the path name followed the rule
1202    def NamingConventionCheckPathName(self):
1203        if EccGlobalData.gConfig.NamingConventionCheckPathName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1204            EdkLogger.quiet("Checking naming covention of file path name ...")
1205            Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1206            SqlCommand = """select ID, Name from File"""
1207            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1208            for Record in RecordSet:
1209                if not Pattern.match(Record[1]):
1210                    if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, Record[1]):
1211                        EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_PATH_NAME, OtherMsg="The file path [%s] does not follow the rules" % (Record[1]), BelongsToTable='File', BelongsToItem=Record[0])
1212
1213    # Rule for path name, variable name and function name
1214    # 1. First character should be upper case
1215    # 2. Existing lower case in a word
1216    # 3. No space existence
1217    # 4. Global variable name must start with a 'g'
1218    # Check whether the variable name followed the rule
1219    def NamingConventionCheckVariableName(self, FileTable):
1220        if EccGlobalData.gConfig.NamingConventionCheckVariableName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1221            EdkLogger.quiet("Checking naming covention of variable name ...")
1222            Pattern = re.compile(r'^[A-Zgm]+\S*[a-z]\S*$')
1223
1224            SqlCommand = """select ID, Name from %s where Model = %s""" % (FileTable, MODEL_IDENTIFIER_VARIABLE)
1225            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1226            for Record in RecordSet:
1227                Var = Record[1]
1228                if Var.startswith('CONST'):
1229                    Var = Var[5:].lstrip()
1230                if not Pattern.match(Var):
1231                    if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, Record[1]):
1232                        EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME, OtherMsg="The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable=FileTable, BelongsToItem=Record[0])
1233
1234    # Rule for path name, variable name and function name
1235    # 1. First character should be upper case
1236    # 2. Existing lower case in a word
1237    # 3. No space existence
1238    # Check whether the function name followed the rule
1239    def NamingConventionCheckFunctionName(self):
1240        if EccGlobalData.gConfig.NamingConventionCheckFunctionName == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1241            EdkLogger.quiet("Checking naming covention of function name ...")
1242            Pattern = re.compile(r'^[A-Z]+\S*[a-z]\S*$')
1243            SqlCommand = """select ID, Name from Function"""
1244            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1245            for Record in RecordSet:
1246                if not Pattern.match(Record[1]):
1247                    if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, Record[1]):
1248                        EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME, OtherMsg="The function name [%s] does not follow the rules" % (Record[1]), BelongsToTable='Function', BelongsToItem=Record[0])
1249
1250    # Check whether NO use short variable name with single character
1251    def NamingConventionCheckSingleCharacterVariable(self, FileTable):
1252        if EccGlobalData.gConfig.NamingConventionCheckSingleCharacterVariable == '1' or EccGlobalData.gConfig.NamingConventionCheckAll == '1' or EccGlobalData.gConfig.CheckAll == '1':
1253            EdkLogger.quiet("Checking naming covention of single character variable name ...")
1254
1255            SqlCommand = """select ID, Name from %s where Model = %s""" % (FileTable, MODEL_IDENTIFIER_VARIABLE)
1256            RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
1257            for Record in RecordSet:
1258                Variable = Record[1].replace('*', '')
1259                if len(Variable) == 1:
1260                    if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, Record[1]):
1261                        EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_SINGLE_CHARACTER_VARIABLE, OtherMsg="The variable name [%s] does not follow the rules" % (Record[1]), BelongsToTable=FileTable, BelongsToItem=Record[0])
1262
1263##
1264#
1265# This acts like the main() function for the script, unless it is 'import'ed into another
1266# script.
1267#
1268if __name__ == '__main__':
1269    Check = Check()
1270    Check.Check()
1271